You are on page 1of 4431

Contents

ASP.NET Core belgeleri


Genel Bakış
ASP.NET Core Hakkında
ASP.NET Core ile ASP.NET Karşılaştırması
.NET Core ile .NET Framework Karşılaştırması
Kullanmaya başlayın
Yenilikler
3.1 sürümündeki yenilikler
3.0 sürümündeki yenilikler
2.2 sürümündeki yenilikler
2.1 sürümündeki yenilikler
2.0 sürümündeki yenilikler
1.1 sürümündeki yenilikler
Öğreticiler
Web uygulamaları
Razor Pages
Genel Bakış
Kullanmaya başlayın
Model ekleme
Yapı iskelesi
Veritabanı ile çalışma
Sayfaları güncelleştirme
Arama ekleme
Yeni alan ekleme
Doğrulama ekleme
MVC
Genel Bakış
Kullanmaya başlayın
Denetleyici ekleme
Görünüm ekleme
Model ekleme
Veritabanı ile çalışma
Denetleyici eylemleri ve görünümleri
Arama ekleme
Yeni alan ekleme
Doğrulama ekleme
Details ve Delete yöntemlerini inceleme
Blazor
Web API’si uygulamaları
Web API’si oluşturma
MongoDB ile Web API
JavaScript ile Web API’si
Mobil için arka uç
Gerçek zamanlı web uygulamaları
JavaScript ile SignalR
TypeScript ile SignalR
Uzaktan Yordam Çağrısı uygulamaları
gRPC hizmetini kullanmaya başlama
Veri erişimi
Razor Pages ile EF Core
Kullanmaya başlayın
Oluşturma, Okuma, Güncelleştirme ve Silme
Sıralama, filtreleme, sayfalama ve gruplandırma
Geçişler
Karmaşık veri modeli oluşturma
İlgili verileri okuma
İlgili verileri güncelleştirme
Eşzamanlılık çakışmalarını işleme
MVC ile EF Core
Genel Bakış
Kullanmaya başlayın
Oluşturma, Okuma, Güncelleştirme ve Silme
Sıralama, filtreleme, sayfalama ve gruplandırma
Geçişler
Karmaşık veri modeli oluşturma
İlgili verileri okuma
İlgili verileri güncelleştirme
Eşzamanlılık çakışmalarını işleme
Devralma
Gelişmiş konular
Öğreticiler (Microsoft Learn)
Web uygulamaları
Web API’si uygulamaları
Veri erişimi
Web uygulaması güvenliği
Temeller
Genel Bakış
Başlangıç sınıfı
Bağımlılık ekleme (hizmetler)
Ara yazılım
Ana bilgisayar
Genel Konak
Web Konağı
Sunucular
Yapılandırma
Seçenekler
Ortamlar (geliştirme, hazırlama, üretim)
Günlüğe Kaydetme
Yönlendirme
Hataları işleme
HTTP isteğinde bulunma
Statik dosyalar
Web uygulamaları
Razor Pages
Razor Pages
Giriş
Eğitmen
Genel Bakış
Kullanmaya başlayın
Model ekleme
Yapı iskelesi
Veritabanı ile çalışma
Sayfaları güncelleştirme
Arama ekleme
Yeni alan ekleme
Doğrulama ekleme
FilTReleri
Yol ve uygulama kuralları
Razor SDK
MVC
Genel Bakış
Eğitmen
Genel Bakış
Kullanmaya başlayın
Denetleyici ekleme
Görünüm ekleme
Model ekleme
Veritabanı ile çalışma
Denetleyici eylemleri ve görünümleri
Arama ekleme
Yeni alan ekleme
Doğrulama ekleme
Details ve Delete yöntemlerini inceleme
Görünümler
Kısmı görünümler
Denetleyiciler
Yönlendirme
Bağımlılık ekleme - denetleyiciler
Bağımlılık ekleme - görünümler
Birim testi
Blazor
Genel Bakış
Desteklenen platformlar
Kullanmaya başlayın
Barındırma modelleri
İlk uygulamanızı oluşturma
Şablonlar
Bileşenler
Yaşam döngüsü
Formlar ve doğrulama
Bileşen kitaplıkları
Düzenler
Bağımlılık ekleme
Yönlendirme
JavaScript ile birlikte çalışma
Güvenlik ve Kimlik
Genel Bakış
Blazor Server
Durum yönetimi
Hataları işleme
Hata ayıklama
Web API çağrısı
Barındırma ve dağıtma
Genel Bakış
Blazor WebAssembly
Blazor Server
Bağlayıcıyı yapılandırma
Örnekler
İstemci tarafı geliştirme
Tek Sayfalı Uygulamalar
Angular
React
Redux ile React
JavaScript Hizmetleri
LibMan
Genel Bakış
CLI
Visual Studio
Grunt
Paketleme ve küçültme
Tarayıcı Bağlantısı
Oturum ve uygulama durumu
Düzen
Razor söz dizimi
Razor sınıf kitaplıkları
Etiket Yardımcıları
Genel Bakış
Etiket Yardımcıları oluşturma
Formlarda Etiket Yardımcılarını kullanma
Etiket Yardımcısı Bileşenleri
Yerleşik Etiket Yardımcıları
Yer işareti
Önbellek
Dağıtılmış Önbellek
Ortam
Form
Form Eylemi
Görüntü
Giriş
Etiketle
Bağlantı
Kısmi
Komut Dosyası
Seçim
Metin Alanı
Doğrulama İletisi
Doğrulama Özeti
Gelişmiş
Görünüm bileşenleri
Görünüm derlemesi
Uygulama modeli
FilTReleri
Alanlar
Dosyaları karşıya yükleme
Uygulama bölümleri
aspnet-codegenerator
Web API’si uygulamaları
Genel Bakış
Öğreticiler
Web API’si oluşturma
MongoDB ile Web API
Swagger / OpenAPI
Genel Bakış
Swashbuckle kullanmaya başlama
NSwag kullanmaya başlama
OpenAPI araçları
Eylem dönüş türleri
JSON Düzeltme eki isteklerini işleme
Yanıt verilerini biçimlendirme
Özel biçimlendiriciler
Çözümleyiciler
Kurallar
Hataları işleme
HTTP REPL ile Test API'leri
Gerçek zamanlı uygulamalar
SignalR’a genel bakış
Desteklenen platformlar
Öğreticiler
JavaScript ile SignalR
TypeScript ile SignalR
Örnekler
Sunucu kavramları
Merkezler
Merkezin dışından gönderme
Kullanıcılar ve gruplar
API tasarımı etkenleri
İstemciler
SignalR istemci özellikleri
.NET istemcisi
.NET API'si başvurusu
Java istemcisi
Java API'si başvurusu
JavaScript istemcisi
JavaScript API'si başvurusu
Konak ve ölçek
Genel Bakış
Azure App Service
Redis kartı
SignalR ile arka plan hizmetleri
Yapılandırma
Kimlik doğrulaması ve yetkilendirme
Güvenlik konuları
MessagePack Hub Protokolü
Akış
SignalR ile SignalR Core Karşılaştırması
SignalR olmadan WebSockets
Günlüğe kaydetme ve tanılama
Belirtimler
Merkez protokolü
Aktarım protokolleri
Uzaktan Yordam Çağrısı uygulamaları
gRPC hizmetlerine giriş
Öğreticiler
gRPC hizmetini kullanmaya başlama
C# içeren gRPC hizmetleri
ASP.NET Core içeren gRPC Hizmetleri
.NET istemcisiyle gRPC hizmetlerini çağırma
gRPC istemci fabrikası tümleştirmesi
Yapılandırma
Kimlik doğrulaması ve yetkilendirme
Günlüğe kaydetme ve tanılama
Güvenlik konuları
dotnet-grpc ile Protobuf başvurularını yönetme
C-core’dan gRPC hizmetlerini geçirme
gRPC hizmetlerini HTTP API’leriyle karşılaştırma
Örnekler
Sorun giderme
Test etme, hata ayıklama ve sorun giderme
Razor Pages birim testleri
Test denetleyicileri
Uzaktan hata ayıklama
Anlık görüntü hatalarını ayıklama
Visual Studio'da anlık görüntü hatalarını ayıklama
Tümleştirme testleri
Yükleme ve stres testleri
Sorun giderme
Günlüğe Kaydetme
Azure ve IIS sorunlarını giderme
Azure ve IIS hataları başvurusu
Veri erişimi
Öğreticiler
Razor Pages ile EF Core
Kullanmaya başlayın
Oluşturma, Okuma, Güncelleştirme ve Silme
Sıralama, filtreleme, sayfalama ve gruplandırma
Geçişler
Karmaşık veri modeli oluşturma
İlgili verileri okuma
İlgili verileri güncelleştirme
Eşzamanlılık çakışmalarını işleme
MVC ile EF Core
Genel Bakış
Kullanmaya başlayın
Oluşturma, Okuma, Güncelleştirme ve Silme
Sıralama, filtreleme, sayfalama ve gruplandırma
Geçişler
Karmaşık veri modeli oluşturma
İlgili verileri okuma
İlgili verileri güncelleştirme
Eşzamanlılık çakışmalarını işleme
Devralma
Gelişmiş konular
ASP.NET Core ile EF 6
Visual Studio ile Azure Depolama
Bağlı Hizmetler
Blob depolama
Kuyruk depolama
Tablo depolama
Barındırma ve dağıtma
Genel Bakış
Azure App Service
Genel Bakış
Visual Studio ile yayımlama
Mac için Visual Studio ile yayımlama
CLI araçları ile yayımlama
Visual Studio ve Git ile yayımlama
Azure Pipelines ile sürekli dağıtım
ASP.NET Core Modülü
Sorun giderme
Hata başvurusu
DevOps
Genel Bakış
Araçlar ve indirmeler
App Service’e dağıtma
Sürekli tümleştirme ve dağıtım
İzleme ve sorun giderme
Sonraki adımlar
IIS
Genel Bakış
IIS’de yayımlama öğreticisi
ASP.NET Core Modülü
Visual Studio'da IIS desteği
IIS Modülleri
Sorun giderme
Hata başvurusu
Web.config’i dönüştürme
Kestrel
HTTP.sys
Windows hizmeti
Nginx ile Linux
Apache ile Linux
Docker
Genel Bakış
Docker görüntüleri oluşturma
Visual Studio Araçları
Docker görüntüsüne yayımlama
Örnek Docker görüntüleri
Ara sunucu ve yük dengeleyiciyi yapılandırma
Web grubu
Visual Studio yayımlama profilleri
Mac için Visual Studio yayımlama klasörü
Dizin yapısı
Sistem durumu denetimleri
Blazor
Genel Bakış
Blazor WebAssembly
Blazor Server
Bağlayıcıyı yapılandırma
Güvenlik ve Kimlik
Genel Bakış
Kimlik doğrulaması
Genel Bakış
Kimliğe giriş
SPA ile kimlik
İskele Kimliği
Özel kullanıcı verilerini Kimlik’e ekleme
Kimlik doğrulaması örnekleri
Kimlik Özelleştirme
Topluluk OSS kimlik doğrulama seçenekleri
Kimliği Yapılandırma
Windows Kimlik Doğrulaması Yapılandırma
Kimlik için özel depolama sağlayıcıları
Google, Facebook ...
Genel Bakış
Google kimlik doğrulaması
Facebook kimlik doğrulaması
Microsoft kimlik doğrulaması
Twitter kimlik doğrulaması
Diğer sağlayıcılar
Ek talepler
İlke şemaları
WS-Federasyon kimlik doğrulaması
Hesap onaylama ve parola kurtarma
Kimlik’te QR kodu oluşturmayı etkinleştirme
SMS ile iki öğeli kimlik doğrulama
Kimlik olmadan Tanımlama Bilgisi Kimlik Doğrulaması kullanma
Kimlik olmadan sosyal Kimlik Doğrulaması kullanma
Azure Active Directory
Genel Bakış
Azure AD’yi web uygulamasıyla tümleştirme
Azure AD BC2’yi web uygulamasıyla tümleştirme
Azure AD BC2’yi web API’siyle tümleştirme
WPF'den bir web API’sini çağırma
Azure AD kullanarak bir web uygulamasında Web API’sini çağırma
IdentityServer4 ile ASP.NET Core uygulamalarının güvenliğini sağlama
Azure App Service kimlik doğrulaması (Kolay Kimlik Doğrulaması) ile ASP.NET Core
uygulamalarının güvenliğini sağlama
Bireysel kullanıcı hesapları
Sertifika kimlik doğrulamasını yapılandırma
Yetkilendirme
Genel Bakış
Yetkilendirme içeren bir web uygulaması oluşturma
Razor Pages yetkilendirme kuralları
Basit yetkilendirme
Rol tabanlı yetkilendirme
Talep tabanlı yetkilendirme
İlke tabanlı yetkilendirme
Yetkilendirme ilkesi sağlayıcıları
Gereksinim işleyicilerine bağımlılık ekleme
Kaynak tabanlı yetkilendirme
Görünüm tabanlı yetkilendirme
Şemayla kimliği sınırlama
Veri koruma
Genel Bakış
Veri koruma API'leri
Tüketici API’leri
Genel Bakış
Amaç dizeleri
Amaç hiyerarşisi ve çok kiracılılık
Karma parolalar
Korumalı yüklerin ömrünü sınırlama
Anahtarları iptal edilen yüklerin korumasını kaldırma
Yapılandırma
Genel Bakış
Veri korumasını yapılandırma
Varsayılan ayarlar
Makine geneli ilke
DI bilgisi içermeyen senaryolar
Genişletilebilirlik API’leri
Genel Bakış
Çekirdek şifreleme genişletilebilirliği
Anahtar yönetimi genişletilebilirliği
Çeşitli API'ler
Uygulama
Genel Bakış
Kimliği doğrulanmış şifreleme ayrıntıları
Alt anahtar türetme ve kimliği doğrulanmış şifreleme
Bağlam üst bilgileri
Anahtar yönetimi
Anahtar depolama sağlayıcıları
Bekleme durumunda anahtar şifreleme
Anahtar değiştirilemezliği ve ayarlar
Anahtar depolama biçimi
Kısa ömürlü veri koruma sağlayıcıları
Uyumluluk
Genel Bakış
ASP.NET'te machineKey değiştirme
Gizli dizi yönetimi
Geliştirmede gizli dizileri koruma
Azure Key Vault Yapılandırma Sağlayıcısı
HTTPS'yi zorunlu tutma
HTTPS ile Docker’ı barındırma
AB Genel Veri Koruma Yönetmeliği (GDPR) desteği
İstek sahteciliğinden koruma
Açık yeniden yönlendirme saldırılarını önleme
Siteler Arası Betik kullanmayı önleme
Kaynaklar Arası İstekleri (CORS) etkinleştirme
Uygulamalar arasında tanımlama bilgilerini paylaşma
SameSite tanımlama bilgileri
IP güvenli listesi
Uygulama güvenliği - OWASP
Blazor
Genel Bakış
Blazor Server
Performans
Genel Bakış
Bellek ve GC
Yanıtları Önbelleğe Alma
Genel Bakış
Belleğe yüklenmiş önbellek
Dağıtılmış önbelleğe alma
Yanıtları önbelleğe alma ara yazılımı
ObjectPool ile yeniden nesne kullanımı
Yanıt sıkıştırma
Tanılama araçları
Yükleme ve stres testleri
Genelleştirme ve yerelleştirme
Genel Bakış
Taşınabilir Nesne yerelleştirmesi
Genişletilebilirlik
Sorun giderme
Gelişmiş
Model bağlama
Özel model bağlama
Model doğrulaması
Uyumluluk sürümü
Ara yazılım yazma
İstek ve yanıt işlemleri
URL yeniden yazma
Dosya sağlayıcıları
Özellik isteği arabirimleri
HttpContext’e erişim
Belirteçleri değiştirme
.NET için Açık Web Arabirimi (OWIN)
Barındırılan hizmetler ile arka plan görevleri
Başlangıç derlemelerini barındırma
Microsoft.AspNetCore.App metapackage
Microsoft.AspNetCore.All metapackage
LoggerMessage ile günlüğe kaydetme
Dosya izleyicisi kullanma
Fabrika tabanlı ara yazılım
Üçüncü taraf kapsayıcı ile fabrika tabanlı ara yazılım
Geçiş
3.0’dan 3.1’e
2.2’den 3.0’a
2.1’den 2.2’ye
2.0’dan 2.1’e
1.x’ten 2.0’a
Genel Bakış
Kimlik Doğrulaması ve Kimlik
ASP.NET’ten ASP.NET Core’a
Genel Bakış
MVC
Web API
Yapılandırma
Kimlik Doğrulaması ve Kimlik
ClaimsPrincipal.Current
Üyelikten Kimliğe
HTTP modüllerinden ara yazılıma
Günlüğe kaydetme (ASP.NET Core dışında)
API başvurusu
Katkıda Bulun
ASP.NET Core’a Giriş
29.04.2019 • 10 minutes to read • Edit Online

Daniel Roth, Rick Anderson ve Shaun Luttin tarafından hazırlanmıştır


ASP.NET Core, modern, bulut tabanlı, İnternet bağlantılı uygulamalar oluşturmaya yönelik platformlar arası,
yüksek performanslı, açık kaynak bir çerçevedir. ASP.NET Core ile şunları yapabilirsiniz:
Web uygulamaları ve hizmetleri, IoT uygulamaları ve mobil arka uçlar oluşturun.
Windows, macOS ve Linux üzerinde tercih ettiğiniz geliştirme araçlarını kullanın.
Buluta veya şirket içine dağıtın.
.NET Core veya .NET Framework üzerinde çalıştırın.

Neden ASP.NET Core kullanılmalı?


Milyonlarca geliştirici, web uygulamaları oluşturmak için ASP.NET 4.x kullandı (ve kullanmaya devam ediyor).
ASP.NET Core, ASP.NET 4.x sürümünün daha yalın, daha modüler bir çerçeve elde edilmesini sağlayan mimari
değişikliklerle yeniden tasarlanmış halidir.
ASP.NET Core aşağıdaki avantajları sağlar:
Web UI ve Web API 'Leri oluşturmak için birleştirilmiş bir hikaye.
, Test edilebilirlik için tasarlanmıştır.
Razor Pages , kodlama sayfasına odaklanmış senaryolara daha kolay ve daha üretken olmasını sağlar.
Blazor , tarayıcıda JavaScript C# 'in yanı sıra kullanmanıza olanak sağlar. Sunucu tarafı ve istemci tarafı
uygulama mantığını tüm .NET ile yazılmış şekilde paylaşabilirsiniz.
Windows, macOS ve Linux 'ta geliştirme ve çalıştırma özelliği.
Açık kaynak ve topluluk odaklı.
Modern, istemci tarafı çerçeveleri ve geliştirme iş akışlarının tümleştirilmesi.
GRPCkullanarak uzak yordam ÇAĞRıSı (RPC ) hizmetlerini barındırmak için destek.
Buluta hazırlanma, ortam tabanlı bir yapılandırma sistemi.
Yerleşik bağımlılık ekleme.
Basit, yüksek performanslıve modüler bir http istek işlem hattı.
Aşağıdakiler üzerinde barındırma özelliği:
Kestrel
ISS
HTTP. sys
NGINX
Apache
Docker
Yan yana sürüm oluşturma.
Modern Web geliştirmeyi kolaylaştıran araç.

ASP.NET Core MVC kullanarak web API'leri ve web kullanıcı arabirimi


oluşturma
ASP.NET Core MVC, web API’leri ve web uygulamaları oluşturmaya yönelik özellikler sağlar:
Model-Görünüm-Denetleyici (MVC ) deseni, web API'lerinin ve web uygulamalarının sınanabilir olmasını
sağlamanıza yardımcı olur.
Razor Pages, web kullanıcı arabirimi oluşturmayı daha kolay ve üretken bir hale getiren, sayfa tabanlı bir
programlama modelidir.
Razor işaretlemesi, Razor Sayfaları ve MVC görünümleri için üretken bir söz dizimi sağlar.
Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir.
Birden çok veri biçimi ve içerik anlaşması için sunulan yerleşik destek, web API'lerinizin tarayıcılar ve mobil
cihazlar dahil olmak üzere birçok çeşit istemciye ulaşmasına imkan tanır.
Model bağlama, HTTP isteklerinden alınan verileri otomatik olarak eylem metodu parametreleriyle eşleştirir.
Model doğrulama, otomatik olarak istemci ve sunucu tarafı doğrulama gerçekleştirir.

İstemci tarafı geliştirme


ASP.NET Core, aralarında Razor Components, Angular, React ve Bootstrap’in bulunduğu popüler istemci tarafı
çerçeve ve kitaplıklarla sorunsuz bir şekilde tümleştirilir. Daha fazla bilgi için Razor Components ve İstemci tarafı
geliştirme altındaki ilgili konulara bakın.

.NET Framework'ü hedefleyen ASP.NET Core


ASP.NET Core 2.x, .NET Core'u veya .NET Framework'ü hedefleyebilir. .NET Framework'ü hedefleyen ASP.NET
Core uygulamaları platformlar arası çalışmaz; bunlar yalnızca Windows üzerinde çalışır. Genel olarak, ASP.NET
Core 2.x .NET Standard kitaplıklarından oluşturulmuştur. .NET Standard 2.0 ile yazılmış uygulamalar .NET
Standard 2.0'ın desteklendiği her yerde çalıştırılır.
ASP.NET Core 2.x, .NET Standard 2.0 ile uyumlu .NET Framework sürümlerinde desteklenir:
.NET Framework 4.7.1 ve üzeri önemle tavsiye edilir.
.NET Framework 4.6.1 ve üzeri.
ASP.NET Core 3.0 ve üzeri yalnızca .NET Core’da çalışır. Bu değişiklik hakkında daha fazla bilgi için bkz.
ASP.NET Core 3.0’daki değişikliklere ilk bakış.
.NET Core hedeflemesinin çeşitli avantajları vardır ve bu avantajlar her yeni sürümle birlikte artmaktadır. .NET
Framework'e göre .NET Core'un bazı avantajları şunlardır:
Platformlar arası. macOS, Linux ve Windows üzerinde çalışır.
Geliştirilmiş performans
Yan yana sürüm oluşturma
Yeni API'ler
Açık kaynak
.NET Framework ile .NET Core arasındaki API açığını kapatmak için çok çalışıyoruz. Windows Uyumluluk Paketi,
.NET Core'da yalnızca Windows'a yönelik binlerce API'yi kullanıma sunmaktadır. Bu API'ler .NET Core 1.x'te
sağlanmamıştı.

Önerilen öğrenme yolu


ASP.NET Core uygulamaları geliştirmeye başlamak için şu öğreticileri ve makaleleri takip etmenizi öneririz:
1. Geliştirmek veya yönetmek istediğiniz uygulama türüne yönelik bir öğreticiyi takip edin:
UYGULAMA TÜRÜ SENARYO EĞITMEN

Web uygulaması Yeni proje geliştirmek için Razor Sayfaları kullanmaya başlama

Web uygulaması MVC uygulaması yönetmek için MVC ile çalışmaya başlama

Web API Web API’si oluşturma*

Gerçek zamanlı uygulama SignalR ile çalışmaya başlama

2. Temel veri erişiminin nasıl yapıldığını gösteren bir öğreticiyi takip edin:

SENARYO EĞITMEN

Yeni proje geliştirmek için Entity Framework Core ile Razor Pages

MVC uygulaması yönetmek için Entity Framework Core ile MVC

3. Tüm uygulama türleri için geçerli olan ASP.NET Core özelliklerine yönelik genel bakışı okuyun:
Temeller
4. İlgilendiğiniz diğer konular için İçindekiler Tablosu’na göz atın.
Tarayıcıda tamamını takip ettiğiniz ve yerel IDE yüklemesi gerektirmeyen * yeni bir web API’si öğreticisi var. Kod
Azure Cloud Shell’de çalışır, curl ise test için kullanılır.

Örnek indirme
Çoğu makale ve öğretici örnek koda bağlantılar içerir.
1. ASP.NET depo zip dosyasını indirin.
2. Docs-master.zip dosyasının sıkıştırmasını açın.
3. Örnek dizinde gezinmek için örnek bağlantıdaki URL’yi kullanın.
Örnek kodda ön işlemci yönergeleri
Örnek uygulamalar birden çok senaryoyu göstermek amacıyla aynı koda ait farklı bölümleri seçmeli olarak
derleyip çalıştırmak için #define ve #if-#else/#elif-#endif C# deyimlerini kullanır. Bu yaklaşımdan yararlanan
örneklerde C# dosyalarının üst kısmındaki #define deyimini, çalıştırmak istediğiniz senaryoyla ilişkili olan
simgeye ayarlayın. Bazı örnekler senaryoyu çalıştırmak için birden çok dosyanın üst kısmındaki simgenin
ayarlanmasını gerektirebilir.
Örneğin, aşağıdaki simge listesi #define dört senaryonun kullanılabilir olduğunu gösterir (her simge için bir
senaryo). Geçerli örnek yapılandırması TemplateCode senaryosunu çalıştırır:

#define TemplateCode // or LogFromMain or ExpandDefault or FilterInCode

Örneği ExpandDefault senaryosunu çalıştıracak şekilde değiştirmek için ExpandDefault simgesini tanımlayın ve
kalan simgeleri açıklama satırı yapılmış şekilde bırakın:

#define ExpandDefault // TemplateCode or LogFromMain or FilterInCode

Kod bölümlerini seçmeli olarak derlemek üzere C# ön işlemci yönergelerini kullanma hakkında daha fazla bilgi
için bkz. #define (C# Başvurusu) ve #if (C# Başvurusu).
Örnek kodda bölgeler
Bazı örnek uygulamalar, #region ve #endregion C# deyimleri içine yerleştirilmiş kod bölümleri içerir. Belge
derleme sistemi bu bölgeleri işlenmiş belge konularının içine ekler.
Bölge adları çoğunlukla şu sözcüğü içerir: "snippet." Aşağıdaki örnekte snippet_FilterInCode adlı bir bölge
gösterilir:

#region snippet_FilterInCode
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace))
.Build();
#endregion

Önündeki C# kod parçacığına, konunun markdown dosyasında aşağıdaki satırla başvurulur:

[!code-csharp[](sample/SampleApp/Program.cs?name=snippet_FilterInCode)]

Kodu çevreleyen #region ve #endregion deyimlerini rahatça yoksayabilirsiniz (veya kaldırabilirsiniz). Konuda
açıklanan örnek senaryoları çalıştırmayı planlıyorsanız, bu deyimlerin anasındaki kodu değiştirmeyin. Başka
senaryolarla denemeler yaparken kodu rahatça değiştirebilirsiniz.
Daha fazla bilgi için bkz. ASP.NET belgelerine katkıda bulunma: Kod parçacıkları.

Sonraki adımlar
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
ASP.NET Core kullanmaya başlayın
Visual Studio ile Azure'a bir ASP.NET Core uygulaması yayımlama
ASP.NET Core temelleri
Haftalık ASP.NET topluluğu toplantısında, takımın ilerleme durumu ve planları ele alınır. Yeni bloglara ve
üçüncü taraf yazılıma yer verilir.
ASP.NET 4. x ve ASP.NET Core arasında seçim yapın
13.11.2019 • 3 minutes to read • Edit Online

ASP.NET Core, ASP.NET 4. x ' in bir tasarlayadır. Bu makalede aralarındaki farklar listelenir.

ASP.NET Core
ASP.NET Core, Windows, macOS veya Linux 'ta modern, bulut tabanlı Web uygulamaları oluşturmaya yönelik açık
kaynaklı, platformlar arası bir çerçevedir.
ASP.NET Core aşağıdaki avantajları sağlar:
Web UI ve Web API 'Leri oluşturmak için birleştirilmiş bir hikaye.
, Test edilebilirlik için tasarlanmıştır.
Razor Pages , kodlama sayfasına odaklanmış senaryolara daha kolay ve daha üretken olmasını sağlar.
Blazor , tarayıcıda JavaScript C# 'in yanı sıra kullanmanıza olanak sağlar. Sunucu tarafı ve istemci tarafı
uygulama mantığını tüm .NET ile yazılmış şekilde paylaşabilirsiniz.
Windows, macOS ve Linux 'ta geliştirme ve çalıştırma özelliği.
Açık kaynak ve topluluk odaklı.
Modern, istemci tarafı çerçeveleri ve geliştirme iş akışlarının tümleştirilmesi.
GRPCkullanarak uzak yordam ÇAĞRıSı (RPC ) hizmetlerini barındırmak için destek.
Buluta hazırlanma, ortam tabanlı bir yapılandırma sistemi.
Yerleşik bağımlılık ekleme.
Basit, yüksek performanslıve modüler bir http istek işlem hattı.
Aşağıdakiler üzerinde barındırma özelliği:
Kestrel
ISS
HTTP. sys
NGINX
Apache
Docker
Yan yana sürüm oluşturma.
Modern Web geliştirmeyi kolaylaştıran araç.

ASP.NET 4. x
ASP.NET 4. x, Windows 'ta kurumsal düzeyde, sunucu tabanlı Web uygulamaları oluşturmak için gereken
hizmetleri sağlayan, yetişkinlere yönelik bir çerçevedir.

Çerçeve seçimi
Aşağıdaki tabloda ASP.NET Core ASP.NET 4. x ile karşılaştırılır.

ASP.NET CORE ASP.NET 4. X

Windows, macOS veya Linux için derleme Windows için derleme


ASP.NET CORE ASP.NET 4. X

Razor Pages , bir Web kullanıcı arabirimini ASP.NET Core 2. x Web Forms, SignalR, MVC, Web API, Web kancalarıveya Web
olarak oluşturmak için önerilen yaklaşımdır. Ayrıca bkz. MVC, sayfaları kullanın
Web APIve SignalR.

Makine başına birden çok sürüm Makine başına bir sürüm

C# Veya kullanarak Visual Studio, Mac için Visual Studioveya , Vb veya kullanarak C# Visual Studio ile geliştirmeF#
Visual Studio Code geliştirinF#

ASP.NET 4. x 'ten daha yüksek performans İyi performans

.NET Core çalışma zamanı kullan .NET Framework çalışma zamanını kullan

.NET Framework üzerinde ASP.NET Core 2. x desteği hakkında bilgi için bkz. ASP.NET Core .NET Framework
Hedefleme .

ASP.NET Core senaryolar


Siteleriniz
GetVersionEx
Gerçek zamanlı
Azure 'a ASP.NET Core uygulaması dağıtma

ASP.NET 4. x senaryoları
Siteleriniz
GetVersionEx
Gerçek zamanlı
Azure 'da bir ASP.NET 4. x Web uygulaması oluşturma

Ek kaynaklar
ASP.NET 'e giriş
ASP.NET Core giriş
ASP.NET Core uygulamalarını Azure App Service dağıtma
Öğretici: ASP.NET Core kullanmaya başlayın
23.11.2019 • 2 minutes to read • Edit Online

Bu öğreticide, bir ASP.NET Core Web uygulaması oluşturmak ve çalıştırmak için .NET Core komut satırı arabirimi
'nin nasıl kullanılacağı gösterilmektedir.
Şunları yapmayı öğreneceksiniz:
Bir Web uygulaması projesi oluşturun.
Geliştirme sertifikasına güvenin.
Uygulamayı çalıştırın.
Razor sayfasını düzenleyin.
Sonunda, yerel makinenizde çalışan bir çalışan Web uygulamanız olacaktır.

Önkoşullar
.NET Core 3,0 SDK veya üzeri

Web uygulaması projesi oluşturma


Bir komut kabuğu açın ve şu komutu girin:

dotnet new webapp -o aspnetcoreapp

Önceki komut:
Yeni bir Web uygulaması oluşturur.
-o aspnetcoreapp parametresi, uygulama için kaynak dosyalarla aspnetcoreapp adlı bir dizin oluşturur.

Geliştirme sertifikasına güven


HTTPS geliştirme sertifikasına güvenin:
Windows
macOS
Linux

dotnet dev-certs https --trust

Yukarıdaki komutta aşağıdaki iletişim kutusu görüntülenir:

Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.


Daha fazla bilgi için bkz . asp.NET Core https geliştirme sertifikasına güven

Uygulamayı çalıştırma
Aşağıdaki komutları çalıştırın:

cd aspnetcoreapp
dotnet watch run

Komut kabuğu, uygulamanın başlatıldığını gösteriyorsa, https://localhost:5001gidin.

Razor sayfasını düzenleme


Pages/Index. cshtml dosyasını açın ve sayfayı aşağıdaki vurgulanmış işaretlerle değiştirin ve kaydedin:

@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Hello, world! The time on the server is @DateTime.Now</p>
</div>

https://localhost:5001gidin, sayfayı yenileyin ve değişikliklerin görüntülendiğini doğrulayın.

Sonraki adımlar
Bu öğreticide, şunların nasıl yapıldığını öğrendiniz:
Bir Web uygulaması projesi oluşturun.
Geliştirme sertifikasına güvenin.
Projeyi çalıştırın.
Değişiklik yapın.
ASP.NET Core hakkında daha fazla bilgi edinmek için bkz. giriş bölümünde önerilen öğrenme yolu:
ASP.NET Core’a Giriş
ASP.NET Core 3,1 ' deki yenilikler
9.12.2019 • 4 minutes to read • Edit Online

Bu makalede, ASP.NET Core 3,1 ' deki en önemli değişiklikler ilgili belgelerin bağlantılarıyla vurgulanır.

Razor bileşenleri için kısmi sınıf desteği


Razor bileşenleri artık kısmi sınıflar olarak oluşturulmuştur. Bir Razor bileşeni kodu, tek bir dosyada bileşen için
tüm kodu tanımlamak yerine kısmi bir sınıf olarak tanımlanmış bir arka plan kod dosyası kullanılarak yazılabilir.
Daha fazla bilgi için bkz. kısmi sınıf desteği.

Bileşen etiketi yardımcısını Blazor ve parametreleri en üst düzey


bileşenlere geçir
ASP.NET Core 3,0 ile Blazor, bileşenler HTML Yardımcısı ( Html.RenderComponentAsync ) kullanılarak sayfalar ve
görünümler halinde işlenmiştir. ASP.NET Core 3,1 ' de, yeni bileşen etiketi Yardımcısı ile bir sayfadan veya
görünümden bir bileşeni işleme:

<component type="typeof(Counter)" render-mode="ServerPrerendered" />

HTML Yardımcısı ASP.NET Core 3,1 ' de desteklenmeye devam eder, ancak bileşen etiketi Yardımcısı önerilir.
Blazor Server uygulamaları artık ilk işleme sırasında parametreleri en üst düzey bileşenlere geçirebilir. Daha önce,
parametreleri yalnızca RenderMode. staticolan en üst düzey bileşene geçirebilirsiniz. Bu sürümle birlikte, hem
RenderMode. Server hem de Rendermodel. Serverprerenimli desteklenir. Belirtilen parametre değerleri JSON
olarak serileştirilir ve başlangıç yanıtına dahil edilir.
Örneğin, PreRender bir artış miktarı olan Counter bileşen ( IncrementAmount ):

<component type="typeof(Counter)" render-mode="ServerPrerendered"


param-IncrementAmount="10" />

Daha fazla bilgi için bkz. bileşenleri Razor Pages ve MVC uygulamalarıyla tümleştirme.

HTTP. sys dosyasındaki paylaşılan sıralar için destek


Http. sys , anonim istek kuyrukları oluşturmayı destekler. ASP.NET Core 3,1 ' de, var olan bir HTTP. sys istek
kuyruğunu oluşturma veya ekleme yeteneğine ekledik. Var olan adlandırılmış bir HTTP. sys istek kuyruğunu
oluşturma veya iliştirme, sıranın sahibi olan HTTP. sys denetleyici işleminin dinleyici işleminden bağımsız olduğu
senaryolara olanak sağlar. Bu bağımsızlık, var olan bağlantıları ve dinleyici işlemi yeniden başlatmalar arasında
sıraya alınmış istekleri korumayı mümkün kılar:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// ...
webBuilder.UseHttpSys(options =>
{
options.RequestQueueName = "MyExistingQueue";
options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
});
});

SameSite tanımlama bilgilerine yönelik son değişiklikler


SameSite tanımlama bilgilerinin davranışı yaklaşan tarayıcı değişikliklerini yansıtacak şekilde değiştirilmiştir. Bu,
AzureAd, Openıdconnect veya WsFederation gibi kimlik doğrulama senaryolarını etkileyebilir. Daha fazla bilgi için
bkz. ASP.NET Core ' de SameSite tanımlama bilgileriyle çalışma.

Blazor uygulamalardaki olaylara yönelik varsayılan eylemleri engelleyin


Bir olayın varsayılan eylemini engellemek için @on{EVENT}:preventDefault Directive özniteliğini kullanın. Aşağıdaki
örnekte, metin kutusunda anahtarın karakterini görüntülemenin varsayılan eylemi engellenir:

<input value="@_count" @onkeypress="KeyHandler" @onkeypress:preventDefault />

Daha fazla bilgi için bkz. varsayılan eylemleri engelleme.

Blazor uygulamalarında olay yaymayı durdur


Olay yaymayı durdurmak için @on{EVENT}:stopPropagation Directive özniteliğini kullanın. Aşağıdaki örnekte, onay
kutusunun seçilmesi alt <div> üst <div> yayılmadan alt öğe için tıklama olaylarını önler:

<input @bind="_stopPropagation" type="checkbox" />

<div @onclick="OnSelectParentDiv">
<div @onclick="OnSelectChildDiv" @onclick:stopPropagation="_stopPropagation">
...
</div>
</div>

@code {
private bool _stopPropagation = false;
}

Daha fazla bilgi için bkz. olay yaymayı durdurma.

Blazor uygulama geliştirme sırasında ayrıntılı hatalar


Geliştirme sırasında Blazor bir uygulama düzgün bir şekilde çalışmadığı zaman, uygulamanın ayrıntılı hata
bilgilerinin alınması sorunu gidermeye ve sorunun giderilmesine yardımcı olur. Bir hata oluştuğunda, Blazor
uygulamalar ekranın alt kısmında altın bir çubuk görüntüler:
Geliştirme sırasında altın çubuk, özel durumu görebileceğiniz tarayıcı konsoluna yönlendirir.
Üretimde, altın çubuk kullanıcıya bir hata oluştuğunu bildirir ve tarayıcıyı yenilemeyi önerir.
Daha fazla bilgi için bkz. geliştirme sırasında ayrıntılı hatalar.
ASP.NET Core 3,0 ' deki yenilikler
6.12.2019 • 25 minutes to read • Edit Online

Bu makalede, ASP.NET Core 3,0 ' deki en önemli değişiklikler ilgili belgelerin bağlantılarıyla vurgulanır.

Blazor
Blazor, .NET ile etkileşimli istemci tarafı Web Kullanıcı arabirimi oluşturmak için ASP.NET Core yeni bir çerçevedir:
JavaScript yerine zengin etkileşimli Uıusing C# oluşturma.
.NET ' te yazılmış sunucu tarafı ve istemci tarafı uygulama mantığını paylaşabilirsiniz.
Mobil tarayıcılar dahil olmak üzere geniş tarayıcı desteği için Kullanıcı arabirimini HTML ve CSS olarak işleme.
Blazor Framework desteklenen senaryolar:
Yeniden kullanılabilir kullanıcı arabirimi bileşenleri (Razor bileşenleri)
İstemci tarafı yönlendirme
Bileşen düzenleri
Bağımlılık ekleme desteği
Formlar ve doğrulama
Razor sınıf kitaplıkları ile bileşen kitaplıkları derleme
JavaScript ile birlikte çalışma
Daha fazla bilgi için bkz. ASP.NET Core Blazor giriş.
Blazor Sunucusu
Blazor, Kullanıcı arabirimi güncelleştirmelerinin uygulanma, bileşen işleme mantığını ayırır. Blazor Server, bir
ASP.NET Core uygulamasındaki sunucuda Razor bileşenlerini barındırmak için destek sağlar. Kullanıcı Arabirimi
güncelleştirmeleri SignalR bir bağlantı üzerinden işlenir. Blazor Server ASP.NET Core 3,0 ' de desteklenir.
Blazor WebAssembly (Önizleme )
Blazor uygulamalar, bir WebAssembly tabanlı .NET çalışma zamanı kullanarak doğrudan tarayıcıda da çalıştırılabilir.
Blazor WebAssembly Önizleme aşamasındadır ve ASP.NET Core 3,0 ' de desteklenmez. Blazor WebAssembly
ASP.NET Core gelecek bir sürümünde desteklenecektir.
Razor bileşenleri
Blazor uygulamalar bileşenlerinden oluşturulmuştur. Bileşenler, bir sayfa, iletişim kutusu veya form gibi kullanıcı
arabirimi (UI) için kendi içinde yer alan öbeklerdir. Bileşenler, Kullanıcı arabirimi işleme mantığını ve istemci tarafı
olay işleyicilerini tanımlayan normal .NET sınıflarıdır. JavaScript olmadan zengin etkileşimli Web uygulamaları
oluşturabilirsiniz.
Blazor bileşenleri genellikle HTML ve C#doğal bir Blend Razor söz dizimi kullanılarak yazılır. Razor bileşenleri, her
ikisi de Razor kullanan Razor Pages ve MVC görünümlerine benzerdir. Bir istek-yanıt modelini temel alan
sayfaların ve görünümlerin aksine, bileşenler Kullanıcı arabirimi oluşturmayı işlemek için kullanılır.

gRPC
GRPC:
Popüler, yüksek performanslı bir RPC (uzak yordam çağrısı) çerçevesidir.
, API geliştirmeye yönelik olarak yapılan bir sözleşmenin ilk yaklaşımını sağlar.
, Gibi modern teknolojiler kullanır:
Taşıma için HTTP/2.
Arabirim açıklaması dili olarak protokol arabellekleri.
İkili serileştirme biçimi.
Şöyle özellikler sağlar:
Kimlik Doğrulama
Çift yönlü akış ve akış denetimi.
İptal ve zaman aşımları.
ASP.NET Core 3,0 ' deki gRPC işlevselliği şunları içerir:
GRPC. AspNetCore , GRPC hizmetlerini barındırmak için bir ASP.NET Core çerçevesini –. gRPC on ASP.NET
Core, günlüğe kaydetme, bağımlılık ekleme (dı), kimlik doğrulama ve yetkilendirme gibi standart ASP.NET Core
özelliklerle tümleştirilir.
GRPC .net. Client – .NET Core Için bir GRPC istemcisini tanıdık HttpClient üzerinde oluşturur.
GRPC .net. ClientFactory – GRPC istemci tümleştirmesi HttpClientFactory .

Daha fazla bilgi için bkz. .NET Core 'da gRPC 'ye giriş.

SignalR
Bkz. geçiş yönergeleri için SignalR kodu güncelleştirme . SignalR artık JSON iletilerini serileştirmek/seri
durumdan çıkarmak için System.Text.Json kullanır. Newtonsoft.Json tabanlı serileştiriciyi geri yükleme yönergeleri
için Newtonsoft. JSON anahtarına geçin .
SignalRiçin JavaScript ve .NET Istemcilerinde, otomatik yeniden bağlanma için destek eklenmiştir. Varsayılan
olarak, istemci hemen yeniden bağlanmaya çalışır ve gerekirse 2, 10 ve 30 saniye sonra yeniden dener. İstemci
başarıyla yeniden bağlanırsa, yeni bir bağlantı KIMLIĞI alır. Otomatik yeniden bağlanma kabul etme:

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.withAutomaticReconnect()
.build();

Yeniden bağlantı aralıkları bir dizi milisaniyelik tabanlı süre geçirerek belirtilebilir:

.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])


//.withAutomaticReconnect([0, 2000, 10000, 30000]) The default intervals.

Yeniden bağlantı aralıklarının tam denetimi için özel bir uygulama geçirilebilir.
Son yeniden bağlanma aralığından sonra yeniden bağlantı başarısız olursa:
İstemci, bağlantının çevrimdışı olduğunu varsayar.
İstemci yeniden bağlanmayı denemeyi durduruyor.
Yeniden bağlanma denemeleri sırasında, kullanıcıya yeniden bağlantı denenmekte olduğunu bildirmek için
uygulama kullanıcı arabirimini güncelleştirin.
Bağlantı kesildiğinde UI geri bildirimi sağlamak için SignalR istemci API 'SI aşağıdaki olay işleyicilerini içerecek
şekilde genişletilir:
onreconnecting : geliştiricilere Kullanıcı arabirimini devre dışı bırakma veya kullanıcıların uygulamanın
çevrimdışı olduğunu bilmesini sağlayan bir fırsat sağlar.
onreconnected : bağlantı kurulduktan sonra geliştiricilere Kullanıcı arabirimini güncelleştirme fırsatı verir.

Aşağıdaki kod, bağlanmaya çalışırken kullanıcı arabirimini güncelleştirmek için onreconnecting kullanır:

connection.onreconnecting((error) => {
const status = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageInput").disabled = true;
document.getElementById("sendButton").disabled = true;
document.getElementById("connectionStatus").innerText = status;
});

Aşağıdaki kod, bağlantıda Kullanıcı arabirimini güncelleştirmek için onreconnected kullanır:

connection.onreconnected((connectionId) => {
const status = `Connection reestablished. Connected.`;
document.getElementById("messageInput").disabled = false;
document.getElementById("sendButton").disabled = false;
document.getElementById("connectionStatus").innerText = status;
});

SignalR 3,0 ve üzeri, bir hub yöntemi yetkilendirme gerektirdiğinde, yetkilendirme işleyicilerine özel bir kaynak
sağlar. Kaynak bir HubInvocationContext örneğidir. HubInvocationContext şunları içerir:
HubCallerContext
Çağrılan hub yönteminin adı.
Hub yöntemi için bağımsız değişkenler.
Azure Active Directory aracılığıyla birden çok kuruluşun oturum açmasına izin veren bir sohbet odası
uygulamasının aşağıdaki örneğini göz önünde bulundurun. Microsoft hesabı herkes sohbet için oturum açabilir,
ancak yalnızca sahip olunan kuruluşun üyeleri kullanıcıları veya kullanıcıların sohbet geçmişlerini görüntüleyebilir.
Uygulama belirli kullanıcılardan belirli işlevleri kısıtlayabilir.
public class DomainRestrictedRequirement :
AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
DomainRestrictedRequirement requirement,
HubInvocationContext resource)
{
if (context.User?.Identity?.Name == null)
{
return Task.CompletedTask;
}

if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name))
{
context.Succeed(requirement);
}

return Task.CompletedTask;
}

private bool IsUserAllowedToDoThis(string hubMethodName, string currentUsername)


{
if (hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase))
{
return currentUsername.Equals("bob42@jabbr.net", StringComparison.OrdinalIgnoreCase);
}

return currentUsername.EndsWith("@jabbr.net", StringComparison.OrdinalIgnoreCase));


}
}

Yukarıdaki kodda, DomainRestrictedRequirement özel bir IAuthorizationRequirement işlevi görür.


HubInvocationContext kaynak parametresi geçirildiğinden iç mantık şunları yapabilir:
Hub 'ın çağrıldığı bağlamı inceleyin.
Kullanıcının bireysel hub yöntemlerini yürütmesine izin verirken kararlar alın.
Tek tek hub yöntemleri, çalışma zamanında kodun denetlediği ilkenin adıyla işaretlenebilir. İstemciler tek tek hub
yöntemlerini çağırmayı denediğinden DomainRestrictedRequirement işleyicisi çalışır ve yöntemlere erişimi denetler.
DomainRestrictedRequirement erişimi denetim altına göre:

Tüm oturum açmış kullanıcılar SendMessage yöntemini çağırabilir.


Yalnızca bir @jabbr.net e-posta adresiyle oturum açan kullanıcılar, kullanıcıların geçmişlerini görüntüleyebilir.
Yalnızca bob42@jabbr.net sohbet odasından kullanıcıları ban edebilir.
[Authorize]
public class ChatHub : Hub
{
public void SendMessage(string message)
{
}

[Authorize("DomainRestricted")]
public void BanUser(string username)
{
}

[Authorize("DomainRestricted")]
public void ViewUserHistory(string username)
{
}
}

DomainRestricted ilkesi oluşturmak şunları içerebilir:


Startup.cs' de, yeni ilkeyi ekleme.
Özel DomainRestrictedRequirement gereksinimini parametre olarak sağlayın.
Yetkilendirme ara yazılımı ile DomainRestricted kaydetme.

services
.AddAuthorization(options =>
{
options.AddPolicy("DomainRestricted", policy =>
{
policy.Requirements.Add(new DomainRestrictedRequirement());
});
});

SignalR hub 'ları uç nokta yönlendirmekullanır. SignalR Hub bağlantısı daha önce açık olarak yapıldı:

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});

Önceki sürümde, geliştiriciler, Razor sayfaları ve hub 'ları çeşitli yerlerde bağlamak için gereklidir.Açık bağlantı,
neredeyse aynı bir dizi yönlendirme segmentine neden olur:

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});

app.UseRouting(routes =>
{
routes.MapRazorPages();
});

SignalR 3,0 hub 'ları, uç nokta yönlendirme aracılığıyla yönlendirilebilir. Uç nokta yönlendirme ile, genellikle tüm
yönlendirme UseRouting yapılandırılabilir:
app.UseRouting(routes =>
{
routes.MapRazorPages();
routes.MapHub<ChatHub>("hubs/chat");
});

ASP.NET Core 3,0 SignalR eklendi:


İstemciden sunucuya akış. İstemci-sunucu akışı ile, sunucu tarafı yöntemleri bir IAsyncEnumerable<T> veya
ChannelReader<T> örnekleri alabilir. Aşağıdaki C# örnekte, Hub 'daki UploadStream yöntemi istemcisinden dizelerin
akışını alacaktır:

public async Task UploadStream(IAsyncEnumerable<string> stream)


{
await foreach (var item in stream)
{
// process content
}
}

.NET istemci uygulamaları, yukarıdaki UploadStream hub yönteminin stream bağımsız değişkeni olarak bir
IAsyncEnumerable<T> veya ChannelReader<T> örneğini geçirebilir.

for döngüsü tamamlandıktan ve yerel işlev çıktıktan sonra, akış tamamlama gönderilir:

async IAsyncEnumerable<string> clientStreamData()


{
for (var i = 0; i < 5; i++)
{
var data = await FetchSomeData();
yield return data;
}
}

await connection.SendAsync("UploadStream", clientStreamData());

JavaScript istemci uygulamaları yukarıdaki UploadStream hub yönteminin stream bağımsız değişkeni için SignalR
Subject (veya bir Rxjs konusu) kullanır.

let subject = new signalR.Subject();


await connection.send("StartStream", "MyAsciiArtStream", subject);

JavaScript kodu, yakalandıkları ve sunucuya gönderilmeye hazırlanıyor gibi dizeleri işlemek için subject.next
yöntemini kullanabilir.

subject.next("example");
subject.complete();

Önceki iki kod parçacığı gibi kodu kullanarak gerçek zamanlı akış deneyimleri oluşturulabilir.

Yeni JSON serileştirmesi


ASP.NET Core 3,0 artık JSON serileştirme için varsayılan olarak System.Text.Json kullanır:
JSON 'yi zaman uyumsuz olarak okur ve yazar.
UTF -8 metni için iyileştirilmiştir.
Genellikle Newtonsoft.Json kıyasla daha yüksek performans.

ASP.NET Core 3,0 ' ye Json.NET eklemek için bkz. Newtonsoft. JSON tabanlı JSON biçimi desteği ekleme.

Yeni Razor yönergeleri


Aşağıdaki listede yeni Razor yönergeleri yer almaktadır:
@attribute – yönergesinin verilen özniteliği oluşturulan sayfanın veya görünümün sınıfına uygular.
@attribute
Örneğin: @attribute [Authorize] .
@implements – @implements yönergesi oluşturulan sınıf için bir arabirim uygular. Örneğin:
@implements IDisposable .

Identityserver4, Web API 'Leri ve maça 'Ları için kimlik doğrulama ve


yetkilendirmeyi destekler
ASP.NET Core 3,0, Web API yetkilendirmesi desteğini kullanarak tek sayfalı uygulamalarda (Spaon) kimlik
doğrulaması sunmaktadır. Kullanıcıların kimliğini doğrulamak ve depolamak için ASP.NET Core kimliği, açık
KIMLIK Connect 'i uygulamak için ıdentityserver4 ile birleştirilir.
Identityserver4, ASP.NET Core 3,0 için bir OpenID Connect ve OAuth 2,0 çerçevesidir. Aşağıdaki güvenlik
özelliklerini sunar:
Hizmet olarak kimlik doğrulaması (AaaS )
Birden çok uygulama türü üzerinde çoklu oturum açma/kapatma (SSO )
API 'Ler için erişim denetimi
Federasyon ağ geçidi
Daha fazla bilgi için bkz. ıdentityserver4 belgeleri veya kimlik doğrulaması ve kimlik doğrulama ve yetkilendirme.

Sertifika ve Kerberos kimlik doğrulaması


Sertifika kimlik doğrulaması şunları gerektirir:
Sunucu, sertifikaları kabul edecek şekilde yapılandırılıyor.
Kimlik doğrulama ara yazılımı Startup.Configure ' ye ekleniyor.
Sertifika kimlik doğrulama hizmeti Startup.ConfigureServices ' de ekleniyor.

public void ConfigureServices(IServiceCollection services)


{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// Other service configuration removed.
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
app.UseAuthentication();
// Other app configuration removed.
}

Sertifika kimlik doğrulaması seçenekleri şunları yapabilme:


Otomatik olarak imzalanan sertifikaları kabul edin.
Sertifika iptali olup olmadığını denetleyin.
Profili oluşturulan sertifikanın, içinde doğru kullanım bayrakları olduğunu denetleyin.
Varsayılan bir Kullanıcı sorumlusu, sertifika özelliklerinden oluşturulur. Kullanıcı sorumlusu, sorumlunun takıma
veya değiştirilmesine izin veren bir olay içerir. Daha fazla bilgi için bkz. ASP.NET Core sertifika kimlik
doğrulamasını yapılandırma.
Windows kimlik doğrulaması , Linux ve MacOS üzerine genişletildi. Önceki sürümlerde, Windows kimlik
doğrulaması IIS ve httpsysile sınırlandırıldı. ASP.NET Core 3,0 ' de Kestrel , Windows etki alanına katılmış konaklar
için Windows, Linux ve MacOS üzerinde Negotiate, Kerberosve NTLMkullanma olanağına sahiptir. Bu kimlik
doğrulama düzenlerinin Kestrel desteği Microsoft. AspNetCore. Authentication. Negotiate NuGet paketi tarafından
sağlanır. Diğer kimlik doğrulama hizmetlerinde olduğu gibi, kimlik doğrulama uygulaması genelinde yapılandırın
ve ardından hizmeti yapılandırın:

public void ConfigureServices(IServiceCollection services)


{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// Other service configuration removed.
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
app.UseAuthentication();
// Other app configuration removed.
}

Ana bilgisayar gereksinimleri:


Windows Konakları, uygulamayı barındıran Kullanıcı hesabına eklenmiş hizmet sorumlusu adlarına (SPN ) sahip
olmalıdır.
Linux ve macOS makineleri etki alanına katılmalıdır.
Web işlemi için SPN oluşturulması gerekir.
Ana makinede keytab dosyalarının oluşturulup yapılandırılması gerekir.
Daha fazla bilgi için bkz. ASP.NET Core Windows kimlik doğrulamasını yapılandırma.

Şablon değişiklikleri
Web UI şablonları (Razor Pages, denetleyici ve görünümlerle MVC ) şu şekilde kaldırılmıştır:
Tanımlama bilgisi onayı Kullanıcı arabirimi artık dahil değildir. ASP.NET Core 3,0 şablon tarafından oluşturulan
bir uygulamada tanımlama bilgisi onay özelliğini etkinleştirmek için, bkz. ASP.NET Core Genel Veri Koruma
Yönetmeliği (GDPR ) desteği.
Betiklerin ve ilgili statik varlıkların artık CDNs kullanmak yerine yerel dosyalar olarak başvuruluyor. Daha fazla
bilgi için, bkz. betiklerin ve ilgili statik varlıkların artık geçerli ortama göre CDNs kullanmak yerine yerel
dosyalar olarak başvuruluyor (ASPNET/AspNetCore. Docs #14350).
Angular şablonu, angular 8 ' i kullanacak şekilde güncelleştirildi.
Razor sınıf kitaplığı (RCL ) şablonu varsayılan olarak Razor bileşen geliştirmeyi varsayılan olarak belirler. Visual
Studio 'da yeni bir şablon seçeneği, sayfalar ve görünümler için şablon desteği sağlar. Bir komut kabuğunda
şablondan RCL oluştururken --support-pages-and-views seçeneğini (
dotnet new razorclasslib --support-pages-and-views ) geçirin.

Genel Konak
ASP.NET Core 3,0 şablonları .NET genel ana bilgisayarkullanır. Önceki sürümler WebHostBuilderkullanıldı. .NET
Core genel ana bilgisayarı 'nı (HostBuilder) kullanarak, Web 'e özgü olmayan diğer sunucu senaryolarıyla
ASP.NET Core uygulamaları daha iyi tümleştirme sağlar. Daha fazla bilgi için bkz. Hostbuilder WebHostBuilder 'ın
yerini alır.
Konak yapılandırması
ASP.NET Core 3,0 ' nin yayınlanmasından önce, ASPNETCORE_ önekli ortam değişkenleri Web konağının ana
bilgisayar yapılandırması için yüklendi. 3,0 ' de AddEnvironmentVariables , CreateDefaultBuilder ile konak
yapılandırması için DOTNET_ ön eki eklenmiş ortam değişkenlerini yüklemek için kullanılır.
Başlangıç Oluşturucu Ekleme değişiklikleri
Genel ana bilgisayar yalnızca Startup Oluşturucu ekleme için aşağıdaki türleri destekler:
IHostEnvironment
IWebHostEnvironment
IConfiguration
Tüm hizmetler yine de Startup.Configure metoduna bağımsız değişken olarak eklenebilir. Daha fazla bilgi için bkz.
genel ana bilgisayar başlangıç Oluşturucu Ekleme (ASPNET/duyurular #353).

Kestrel
Kestrel yapılandırması, genel konağa geçiş için güncelleştirildi. 3,0 ' de Kestrel, ConfigureWebHostDefaults
tarafından belirtilen Web ana bilgisayar Oluşturucu üzerinde yapılandırılır.
Bağlantı bağdaştırıcıları, Kestrel adresinden kaldırılmıştır ve bağlantı ara yazılımı ile değiştirilmiştir ve bu,
ASP.NET Core işlem hattındaki HTTP ara hattına benzer ancak alt düzey bağlantılar için kullanılır.
Kestrel aktarım katmanı Connections.Abstractions bir ortak arabirim olarak kullanıma sunuldu.
Sondaki üstbilgiler yeni bir koleksiyona taşınarak üstbilgiler ve tanıtımları arasındaki belirsizlik çözüldü.
HttpRequest.Body.Read gibi zaman uyumlu GÇ API 'Leri, uygulama kilitlenmelerine neden olan yaygın bir iş
parçacığı kaynağıdır. 3,0 ' de, AllowSynchronousIO varsayılan olarak devre dışıdır.

Daha fazla bilgi için bkz. ASP.NET Core 2,2 ' den 3,0 ' e geçiş yapın.

Varsayılan olarak etkin HTTP/2


HTTP/2, HTTPS uç noktaları için Kestrel içinde varsayılan olarak etkindir. IIS veya HTTP. sys için HTTP/2 desteği,
işletim sistemi tarafından desteklendikleri zaman etkindir.

İstek üzerine EventCounters


Microsoft.AspNetCore.Hosting barındırma EventSource, gelen isteklerle ilgili aşağıdaki yeni EventCounter türlerini
yayar:
requests-per-second
total-requests
current-requests
failed-requests

Uç nokta yönlendirme
Çerçeveler 'in (örneğin, MVC ) ara yazılım ile iyi çalışmasına izin veren uç nokta yönlendirme geliştirildi:
Ara yazılım ve uç noktaların sırası, Startup.Configure istek işleme ardışık düzeninde yapılandırılabilir.
Uç noktalar ve ara yazılımlar, sistem durumu denetimleri gibi diğer ASP.NET Core tabanlı teknolojilerle birlikte.
Uç noktalar, hem yazılım hem de MVC 'de CORS veya yetkilendirme gibi bir ilke uygulayabilir.
Filtreler ve öznitelikler, denetleyicilerde yöntemler üzerine yerleştirilebilir.
Daha fazla bilgi için bkz. ASP.NET Core yönlendirme.

Sistem durumu denetimleri


Sistem durumu denetimleri, genel ana bilgisayar ile Endpoint Routing kullanır. Startup.Configure , uç nokta URL
'SI veya göreli yol ile Endpoint Builder üzerinde MapHealthChecks çağırın:

app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});

Durum denetimleri uç noktaları şunları yapabilir:


İzin verilen bir veya daha fazla Konakları/bağlantı noktasını belirtin.
Yetkilendirme gerektir.
CORS gerektir.
Daha fazla bilgi için aşağıdaki makalelere bakın:
ASP.NET Core 2,2 ' den 3,0 ' e geçiş yapın
ASP.NET Core durum denetimleri

HttpContext üzerindeki kanallar


Artık istek gövdesini okumak ve System.IO.Pipelines API 'sini kullanarak yanıt gövdesini yazmak mümkündür.
Bağlamayı içeren HttpRequest.BodyReader özellik, istek gövdesini okumak için kullanılabilecek bir PipeReader
sağlar. Bağlamayı içeren HttpResponse.BodyWriter özellik, yanıt gövdesini yazmak için kullanılabilecek bir
PipeWriter sağlar. HttpRequest.BodyReader , HttpRequest.Body akışının analogıdır. HttpResponse.BodyWriter ,
HttpResponse.Body akışının analogıdır.

IIS 'de geliştirilmiş hata raporlama


IIS 'de ASP.NET Core uygulamalar barındırırken başlatma hataları artık daha zengin Tanılama verileri oluşturuyor.
Bu hatalar, geçerli her yerde yığın izlemelerle Windows olay günlüğü 'ne bildirilir.Ayrıca, tüm uyarılar, hatalar ve
işlenmemiş özel durumlar Windows olay günlüğü 'ne kaydedilir.

Çalışan hizmeti ve çalışan SDK 'Sı


.NET Core 3,0 yeni çalışan hizmeti uygulama şablonunu tanıtır. Bu şablon, .NET Core 'da uzun süre çalışan
hizmetler yazmak için bir başlangıç noktası sağlar.
Daha fazla bilgi için bkz.
Windows Hizmetleri olarak .NET Core çalışanları
ASP.NET Core içinde barındırılan hizmetlerle arka plan görevleri
Windows hizmetinde konak ASP.NET Core

İletilen üstbilgiler ara yazılımı geliştirmeleri


Önceki ASP.NET Core sürümlerinde, UseHsts ve UseHttpsRedirection çağırmak, bir Azure Linux 'a veya IIS
dışında herhangi bir ters proxy 'nin arkasına dağıtıldığında sorunlu bir sorun oluştu. Önceki sürümlere yönelik
düzeltmeler, Linux ve IIS olmayan ters proxy 'lerin düzenini iletmebölümünde belgelenmiştir.
Bu senaryo ASP.NET Core 3,0 ' de düzeltilmiştir. ASPNETCORE_FORWARDEDHEADERS_ENABLED ortam değişkeni true
olarak ayarlandığında, ana bilgisayar Iletilen üstbilgiler ara yazılımını sağlar. ASPNETCORE_FORWARDEDHEADERS_ENABLED ,
kapsayıcı görüntülerimizde true olarak ayarlanır.

Performans geliştirmeleri
ASP.NET Core 3,0, bellek kullanımını azaltan ve üretilen işi geliştiren birçok geliştirme içerir:
Kapsamlı hizmetler için yerleşik bağımlılık ekleme kapsayıcısını kullanırken bellek kullanımında azaltma.
Ara yazılım senaryoları ve yönlendirme dahil olmak üzere çerçeve genelinde ayırmalarda azaltma.
WebSocket bağlantıları için bellek kullanımında azaltma.
HTTPS bağlantıları için bellek azaltma ve verimlilik geliştirmeleri.
Yeni iyileştirilmiş ve tamamen zaman uyumsuz JSON serileştiricisi.
Form ayrıştırılırken bellek kullanımı ve üretilen iş iyileştirmeleri azaltılması.

ASP.NET Core 3,0 yalnızca .NET Core 3,0 üzerinde çalışır


ASP.NET Core 3,0 itibariyle, .NET Framework artık desteklenen bir hedef çerçeve değildir. .NET Framework
hedefleyen projeler .NET Core 2,1 LTS sürümünükullanarak tam olarak desteklenen bir biçimde devam edebilir.
ASP.NET Core 2.1. x ile ilgili paketlerin çoğu, .NET Core 2,1 için üç yıllık LTS döneminin ötesinde süresiz olarak
desteklenecektir.
Geçiş bilgileri için bkz. kodunuzu .NET Core 'a .NET Framework.

ASP.NET Core paylaşılan çerçevesini kullanma


Microsoft. AspNetCore. app metapackageiçinde bulunan ASP.NET Core 3,0 paylaşılan çerçevesi artık proje
dosyasında açık bir <PackageReference /> öğesi gerektirmez. Paylaşılan çerçeveye proje dosyasında
Microsoft.NET.Sdk.Web SDK kullanılırken otomatik olarak başvurulur:

<Project Sdk="Microsoft.NET.Sdk.Web">

ASP.NET Core paylaşılan çerçevesinden kaldırılan derlemeler


ASP.NET Core 3,0 paylaşılan çerçevesinden çıkarılan en önemli derlemeler şunlardır:
Newtonsoft. JSON (JSON.net). ASP.NET Core 3,0 ' ye Json.NET eklemek için bkz. Newtonsoft. JSON tabanlı
JSON biçimi desteği ekleme. ASP.NET Core 3,0, JSON okuma ve yazma için System.Text.Json tanıtır. Daha
fazla bilgi için bu belgede yenı JSON serileştirmesi bölümüne bakın.
Entity Framework Core
Paylaşılan çerçeveden kaldırılan derlemelerin tamamen listesi için bkz . Microsoft. AspNetCore. App 3,0 ' den
kaldırılan derlemeler. Bu değişiklik için mosyon hakkında daha fazla bilgi için bkz. 3,0 'de Microsoft. AspNetCore.
app 'e yönelik son değişiklikler ve ASP.NET Core 3,0 ' de gelen değişikliklere ilk bakış.
ASP.NET Core 2,2 ' deki yenilikler
6.12.2019 • 9 minutes to read • Edit Online

Bu makalede, ASP.NET Core 2,2 ' deki en önemli değişiklikler, ilgili belgelerin bağlantılarıyla vurgulanır.

Openapı Çözümleyicileri & kuralları


Openapı (eski adıyla Swagger), REST API 'Leri açıklamak için dilden bağımsız bir belirtimdir. Openapı ekosistemi,
belirtimi kullanarak istemci kodu bulma, test etme ve oluşturmaya imkan tanıyan araçlara sahiptir. ASP.NET Core
MVC 'de Openapı belgelerini oluşturma ve görselleştirmeye yönelik destek, Nswag ve swashbuckle. aspnetcoregibi
topluluk odaklı projeler aracılığıyla sağlanır. ASP.NET Core 2,2, Openapı belgelerini oluşturmak için geliştirilmiş
araç ve çalışma zamanı deneyimleri sağlar.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
Web API Çözümleyicileri kullanma
Web API 'SI kurallarını kullanma
ASP.NET Core 2.2.0-preview1 'i: Openapı Çözümleyicileri & kuralları

Sorun ayrıntıları desteği


ASP.NET Core 2,1, HTTP yanıtıyla bir hatanın ayrıntılarını taşıyan RFC 7807 belirtimine göre ProblemDetails
tanıtılmıştır. 2,2 ' de ProblemDetails , ApiControllerAttribute öznitelikli denetleyicilerde istemci hata kodları için
standart yanıttır. İstemci hata durum kodu (4xx) döndüren bir IActionResult , artık bir ProblemDetails gövdesi
döndürüyor. Sonuç Ayrıca, istek günlüklerini kullanarak hatayı ilişkilendirmek için kullanılabilecek bir bağıntı
KIMLIĞI içerir. İstemci hataları için ProducesResponseType varsayılan olarak yanıt türü olarak ProblemDetails
kullanın. Bu, NSwag veya swashbuckle. AspNetCore kullanılarak oluşturulan OpenAPI/Swagger çıktısında
belgelenmiştir.

Uç nokta yönlendirme
ASP.NET Core 2,2, isteklerin gelişmiş şekilde gönderilirken yeni bir uç nokta yönlendirme sistemi kullanır.
Değişiklikler yeni bağlantı oluşturma API 'SI üyelerini ve yol parametresi dönüştürücüler içerir.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
2,2 içinde Endpoint Routing
Yol parametresi dönüştürücüler (bkz. yönlendirme bölümü)
IRouter ve uç nokta tabanlı yönlendirme arasındaki farklar

Sistem durumu denetimleri


Yeni bir sistem durumu denetimleri hizmeti, Kubernetes gibi sistem durumu denetimleri gerektiren ortamlarda
ASP.NET Core kullanmayı kolaylaştırır. Sistem durumu denetimleri, ara yazılım ve bir IHealthCheck soyutlama ve
hizmet tanımlayan bir kitaplık kümesi içerir.
Sistem durum denetimleri bir kapsayıcı Orchestrator veya yük dengeleyici tarafından, sistemin isteklere normal
olarak yanıt verip vermediğini hızlı bir şekilde tespit etmek için kullanılır. Bir kapsayıcı Orchestrator, sıralı bir
dağıtımı kaldırarak veya kapsayıcıyı yeniden başlatarak başarısız olan bir sistem durumu denetimine yanıt verebilir.
Yük dengeleyici, trafiği hizmetin başarısız olan örneğinden dışarıda yönlendirerek bir sistem durumu denetimine
yanıt verebilir.
Sistem durumu denetimleri, bir uygulama tarafından, izleme sistemleri tarafından kullanılan bir HTTP uç noktası
olarak sunulur. Sistem durumu denetimleri, çeşitli gerçek zamanlı izleme senaryoları ve izleme sistemleri için
yapılandırılabilir. Sistem durumu denetimleri hizmeti, Beatpulse projesiyletümleştirilir. Bu, düzinelerce popüler
sistemler ve Bağımlılıklar için denetim eklemenizi kolaylaştırır.
Daha fazla bilgi için bkz. ASP.NET Core durum denetimleri.

Kestrel içinde HTTP/2


ASP.NET Core 2,2, HTTP/2 desteği ekliyor.
HTTP/2, HTTP protokolünün önemli bir düzeltmesidir. HTTP/2 ' nin önemli özellikleri şunlardır:
Üst bilgi sıkıştırma desteği.
Tek bir bağlantı üzerinden tamamen çoğullanmış akışlar.
Http/2, HTTP 'nin semantiğini (örneğin, HTTP üst bilgileri ve yöntemleri) korur, ancak istemci ve sunucu arasında
verilerin nasıl çerçeveli ve gönderilir olduğunu HTTP/1. x ' den önemli bir değişiklik olur.
Çerçeveleme içindeki bu değişikliğin bir sonucu olarak, sunucuların ve istemcilerin kullanılan protokol sürümünü
anlaşması gerekir. Uygulama katmanı protokol anlaşması (ALPN ), sunucunun ve istemcisinin TLS el sıkışmasının
bir parçası olarak kullanılan protokol sürümünü anlaşmasına izin veren bir TLS uzantısıdır. Sunucu ve protokoldeki
istemci arasında bir önceki bilgi sahibi olmak mümkün olsa da, tüm büyük tarayıcılarda bir HTTP/2 bağlantısı
kurmak için tek yol olarak tüm büyük tarayıcılar desteklenir.
Daha fazla bilgi için bkz. http/2 desteği.

Kestrel yapılandırması
ASP.NET Core önceki sürümlerinde, Kestrel seçenekleri UseKestrel çağırarak yapılandırılır. 2,2 ' de, Kestrel
seçenekleri konak Oluşturucu üzerinde ConfigureKestrel çağırarak yapılandırılır. Bu değişiklik, işlem içi barındırma
için IServer kayıtları sırasıyla bir sorunu çözer. Daha fazla bilgi için aşağıdaki kaynaklara bakın:
Useııs çakışmasını azaltma
ConfigureKestrel ile Kestrel Server seçeneklerini yapılandırma

IIS işlem içi barındırma


ASP.NET Core önceki sürümlerinde IIS, ters proxy işlevi görür. 2,2 ' de ASP.NET Core modülü CoreCLR 'yi
önyükleyebilir ve IIS çalışan işleminin (W3wp. exe) içinde bir uygulamayı barındırabilir. İşlem içi barındırma, IIS ile
çalışırken performans ve tanılama kazançları sağlar.
Daha fazla bilgi için bkz. IIS için işlem içi barındırma.

SignalR Java istemcisi


ASP.NET Core 2,2 SignalRiçin bir Java Istemcisi sunar. Bu istemci, Android uygulamaları dahil olmak üzere Java
kodundan bir ASP.NET Core SignalR sunucusuna bağlanmayı destekler.
Daha fazla bilgi için bkz. ASP.NET Core SignalR Java istemcisi.

CORS geliştirmeleri
ASP.NET Core önceki sürümlerinde, CORS ara yazılımı Origin yapılandırılan değerlere bakılmaksızın Accept ,
Accept-Language , Content-Language ve CorsPolicy.Headers üst bilgilerinin gönderilmesini sağlar. 2,2 ' de, bir CORS
ara yazılım ilkesi eşleşmesi yalnızca Access-Control-Request-Headers ' de gönderilen üstbilgiler WithHeaders
belirtilen üstbilgileriyle tam olarak eşleşiyorsa mümkündür.
Daha fazla bilgi için bkz. CORS ara yazılımı.

Yanıt sıkıştırma
ASP.NET Core 2,2, yanıtları Brotli sıkıştırma biçimiylesıkıştırabilir.
Daha fazla bilgi için bkz. Yanıt sıkıştırma ara yazılımı Brotli sıkıştırmayı destekler.

Proje şablonları
ASP.NET Core Web projesi şablonları, önyükleme 4 ve angular 6' ya güncelleştirildi. Yeni görünüm görsel açıdan
basittir ve uygulamanın önemli yapılarını görmeyi kolaylaştırır.

Doğrulama performansı
MVC 'nin doğrulama sistemi genişletilebilir ve esnek olacak şekilde tasarlanmıştır. bu sayede, belirli bir modele
yönelik doğrulayıcıların hangi istek tabanlı olarak uygulanacağını belirlemenizi sağlar. Bu, karmaşık doğrulama
sağlayıcıları yazmak için idealdir. Ancak, en yaygın durumda bir uygulama yalnızca yerleşik Doğrulayıcıları kullanır
ve bu fazladan esneklik gerektirmez. Yerleşik doğrulayıcılar, [gerekli] ve [StringLength] gibi veri açıklamalarını içerir
ve IValidatableObject .
ASP.NET Core 2,2 ' de, MVC, belirli bir model grafiğinin doğrulama gerektirmediğini belirlerse kısa devre
doğrulaması yapabilir. Doğrulama sonuçları, hiçbir doğrulayıcıya sahip olmayan modelleri doğrularken önemli
geliştirmelere karşı atlanıyor. Bu, çok sayıda Doğrulayıcıları olmayan temel elemanlar koleksiyonları ( byte[] ,
string[] , Dictionary<string, string> ) veya karmaşık nesne grafikleri gibi nesneleri içerir.

HTTP Istemci performansı


ASP.NET Core 2,2 ' de, bağlantı havuzu kilitleme çakışması azaltılarak SocketsHttpHandler performansı
geliştirilmiştir. Bazı mikro hizmet mimarileri gibi birçok giden HTTP isteğini yapan uygulamalar için üretilen iş
geliştirildi. Yük altında HttpClient işleme, Linux üzerinde %60 ' e kadar ve Windows üzerinde %20 oranında
artırılabilir.
Daha fazla bilgi için Bu geliştirmeyi yapan çekme isteğinebakın.
Ek bilgiler
Değişikliklerin tamamı listesi için ASP.NET Core 2,2 sürüm notlarınabakın.
ASP.NET Core 2,1 ' deki yenilikler
6.12.2019 • 11 minutes to read • Edit Online

Bu makalede, ASP.NET Core 2,1 ' deki en önemli değişiklikler, ilgili belgelerin bağlantılarıyla vurgulanır.

SignalR
SignalR ASP.NET Core 2,1 için yeniden yazıldı. ASP.NET Core SignalR bir dizi geliştirme içerir:
Basitleştirilmiş bir genişleme modeli.
JQuery bağımlılığı olmayan yeni bir JavaScript istemcisi.
MessagePack tabanlı yeni bir Compact binary protokolü.
Özel protokoller için destek.
Yeni bir akış yanıt modeli.
Çıplak WebSockets tabanlı istemciler için destek.
Daha fazla bilgi için bkz. ASP.NET Core SignalR.

Razor sınıf kitaplıkları


ASP.NET Core 2,1, bir kitaplıkta Razor tabanlı kullanıcı arabirimini oluşturmayı ve eklemeyi kolaylaştırır ve birden
fazla proje arasında paylaşabilir. Yeni Razor SDK 'Sı, bir NuGet paketine paketlenebilecek bir sınıf kitaplığı
projesinde Razor dosyaları oluşturulmasına izin verebilir. Kitaplıklardaki görünümler ve sayfalar otomatik olarak
keşfedilir ve uygulama tarafından geçersiz kılınabilir. Razor derlemesini yapıyla tümleştirerek:
Uygulama başlatma süresi önemli ölçüde daha hızlıdır.
Çalışma zamanında Razor görünümlerinin ve sayfalarının hızlı güncelleştirmeleri, yinelemeli bir geliştirme iş
akışının bir parçası olarak hala kullanılabilir.
Daha fazla bilgi için bkz. Razor Sınıf Kitaplığı projesini kullanarak yeniden kullanılabilir kullanıcı arabirimi
oluşturma.

Identity UI kitaplığı & Yapı iskelesi


ASP.NET Core 2,1, Razor sınıf kitaplığıolarak ASP.NET Core kimliği sağlar. Kimlik içeren uygulamalar, kimlik Razor
sınıf kitaplığı 'nda (RCL ) bulunan kaynak kodu seçmeli olarak eklemek için yeni Identity desteği 'ı uygulayabilir.
Kodu değiştirebilmeniz ve davranışı değiştirebilmek için kaynak kodu oluşturmak isteyebilirsiniz. Örneğin, kayıt
sırasında kullanılan kodu oluşturmak için desteği ' ı söyleyebilirsiniz. Oluşturulan kod, RCL kimliği içindeki aynı
koddan önceliklidir.
Kimlik doğrulaması içermeyen uygulamalar , RCL kimlik paketini eklemek için Identity desteği 'ı uygulayabilir.
Oluşturulacak kimlik kodunu seçme seçeneğiniz vardır.
Daha fazla bilgi için ASP.NET Core projelerinde yapı Iskelesi kimliği' ne bakın.

HTTPS
Güvenlik ve gizlilikle ilgili daha fazla odaklanarak Web Apps için HTTPS 'nin etkinleştirilmesi önemlidir. HTTPS
zorlaması Web üzerinde giderek daha sıkı hale geliyor. HTTPS kullanmayan siteler güvensiz olarak değerlendirilir.
Tarayıcılar (Bermıum, Mozilla), Web özelliklerinin güvenli bir içerikten kullanılması gerektiğini zorlamaya başlıyor.
GDPR , Kullanıcı gizliliğini korumak için https kullanılmasını gerektirir. Üretimde HTTPS kullanılması kritiktir, ancak
geliştirme sırasında HTTPS kullanılması, dağıtımdaki sorunları önlemeye yardımcı olabilir (örneğin, güvenli
olmayan bağlantılar). ASP.NET Core 2,1, geliştirme sırasında HTTPS kullanmayı ve üretimde HTTPS 'yi
yapılandırmayı kolaylaştıran bir dizi geliştirme içerir. Daha fazla bilgi için bkz. https 'Yi zorlama.
Varsayılan olarak açık
Güvenli Web sitesi geliştirmeyi kolaylaştırmak için, HTTPS artık varsayılan olarak etkinleştirilmiştir. 2,1 ' den
başlayarak, yerel bir geliştirme sertifikası mevcut olduğunda, Kestrel https://localhost:5001 dinler. Geliştirme
sertifikası oluşturuldu:
İlk kez .NET Core SDK ilk çalıştırma deneyiminin bir parçası olarak SDK 'Yı ilk kez kullandığınızda.
Yeni dev-certs aracını kullanarak el ile.
Sertifikaya güvenmek için dotnet dev-certs https --trust çalıştırın.
HTTPS yönlendirmesi ve zorlaması
Web uygulamalarının genellikle hem HTTP hem de HTTPS üzerinde dinlemesi gerekir, ancak tüm HTTP trafiğini
HTTPS 'ye yeniden yönlendirir. 2,1 ' de, yapılandırma veya bağlı sunucu bağlantı noktalarının varlığına göre daha
fazla yeniden yönlendirilen özelleştirilmiş HTTPS yeniden yönlendirme ara yazılımı sunulmuştur.
HTTPS kullanımı, http katı aktarım güvenliği Protokolü (HSTS )kullanılarak daha fazla zorlanabilir. HSTS,
tarayıcıların siteye her zaman HTTPS aracılığıyla erişmesini söyler. ASP.NET Core 2,1, maksimum yaş, alt etki
alanları ve HSTS önyükleme listesi seçeneklerini destekleyen HSTS ara yazılımı ekler.
Üretim için yapılandırma
Üretimde HTTPS 'nin açıkça yapılandırılması gerekir. 2,1 ' de, Kestrel için HTTPS yapılandırmasına yönelik
varsayılan yapılandırma şeması eklenmiştir. Uygulamalar aşağıdakileri kullanacak şekilde yapılandırılabilir:
URL 'Ler dahil olmak üzere birden fazla uç nokta. Daha fazla bilgi için bkz. Kestrel Web Server Implementation:
Endpoint Configuration.
Diskteki bir dosyadan veya bir sertifika deposundan HTTPS için kullanılacak sertifika.

GDPR
ASP.NET Core, bazı ab genel veri koruma yönetmeliği (GDPR ) gereksinimlerini karşılamaya yardımcı olmak Için
API 'ler ve şablonlar sağlar. Daha fazla bilgi için bkz. GDPR Support in ASP.NET Core. Örnek bir uygulama , ' nin
nasıl kullanılacağını gösterir ve ASP.NET Core 2,1 ŞABLONLARıNA eklenen GDPR uzantı noktalarının ve API
'lerin çoğunu test etmenizi sağlar.

Tümleştirme testleri
Test oluşturma ve yürütmeyi kolaylaştıran yeni bir paket tanıtılmıştır. Microsoft. AspNetCore. Mvc. Testing paketi
aşağıdaki görevleri gerçekleştirir:
Bağımlılık dosyasını ( *. Deps) test projesinin bin klasörüne kopyalar.
Testler yürütüldüğünde statik dosya ve sayfa/görünümlerin bulunması için, içerik kökünü test edilen
uygulamanın proje köküne ayarlar.
TestServerile sınanan uygulamayı daha kolay hale getirmek Için webapplicationfactory sınıfını sağlar.
Aşağıdaki test, dizin sayfasının başarılı durum kodu ve doğru Content-Type üst bilgisi ile yüklenip yüklenduğunu
denetlemek için xUnit kullanır:
public class BasicTests
: IClassFixture<WebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly HttpClient _client;

public BasicTests(WebApplicationFactory<RazorPagesProject.Startup> factory)


{
_client = factory.CreateClient();
}

[Fact]
public async Task GetHomePage()
{
// Act
var response = await _client.GetAsync("/");

// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}

Daha fazla bilgi için bkz. tümleştirme testleri konusu.

[ApiController], ActionResult<T >


ASP.NET Core 2,1, temiz ve açıklayıcı Web API 'Leri oluşturmayı kolaylaştıran yeni programlama kuralları ekliyor.
ActionResult<T> , bir uygulamanın yanıt türünü ya da başka bir eylem sonucunu (ıactionresult gibi) döndürmesini
sağlamak için eklenen yeni bir türdür, yine de yanıt türünü gösterir. [ApiController] özniteliği, Web API 'sine özgü
kuralları ve davranışları kabul etmenin yolu olarak da eklenmiştir.
Daha fazla bilgi için bkz. ASP.NET Core Web API 'Leri oluşturma.

Ihttpclientfactory
ASP.NET Core 2,1, uygulamalarda HttpClient örneklerinin daha kolay yapılandırılacağını ve kullanılmasını
kolaylaştıran yeni bir IHttpClientFactory hizmeti içerir. HttpClient , giden HTTP istekleri için birlikte bağlanabilen
işleyicileri temsilci seçme kavramına zaten sahiptir. Fabrika:
Adlandırılmış istemci başına HttpClient örneklerinin kaydını daha sezgisel hale getirir.
Yeniden deneme, devre kesiciler vb. için, Polly ilkelerinin kullanılmasına izin veren bir Polly işleyici uygular.
Daha fazla bilgi için bkz. http Isteklerini başlatma.

Kestrel aktarma yapılandırması


ASP.NET Core 2,1 sürümü ile Kestrel 'in varsayılan taşıması artık libuv ' d i temel değildir ancak bunun yerine
yönetilen yuvaları temel alır. Daha fazla bilgi için bkz. Kestrel Web sunucusu uygulama: aktarım yapılandırması.

Genel konak Oluşturucu


Genel ana bilgisayar Oluşturucu ( HostBuilder ) sunulmuştur. Bu Oluşturucu, HTTP isteklerini (mesajlaşma, arka
plan görevleri vb.) işlemeyecek uygulamalar için kullanılabilir.
Daha fazla bilgi için bkz. .NET genel ana bilgisayar.

Güncelleştirilmiş SPA şablonları


Redux ile ilgili angular, tepki verme ve tepki verme için tek sayfalı uygulama şablonları, her bir çerçeve için Standart
proje yapılarını ve derleme sistemlerini kullanacak şekilde güncelleştirilir.
Angular şablonu angular CLı 'yı temel alır ve yanıt verme şablonları Create-tepki-App ' i temel alır.
Daha fazla bilgi için bkz.
Angular proje şablonunu ASP.NET Core ile kullanma
ASP.NET Core ile tepki verme proje şablonunu kullanın
ASP.NET Core ile React-ile-Redux proje şablonu kullanın

Razor varlıkları için arama Razor Pages


2,1 Razor Pages ' de, listelenen sırayla aşağıdaki dizinlerde Razor varlıklarını (örneğin, düzenler ve parals) arayın:
1. Geçerli sayfalar klasörü.
2. /Pages/Shared/
3. /Views/Shared/

Bir alanda Razor Pages


Artık Razor Pages alanıdesteklemektedir. Bir alan örneği görmek için, bireysel kullanıcı hesaplarıyla yeni bir Razor
Pages Web uygulaması oluşturun. Bireysel kullanıcı hesaplarıyla bir Razor Pages Web uygulaması
/Areas/Identity/Pagesiçerir.

MVC uyumluluk sürümü


SetCompatibilityVersion yöntemi, bir uygulamanın, ASP.NET Core MVC 2,1 veya sonraki sürümlerde ortaya çıkan
olası davranış değişikliklerinin kabul etmesine veya devre dışı olmasına izin verir.
Daha fazla bilgi için bkz. ASP.NET Core MVC için uyumluluk sürümü.

2,0 ' den 2,1 ' e geçiş


Bkz. ASP.NET Core 2,0 ' den 2,1 ' e geçiş.

Ek bilgiler
Değişikliklerin tamamı listesi için ASP.NET Core 2,1 sürüm notlarınabakın.
ASP.NET Core 2,0 ' deki yenilikler
6.12.2019 • 11 minutes to read • Edit Online

Bu makalede, ASP.NET Core 2,0 ' deki en önemli değişiklikler, ilgili belgelerin bağlantılarıyla vurgulanır.

Razor Pages
Razor Pages, kod odaklı senaryoları daha kolay ve daha üretken hale getiren ASP.NET Core MVC 'nin yeni bir
özelliğidir.
Daha fazla bilgi için bkz. giriş ve öğretici:
Razor Pages’e giriş
Razor Sayfaları kullanmaya başlama

ASP.NET Core metapackage


Yeni bir ASP.NET Core metapackage, ASP.NET Core ve Entity Framework Core ekipleri tarafından oluşturulan ve
desteklenen tüm paketleri dahili ve üçüncü taraf bağımlılıklarıyla birlikte içerir. Artık pakete göre bireysel ASP.NET
Core özelliklerini seçmeniz gerekmez. Tüm Özellikler Microsoft. AspNetCore. All paketine dahildir. Varsayılan
Şablonlar bu paketi kullanır.
Daha fazla bilgi için bkz. Microsoft. AspNetCore. All metapackage for ASP.NET Core 2,0.

Çalışma zamanı deposu


Microsoft.AspNetCore.All metapackage kullanan uygulamalar, yeni .NET Core çalışma zamanı deposundan
otomatik olarak yararlanır. Mağaza ASP.NET Core 2,0 uygulamalarını çalıştırmak için gereken tüm çalışma zamanı
varlıklarını içerir. Microsoft.AspNetCore.All metapackage kullandığınızda, başvurulan ASP.NET Core NuGet
paketlerinden hiçbir varlık hedef sistemde zaten bulunduğundan uygulamayla birlikte dağıtılır. Çalışma zamanı
deposundaki varlıklar Ayrıca uygulama başlatma süresini geliştirmek için önceden derlenmiş.
Daha fazla bilgi için bkz. çalışma zamanı deposu

.NET Standard 2,0


ASP.NET Core 2,0 paketleri .NET Standard 2,0 ' dir. Paketlere diğer .NET Standard 2,0 kitaplıkları tarafından
başvurulabilir ve .NET Core 2,0 ve .NET Framework 4.6.1 dahil olmak üzere .NET Standard 2,0 uyumlu .NET
uygulamalarında çalıştırılabilir.
Microsoft.AspNetCore.All metapackage, .NET Core 2,0 çalışma zamanı deposuyla kullanılması amaçlanan için
yalnızca .NET Core 2,0 ' i hedefler.

Yapılandırma güncelleştirmesi
ASP.NET Core 2,0 ' de hizmetler kapsayıcısına varsayılan olarak bir IConfiguration örneği eklenir. Hizmetler
kapsayıcısında IConfiguration , uygulamaların kapsayıcıdan yapılandırma değerlerini almasına daha kolay hale
getirir.
Planlı belgelerin durumu hakkında daha fazla bilgi için bkz. GitHub sorunu.
Günlük güncelleştirme
ASP.NET Core 2,0 ' de günlüğe kaydetme, varsayılan olarak bağımlılık ekleme (dı) sistemine dahil edilir.
Sağlayıcılar ekler ve Startup.cs dosyası yerine program.cs dosyasında filtrelemeyi yapılandırırsınız. Ve varsayılan
ILoggerFactory , çapraz sağlayıcı filtreleme ve belirli sağlayıcı filtreleme için tek bir esnek yaklaşım kullanmanıza
imkan tanıyan bir şekilde filtrelemeyi destekler.
Daha fazla bilgi için bkz. günlüğe giriş.

Kimlik doğrulama güncelleştirmesi


Yeni bir kimlik doğrulama modeli, DI kullanarak bir uygulama için kimlik doğrulamasını yapılandırmayı
kolaylaştırır.
Azure AD B2Ckullanarak Web uygulamaları ve Web API 'lerinin kimlik doğrulamasını yapılandırmak için yeni
şablonlar kullanılabilir.
Planlı belgelerin durumu hakkında daha fazla bilgi için bkz. GitHub sorunu.

Kimlik güncelleştirmesi
ASP.NET Core 2,0 ' deki kimliği kullanarak güvenli Web API 'Leri oluşturmayı kolaylaştırdık. Microsoft kimlik
doğrulama kitaplığı 'nı (msal)kullanarak Web API 'lerinize erişmek için erişim belirteçleri edinebilirsiniz.
2,0 sürümündeki kimlik doğrulama değişiklikleriyle ilgili daha fazla bilgi için aşağıdaki kaynaklara bakın:
ASP.NET Core hesap onaylama ve parola kurtarma
ASP.NET Core 'de Authenticator uygulamaları için QR kodu oluşturmayı etkinleştirme
Kimlik doğrulaması ve kimliği 2,0 ASP.NET Core geçirin

SPA şablonları
Angular, Aurelia, altını gizleme. js, tepki. js ve Redux ile tepki. js için tek sayfalı uygulama (SPA) proje şablonları
mevcuttur. Angular şablonu angular 4 ' e güncelleştirildi. Angular ve tepki verme şablonları varsayılan olarak
kullanılabilir; diğer şablonları alma hakkında daha fazla bilgi için bkz. Yeni BIR Spa projesi oluşturma. ASP.NET
Core 'de SPA oluşturma hakkında daha fazla bilgi için bkz. ASP.NET Core içinde tek sayfalı uygulamalar
oluşturmak için JavaScript hizmetlerini kullanın.

Kestrel geliştirmeleri
Kestrel Web sunucusu, Internet 'e yönelik bir sunucu olarak daha uygun hale getirmek için yeni özelliklere sahiptir.
KestrelServerOptions sınıfının yeni Limits özelliğine bir dizi sunucu kısıtlaması yapılandırma seçeneği eklenir.
Aşağıdakiler için sınır ekleyin:
İstemci bağlantıları üst sınırı
En büyük istek gövdesi boyutu
En az istek gövdesi veri hızı
Daha fazla bilgi için bkz. Kestrel Web Server Implementation For ASP.NET Core.

WebListener, HTTP. sys olarak yeniden adlandırıldı


Microsoft.AspNetCore.Server.WebListener ve Microsoft.Net.Http.Server paketleri yeni bir paket
Microsoft.AspNetCore.Server.HttpSys birleştirildi. Ad alanları eşleşecek şekilde güncelleştirildi.

Daha fazla bilgi için ASP.NET Core 'de http. sys Web sunucusu uygulamasınabakın.
Gelişmiş HTTP üst bilgisi desteği
FileStreamResult veya iletmek için MVC kullanırken, artık gönderdiğiniz içerik üzerinde bir
FileContentResult
ETag veya bir LastModified tarihi ayarlama seçeneğiniz vardır. Bu değerleri, döndürülen içerikte aşağıdakine
benzer kodla ayarlayabilirsiniz:

var data = Encoding.UTF8.GetBytes("This is a sample text from a binary array");


var entityTag = new EntityTagHeaderValue("\"MyCalculatedEtagValue\"");
return File(data, "text/plain", "downloadName.txt", lastModified: DateTime.UtcNow.AddSeconds(-5), entityTag:
entityTag);

Ziyaretçilere döndürülen dosya ETag ve LastModified değerleri için uygun HTTP başlıklarına sahiptir.
Bir uygulama ziyaretçisi bir Aralık Isteği üstbilgisiyle içerik isterse, ASP.NET Core isteği tanır ve üstbilgiyi işler.
İstenen içerik kısmen teslim edilebiliyorsa, ASP.NET Core uygun şekilde atlar ve yalnızca istenen bayt kümesini
döndürür. Bu özelliği uyarlamak veya işlemek için yöntemlerinize özel işleyiciler yazmanız gerekmez; sizin için
otomatik olarak işlenir.

Barındırma başlatma ve Application Insights


Barındırma ortamları artık uygulamanın başlatılması sırasında ek paket bağımlılıklarını ekleyebilir ve uygulama
başlatma sırasında kodu yürütebilir. Bu özellik, belirli ortamların, uygulamanın daha önce haberdar olması
gerekmeden bu ortama özgü olan "hafif" özelliklere olanak tanımak için kullanılabilir.
ASP.NET Core 2,0 ' de, bu özellik, Visual Studio 'da hata ayıklarken Application Insights tanılamayı otomatik olarak
etkinleştirmek için kullanılır ve Azure Uygulama Hizmetleri 'nde çalışırken (uygulamasına geçtikten sonra). Sonuç
olarak, proje şablonları artık varsayılan olarak Application Insights paketleri ve kodu eklemez.
Planlı belgelerin durumu hakkında daha fazla bilgi için bkz. GitHub sorunu.

Anti-forgery belirteçlerinin otomatik kullanımı


ASP.NET Core, varsayılan olarak her zaman HTML kodsuz içeriğe yardımcı olur, ancak yeni sürüme, siteler arası
istek sahteciliği (XSRF ) saldırılarını önlemeye yardımcı olmak için ek bir adım alınmıştır. ASP.NET Core artık
varsayılan olarak korsanlığa karşı koruma belirteçleri yayıp bunları, ek yapılandırma olmadan bu eylemleri ve
sayfaları form SONRASı olarak doğrular.
Daha fazla bilgi için bkz. siteler arası Istek forgery (XSRF/CSRF ) saldırılarını önleme.

Otomatik ön derleme
Razor görünümü ön derlemesi varsayılan olarak yayımlama sırasında etkinleştirilir ve yayımlama çıkış boyutunu ve
uygulama başlatma süresini azaltır.
Daha fazla bilgi için ASP.NET Core Razor görünümü derleme ve ön derleme' a bakın.

7,1 için C# Razor desteği


Razor görüntüleme altyapısı, yeni Roslyn derleyicisi ile çalışacak şekilde güncelleştirilmiştir. Bu, varsayılan Ifadeler
C# , gösterilen tanımlama grubu adları ve genel türler Ile kalıp eşleme gibi 7,1 özellikleri için destek içerir.
Projenizde 7,1 C# kullanmak için, proje dosyanıza aşağıdaki özelliği ekleyin ve çözümü yeniden yükleyin:

<LangVersion>latest</LangVersion>

C# 7,1 özelliklerinin durumu hakkında daha fazla bilgi için bkz. Roslyn GitHub deposu.
2,0 için diğer belge güncelleştirmeleri
ASP.NET Core uygulama dağıtımı için Visual Studio yayımlama profilleri
Anahtar Yönetimi
Facebook kimlik doğrulamasını yapılandırma
Twitter kimlik doğrulamasını yapılandırma
Google kimlik doğrulamasını yapılandırma
Microsoft hesabı kimlik doğrulamasını yapılandırma

Geçiş Kılavuzu
ASP.NET Core 1. x uygulamalarının ASP.NET Core 2,0 ' e nasıl geçirileceğiyle ilgili yönergeler için aşağıdaki
kaynaklara bakın:
ASP.NET Core 1. x öğesinden ASP.NET Core 2,0 'e geçirin
Kimlik doğrulaması ve kimliği 2,0 ASP.NET Core geçirin

Ek Bilgiler
Değişikliklerin tamamı listesi için ASP.NET Core 2,0 sürüm notlarınabakın.
ASP.NET Core geliştirme ekibinin ilerleme ve planlarıyla bağlantı kurmak için, ASP.net Community' ye ayarlayın.
ASP.NET Core 1.1 yenilikler
13.06.2019 • 2 minutes to read • Edit Online

ASP.NET Core 1.1 aşağıdaki yeni özellikler içerir:


URL Yeniden Yazma Ara Yazılımı
Yanıtları Önbelleğe Alma Ara Yazılımı
Görünüm bileşenleri olarak etiket Yardımcıları
MVC filtre olarak ara yazılımı
Tanımlama bilgisi tabanlı TempData sağlayıcısı
Azure App Service oturum açma sağlayıcısı
Azure Key Vault yapılandırma sağlayıcısı
Azure ve Redis depolama veri koruma anahtar deposu
WebListener Windows Server'de
WebSockets desteği

Arasındaki sürümleri 1.0 ve ASP.NET Core 1.1 seçme


ASP.NET Core 1.1, 1.0 daha fazla özelliği vardır. Genel olarak, en son sürümünü kullanmanızı öneririz.

Ek Bilgiler
ASP.NET Core 1.1.0 sürüm notları
ASP.NET Core geliştirme takımın ilerleme durumu ve planları ile bağlanmak için etkinliğindeki ASP.NET
topluluğu toplantısında.
Öğretici: ASP.NET Core ile Razor Pages Web
uygulaması oluşturma
1.10.2019 • 2 minutes to read • Edit Online

Bu öğretici dizisinde Razor Pages Web uygulaması oluşturma temelleri açıklanmaktadır.


Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz. tanıtım Razor
Pages.
Bu seri aşağıdaki öğreticileri içerir:
1. Razor Sayfaları web uygulaması oluşturma
2. Razor Pages uygulamasına model ekleme
3. Yapı iskelesi (oluşturma) Razor sayfaları
4. Bir veritabanıyla çalışma
5. Razor sayfalarını güncelleştirme
6. Arama ekleme
7. Yeni alan ekleme
8. Doğrulama ekleme
Son olarak, bir film veritabanını görüntüleyebilen ve yönetebileceğini bir uygulamanıza sahip olacaksınız.
Öğretici: ASP.NET Core Razor Pages ile çalışmaya
başlama
10.12.2019 • 19 minutes to read • Edit Online

Tarafından Rick Anderson


Bu, bir serinin ASP.NET Core Razor Pages Web uygulaması oluşturma hakkında temel bilgileri öğretir.
Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz. tanıtım Razor
Pages.
Serinin sonunda, bir film veritabanını yöneten bir uygulamanız olacaktır.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu öğreticide şunları yaptınız:
Razor Pages bir Web uygulaması oluşturun.
Uygulamayı çalıştırın.
Proje dosyalarını inceleyin.
Bu öğreticinin sonunda, daha sonraki öğreticilerde oluşturacağınız çalışan bir Razor Pages Web uygulamasına
sahipsiniz.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019 16,4 veya üzeri
.NET Core 3,1 SDK veya üzeri
Razor Pages Web uygulaması oluşturma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun ve İleri ' yiseçin. Yeni ASP.NET Core Web uygulaması

Projeyi RazorPagesMovieolarak adlandırın. Kodu kopyaladığınızda ve yapıştırdığınızda ad alanlarının


eşleşmesi için Project RazorPagesMovie olarak adı vermek önemlidir. Yeni ASP.NET Core Web uygulaması
Açılan Web uygulamasındaki ASP.NET Core 3,1 ' i seçin ve ardından Oluştur' u seçin.

Aşağıdaki Başlatıcı proje oluşturulur:


Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve example.com
gibi bir şey görüntülenir. Bunun nedeni, localhost yerel bilgisayar için Standart ana bilgisayar adıdır.
Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual Studio bir Web projesi
oluşturduğunda, Web sunucusu için rastgele bir bağlantı noktası kullanılır.

Proje dosyalarını inceleyin


Aşağıda, daha sonraki öğreticilerde birlikte çalışacağımız ana proje klasörlerine ve dosyalarına genel bir bakış
sunulmaktadır.
Sayfalar klasörü
Razor sayfaları ve destekleyici dosyalar içerir. Her Razor sayfası bir dosya çiftidir:
Razor söz dizimi kullanarak C# kodla HTML işaretlemesi içeren bir . cshtml dosyası.
Sayfa olaylarını işleyen kodu içeren C# bir . cshtml.cs dosyası.
Destekleyici dosyalar bir alt çizgiyle başlayan adlara sahiptir. Örneğin, _Layout. cshtml dosyası tüm sayfalarda ortak
kullanıcı arabirimi öğelerini yapılandırır. Bu dosya sayfanın en üstündeki gezinti menüsünü ve sayfanın alt
kısmındaki telif hakkı bildirimini ayarlar. Daha fazla bilgi için bkz. ASP.NET Core düzen.
Wwwroot klasörü
HTML dosyaları, JavaScript dosyaları ve CSS dosyaları gibi statik dosyaları içerir. Daha fazla bilgi için bkz. ASP.NET
Core statik dosyalar.
appSettings. JSON
Bağlantı dizeleri gibi yapılandırma verilerini içerir. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Program.cs
Programın giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs
Uygulama davranışını yapılandıran kodu içerir. Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama başlatma.

Sonraki adımlar
Serideki bir sonraki öğreticiye ilerleyin:
M ODEL
EKLEM E

Bu, bir serinin ilk öğreticisidir. Seriler , bir ASP.NET Core Razor pages Web uygulaması oluşturma hakkında temel
bilgileri öğretir.
Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz. tanıtım Razor
Pages.
Serinin sonunda, bir film veritabanını yöneten bir uygulamanız olacaktır.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu öğreticide şunları yaptınız:
Razor Pages bir Web uygulaması oluşturun.
Uygulamayı çalıştırın.
Proje dosyalarını inceleyin.
Bu öğreticinin sonunda, daha sonraki öğreticilerde oluşturacağınız çalışan bir Razor Pages Web uygulamasına
sahipsiniz.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri
WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Razor Pages Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun ve İleri ' yiseçin.

Projeyi RazorPagesMovieolarak adlandırın. Kodu kopyaladığınızda ve yapıştırdığınızda ad alanlarının


eşleşmesi için Project RazorPagesMovie olarak adı vermek önemlidir.
Açılan Web uygulamasındaki ASP.NET Core 2,2 ' i seçin ve ardından Oluştur' u seçin.

Aşağıdaki Başlatıcı proje oluşturulur:


Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğu example.com gibi değil
localhost:port# gösterir. Bunun nedeni, localhost yerel bilgisayar için Standart ana bilgisayar adıdır.
Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual Studio bir web projesi
oluşturduğunda, web sunucusu için rastgele bir bağlantı noktası kullanılır.
Uygulamanın giriş sayfasında, izlemeye izin vermek için kabul et ' i seçin.
Bu uygulama kişisel bilgileri izlemez, ancak proje şablonu, Avrupa Birliği 'nin genel veri koruma yönetmeliği
(GDPR )ile uyumlu olması için ihtiyaç duymanız durumunda izin özelliğini içerir.

Aşağıdaki görüntüde, izlemeye onay verdikten sonra uygulama gösterilmektedir:


Proje dosyalarını inceleyin
Aşağıda, daha sonraki öğreticilerde birlikte çalışacağımız ana proje klasörlerine ve dosyalarına genel bir bakış
sunulmaktadır.
Sayfalar klasörü
Razor sayfaları ve destekleyici dosyalar içerir. Her Razor sayfası bir dosya çiftidir:
Razor söz dizimi kullanarak C# kodla HTML işaretlemesi içeren bir . cshtml dosyası.
Sayfa olaylarını işleyen kodu içeren C# bir . cshtml.cs dosyası.
Destekleyici dosyalar bir alt çizgiyle başlayan adlara sahiptir. Örneğin, _Layout. cshtml dosyası tüm sayfalarda ortak
kullanıcı arabirimi öğelerini yapılandırır. Bu dosya sayfanın en üstündeki gezinti menüsünü ve sayfanın alt
kısmındaki telif hakkı bildirimini ayarlar. Daha fazla bilgi için bkz. ASP.NET Core düzen.
Wwwroot klasörü
HTML dosyaları, JavaScript dosyaları ve CSS dosyaları gibi statik dosyaları içerir. Daha fazla bilgi için bkz. ASP.NET
Core statik dosyalar.
appSettings. JSON
Bağlantı dizeleri gibi yapılandırma verilerini içerir. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Program.cs
Programın giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs
Tanımlama bilgilerinin onayını gerektirip gerektirmediğini belirten uygulama davranışını yapılandıran kodu içerir.
Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama başlatma.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Sonraki adımlar
Serideki bir sonraki öğreticiye ilerleyin:
M ODEL
EKLEM E
Bir ASP.NET Core Razor sayfaları uygulama için model
ekleme
10.12.2019 • 40 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, platformlar arası bir SQLite veritabanındafilm yönetimi için sınıflar eklenir. Bir ASP.NET Core
şablondan oluşturulan uygulamalar bir SQLite veritabanı kullanır. Uygulamanın model sınıfları, veritabanıyla
çalışmak için Entity Framework Core (EF Core) (SQLite EF Core veritabanı sağlayıcısı) ile kullanılır. EF Core, veri
erişimini kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
EF Core üzerinde herhangi bir bağımlılığı olmadığından model sınıfları ("düz eski CLR nesnelerden") POCO
sınıfları olarak bilinir. Bunlar, veritabanında depolanan verilerin özelliklerini tanımlayın.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Bir veri modeli ekleme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Sağ RazorPagesMovie Proje > Ekle > yeni klasör. Klasör adı modelleri.
Sağ tıklayın modelleri klasör. Seçin ekleme > sınıfı. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfına ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı şunları içerir:


ID alanı birincil anahtar için veritabanı gerektirir.
[DataType(DataType.Date)] : DataType özniteliği verilerin türünü belirtir (Tarih). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.
Derleme hata doğrulamak için projeyi derleyin.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Oluşturma bir sayfaları/filmler klasörü:
Yeni > klasör eklemek > Sayfalar klasörüne sağ tıklayın.
Klasör adı filmler
Sayfalar/filmler klasörüne sağ tıklayın > > yeni yapı Iskelesi öğesi ekleyin .

Yapı Iskelesi Ekle iletişim kutusunda Razor Pages Entity Framework (crud) > Ekle' yi seçin.
Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:
İçinde Model sınıfı seçin, açılan menü film (RazorPagesMovie.Models) .
Veri bağlamı sınıfı satırında + (artı) işaretini seçin ve oluşturulan adı RazorPagesMovie ' dan değiştirin.
Modeller. RazorPagesMovieContext to RazorPagesMovie. Veri. RazorPagesMovieContext. Bu değişiklik gerekli
değildir. Doğru ad alanıyla veritabanı bağlamı sınıfını oluşturur.
Add (Ekle) seçeneğini belirleyin.

Appsettings.json dosya yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi ile güncelleştirilir.
Oluşturulan dosyalar
Visual Studio
Visual Studio Code/Mac için Visual Studio
İskele işlem oluşturur ve aşağıdaki dosyaları güncelleştirir:
Sayfa/filmler: oluşturma, silme, Ayrıntılar, düzenleme ve dizin.
Data/RazorPagesMovieContext.cs
Güncelleştirme tarihi
Startup.cs
Oluşturulan ve güncelleştirilen dosyalar, sonraki bölümde açıklanmıştır.

İlk geçiş
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bu bölümde, Paket Yöneticisi Konsolu (PMC'yi) için kullanılır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.

PMC'de aşağıdaki komutları girin:

Add-Migration InitialCreate
Update-Database

Yukarıdaki komutlar şu uyarıyı oluşturur: "' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür belirtilmedi. Bu,
varsayılan duyarlık ve ölçeğe uygun olmadıkları takdirde değerlerin sessizce kesilmesine neden olur. '
Hasccolumntype () ' kullanarak tüm değerleri barındırabilecek SQL Server sütun türünü açık olarak belirtin. "
Bu uyarıyı yoksayabilirsiniz, daha sonraki bir öğreticide düzeltilecektir.
Geçişler komutu, ilk veritabanı şemasını oluşturmak için kod üretir. Şema, DbContext belirtilen modeli temel alır.
InitialCreate Bağımsız değişkeni, geçişlerin adlandırmak için kullanılır. Herhangi bir ad kullanılabilir, ancak bir adı
seçili kural gereği, geçiş açıklar.
update komutu uygulanmamış geçişlerde Up yöntemini çalıştırır. Bu durumda update , veritabanını oluşturan
geçiş/<zaman damgası > _InitialCreate. cs dosyasında Up yöntemini çalıştırır.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı), uygulama başlatma
sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler
Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin ilerleyen
bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme kapsayıcısını ile
kayıtlı.
İnceleme Startup.ConfigureServices yöntemi. Vurgulanan satırı iskele kurucu tarafından eklendi:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

RazorPagesMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları Movie
modeli. Veri bağlamı RazorPagesMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı,
(
hangi varlıkları veri modelinde yer alan belirtir.

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
public class RazorPagesMovieContext : DbContext
{
public RazorPagesMovieContext (DbContextOptions<RazorPagesMovieContext> options)
: base(options)
{
}

public DbSet<RazorPagesMovie.Models.Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Hatası alırsanız:

SqlException: Cannot open database "RazorPagesMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül İngilizce
olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer gerekir.
Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Sonraki öğreticiye yapı iskelesi tarafından oluşturulan dosyaları açıklar.

Ek kaynaklar

Ö N C E K I: S O N R A K I: R A Z O R S A Y F A L A R I IÇ IN IS K E L E
BA ŞL A M A KURULM UŞ

Bu bölümde, platformlar arası bir SQLite veritabanındafilm yönetimi için sınıflar eklenir. Bir ASP.NET Core
şablondan oluşturulan uygulamalar bir SQLite veritabanı kullanır. Uygulamanın model sınıfları, veritabanıyla
çalışmak için Entity Framework Core (EF Core) (SQLite EF Core veritabanı sağlayıcısı) ile kullanılır. EF Core, veri
erişimini kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
EF Core üzerinde herhangi bir bağımlılığı olmadığından model sınıfları ("düz eski CLR nesnelerden") POCO
sınıfları olarak bilinir. Bunlar, veritabanında depolanan verilerin özelliklerini tanımlayın.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Bir veri modeli ekleme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Sağ RazorPagesMovie Proje > Ekle > yeni klasör. Klasör adı modelleri.
Sağ tıklayın modelleri klasör. Seçin ekleme > sınıfı. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfına ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı şunları içerir:


ID alanı birincil anahtar için veritabanı gerektirir.
[DataType(DataType.Date)] : DataType özniteliği verilerin türünü belirtir (Tarih). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.
Derleme hata doğrulamak için projeyi derleyin.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Oluşturma bir sayfaları/filmler klasörü:
Yeni > klasör eklemek > Sayfalar klasörüne sağ tıklayın.
Klasör adı filmler
Sayfalar/filmler klasörüne sağ tıklayın > > yeni yapı Iskelesi öğesi ekleyin .

Yapı Iskelesi Ekle iletişim kutusunda Razor Pages Entity Framework (crud) > Ekle' yi seçin.

Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:


İçinde Model sınıfı seçin, açılan menü film (RazorPagesMovie.Models) .
İçinde veri bağlamı sınıfının satır, select + (artı) oturum açın ve oluşturulan adı kabul
RazorPagesMovie.Models.RazorPagesMovieContext.
Add (Ekle) seçeneğini belirleyin.

Appsettings.json dosya yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi ile güncelleştirilir.
İskele işlem oluşturur ve aşağıdaki dosyaları güncelleştirir:
Oluşturulan dosyalar
Sayfa/filmler: oluşturma, silme, Ayrıntılar, düzenleme ve dizin.
Data/RazorPagesMovieContext.cs
Dosya güncelleştirildi
Startup.cs
Oluşturulan ve güncelleştirilen dosyalar, sonraki bölümde açıklanmıştır.

İlk geçiş
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bu bölümde, Paket Yöneticisi Konsolu (PMC'yi) için kullanılır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.
PMC'de aşağıdaki komutları girin:

Add-Migration Initial
Update-Database

Add-Migration Komut, ilk veritabanı şeması oluşturmak için kod oluşturur. Şema, DbContext belirtilen modele
dayalıdır ( RazorPagesMovieContext.cs dosyasında). InitialCreate bağımsız değişkeni, geçişi adlandırmak için
kullanılır. Herhangi bir ad kullanılabilir, ancak kurala göre geçiş tanımlayan bir ad kullanılır.Daha fazla bilgi için bkz.
Öğretici: EF Core ile geçiş özelliğini kullanma-ASP.NET MVC.
Update-Database Komutu çalıştırmaları Up yönteminde geçişleri /<zaman damgası > _InitialCreate.cs dosya. Up
Yöntemi veritabanı oluşturur.

NOTE
Yukarıdaki komutlar şu uyarıyı oluşturur: " ' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür belirtilmedi. Bu,
varsayılan duyarlık ve ölçeğe uygun olmadıkları takdirde değerlerin sessizce kesilmesine neden olur. ' Hasccolumntype () '
kullanarak tüm değerleri barındırabilecek SQL Server sütun türünü açık olarak belirtin. " Bu uyarıyı yoksayabilirsiniz, daha
sonraki bir öğreticide düzeltilecektir.

Visual Studio
Visual Studio Code
Mac için Visual Studio
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı), uygulama başlatma
sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler
Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin ilerleyen
bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme kapsayıcısını ile
kayıtlı.
İnceleme Startup.ConfigureServices yöntemi. Vurgulanan satırı iskele kurucu tarafından eklendi:
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
// needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("RazorPagesMovieContext")));
}

RazorPagesMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları Movie
modeli. Veri bağlamı ( RazorPagesMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı,
hangi varlıkları veri modelinde yer alan belirtir.

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
public class RazorPagesMovieContext : DbContext
{
public RazorPagesMovieContext (DbContextOptions<RazorPagesMovieContext> options)
: base(options)
{
}

public DbSet<RazorPagesMovie.Models.Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Hatası alırsanız:

SqlException: Cannot open database "RazorPagesMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı.
NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül İngilizce
olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer gerekir.
Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Sonraki öğreticiye yapı iskelesi tarafından oluşturulan dosyaları açıklar.

Ek kaynaklar

Ö N C E K I: S O N R A K I: R A Z O R S A Y F A L A R I IÇ IN IS K E L E
BA ŞL A M A KURULM UŞ
ASP.NET Core Razor Pages scafkatlama
23.11.2019 • 25 minutes to read • Edit Online

Tarafından Rick Anderson


Bu öğreticide, önceki öğreticidescafkatlama tarafından oluşturulan Razor Pages incelenir.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Oluşturma, silme, Ayrıntılar ve düzenleme sayfaları


Pages/filmler/Index. cshtml. cs sayfa modelini inceleyin:

// Unused usings removed.


using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get;set; }

public async Task OnGetAsync()


{
Movie = await _context.Movie.ToListAsync();
}
}
}

Razor Pages PageModel türetilir. Kurala göre PageModel türetilmiş sınıf <PageName>Model olarak adlandırılır.
Oluşturucu, RazorPagesMovieContext sayfaya eklemek için bağımlılık ekleme işlemini kullanır. Tüm yapı iskelesi
sayfaları bu düzene uyar. Entity Framework zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman
uyumsuz kod .
Sayfa için bir istek yapıldığında OnGetAsync yöntemi, Razor sayfasına bir film listesi döndürür. OnGetAsync veya
OnGet , sayfanın durumunu başlatmak için çağırılır. Bu durumda, OnGetAsync film listesini alır ve görüntüler.

OnGet döndürdüğünde veya OnGetAsync``Task döndürürse, hiçbir dönüş açıklaması kullanılmaz. Dönüş türü
void
IActionResult veya Task<IActionResult> olduğunda, return ifadesinin sağlanması gerekir. Örneğin,
Pages/filmler/Create. cshtml. cs OnPostAsync yöntemi:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}

Pages/filmler/Index. cshtml Razor sayfasını inceleyin:


@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Razor, HTML 'den C# ya da Razor 'e özgü biçimlendirmeye geçiş yapabilir. Bir @ sembol sonrasında Razor
ayrılmış bir anahtar sözcükolduğunda, bu, ' a geçiş yapar C#.
@page yönergesi
@page Razor yönergesi, dosyayı bir MVC eylemi yapar, bu da istekleri işleyebileceği anlamına gelir. @page
sayfadaki ilk Razor yönergesi olmalıdır. @page , Razor 'e özgü biçimlendirmeye geçme örneğidir. Daha fazla bilgi
için bkz. Razor söz dizimi .
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movie[0].Title)

DisplayNameFor HTML Yardımcısı, görünen adı belirlemede lambda ifadesinde başvurulan Title özelliğini inceler.
Lambda ifadesi değerlendirilmek yerine incelenir. Bu, model , model.Movie veya model.Movie[0] null veya boş
olduğunda herhangi bir erişim ihlali olmadığı anlamına gelir. Lambda ifadesi değerlendirildiğinde (örneğin,
@Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.

@model yönergesi

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@model yönergesi, Razor sayfasına geçirilen modelin türünü belirtir. Yukarıdaki örnekte @model satırı, PageModel
türetilmiş sınıfı Razor sayfası için kullanılabilir hale getirir. Model, @Html.DisplayNameFor ve sayfadaki HTML
yardımcılarını @Html.DisplayFor kullanılır.
Düzen sayfası
Menü bağlantılarını (RazorPagesMovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü
düzeni sayfa/paylaşılan/_Layout. cshtml dosyasında uygulanır. Pages/Shared/_Layout. cshtml dosyasını açın.
Düzen ŞABLONLARı, HTML kapsayıcı düzeninin şu şekilde olmasını sağlar:
Tek bir yerde belirtildi.
Sitede birden çok sayfada uygulandı.
@RenderBody() satırını bulun. RenderBody , tüm sayfaya özgü görünümlerin, Düzen sayfasında kaydırılan bir yer
tutucudur. Örneğin, Gizlilik bağlantısını seçin ve Sayfalar/gizlilik. cshtml görünümü RenderBody yöntemi içinde
işlenir.
ViewData ve Layout
Pages/filmler/Index. cshtml dosyasından aşağıdaki biçimlendirmeyi göz önünde bulundurun:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

Önceki vurgulanan biçimlendirme, Razor geçişi örneği olan bir örnektir C#. { ve } karakterler bir C# kod
bloğunu kapsar.
PageModel temel sınıfı, verileri bir görünüme geçirmek için kullanılabilen bir ViewData Dictionary özelliği içerir.
Nesneler, anahtar/değer düzeniyle ViewData sözlüğüne eklenir. Yukarıdaki örnekte, "Title" özelliği ViewData
sözlüğüne eklenir.
"Title" özelliği sayfa/paylaşılan/_Layout. cshtml dosyasında kullanılır. Aşağıdaki biçimlendirme _Layout. cshtml
dosyasının ilk birkaç satırını gösterir.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>

@*Markup removed for brevity.*@

Satır @*Markup removed for brevity.*@ bir Razor açıklamadır. HTML yorumlarının ( <!-- --> ) aksine, Razor
açıklamaları istemciye gönderilmez.
Düzeni güncelleştirme
Pages/Shared/_Layout. cshtml dosyasındaki <title> öğesini RazorPagesMovieyerine filmi görüntüleyecek
şekilde değiştirin.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie</title>

Sayfa/paylaşılan/_Layout. cshtml dosyasında aşağıdaki tutturucu öğeyi bulun.

<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>

Önceki öğeyi aşağıdaki biçimlendirmeyle değiştirin:

<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>

Önceki tutturucu öğesi bir etiket yardımcıdır. Bu durumda, bağlantı etiketi yardımcısınınolması gerekir.
asp-page="/Movies/Index" Tag Helper özniteliği ve değeri, /Movies/Index Razor sayfasına bir bağlantı oluşturur.
asp-area öznitelik değeri boş olduğundan, alan bağlantıda kullanılmaz. Daha fazla bilgi için bkz. alanlara bakın.

Değişikliklerinizi kaydedin ve Rpmovie bağlantısına tıklayarak uygulamayı test edin. Herhangi bir sorununuz varsa
GitHub 'daki _Layout. cshtml dosyasına bakın.
Diğer bağlantıları test edin (giriş, rpmovie, oluşturma, düzenlemeve silme). Her sayfada, tarayıcı sekmesinde
görebileceğiniz başlık ayarlanır. Bir sayfada yer işareti eklediğinizde başlık, yer işareti için kullanılır.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih
biçimleri için virgül (",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı
globalize için adımlar uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .

Layout özelliği Pages/_ViewStart. cshtml dosyasında ayarlanır:

@{
Layout = "_Layout";
}

Yukarıdaki biçimlendirme düzen dosyasını Sayfalar klasörü altındaki tüm Razor dosyaları için
Sayfalar/paylaşılan/_Layout. cshtml olarak ayarlar. Daha fazla bilgi için bkz. Düzen .
Sayfa oluştur modeli
Pages/filmler/Create. cshtml. cs sayfa modelini inceleyin:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}
}

OnGet yöntemi, sayfa için gereken tüm durumları başlatır. Oluşturma sayfasında başlatılacak durum yok, bu
nedenle Page döndürülür. Öğreticide daha sonra, OnGet başlatma durumuna bir örnek gösterilir. Page yöntemi
Create. cshtml sayfasını işleyen bir PageResult nesnesi oluşturur.
Movie özelliği, model bağlamayıkabul etmek için [BindProperty] özniteliğini kullanır. Oluşturma formu form
değerlerini gönderirse, ASP.NET Core çalışma zamanı, postalanan değerleri Movie modeline bağlar.
OnPostAsync yöntemi, sayfa form verileri gönderdiğinde çalıştırılır:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

Herhangi bir model hatası varsa, form, gönderilen tüm form verileriyle birlikte yeniden görüntülenir. Form
gönderilmeden önce çoğu model hatası istemci tarafında yakalanabilir. Bir model hatasına bir örnek, Date alanı için
bir tarihe dönüştürülemeyen bir değer gönderme. İstemci tarafı doğrulama ve model doğrulaması Öğreticinin
ilerleyen kısımlarında ele alınmıştır.
Model hatası yoksa, veriler kaydedilir ve tarayıcı dizin sayfasına yönlendirilir.
Razor Oluştur sayfası
Pages/filmler/Create. cshtml Razor sayfa dosyasını inceleyin:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel

@{
ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio, etiket yardımcıları için kullanılan farklı kalın yazı tipiyle aşağıdaki etiketleri görüntüler:
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post"> öğesi bir form etiketi yardımcıdır. Form etiketi Yardımcısı, bir antiforgery belirteciniotomatik
olarak içerir.
Yapı iskelesi altyapısı, modeldeki her alan için (KIMLIK hariç), aşağıdakine benzer Razor biçimlendirmesi oluşturur:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>


<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Doğrulama etiketi yardımcıları ( <div asp-validation-summary ve <span asp-validation-for ) doğrulama hatalarını


görüntüler. Doğrulama, bu serinin ilerleyen kısımlarında daha ayrıntılı bir şekilde ele alınmıştır.
Etiket etiketi Yardımcısı ( <label asp-for="Movie.Title" class="control-label"></label> ), Title özelliği için etiket
başlığını ve for özniteliğini oluşturur.
Giriş etiketi Yardımcısı ( <input asp-for="Movie.Title" class="form-control"> ), dataaçıklamaların özniteliklerini
kullanır ve istemci tarafında jQuery doğrulaması için gerekli HTML özniteliklerini üretir.
<form method="post"> gibi etiket yardımcıları hakkında daha fazla bilgi için bkz. ASP.NET Core etiket yardımcıları.

Ek kaynaklar

Ö N C E K I: B IR M O D E L SON RA KI :
EKLEM E V E R IT A B A N I
Tarafından Rick Anderson
Bu öğreticide, önceki öğreticidescafkatlama tarafından oluşturulan Razor Pages incelenir.
Görüntüleme veya indirme örnek.

Oluşturma, silme, Ayrıntılar ve düzenleme sayfaları


Pages/filmler/Index. cshtml. cs sayfa modelini inceleyin:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;

namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get;set; }

public async Task OnGetAsync()


{
Movie = await _context.Movie.ToListAsync();
}
}
}

Razor Pages PageModel türetilir. Kurala göre PageModel türetilmiş sınıf <PageName>Model olarak adlandırılır.
Oluşturucu, RazorPagesMovieContext sayfaya eklemek için bağımlılık ekleme işlemini kullanır. Tüm yapı iskelesi
sayfaları bu düzene uyar. Entity Framework zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman
uyumsuz kod .
Sayfa için bir istek yapıldığında OnGetAsync yöntemi, Razor sayfasına bir film listesi döndürür. OnGetAsync veya
OnGet bir Razor sayfasında, sayfanın durumunu başlatmak için çağrılır. Bu durumda, OnGetAsync film listesini alır
ve görüntüler.
OnGet döndürdüğünde veya OnGetAsync``Task döndürürse, hiçbir dönüş yöntemi kullanılmaz. Dönüş türü
void
IActionResult veya Task<IActionResult> olduğunda, return ifadesinin sağlanması gerekir. Örneğin,
Pages/filmler/Create. cshtml. cs OnPostAsync yöntemi:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

Pages/filmler/Index. cshtml Razor sayfasını inceleyin:


@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Razor, HTML 'den C# ya da Razor 'e özgü biçimlendirmeye geçiş yapabilir. Bir @ sembol sonrasında Razor
ayrılmış bir anahtar sözcükolduğunda, bu, ' a geçiş yapar C#.
@page Razor yönergesi, dosyayı bir MVC eylemine dönüştürür, bu da istekleri işleyebileceği anlamına gelir. @page
sayfadaki ilk Razor yönergesi olmalıdır. @page , Razor 'e özgü biçimlendirmeye geçme örneğidir. Daha fazla bilgi
için bkz. Razor söz dizimi .
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movie[0].Title)

DisplayNameFor HTML Yardımcısı, görünen adı belirlemede lambda ifadesinde başvurulan Title özelliğini inceler.
Lambda ifadesi değerlendirilmek yerine incelenir. Bu, model , model.Movie veya model.Movie[0] null veya boş
olduğunda herhangi bir erişim ihlali olmadığı anlamına gelir. Lambda ifadesi değerlendirildiğinde (örneğin,
@Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.

@model yönergesi

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@model yönergesi, Razor sayfasına geçirilen modelin türünü belirtir. Yukarıdaki örnekte @model satırı, PageModel
türetilmiş sınıfı Razor sayfası için kullanılabilir hale getirir. Model, @Html.DisplayNameFor ve sayfadaki HTML
yardımcılarını @Html.DisplayFor kullanılır.
Düzen sayfası
Menü bağlantılarını (RazorPagesMovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü
düzeni sayfa/paylaşılan/_Layout. cshtml dosyasında uygulanır. Pages/Shared/_Layout. cshtml dosyasını açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden çok
sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm sayfaya özgü
görünümlerin, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını seçerseniz,
Sayfa/Gizlilik. cshtml görünümü RenderBody yöntemi içinde işlenir.
ViewData ve Layout
Pages/filmler/Index. cshtml dosyasından aşağıdaki kodu göz önünde bulundurun:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

Önceki vurgulanan kod, Razor geçişi örneği olan bir örnektir C#. { ve } karakterler bir C# kod bloğunu kapsar.
PageModel temel sınıfında, bir görünüme geçirmek istediğiniz verileri eklemek için kullanılabilecek bir ViewData
Dictionary özelliği vardır. Bir anahtar/değer düzeniyle ViewData sözlüğüne nesne eklersiniz. Yukarıdaki örnekte,
"title" özelliği ViewData sözlüğüne eklenir.
"Title" özelliği sayfa/paylaşılan/_Layout. cshtml dosyasında kullanılır. Aşağıdaki biçimlendirme _Layout. cshtml
dosyasının ilk birkaç satırını gösterir.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>

@*Markup removed for brevity.*@

Satır @*Markup removed for brevity.*@ , düzen dosyanızda görünmeyen bir Razor açıklamadır. HTML yorumlarının (
<!-- --> ) aksine, Razor açıklamaları istemciye gönderilmez.
Düzeni güncelleştirme
Pages/Shared/_Layout. cshtml dosyasındaki <title> öğesini RazorPagesMovieyerine filmi görüntüleyecek
şekilde değiştirin.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie</title>

Sayfa/paylaşılan/_Layout. cshtml dosyasında aşağıdaki tutturucu öğeyi bulun.

<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>

Önceki öğeyi aşağıdaki biçimlendirme ile değiştirin.

<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>

Önceki tutturucu öğesi bir etiket yardımcıdır. Bu durumda, bağlantı etiketi yardımcısınınolması gerekir.
asp-page="/Movies/Index" Tag Helper özniteliği ve değeri, /Movies/Index Razor sayfasına bir bağlantı oluşturur.
asp-area öznitelik değeri boş olduğundan, alan bağlantıda kullanılmaz. Daha fazla bilgi için bkz. alanlara bakın.

Değişikliklerinizi kaydedin ve Rpmovie bağlantısına tıklayarak uygulamayı test edin. Herhangi bir sorununuz varsa
GitHub 'daki _Layout. cshtml dosyasına bakın.
Diğer bağlantıları test edin (giriş, rpmovie, oluşturma, düzenlemeve silme). Her sayfada, tarayıcı sekmesinde
görebileceğiniz başlık ayarlanır. Bir sayfada yer işareti eklediğinizde başlık, yer işareti için kullanılır.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih
biçimleri için virgül (",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı
globalize için adımlar uygulamanız gerekir. Bu GitHub, ondalık virgülden ekleme hakkında yönergeler için 4076 sorun .

Layout özelliği Pages/_ViewStart. cshtml dosyasında ayarlanır:

@{
Layout = "_Layout";
}

Yukarıdaki biçimlendirme düzen dosyasını Sayfalar klasörü altındaki tüm Razor dosyaları için
Sayfalar/paylaşılan/_Layout. cshtml olarak ayarlar. Daha fazla bilgi için bkz. Düzen .
Sayfa oluştur modeli
Pages/filmler/Create. cshtml. cs sayfa modelini inceleyin:
// Unused usings removed.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public CreateModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}
}

OnGet yöntemi, sayfa için gereken tüm durumları başlatır. Oluşturma sayfasında başlatılacak durum yok, bu
nedenle Page döndürülür. Öğreticide daha sonra OnGet yöntemi başlatma durumunu görürsünüz. Page yöntemi
Create. cshtml sayfasını işleyen bir PageResult nesnesi oluşturur.
Movie özelliği, model bağlamayıkabul etmek için [BindProperty] özniteliğini kullanır. Oluşturma formu form
değerlerini gönderirse, ASP.NET Core çalışma zamanı, postalanan değerleri Movie modeline bağlar.
OnPostAsync yöntemi, sayfa form verileri gönderdiğinde çalıştırılır:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
Herhangi bir model hatası varsa, form, gönderilen tüm form verileriyle birlikte yeniden görüntülenir. Form
gönderilmeden önce çoğu model hatası istemci tarafında yakalanabilir. Bir model hatasına bir örnek, Date alanı için
bir tarihe dönüştürülemeyen bir değer gönderme. İstemci tarafı doğrulama ve model doğrulaması Öğreticinin
ilerleyen kısımlarında ele alınmıştır.
Model hatası yoksa, veriler kaydedilir ve tarayıcı dizin sayfasına yönlendirilir.
Razor Oluştur sayfası
Pages/filmler/Create. cshtml Razor sayfa dosyasını inceleyin:

@page
@model RazorPagesMovie.Pages.Movies.CreateModel

@{
ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio, etiket yardımcıları için kullanılan farklı kalın yazı tipiyle <form method="post"> etiketini görüntüler:

<form method="post"> öğesi bir form etiketi yardımcıdır. Form etiketi Yardımcısı, bir antiforgery belirteciniotomatik
olarak içerir.
Yapı iskelesi altyapısı, modeldeki her alan için (KIMLIK hariç), aşağıdakine benzer Razor biçimlendirmesi oluşturur:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>


<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Doğrulama etiketi yardımcıları ( <div asp-validation-summary ve <span asp-validation-for ) doğrulama hatalarını


görüntüler. Doğrulama, bu serinin ilerleyen kısımlarında daha ayrıntılı bir şekilde ele alınmıştır.
Etiket etiketi Yardımcısı ( <label asp-for="Movie.Title" class="control-label"></label> ), Title özelliği için etiket
başlığını ve for özniteliğini oluşturur.
Giriş etiketi Yardımcısı ( <input asp-for="Movie.Title" class="form-control"> ), dataaçıklamaların özniteliklerini
kullanır ve istemci tarafında jQuery doğrulaması için gerekli HTML özniteliklerini üretir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü
Ö N C E K I: B IR M O D E L SON RA KI :
EKLEM E V E R IT A B A N I
Veritabanı ve ASP.NET Core çalışma
23.11.2019 • 20 minutes to read • Edit Online

Tarafından Rick Anderson ve ALi Audette


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
RazorPagesMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini
işler. Veritabanı bağlamı, Startup.csiçindeki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON dosyasından
bağlantı dizesini alır.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Veritabanı ( Database={Database name} ) için ad değeri, oluşturulan kodunuz için farklı olacaktır. Ad değeri rastgele.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-
bc;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini gerçek bir veritabanı sunucusuna
ayarlamak için bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür. LocalDB,
isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak,
LocalDB veritabanı C:\Users\<user>\ dizininde *.mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.

Movie tabloya sağ tıklayıp Görünüm Tasarımcısı' nı seçin:


ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar için ID adlı bir özellik
oluşturur.
Movie tabloya sağ tıklayın ve verileri görüntüle' yi seçin:

Veritabanının çekirdeğini oluşturma


Modeller klasöründe aşağıdaki kodla SeedData adlı yeni bir sınıf oluşturun:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
using System;
using System.Linq;

namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Temel yöntemi çağırın ve bu yönteme geçerek bağlamı geçer.
Çekirdek yöntemi tamamlandığında bağlamı atın.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;

namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Update-Database çalıştırılmayan aşağıdaki özel durum oluşur:

SqlException: Cannot open database "RazorPagesMovieContext-" requested by the login. The login failed.
Login failed for user 'user name'.
Uygulamayı test etme
Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya Ssox 'ten silme bağlantılarıyla yapabilirsiniz
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur' a
dokunun:

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 tuşuna
basın.
Ile hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Sonraki öğreticide, verilerin sunumu gelişmeyecektir.

Ek kaynaklar

Ö N C E K I: Y A P I IS K E L E S I R A Z O R IL E R I: S A Y F A L A R I
PAGES G Ü N C E L L E Ş T IR M E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
RazorPagesMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini
işler. Veritabanı bağlamı, Startup.csiçindeki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
// needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("RazorPagesMovieContext")));
}

ConfigureServices ' de kullanılan yöntemler hakkında daha fazla bilgi için bkz.:
CookiePolicyOptionsiçin ASP.NET Core ab genel veri koruma yönetmeliği (GDPR ) desteği .
SetCompatibilityVersion
ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON dosyasından
bağlantı dizesini alır.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Veritabanı ( Database={Database name} ) için ad değeri, oluşturulan kodunuz için farklı olacaktır. Ad değeri rastgele.

{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-
1234;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini gerçek bir veritabanı sunucusuna
ayarlamak için bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code
Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür. LocalDB,
isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak,
LocalDB veritabanı C:/Users/<user/> dizininde *.mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.

Movie tabloya sağ tıklayıp Görünüm Tasarımcısı' nı seçin:


ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar için ID adlı bir özellik
oluşturur.
Movie tabloya sağ tıklayın ve verileri görüntüle' yi seçin:

Veritabanının çekirdeğini oluşturma


Modeller klasöründe aşağıdaki kodla SeedData adlı yeni bir sınıf oluşturun:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Temel yöntemi çağırın ve bu yönteme geçerek bağlamı geçer.
Çekirdek yöntemi tamamlandığında bağlamı atın.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;
using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context=services.
GetRequiredService<RazorPagesMovieContext>();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

Bir üretim uygulaması Database.Migrate çağırmaz. Update-Database çalıştırılmadığından aşağıdaki özel durumu
engellemek için yukarıdaki koda eklenir:
SqlException: oturum açma tarafından istenen "RazorPagesMovieContext-21" veritabanı açılamıyor. Oturum
açılamadı. ' Kullanıcı adı ' kullanıcısı için oturum açma başarısız.
Uygulamayı test etme
Visual Studio
Visual Studio Code
Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya Ssox 'ten silme bağlantılarıyla yapabilirsiniz
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur' a
dokunun:

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 tuşuna
basın.
Ile hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir:

Sonraki öğretici, verilerin sunumunu temizler.


Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: Y A P I IS K E L E S I R A Z O R IL E R I: S A Y F A L A R I
PAGES G Ü N C E L L E Ş T IR M E
ASP.NET Core uygulamasında oluşturulan sayfaları
güncelleştirme
23.11.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate Yayın tarihi (iki
sözcük) olmalıdır.

Oluşturulan kodu Güncelleştir


Modeller/film. cs dosyasını açın ve aşağıdaki kodda gösterilen vurgulanmış satırları ekleyin:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

[Column(TypeName = "decimal(18, 2)")] veri ek açıklaması, Entity Framework Core veritabanında Price para
birimine doğru şekilde eşlemesine olanak sağlar. Daha fazla bilgi için bkz. veri türleri.
Veri açıklamaları sonraki öğreticide ele alınmıştır. Display özniteliği bir alanın adı için (Bu durumda "ReleaseDate"
yerine "Yayın tarihi") görüntüleneceğini belirtir. DataType özniteliği verilerin türünü belirtir (Tarih), bu nedenle
alanda depolanan zaman bilgileri gösterilmez.
Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/filmler/Index. cshtml dosyasındaki tutturucu etiketi Yardımcısı
tarafından oluşturulur.
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper , Razor sayfasından (yol göreli), asp-page ve yol kimliği (
asp-route-id ) HTML href öznitelik değerini dinamik olarak oluşturur. Daha fazla bilgi için bkz. Sayfalar Için URL
oluşturma .
Oluşturulan biçimlendirmeyi incelemek için sık kullandığınız tarayıcıdan Görünüm kaynağını kullanın.
Oluşturulan HTML 'nin bir bölümü aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>

Dinamik olarak oluşturulan bağlantılar, film KIMLIĞINI bir sorgu dizesiyle (örneğin,
https://localhost:5001/Movies/Details?id=1``?id=1 ) iletir.

Rota şablonu Ekle


"{İd: int}" yol şablonunu kullanmak için Düzenle, Ayrıntılar ve Sil Razor Pages güncelleştirin. Bu sayfaların her biri
için Page yönergesini @page "{id:int}"``@page değiştirin. Uygulamayı çalıştırın ve kaynağı görüntüleyin.
Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI ekler:

<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>

Tamsayıyı içermeyen " {id: int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404 (bulunamadı) hatası
döndürüyor. Örneğin, http://localhost:5000/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı yapmak
için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"
@page "{id:int?}" davranışını test etmek için:
Pages/filmler/details. cshtml içindeki page yönergesini @page "{id:int?}" olarak ayarlayın.
public async Task<IActionResult> OnGetAsync(int? id) ( sayfalarda/filmlerde/details. cshtml. cs) bir kesme
noktası ayarlayın.
https://test-cors.org sayfasına gidin.
@page "{id:int}" yönergesi ile, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404 döndürür.
@page "{id:int?}" kullanarak OnGetAsync yöntemi NotFound ( HTTP 404 ) döndürür.

Eşzamanlılık özel durum işlemeyi gözden geçirme


Pages/filmler/Edit. cshtml. cs dosyasındaki OnPostAsync yöntemini gözden geçirin:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Önceki kod, bir istemci filmi sildiği ve diğer istemci filmle değişiklik yaptığı zaman eşzamanlılık özel durumlarını
algılar.
catch bloğunu test etmek için:
catch (DbUpdateConcurrencyException) kesme noktası ayarlama
Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
Önceki tarayıcı penceresinde filmdeki değişiklikleri gönderin.
Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. eşzamanlılık çakışmalarını
işleme .
Gönderme ve bağlama incelemesi
Pages/filmler/Edit. cshtml. cs dosyasını inceleyin:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);

if (Movie == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Filmler/düzenleme sayfasına HTTP GET isteği yapıldığında (örneğin, http://localhost:5000/Movies/Edit/2 ):


OnGetAsync yöntemi, filmi veritabanından getirir ve Page yöntemini döndürür.
Page yöntemi, Pages/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası, film modelinin
sayfada kullanılabilir olmasını sağlayan model yönergesini ( @model RazorPagesMovie.Pages.Movies.EditModel )
içerir.
Düzenleme formu filmdeki değerlerle birlikte görüntülenir.
Filmler/Düzenle sayfası gönderildiğinde:
Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty] özniteliği model bağlamayımümkün.

[BindProperty]
public Movie Movie { get; set; }

Model durumunda hatalar varsa (örneğin, ReleaseDate bir tarihe dönüştürülemiyorsa), form gönderilen
değerlerle yeniden görüntülenir.
Model hatası yoksa, film kaydedilir.
Razor sayfalarında Dizin, oluşturma ve silme gibi HTTP GET yöntemleri benzer bir düzende yer alır. Razor Oluştur
sayfasındaki HTTP POST OnPostAsync yöntemi, Razor düzenleme sayfasındaki OnPostAsync yöntemine benzer bir
düzen izler.

Ek kaynaklar

Ö N C E K I: B IR V E R IT A B A N IY L A IL E R I: A R A M A
Ç A L IŞ M A EKLE

Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate Yayın tarihi (iki
sözcük) olmalıdır.

Oluşturulan kodu Güncelleştir


Modeller/film. cs dosyasını açın ve aşağıdaki kodda gösterilen vurgulanmış satırları ekleyin:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

[Column(TypeName = "decimal(18, 2)")] veri ek açıklaması, Entity Framework Core veritabanında Price para
birimine doğru şekilde eşlemesine olanak sağlar. Daha fazla bilgi için bkz. veri türleri.
Veri açıklamaları sonraki öğreticide ele alınmıştır. Display özniteliği bir alanın adı için (Bu durumda "ReleaseDate"
yerine "Yayın tarihi") görüntüleneceğini belirtir. DataType özniteliği verilerin türünü belirtir (Tarih), bu nedenle
alanda depolanan zaman bilgileri gösterilmez.
Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/filmler/Index. cshtml dosyasındaki tutturucu etiketi Yardımcısı
tarafından oluşturulur.
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper , Razor sayfasından (yol göreli), asp-page ve yol kimliği (
asp-route-id ) HTML href öznitelik değerini dinamik olarak oluşturur. Daha fazla bilgi için bkz. Sayfalar Için URL
oluşturma .
Oluşturulan biçimlendirmeyi incelemek için sık kullandığınız tarayıcıdan Görünüm kaynağını kullanın.
Oluşturulan HTML 'nin bir bölümü aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>

Dinamik olarak oluşturulan bağlantılar, film KIMLIĞINI bir sorgu dizesiyle (örneğin,
https://localhost:5001/Movies/Details?id=1``?id=1 ) iletir.

"{İd: int}" yol şablonunu kullanmak için Düzenle, Ayrıntılar ve Sil Razor Pages güncelleştirin. Bu sayfaların her biri
için Page yönergesini @page "{id:int}"``@page değiştirin. Uygulamayı çalıştırın ve kaynağı görüntüleyin.
Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI ekler:

<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>

Tamsayıyı içermeyen " {id: int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404 (bulunamadı) hatası
döndürüyor. Örneğin, http://localhost:5000/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı yapmak
için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

@page "{id:int?}" davranışını test etmek için:


Pages/filmler/details. cshtml içindeki page yönergesini @page "{id:int?}" olarak ayarlayın.
public async Task<IActionResult> OnGetAsync(int? id) ( sayfalarda/filmlerde/details. cshtml. cs) bir kesme
noktası ayarlayın.
https://test-cors.org sayfasına gidin.
@page "{id:int}" yönergesi ile, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404 döndürür.
@page "{id:int?}" kullanarak OnGetAsync yöntemi NotFound ( HTTP 404 ) döndürür.

Eşzamanlılık özel durum işlemeyi gözden geçirme


Pages/filmler/Edit. cshtml. cs dosyasındaki OnPostAsync yöntemini gözden geçirin:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Önceki kod, bir istemci filmi sildiği ve diğer istemci filmle değişiklik yaptığı zaman eşzamanlılık özel durumlarını
algılar.
catch bloğunu test etmek için:
catch (DbUpdateConcurrencyException) kesme noktası ayarlama
Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
Önceki tarayıcı penceresinde filmdeki değişiklikleri gönderin.
Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. eşzamanlılık çakışmalarını
işleme .
Gönderme ve bağlama incelemesi
Pages/filmler/Edit. cshtml. cs dosyasını inceleyin:
public class EditModel : PageModel
{
private readonly RazorPagesMovieContext _context;

public EditModel(RazorPagesMovieContext context)


{
_context = context;
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);

if (Movie == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Movie.Any(e => e.ID == Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}
}

Filmler/düzenleme sayfasına HTTP GET isteği yapıldığında (örneğin, http://localhost:5000/Movies/Edit/2 ):


OnGetAsync yöntemi, filmi veritabanından getirir ve Page yöntemini döndürür.
Page yöntemi, Pages/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası, film modelinin
sayfada kullanılabilir olmasını sağlayan model yönergesini ( @model RazorPagesMovie.Pages.Movies.EditModel )
içerir.
Düzenleme formu filmdeki değerlerle birlikte görüntülenir.
Filmler/Düzenle sayfası gönderildiğinde:
Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty] özniteliği model bağlamayımümkün.

[BindProperty]
public Movie Movie { get; set; }

Model durumunda hatalar varsa (örneğin, ReleaseDate bir tarihe dönüştürülemiyorsa), form gönderilen
değerlerle birlikte görüntülenir.
Model hatası yoksa, film kaydedilir.
Razor sayfalarında Dizin, oluşturma ve silme gibi HTTP GET yöntemleri benzer bir düzende yer alır. Razor Oluştur
sayfasındaki HTTP POST OnPostAsync yöntemi, Razor düzenleme sayfasındaki OnPostAsync yöntemine benzer bir
düzen izler.
Arama sonraki öğreticiye eklenir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: B IR V E R IT A B A N IY L A IL E R I: A R A M A
Ç A L IŞ M A EKLE
ASP.NET Core Razor Pages arama Ekle
6.12.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Aşağıdaki bölümlerde, film tarzya veya ada göre arama eklenir.
Aşağıdaki Vurgulanan özellikleri sayfalara/filmlere/Index. cshtml. csöğesine ekleyin:

public class IndexModel : PageModel


{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get; set; }


[BindProperty(SupportsGet = true)]
public string SearchString { get; set; }
// Requires using Microsoft.AspNetCore.Mvc.Rendering;
public SelectList Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string MovieGenre { get; set; }

SearchString : kullanıcıların arama metin kutusuna girebileceği metni içerir. SearchString [BindProperty]
özniteliği vardır. [BindProperty] form değerlerini ve Sorgu dizelerini özelliğiyle aynı ada bağlar. GET isteklerinde
bağlama için (SupportsGet = true) gereklidir.
Genres : tarzlar listesini içerir. Genres , kullanıcının listeden bir tarz seçmesine izin verir. SelectList
using Microsoft.AspNetCore.Mvc.Rendering; gerektiriyor
MovieGenre : kullanıcının seçtiği belirli tarzı içerir (örneğin, "Batı").
Genres ve MovieGenre daha sonra bu öğreticide kullanılır.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir. Özelliklerle
eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine veya rota değerlerine dayanan
senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true olarak ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Dizin sayfasının OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:


public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

Movie = await movies.ToListAsync();


}

OnGetAsync yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

// using System.Linq;
var movies = from m in _context.Movie
select m;

Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.


SearchString özelliği null veya boş değilse, filmler sorgusu arama dizesinde filtrelenecek şekilde değiştirilir:

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() kodu bir lambda ifadesidir. Lambdalar, Yöntem tabanlı LINQ sorgularında, Where
yöntemi veya Contains (önceki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız değişkenler
olarak kullanılır. LINQ sorguları tanımlandıklarında veya bir Yöntem (örneğin, Where , Contains veya OrderBy )
çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir ifadenin
değerlendirmesi, gerçekleştirilmiş değeri yinelenene veya ToListAsync yöntemi çağrılana kadar gecikir. Daha fazla
bilgi için bkz. sorgu yürütme .

NOTE
Contains yöntemi C# kodda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve
harmanlamaya bağlıdır. SQL Server, SQL Ile benzer, büyük/küçük harfe duyarsız Contains eşlenir. SQLite ' da, varsayılan
harmanlama ile büyük/küçük harfe duyarlıdır.

Filmler sayfasına gidin ve URL 'ye gibi bir sorgu dizesi ekleyin (örneğin,
?searchString=Ghost
https://localhost:5001/Movies?searchString=Ghost ). Filtrelenmiş filmler görüntülenir.
Aşağıdaki yol şablonu dizin sayfasına eklendiyse, arama dizesi bir URL segmenti olarak geçirilebilir (örneğin,
https://localhost:5001/Movies/Ghost ).

@page "{searchString?}"

Önceki yol kısıtlaması, başlığın sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak aranmasına olanak
tanır. "{searchString?}" ? , bu isteğe bağlı bir yol parametresi anlamına gelir.

ASP.NET Core çalışma zamanı, SearchString özelliğinin değerini sorgu dizesinden ( ?searchString=Ghost ) veya
rota verilerinden ( https://localhost:5001/Movies/Ghost ) ayarlamak için model bağlamayı kullanır. Model bağlama
büyük/küçük harfe duyarlı değildir.
Ancak, kullanıcıların bir filmi aramak için URL 'YI değiştirmesini beklemeniz gerekmez. Bu adımda, filmleri
filtrelemek için Kullanıcı arabirimi eklenir. "{searchString?}" yol kısıtlaması eklediyseniz, kaldırın.
Pages/filmler/Index. cshtml dosyasını açın ve aşağıdaki kodda vurgulanan <form> işaretlemesini ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

HTML <form> etiketi aşağıdaki Etiket Yardımcılarıkullanır:


Form etiketi Yardımcısı. Form gönderildiğinde, filtre dizesi, sorgu dizesi aracılığıyla Sayfalar/filmler/Dizin
sayfasına gönderilir.
Giriş Etiketi Yardımcısı
Değişiklikleri kaydedin ve filtreyi test edin.
Tarza göre ara
OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}

Aşağıdaki kod, veritabanından tüm tarzları alan bir LINQ sorgusudur.

// Use LINQ to get list of genres.


IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Tarzın SelectList , farklı tarzlar yansıtılayarak oluşturulur.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Türe göre, Razor sayfasına arama ekleme


Index. cshtml 'yi aşağıdaki şekilde güncelleştirin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: S A Y F A L A R I İL E R I: Y E N I B IR A L A N
G Ü N C E L L E Ş T IR M E EKLEM E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
Aşağıdaki bölümlerde, film tarzya veya ada göre arama eklenir.
Aşağıdaki Vurgulanan özellikleri sayfalara/filmlere/Index. cshtml. csöğesine ekleyin:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get; set; }


[BindProperty(SupportsGet = true)]
public string SearchString { get; set; }
// Requires using Microsoft.AspNetCore.Mvc.Rendering;
public SelectList Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string MovieGenre { get; set; }

SearchString : kullanıcıların arama metin kutusuna girebileceği metni içerir. SearchString [BindProperty]
özniteliği vardır. [BindProperty] form değerlerini ve Sorgu dizelerini özelliğiyle aynı ada bağlar. GET isteklerinde
bağlama için (SupportsGet = true) gereklidir.
Genres : tarzlar listesini içerir. Genres , kullanıcının listeden bir tarz seçmesine izin verir. SelectList
using Microsoft.AspNetCore.Mvc.Rendering; gerektiriyor
MovieGenre : kullanıcının seçtiği belirli tarzı içerir (örneğin, "Batı").
Genres ve MovieGenre daha sonra bu öğreticide kullanılır.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir. Özelliklerle
eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine veya rota değerlerine dayanan
senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true olarak ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Dizin sayfasının OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

Movie = await movies.ToListAsync();


}

OnGetAsync yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

// using System.Linq;
var movies = from m in _context.Movie
select m;
Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.
SearchString özelliği null veya boş değilse, filmler sorgusu arama dizesinde filtrelenecek şekilde değiştirilir:

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() kodu bir lambda ifadesidir. Lambdalar, Yöntem tabanlı LINQ sorgularında, Where
yöntemi veya Contains (önceki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız değişkenler
olarak kullanılır. LINQ sorguları tanımlandıklarında veya bir Yöntem (örneğin, Where , Contains veya OrderBy )
çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir ifadenin
değerlendirmesi, gerçekleştirilmiş değeri yinelenene veya ToListAsync yöntemi çağrılana kadar gecikir. Daha fazla
bilgi için bkz. sorgu yürütme .
Note: Contains yöntemi C# kodda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı
veritabanına ve harmanlamaya bağlıdır. SQL Server, SQL Ile benzer, büyük/küçük harfe duyarsız Contains eşlenir.
SQLite ' da, varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.
Filmler sayfasına gidin ve URL 'ye ?searchString=Ghost gibi bir sorgu dizesi ekleyin (örneğin,
https://localhost:5001/Movies?searchString=Ghost ). Filtrelenmiş filmler görüntülenir.

Aşağıdaki yol şablonu dizin sayfasına eklendiyse, arama dizesi bir URL segmenti olarak geçirilebilir (örneğin,
https://localhost:5001/Movies/Ghost ).

@page "{searchString?}"

Önceki yol kısıtlaması, başlığın sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak aranmasına olanak
tanır. "{searchString?}" ? , bu isteğe bağlı bir yol parametresi anlamına gelir.
ASP.NET Core çalışma zamanı, SearchString özelliğinin değerini sorgu dizesinden ( ?searchString=Ghost ) veya
rota verilerinden ( https://localhost:5001/Movies/Ghost ) ayarlamak için model bağlamayı kullanır. Model bağlama
büyük/küçük harfe duyarlı değildir.
Ancak, kullanıcıların bir filmi aramak için URL 'YI değiştirmesini beklemeniz gerekmez. Bu adımda, filmleri
filtrelemek için Kullanıcı arabirimi eklenir. "{searchString?}" yol kısıtlaması eklediyseniz, kaldırın.
Pages/filmler/Index. cshtml dosyasını açın ve aşağıdaki kodda vurgulanan <form> işaretlemesini ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

HTML <form> etiketi aşağıdaki Etiket Yardımcılarıkullanır:


Form etiketi Yardımcısı. Form gönderildiğinde, filtre dizesi, sorgu dizesi aracılığıyla Sayfalar/filmler/Dizin
sayfasına gönderilir.
Giriş Etiketi Yardımcısı
Değişiklikleri kaydedin ve filtreyi test edin.

Tarza göre ara


OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}

Aşağıdaki kod, veritabanından tüm tarzları alan bir LINQ sorgusudur.


// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

Tarzın SelectList , farklı tarzlar yansıtılayarak oluşturulur.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Türe göre, Razor sayfasına arama ekleme


Index. cshtml 'yi aşağıdaki şekilde güncelleştirin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin. Önceki kod, Select etiketi
yardımcısını ve seçenek etiketi yardımcısını kullanır.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: S A Y F A L A R I İL E R I: Y E N I B IR A L A N
G Ü N C E L L E Ş T IR M E EKLEM E
ASP.NET Core Razor sayfasına yeni bir alan ekleyin
23.11.2019 • 17 minutes to read • Edit Online

Tarafından Rick Anderson


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alan şeması değişikliğini veritabanına geçirin.
Bir veritabanını otomatik olarak oluşturmak için EF Code First kullanırken Code First:
Veritabanı şemasının oluşturulduğu model sınıflarıyla eşitlenmiş olup olmadığını izlemek için veritabanına bir
__EFMigrationsHistory tablosu ekler.
Model sınıfları DB ile eşitlenmiyorsa, EF bir özel durum oluşturur.
Şema/modelin eşitlemede otomatik olarak doğrulanması, tutarsız veritabanı/kod sorunlarını bulmayı kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleme


Modeller/film. cs dosyasını açın ve bir Rating özelliği ekleyin:

public class Movie


{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulamayı derleyin.
Sayfaları/filmleri/dizini. cshtml'yi düzenleyin ve bir Rating alanı ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Aşağıdaki sayfaları güncelleştirin:


Silme ve Ayrıntılar sayfalarına Rating alanını ekleyin.
Create. cshtml dosyasını bir Rating alanla güncelleştirin.
Düzenleme sayfasına Rating alanını ekleyin.
VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Veritabanını güncelleştirmeden
uygulamayı çalıştırmak bir SqlException oluşturur:
SqlException: Invalid column name 'Rating'.

SqlException özel durumu, güncelleştirilmiş film modeli sınıfının, veritabanının film tablosunun şemasından farklı
olmasından kaynaklanır. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Yeni model sınıfı şemasını kullanarak veritabanını otomatik olarak bırakıp yeniden oluşturmaya Entity
Framework. Bu yaklaşım, geliştirme döngüsünün başlarında daha erken bir yoldur; modeli ve veritabanı
şemasını birlikte hızla gelişmenize olanak tanır. Downsıde, veritabanında var olan verileri kaybetmeniz. Bu
yaklaşımı bir üretim veritabanında kullanmayın! DB 'yi şema değişikliklerinde bırakıp bir başlatıcı kullanarak
veritabanının test verileriyle otomatik olarak çekirdeğini oluşturmak, genellikle bir uygulama geliştirmeye
yönelik üretken bir yoldur.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın avantajı,
verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği oluşturarak
yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanın.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie bloğu için bu değişikliği yapmak isteyeceksiniz.

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M,
Rating = "R"
},

Tamamlanan SeedData.cs dosyasınabakın.


Çözümü oluşturun.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Derecelendirme alanı için bir geçiş ekleyin
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC'de aşağıdaki komutları
girin:

Add-Migration Rating
Update-Database

Add-Migration komutu, çerçeveye şunları belirtir:


Moviemodelini Movie DB şemasıyla karşılaştırın.
DB şemasını yeni modele geçirmek için kod oluşturun.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir ad
kullanılması yararlı olur.
Update-Database komutu, çerçeveye şema değişikliklerini uygulamaya ve var olan verileri korumanıza bildirir.
VERITABANıNDAKI tüm kayıtları silerseniz, başlatıcı DB 'yi temel alır ve Rating alanını içerir. Bunu, tarayıcıda veya
SQL Server Nesne Gezgini (ssox) silme bağlantılarıyla yapabilirsiniz.
Başka bir seçenek de veritabanını silmek ve geçişleri kullanarak veritabanını yeniden oluşturmaktır. SSOX 'te
veritabanını silmek için:
SSOX 'te veritabanını seçin.
Veritabanına sağ tıklayın ve Sil' i seçin.
Mevcut bağlantıları kapat' a bakın.
Seçin Tamam.
PMC'de veritabanını güncelleştirin:

Update-Database

Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi


doğrulayın. Veritabanı birlikte olmazsa, SeedData.Initialize yönteminde bir kesme noktası ayarlayın.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: ekleme S O N R A K I: D O Ğ R U L A M A
A RA M A EKLEM E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alan şeması değişikliğini veritabanına geçirin.
Bir veritabanını otomatik olarak oluşturmak için EF Code First kullanırken Code First:
Veritabanı şemasının oluşturulduğu model sınıflarıyla uyumlu olup olmadığını izlemek için veritabanına bir tablo
ekler.
Model sınıfları DB ile eşitlenmiyorsa, EF bir özel durum oluşturur.
Şema/modelin eşitlemede otomatik olarak doğrulanması, tutarsız veritabanı/kod sorunlarını bulmayı kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleme


Modeller/film. cs dosyasını açın ve bir Rating özelliği ekleyin:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulamayı derleyin.
Sayfaları/filmleri/dizini. cshtml'yi düzenleyin ve bir Rating alanı ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie)
{
<tr><td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Aşağıdaki sayfaları güncelleştirin:


Silme ve Ayrıntılar sayfalarına Rating alanını ekleyin.
Create. cshtml dosyasını bir Rating alanla güncelleştirin.
Düzenleme sayfasına Rating alanını ekleyin.

VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Şimdi çalıştırırsanız, uygulama
bir SqlException oluşturur:
SqlException: Invalid column name 'Rating'.

Bu hata, güncelleştirilmiş film modeli sınıfının, veritabanının film tablosunun şemasından farklı olmasından
kaynaklanır. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Yeni model sınıfı şemasını kullanarak veritabanını otomatik olarak bırakıp yeniden oluşturmaya Entity
Framework. Bu yaklaşım, geliştirme döngüsünün başlarında daha erken bir yoldur; modeli ve veritabanı
şemasını birlikte hızla gelişmenize olanak tanır. Downsıde, veritabanında var olan verileri kaybetmeniz. Bu
yaklaşımı bir üretim veritabanında kullanmayın! DB 'yi şema değişikliklerinde bırakıp bir başlatıcı kullanarak
veritabanının test verileriyle otomatik olarak çekirdeğini oluşturmak, genellikle bir uygulama geliştirmeye
yönelik üretken bir yoldur.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın avantajı,
verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği oluşturarak
yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanın.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie bloğu için bu değişikliği yapmak isteyeceksiniz.
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M,
Rating = "R"
},

Tamamlanan SeedData.cs dosyasınabakın.


Çözümü oluşturun.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Derecelendirme alanı için bir geçiş ekleyin
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC'de aşağıdaki komutları
girin:

Add-Migration Rating
Update-Database

Add-Migration komutu, çerçeveye şunları belirtir:


Moviemodelini Movie DB şemasıyla karşılaştırın.
DB şemasını yeni modele geçirmek için kod oluşturun.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir ad
kullanılması yararlı olur.
Update-Database komutu, çerçeveye şema değişikliklerini veritabanına uygulamasını söyler.
VERITABANıNDAKI tüm kayıtları silerseniz, başlatıcı DB 'yi temel alır ve Rating alanını içerir. Bunu, tarayıcıda veya
SQL Server Nesne Gezgini (ssox) silme bağlantılarıyla yapabilirsiniz.
Başka bir seçenek de veritabanını silmek ve geçişleri kullanarak veritabanını yeniden oluşturmaktır. SSOX 'te
veritabanını silmek için:
SSOX 'te veritabanını seçin.
Veritabanına sağ tıklayın ve Sil' i seçin.
Mevcut bağlantıları kapat' a bakın.
Seçin Tamam.
PMC'de veritabanını güncelleştirin:

Update-Database

Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi


doğrulayın. Veritabanı birlikte olmazsa, SeedData.Initialize yönteminde bir kesme noktası ayarlayın.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: ekleme S O N R A K I: D O Ğ R U L A M A
A RA M A EKLEM E
ASP.NET Core Razor sayfasına doğrulama ekleme
15.10.2019 • 15 minutes to read • Edit Online

Rick Anderson tarafından


Bu bölümde, Movie modeline doğrulama mantığı eklenir. Doğrulama kuralları, bir Kullanıcı bir filmi
oluşturduğunda veya düzenleişinizde zorlanır.

Doğrulama
Yazılım geliştirmeye yönelik temel bir temel kuru ("Don't Repeon Yourself") olarak adlandırılır. Razor Pages,
işlevselliği bir kez belirtildiğinde geliştirme ve uygulama genelinde yansıtılmıştır. Kuru şu şekilde yardımcı olabilir:
Uygulamadaki kod miktarını azaltın.
Kodu daha az hata haline getirin ve test ve bakım yapmayı kolaylaştırın.
Razor Pages ve Entity Framework tarafından sunulan doğrulama desteği, Kuru ilkesine iyi bir örnektir. Doğrulama
kuralları tek bir yerde (model sınıfında) bildirimli olarak belirtilir ve kurallar uygulamada her yerde zorlanır.

Film modeline doğrulama kuralları ekleme


Dataaçıklamalarda ad alanı, bir sınıfa veya özelliğe bildirimli olarak uygulanan bir yerleşik doğrulama öznitelikleri
kümesi sağlar. Veri açıklamaları, biçimlendirme ile yardım eden ve herhangi bir doğrulama sağlamayan DataType
gibi biçimlendirme öznitelikleri de içerir.
@No__t-0 sınıfını, yerleşik Required , StringLength , RegularExpression ve Range doğrulama özniteliklerinden
faydalanmak için güncelleştirin.

public class Movie


{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}
Doğrulama öznitelikleri, uygulanan model özellikleri üzerinde zorlamak istediğiniz davranışı belirtir:
@No__t-0 ve MinimumLength öznitelikleri bir özelliğin bir değere sahip olması gerektiğini belirtir; Ancak
hiçbir şey, kullanıcının bu doğrulamayı karşılamak için boşluk girmesini engeller.
@No__t-0 özniteliği, hangi karakterlerin girişi yapabileceğini sınırlamak için kullanılır. Yukarıdaki kodda,
"tarz":
Yalnızca harfler kullanılmalıdır.
İlk harfin büyük harfle olması gerekir. Boşluk, sayı ve özel karakterlere izin verilmez.
@No__t-0 "derecelendirmesi":
İlk karakterin büyük harf olmasını gerektirir.
Sonraki boşlukların içindeki özel karakter ve sayılara izin verir. "PG -13" bir derecelendirme için geçerlidir,
ancak bir "tarz" için başarısız olur.
@No__t-0 özniteliği, bir değeri belirtilen bir Aralık içinde kısıtlar.
@No__t-0 özniteliği, bir dize özelliğinin en büyük uzunluğunu ve isteğe bağlı olarak en düşük uzunluğunu
ayarlamanıza olanak sağlar.
Değer türleri (örneğin decimal , int , float , DateTime ), doğal olarak gereklidir ve [Required] özniteliğine
gerek kalmaz.
Doğrulama kurallarının otomatik olarak uygulanmasını ASP.NET Core uygulamanızın daha sağlam olmasına
yardımcı olur. Ayrıca, bir şeyi doğrulamayı unutmanızı ve veritabanına yanlışlıkla veri vermemesini de sağlar.
Razor Pages 'de doğrulama hatası Kullanıcı arabirimi
Uygulamayı çalıştırın ve sayfalar/Filmler ' e gidin.
Yeni oluştur bağlantısını seçin. Formu, bazı geçersiz değerlerle doldurun. JQuery istemci tarafı doğrulaması hatayı
algıladığında, bir hata iletisi görüntüler.
NOTE
Ondalık alanlara ondalık virgüller giremeyebilirsiniz. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih biçimleri için virgül (",")
kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı globalize için adımlar
uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .

Formun geçersiz bir değer içeren her alanda otomatik olarak bir doğrulama hata iletisi nasıl oluşturulduğuna dikkat
edin. Hatalar hem istemci tarafında (JavaScript ve jQuery kullanılarak) hem de sunucu tarafında (bir Kullanıcı
JavaScript devre dışı bırakıldığında) zorlanır.
Önemli bir avantaj, oluşturma veya düzenleme sayfalarında hiçbir kod değişikliği gerekli değildir. Veri ek
açıklamaları modele uygulandıktan sonra, doğrulama kullanıcı arabirimi etkinleştirilmiştir. Bu öğreticide oluşturulan
Razor Pages otomatik olarak doğrulama kurallarını ( Movie Model sınıfının özelliklerinde doğrulama özniteliklerini
kullanarak) otomatik olarak alır. Düzenleme sayfasını kullanarak doğrulama testi, aynı doğrulama uygulanır.
Form verileri, istemci tarafı doğrulama hatası kalmayana kadar sunucuya nakledilmez. Form verilerinin aşağıdaki
yaklaşımlardan bir veya daha fazlası tarafından nakledilmediğinden emin olun:
@No__t-0 yöntemine bir kesme noktası koyun. Formu gönder ( Oluştur veya Kaydet' i seçin). Kesme noktası
hiçbir şekilde isabet ettirilmez.
Fiddler aracınıkullanın.
Ağ trafiğini izlemek için tarayıcı Geliştirici Araçları ' nı kullanın.
Sunucu tarafı doğrulaması
Tarayıcıda JavaScript devre dışı bırakıldığında, formun hatalarla gönderilmesi sunucuya gönderilir.
İsteğe bağlı, test sunucusu-tarafı doğrulaması:
Tarayıcıda JavaScript 'ı devre dışı bırakın. Tarayıcının geliştirici araçlarını kullanarak JavaScript 'ı devre dışı
bırakabilirsiniz. Tarayıcıda JavaScript 'ı devre dışı bırakadıysanız başka bir tarayıcı deneyin.
Oluşturma veya düzenleme sayfasının OnPostAsync yönteminde bir kesme noktası ayarlayın.
Geçersiz verilerle form gönderme.
Model durumunun geçersiz olduğunu doğrulayın:

if (!ModelState.IsValid)
{
return Page();
}

Aşağıdaki kod, öğreticide daha önce Create. cshtml sayfa scafkatın bir bölümünü gösterir. İlk formu görüntülemek
ve bir hata durumunda formu yeniden görüntülemek için sayfa oluşturma ve düzenleme sayfaları tarafından
kullanılır.

<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Giriş etiketi Yardımcısı , dataaçıklamaların özniteliklerini kullanır ve istemci tarafında jQuery doğrulaması için
gerekli HTML özniteliklerini üretir. Doğrulama etiketi Yardımcısı doğrulama hatalarını görüntüler. Daha fazla bilgi
için bkz. doğrulama .
Oluşturma ve düzenleme sayfalarında hiçbir doğrulama kuralı yoktur. Doğrulama kuralları ve hata dizeleri yalnızca
Movie sınıfında belirtilmiştir. Bu doğrulama kuralları, Movie modelini düzenleyebilen Razor Pages otomatik olarak
uygulanır.
Doğrulama mantığının değişmesi gerektiğinde, yalnızca modelde yapılır. Doğrulama, uygulamanın tamamında
tutarlı bir şekilde uygulanır (doğrulama mantığı tek bir yerde tanımlanır). Tek bir yerde doğrulama, kodun temiz
kalmasına yardımcı olur ve bakım ve güncelleştirme işlemlerini kolaylaştırır.

DataType özniteliklerini kullanma


@No__t-0 sınıfını inceleyin. @No__t-0 ad alanı, yerleşik doğrulama öznitelikleri kümesine ek olarak biçimlendirme
öznitelikleri sağlar. @No__t-0 özniteliği ReleaseDate ve Price özelliklerine uygulanır.

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
@No__t-0 öznitelikleri yalnızca görünüm altyapısının verileri biçimlendirmek için ipuçları sağlar (ve URL için <a>
ve e-posta için <a href="mailto:EmailAddress.com"> gibi öznitelikleri sağlar). Verilerin biçimini doğrulamak için
RegularExpression özniteliğini kullanın. @No__t-0 özniteliği, veritabanı iç türünden daha belirgin bir veri türü
belirtmek için kullanılır. DataType öznitelikleri doğrulama öznitelikleri değildir. Örnek uygulamada, yalnızca tarih ve
saat olmadan görüntülenir.
@No__t-0 numaralandırması, tarih, saat, PhoneNumber, para birimi, Emaadresi ve daha fazlası gibi birçok veri türü
sağlar. @No__t-0 özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak sağlamasını da sağlayabilir.
Örneğin, DataType.EmailAddress için mailto: bağlantısı oluşturulabilir. HTML5 'i destekleyen tarayıcılarda
DataType.Date için bir tarih seçici sağlanmış olabilir. @No__t-0 öznitelikleri HTML 5 tarayıcıların kullandığı HTML 5
data- (veri Dash) özniteliklerini yayar. @No__t-0 öznitelikleri herhangi bir doğrulama sağlamaz.

DataType.Date , görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, veri alanı, sunucunun CultureInfo 'a
göre varsayılan biçimlere göre görüntülenir.
@No__t-0 veri ek açıklaması gereklidir, bu nedenle Entity Framework Core veritabanındaki para birimine Price 'i
doğru şekilde eşleyebilir. Daha fazla bilgi için bkz. veri türleri.
@No__t-0 özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]


public DateTime ReleaseDate { get; set; }

@No__t-0 ayarı, değer düzenlenmek üzere görüntülendiğinde biçimlendirmenin uygulanacağını belirtir. Bazı alanlar
için bu davranışı istemiyor olabilirsiniz. Örneğin, para birimi değerlerinde, büyük olasılıkla düzenleme kullanıcı
arabirimindeki para birimi sembolünü istemezsiniz.
@No__t-0 özniteliği kendisi tarafından kullanılabilir, ancak genellikle DataType özniteliğini kullanmak iyi bir fikir
olabilir. @No__t-0 özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini değil ve DisplayFormat ile elde
olmadığınız avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını vb. göstermek için)
Varsayılan olarak tarayıcı, verileri yerel ayarınızı temel alarak doğru biçimi kullanarak işleyebilir.
@No__t-0 özniteliği, ASP.NET Core çerçevesinin verileri işlemek için doğru alan şablonunu seçmesini
sağlayabilir. Kendisi tarafından kullanılıyorsa DisplayFormat , dize şablonunu kullanır.

Note: jQuery doğrulaması Range özniteliğiyle ve DateTime ile çalışmaz. Örneğin, aşağıdaki kod, tarih belirtilen
aralıkta olduğunda bile her zaman bir istemci tarafı doğrulama hatası görüntüler:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Modellerinizde sabit tarihleri derlemek genellikle iyi bir uygulamadır, bu nedenle Range özniteliği ve DateTime
kullanılması önerilmez.
Aşağıdaki kod, öznitelikleri tek bir satırda birleştirmeyi gösterir:
public class Movie
{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


public string Title { get; set; }

[Display(Name = "Release Date"), DataType(DataType.Date)]


public DateTime ReleaseDate { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$"), Required, StringLength(30)]


public string Genre { get; set; }

[Range(1, 100), DataType(DataType.Currency)]


[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; }
}

Razor Pages kullanmaya başlayın ve EF Core gelişmiş EF Core işlemlerini Razor Pages gösterir.
Geçişleri Uygula
Sınıfa uygulanan Dataek açıklamaları şemayı değiştirir. Örneğin, Title alanına uygulanan veri ek açıklamaları:

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

Karakterleri 60 olarak sınırlandırır.


@No__t-0 değerine izin vermez.
Visual Studio
Visual Studio Code/Mac için Visual Studio
@No__t-0 tablosu şu anda aşağıdaki şemaya sahiptir:

CREATE TABLE [dbo].[Movie] (


[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (MAX) NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (MAX) NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Önceki şema değişiklikleri, EF 'in özel durum oluşturmasına neden olmaz. Ancak, şemanın modelle tutarlı olması
için bir geçiş oluşturun.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC 'de aşağıdaki komutları
girin:

Add-Migration New_DataAnnotations
Update-Database

Update-Database New_DataAnnotations sınıfının Up yöntemlerini çalıştırır. @No__t-0 yöntemini inceleyin:


public partial class New_DataAnnotations : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Movie",
maxLength: 60,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);

migrationBuilder.AlterColumn<string>(
name: "Rating",
table: "Movie",
maxLength: 5,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);

migrationBuilder.AlterColumn<string>(
name: "Genre",
table: "Movie",
maxLength: 30,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);
}

Güncelleştirilmiş Movie tablosu aşağıdaki şemaya sahiptir:

CREATE TABLE [dbo].[Movie] (


[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (60) NOT NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (30) NOT NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (5) NOT NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure'a Yayımlama
Azure 'a dağıtma hakkında bilgi için bkz. öğretici: Azure 'DA SQL veritabanı ile ASP.NET Core uygulama oluşturma.
Razor Pages için bu giriş tamamlanırken teşekkürler. Razor Pages kullanmaya başlayın ve Bu öğreticiye en uygun
harika bir izleme EF Core.

Ek kaynaklar
ASP.NET Core formlardaki etiket yardımcıları
ASP.NET Core Genelleştirme ve yerelleştirme
ASP.NET Core etiket yardımcıları
ASP.NET core'da Yazar etiket Yardımcıları
Bu öğreticinin YouTube sürümü

Ö N C E K I: Y E N I B IR A L A N
EKLEM E
ASP.NET Core MVC ile bir web uygulaması oluşturma
10.05.2019 • 2 minutes to read • Edit Online

Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay bir
başlangıç noktası sağlar.
Öğretici serisinin aşağıdakileri içerir:
1. Kullanmaya başlama
2. Denetleyici ekleme
3. Görünüm ekleme
4. Model ekleme
5. SQL Server LocalDB ile çalışma
6. Denetleyici metotları ve görünümleri
7. Arama ekleme
8. Yeni alan ekleme
9. Doğrulama ekleme
10. Details ve Delete metotlarını inceleme
ASP.NET Core MVC ile çalışmaya başlama
7.11.2019 • 20 minutes to read • Edit Online

Rick Anderson tarafından


Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay bir
başlangıç noktası sağlar.
Bu öğretici, ASP.NET Core MVC web uygulaması oluşturma hakkında temel bilgileri öğretir.
Uygulama, bir film başlıkları veritabanını yönetir. Aşağıdakilerin nasıl yapıldığını öğreneceksiniz:
Bir Web uygulaması oluşturun.
Bir modeli ekleyin ve yapı iskelesi yapın.
Bir veritabanıyla çalışın.
Arama ve doğrulama ekleyin.
Sonunda, film verilerini yönetebilen ve görüntüleyebilen bir uygulamanız vardır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini).

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'da Yeni proje oluştur' u seçin.
ASP.NET Core Web uygulaması ' nı seçin ve ardından İleri' yi seçin.
Projeyi Mvcfilmi olarak adlandırın ve Oluştur' u seçin. Kodu kopyaladığınızda, ad alanının eşleşmesi için,
projeyi Mvcfilmi olarak adlandırmak önemlidir.

Web uygulaması (Model-View-Controller) öğesini seçin ve ardından Oluştur' u seçin.


Visual Studio, az önce oluşturduğunuz MVC projesi için varsayılan şablonu kullandı. Şimdi bir proje adı girip birkaç
seçenek belirleyerek, çalışan bir uygulamanız var. Bu, temel bir başlatıcı projem.
Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamasız modda çalıştırmak için CTRL -F5 ' i seçin.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve example.com
gibi bir şey gösterilmediğine dikkat edin. Bunun nedeni, localhost yerel bilgisayarınız için Standart ana
bilgisayar adıdır. Visual Studio bir Web projesi oluşturduğunda, Web sunucusu için rastgele bir bağlantı
noktası kullanılır.
Uygulamayı CTRL + F5 (hata ayıklama modu) ile başlatmak, kod değişiklikleri yapmanıza, dosyayı
kaydetmenize, tarayıcıyı yenilemanıza ve kod değişikliklerini görmenize olanak tanır. Birçok geliştirici,
uygulamayı hızlı bir şekilde başlatmak ve değişiklikleri görüntülemek için hata ayıklama olmayan modu
kullanmayı tercih eder.
Hata ayıklama menü öğesinden uygulamayı hata ayıklama veya hata ayıklama olmayan modda
başlatabilirsiniz:

IIS Express düğmesini seçerek uygulamada hata ayıklaması yapabilirsiniz


Aşağıdaki görüntüde uygulama gösterilmektedir:

Visual Studio
Visual Studio Code
Mac için Visual Studio

Visual Studio Yardım


Hata ayıklamayı öğrenin C# kullanarak Visual Studio code
Visual Studio IDE'yi giriş
Bu öğreticinin bir sonraki bölümünde, MVC hakkında bilgi edinirsiniz ve kod yazmaya başlayabilirsiniz.

NEXT

Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay bir
başlangıç noktası sağlar.
Bu öğretici, ASP.NET Core MVC web uygulaması oluşturma hakkında temel bilgileri öğretir.
Uygulama, bir film başlıkları veritabanını yönetir. Aşağıdakilerin nasıl yapıldığını öğreneceksiniz:
Bir Web uygulaması oluşturun.
Bir modeli ekleyin ve yapı iskelesi yapın.
Bir veritabanıyla çalışın.
Arama ve doğrulama ekleyin.
Sonunda, film verilerini yönetebilen ve görüntüleyebilen bir uygulamanız vardır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini).

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'da Yeni proje oluştur' u seçin.
ASP.NET Core Web uygulaması ' nı seçin ve ardından İleri' yi seçin.
Projeyi Mvcfilmi olarak adlandırın ve Oluştur' u seçin. Kodu kopyaladığınızda, ad alanının eşleşmesi için,
projeyi Mvcfilmi olarak adlandırmak önemlidir.

Web uygulaması (Model-View-Controller) öğesini seçin ve ardından Oluştur' u seçin.


Visual Studio, az önce oluşturduğunuz MVC projesi için varsayılan şablonu kullandı. Şimdi bir proje adı girip birkaç
seçenek belirleyerek, çalışan bir uygulamanız var. Bu, temel bir başlatıcı projem ve başlamak için iyi bir yerdir.
Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamasız modda çalıştırmak için CTRL -F5 ' i seçin.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve example.com
gibi bir şey gösterilmediğine dikkat edin. Bunun nedeni, localhost yerel bilgisayarınız için Standart ana
bilgisayar adıdır. Visual Studio bir Web projesi oluşturduğunda, Web sunucusu için rastgele bir bağlantı
noktası kullanılır.
Uygulamayı CTRL + F5 (hata ayıklama modu) ile başlatmak, kod değişiklikleri yapmanıza, dosyayı
kaydetmenize, tarayıcıyı yenilemanıza ve kod değişikliklerini görmenize olanak tanır. Birçok geliştirici,
uygulamayı hızlı bir şekilde başlatmak ve değişiklikleri görüntülemek için hata ayıklama olmayan modu
kullanmayı tercih eder.
Hata ayıklama menü öğesinden uygulamayı hata ayıklama veya hata ayıklama olmayan modda
başlatabilirsiniz:

IIS Express düğmesini seçerek uygulamada hata ayıklaması yapabilirsiniz


İzlemeye izin vermek için kabul et ' i seçin. Bu uygulama kişisel bilgileri izlemez. Şablon tarafından
oluşturulan kod, genel veri koruma yönetmeliği (GDPR )buluşmanıza yardımcı olan varlıkları içerir.

Aşağıdaki görüntüde izlemeyi kabul ettikten sonra uygulama gösterilmektedir:


Visual Studio
Visual Studio Code
Mac için Visual Studio

Visual Studio Yardım


Hata ayıklamayı öğrenin C# kullanarak Visual Studio code
Visual Studio IDE'yi giriş
Bu öğreticinin bir sonraki bölümünde, MVC hakkında bilgi edinirsiniz ve kod yazmaya başlayabilirsiniz.

NEXT
ASP.NET Core MVC uygulamasına denetleyici ekleme
7.08.2019 • 21 minutes to read • Edit Online

Tarafından Rick Anderson


Model-View -Controller (MVC ) mimari modeli, bir uygulamayı üç ana bileşene ayırır: Model, VIEW ve Controller.
MVC deseninin daha kararlı ve geleneksel tek parçalı uygulamalardan güncelleştirilmesi daha kolay olan
uygulamalar oluşturmanıza yardımcı olur. MVC tabanlı uygulamalar şunları içerir:
Aodels: Uygulamanın verilerini temsil eden sınıflar. Model sınıfları, bu veriler için iş kurallarını zorlamak
üzere doğrulama mantığını kullanır. Genellikle, model nesneleri bir veritabanında model durumunu alır ve
saklar. Bu öğreticide, bir Movie model bir veritabanından film verileri alır, bunu görünüme sağlar veya
güncelleştirir. Güncelleştirilmiş veriler bir veritabanına yazılır.
Vıews: Görünümler, uygulamanın kullanıcı arabirimini (UI) görüntüleyen bileşenlerdir. Genellikle, bu
kullanıcı arabirimi model verilerini görüntüler.
Controlleyiciler: Tarayıcı isteklerini işleyen sınıflar. Model verileri alır ve yanıt döndüren çağrı görünümü
şablonları. MVC uygulamasında, görünüm yalnızca bilgileri görüntüler; denetleyici, Kullanıcı girişini ve
etkileşimini işler ve yanıtlar. Örneğin, denetleyici rota verilerini ve sorgu dizesi değerlerini işler ve bu
değerleri modele geçirir. Model bu değerleri veritabanını sorgulamak için kullanabilir. Örneğin,
https://localhost:5001/Home/Privacy Home (denetleyici) ve Privacy (ana denetleyicide çağrılacak eylem
yöntemi) verilerinin yolunu içerir. https://localhost:5001/Movies/Edit/5 filmi film denetleyicisi kullanarak, ID
= 5 olan filmi düzenleme isteği. Rota verileri öğreticide daha sonra açıklanmaktadır.
MVC deseninin uygulamanın farklı yönlerini (Giriş mantığı, iş mantığı ve Kullanıcı arabirimi mantığı) ayıran
uygulamalar oluşturmanıza yardımcı olur. bu öğeler arasında gevşek bir bağ sağlanır. Bu model, her bir mantık
türünün uygulamada nerede bulunması gerektiğini belirtir. Kullanıcı arabirimi mantığı görünüme aittir. Giriş
mantığı denetleyiciye aittir. İş mantığı modele aittir. Bu ayrım, bir uygulama oluşturduğunuzda karmaşıklığın
yönetilmesine yardımcı olur, çünkü uygulamanın bir tek tarafında, başka bir kodu etkilemeden bir kez çalışmanıza
olanak sağlar. Örneğin, iş mantığı koduna bağlı kalmadan görünüm kodu üzerinde çalışabilirsiniz.
Bu kavramları, bu öğretici serisinde ele alınmaktadır ve bir film uygulaması oluşturmak için nasıl kullanacağınızı
gösterir. MVC projesi denetleyiciler ve Görünümleriçin klasörler içerir.

Denetleyici ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler öğesine sağ tıklayın > > denetleyicisi
Yapı Iskelesi Ekle iletişim kutusunda, MVC denetleyicisi-boş seçeneğini belirleyin

Boş MVC denetleyicisi Ekle iletişim kutusunda, Merhaba worldcontroller yazın ve Ekle' yi seçin.
Controllers/HelloWorldController. cs içeriğini aşağıdakiler ile değiştirin:
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/

public string Index()


{
return "This is my default action...";
}

//
// GET: /HelloWorld/Welcome/

public string Welcome()


{
return "This is the Welcome action method...";
}
}
}

Bir public denetleyicideki her yöntem bir HTTP uç noktası olarak çağrılabilir. Yukarıdaki örnekte her iki yöntem de
bir dize döndürür. Her yöntemden önceki açıklamalara göz önüne alın.
HTTP uç noktası, https://localhost:5001/HelloWorld gibi Web uygulamasındaki bir hedeflenebilir URL 'sidir ve
HTTPS kullanılan protokolü, Web sunucusunun ağ konumunu ( TCP bağlantı noktası dahil): localhost:5001 ve hedef
URI HelloWorld 'yi birleştirir.
İlk açıklama bu, temel URL 'ye eklenerek /HelloWorld/ çağrılan bir http get yöntemi olduğunu belirtir. İkinci
açıklama URL 'ye eklenerek /HelloWorld/Welcome/ çağrılan bir http get yöntemini belirtir. Öğreticide daha sonra,
verileri güncelleştiren Yöntemler oluşturmak HTTP POST için scafkatlama altyapısı kullanılır.
Uygulamayı hata ayıklama modunda çalıştırın ve adres çubuğundaki yola "HelloWorld" ekleyin. Index Yöntemi bir
dize döndürür.
MVC, gelen URL 'ye bağlı olarak denetleyici sınıflarını (ve içindeki eylem yöntemlerini) çağırır. MVC tarafından
kullanılan varsayılan URL yönlendirme mantığı , çağrılacak kodu belirlemek için şöyle bir biçim kullanır:
/[Controller]/[ActionName]/[Parameters]

Yönlendirme biçimi Configure Startup.cs dosyasındaki yönteminde ayarlanır.

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

Uygulamaya gözatıp hiçbir URL kesimini sağlamadığınızda, varsayılan olarak "giriş" denetleyicisi ve yukarıda
vurgulanan şablon satırında belirtilen "Dizin" yöntemi varsayılan olarak belirtilir.
İlk URL segmenti, çalıştırılacak denetleyici sınıfını belirler. Bu localhost:{PORT}/HelloWorld nedenle
HelloWorldController sınıfıyla eşlenir. URL segmentinin ikinci bölümü, sınıfındaki Action metodunu belirler. Bu
localhost:{PORT}/HelloWorld/Index nedenle, HelloWorldController sınıfın Index yönteminin çalışmasına neden
olur. Yalnızca göz atmanızı localhost:{PORT}/HelloWorld Index ve yönteme varsayılan olarak çağrıldığına dikkat
edin. Bunun nedeni Index , açıkça bir yöntem adı belirtilmemişse bir denetleyicide çağrılacak varsayılan yöntemdir.
URL segmentinin ( id ) üçüncü bölümü rota verileri içindir. Rota verileri öğreticide daha sonra açıklanmaktadır.
konumuna gözatın . Yöntemi çalışır ve dizeyi
https://localhost:{PORT}/HelloWorld/Welcome
This is the Welcome action method... döndürür. Welcome Bu URL için denetleyici HelloWorld , ve Welcome eylem
yöntemidir. URL 'nin bir [Parameters] bölümünü henüz kullanmadınız.

URL 'den denetleyiciye bazı parametre bilgilerini geçirmek için kodu değiştirin. Örneğin:
/HelloWorld/Welcome?name=Rick&numtimes=4 . Welcome Yöntemi aşağıdaki kodda gösterildiği gibi iki parametre
içerecek şekilde değiştirin.
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is: {numTimes}");
}

Yukarıdaki kod:
Parametresi için C# hiçbir değer geçirilmemişse, numTimes parametrenin varsayılan olarak 1 ' e ait olduğunu
belirtmek için isteğe bağlı parametre özelliğini kullanır.
Uygulamayı HtmlEncoder.Default.Encode kötü amaçlı girişten korumak için kullanır (yani JavaScript).
Içinde $"Hello {name}, NumTimes is: {numTimes}" enterpolasyonlu dizeler kullanır.

Uygulamayı çalıştırın ve şu konuma gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

(Bağlantı {PORT} noktası numaranız ile değiştirin.) URL 'de ve name numtimes için farklı değerler deneyebilirsiniz.
MVC model bağlama sistemi, adlandırılmış parametreleri adres çubuğundaki sorgu dizesinden yöntemdeki
parametrelere otomatik olarak eşler. Daha fazla bilgi için bkz. model bağlama .

Yukarıdaki görüntüde, Parameters URL segmenti () kullanılmaz name , ve numTimes parametreleri sorgu
dizeleriolarak geçirilir. Yukarıdaki URL 'deki (soru işareti) bir ayırıcı ve sorgu dizeleri izler. ? & Karakter Sorgu
dizelerini ayırır.
Welcome Yöntemini aşağıdaki kodla değiştirin:

public string Welcome(string name, int ID = 1)


{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}

Uygulamayı çalıştırın ve aşağıdaki URL 'YI girin: https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick


Bu kez, üçüncü URL segmenti rota parametresiyle id eşleşti. Yöntemi, MapControllerRoute yöntemindeki URL
şablonuyla id eşleşen bir parametre içerir. Welcome Sondaki ? (içinde id? ) id parametresinin isteğe bağlı
olduğunu gösterir.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

Bu örneklerde, denetleyici MVC 'nin "VC" bölümünü (yani, VIEW ve C ) çalışır. Denetleyici HTML 'i doğrudan
döndürüyor. Genellikle, bu, kod ve bakım için çok daha fazla hale geldiği için denetleyicilerin doğrudan HTML
döndürmesini istemezsiniz. Bunun yerine, genellikle HTML yanıtı oluşturmak için ayrı bir Razor görünümü şablon
dosyası kullanırsınız. Bunu bir sonraki öğreticide yapabilirsiniz.

ÖN CEKI İleri

Model-View -Controller (MVC ) mimari modeli, bir uygulamayı üç ana bileşene ayırır: Model, VIEW ve Controller.
MVC deseninin daha kararlı ve geleneksel tek parçalı uygulamalardan güncelleştirilmesi daha kolay olan
uygulamalar oluşturmanıza yardımcı olur. MVC tabanlı uygulamalar şunları içerir:
Aodels: Uygulamanın verilerini temsil eden sınıflar. Model sınıfları, bu veriler için iş kurallarını zorlamak
üzere doğrulama mantığını kullanır. Genellikle, model nesneleri bir veritabanında model durumunu alır ve
saklar. Bu öğreticide, bir Movie model bir veritabanından film verileri alır, bunu görünüme sağlar veya
güncelleştirir. Güncelleştirilmiş veriler bir veritabanına yazılır.
Vıews: Görünümler, uygulamanın kullanıcı arabirimini (UI) görüntüleyen bileşenlerdir. Genellikle, bu
kullanıcı arabirimi model verilerini görüntüler.
Controlleyiciler: Tarayıcı isteklerini işleyen sınıflar. Model verileri alır ve yanıt döndüren çağrı görünümü
şablonları. MVC uygulamasında, görünüm yalnızca bilgileri görüntüler; denetleyici, Kullanıcı girişini ve
etkileşimini işler ve yanıtlar. Örneğin, denetleyici rota verilerini ve sorgu dizesi değerlerini işler ve bu
değerleri modele geçirir. Model bu değerleri veritabanını sorgulamak için kullanabilir. Örneğin,
https://localhost:5001/Home/About Home (denetleyici) ve About (ana denetleyicide çağrılacak eylem
yöntemi) verilerinin yolunu içerir. https://localhost:5001/Movies/Edit/5 filmi film denetleyicisi kullanarak, ID
= 5 olan filmi düzenleme isteği. Rota verileri öğreticide daha sonra açıklanmaktadır.
MVC deseninin uygulamanın farklı yönlerini (Giriş mantığı, iş mantığı ve Kullanıcı arabirimi mantığı) ayıran
uygulamalar oluşturmanıza yardımcı olur. bu öğeler arasında gevşek bir bağ sağlanır. Bu model, her bir mantık
türünün uygulamada nerede bulunması gerektiğini belirtir. Kullanıcı arabirimi mantığı görünüme aittir. Giriş
mantığı denetleyiciye aittir. İş mantığı modele aittir. Bu ayrım, bir uygulama oluşturduğunuzda karmaşıklığın
yönetilmesine yardımcı olur, çünkü uygulamanın bir tek tarafında, başka bir kodu etkilemeden bir kez çalışmanıza
olanak sağlar. Örneğin, iş mantığı koduna bağlı kalmadan görünüm kodu üzerinde çalışabilirsiniz.
Bu kavramları, bu öğretici serisinde ele alınmaktadır ve bir film uygulaması oluşturmak için nasıl kullanacağınızı
gösterir. MVC projesi denetleyiciler ve Görünümleriçin klasörler içerir.

Denetleyici ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler öğesine sağ tıklayın > > denetleyicisi
Yapı Iskelesi Ekle iletişim kutusunda, MVC denetleyicisi-boş seçeneğini belirleyin

Boş MVC denetleyicisi Ekle iletişim kutusunda, Merhaba worldcontroller yazın ve Ekle' yi seçin.
Controllers/HelloWorldController. cs içeriğini aşağıdakiler ile değiştirin:
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/

public string Index()


{
return "This is my default action...";
}

//
// GET: /HelloWorld/Welcome/

public string Welcome()


{
return "This is the Welcome action method...";
}
}
}

Bir public denetleyicideki her yöntem bir HTTP uç noktası olarak çağrılabilir. Yukarıdaki örnekte her iki yöntem de
bir dize döndürür. Her yöntemden önceki açıklamalara göz önüne alın.
HTTP uç noktası, https://localhost:5001/HelloWorld gibi Web uygulamasındaki bir hedeflenebilir URL 'sidir ve
HTTPS kullanılan protokolü, Web sunucusunun ağ konumunu ( TCP bağlantı noktası dahil): localhost:5001 ve hedef
URI HelloWorld 'yi birleştirir.
İlk açıklama bu, temel URL 'ye eklenerek /HelloWorld/ çağrılan bir http get yöntemi olduğunu belirtir. İkinci
açıklama URL 'ye eklenerek /HelloWorld/Welcome/ çağrılan bir http get yöntemini belirtir. Öğreticide daha sonra,
verileri güncelleştiren Yöntemler oluşturmak HTTP POST için scafkatlama altyapısı kullanılır.
Uygulamayı hata ayıklama modunda çalıştırın ve adres çubuğundaki yola "HelloWorld" ekleyin. Index Yöntemi bir
dize döndürür.
MVC, gelen URL 'ye bağlı olarak denetleyici sınıflarını (ve içindeki eylem yöntemlerini) çağırır. MVC tarafından
kullanılan varsayılan URL yönlendirme mantığı , çağrılacak kodu belirlemek için şöyle bir biçim kullanır:
/[Controller]/[ActionName]/[Parameters]

Yönlendirme biçimi Configure Startup.cs dosyasındaki yönteminde ayarlanır.

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Uygulamaya gözatıp hiçbir URL kesimini sağlamadığınızda, varsayılan olarak "giriş" denetleyicisi ve yukarıda
vurgulanan şablon satırında belirtilen "Dizin" yöntemi varsayılan olarak belirtilir.
İlk URL segmenti, çalıştırılacak denetleyici sınıfını belirler. Bu localhost:{PORT}/HelloWorld nedenle,
HelloWorldController sınıfıyla eşlenir. URL segmentinin ikinci bölümü, sınıfındaki Action metodunu belirler. Bu
localhost:{PORT}/HelloWorld/Index nedenle, HelloWorldController sınıfın Index yönteminin çalışmasına neden
olur. Yalnızca göz atmanızı localhost:{PORT}/HelloWorld Index ve yönteme varsayılan olarak çağrıldığına dikkat
edin. Bunun nedeni Index , açıkça bir yöntem adı belirtilmemişse bir denetleyicide çağrılacak varsayılan yöntemdir.
URL segmentinin ( id ) üçüncü bölümü rota verileri içindir. Rota verileri öğreticide daha sonra açıklanmaktadır.
konumuna gözatın . Yöntemi çalışır ve dizeyi
https://localhost:{PORT}/HelloWorld/Welcome
This is the Welcome action method... döndürür. Welcome Bu URL için denetleyici HelloWorld , ve Welcome eylem
yöntemidir. URL 'nin bir [Parameters] bölümünü henüz kullanmadınız.

URL 'den denetleyiciye bazı parametre bilgilerini geçirmek için kodu değiştirin. Örneğin:
/HelloWorld/Welcome?name=Rick&numtimes=4 . Welcome Yöntemi aşağıdaki kodda gösterildiği gibi iki parametre
içerecek şekilde değiştirin.
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is: {numTimes}");
}

Yukarıdaki kod:
Parametresi için C# hiçbir değer geçirilmemişse, numTimes parametrenin varsayılan olarak 1 ' e ait olduğunu
belirtmek için isteğe bağlı parametre özelliğini kullanır.
Uygulamayı HtmlEncoder.Default.Encode kötü amaçlı girişten korumak için kullanır (yani JavaScript).
Içinde $"Hello {name}, NumTimes is: {numTimes}" enterpolasyonlu dizeler kullanır.

Uygulamayı çalıştırın ve şu konuma gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

(Bağlantı {PORT} noktası numaranız ile değiştirin.) URL 'de ve name numtimes için farklı değerler deneyebilirsiniz.
MVC model bağlama sistemi, adlandırılmış parametreleri adres çubuğundaki sorgu dizesinden yöntemdeki
parametrelere otomatik olarak eşler. Daha fazla bilgi için bkz. model bağlama .

Yukarıdaki görüntüde, Parameters URL segmenti () kullanılmaz name , ve numTimes parametreleri sorgu
dizeleriolarak geçirilir. Yukarıdaki URL 'deki (soru işareti) bir ayırıcı ve sorgu dizeleri izler. ? & Karakter Sorgu
dizelerini ayırır.
Welcome Yöntemini aşağıdaki kodla değiştirin:

public string Welcome(string name, int ID = 1)


{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}

Uygulamayı çalıştırın ve aşağıdaki URL 'YI girin: https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick


Bu kez, üçüncü URL segmenti rota parametresiyle id eşleşti. Yöntemi, MapRoute yöntemindeki URL şablonuyla
id eşleşen bir parametre içerir. Welcome Sondaki ? (içinde id? ) id parametresinin isteğe bağlı olduğunu
gösterir.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Bu örneklerde, denetleyici MVC 'nin "VC" bölümünü (yani, görünüm ve denetleyici çalışır) yapıyor. Denetleyici
HTML 'i doğrudan döndürüyor. Genellikle, bu, kod ve bakım için çok daha fazla hale geldiği için denetleyicilerin
doğrudan HTML döndürmesini istemezsiniz. Bunun yerine, genellikle HTML yanıtı oluşturmaya yardımcı olması
için ayrı bir Razor görünümü şablon dosyası kullanırsınız. Bunu bir sonraki öğreticide yapabilirsiniz.

ÖN CEKI İleri
ASP.NET Core MVC uygulamasına görünüm ekleme
23.11.2019 • 26 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, bir istemciye HTML yanıtları oluşturma işlemini düzgün bir şekilde kapsüllemek için
HelloWorldController sınıfını Razor görünümü dosyalarını kullanacak şekilde değiştirirsiniz.

Razor kullanarak bir görünüm şablonu dosyası oluşturursunuz. Razor tabanlı görünüm şablonlarının . cshtml dosya
uzantısı vardır. Bu kişiler ile C#HTML çıktısı oluşturmanın zarif bir yolunu sağlarlar.
Şu anda Indexyöntemi, denetleyici sınıfında sabit kodlanmış bir ileti içeren bir dize döndürür.
HelloWorldController sınıfında, Index yöntemini aşağıdaki kodla değiştirin:

public IActionResult Index()


{
return View();
}

Yukarıdaki kod denetleyicinin View yöntemini çağırır. HTML yanıtı oluşturmak için bir görünüm şablonu kullanır.
Yukarıdaki Index yöntemi gibi denetleyici Yöntemleri ( eylem yöntemleriolarak da bilinir), genellikle, string gibi
bir tür değil, genellikle bir IActionResult (veya ActionResulttüretilen bir sınıf) döndürür.

Görünüm ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Görünümler klasörüne sağ tıklayın ve ardından Yeni > klasör ekleyin ve HelloWorldklasörünü adlandırın.
Görünümler/HelloWorld klasörüne sağ tıklayın ve ardından > yeni öğe ekleyin.
Yeni öğe Ekle-Mvcfilmi iletişim kutusunda
Sağ üst köşedeki arama kutusuna Görünüm girin
Razor görünümü seçin
Index. cshtml adlı ad kutusu değerini saklayın.
Ekle 'yi seçin
Views/HelloWorld/Index. cshtml Razor görünüm dosyasının içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://test-cors.org sayfasına gidin. HelloWorldController Index yöntemi çok bitmedi; Bu, yönteminin tarayıcıya
yanıt işlemek için bir görünüm şablonu dosyası kullanması gerektiğini belirten return View(); ifadesini çalıştırdı.
Bir görünüm şablonu dosya adı belirtilmediğinden, MVC varsayılan görünüm dosyasını kullanmaya göre varsayılan
olarak ayarlanmış. Varsayılan görünüm dosyası yöntemiyle aynı ada sahiptir ( Index ), bu nedenle
/views/HelloWorld/Index.cshtml kullanılır. Aşağıdaki görüntüde "görünüm Şablonumuzdan Merhaba!" dizesi
gösterilmektedir görünümde sabit kodlanmış.
Görünümleri ve düzen sayfalarını değiştirme
Menü bağlantılarını (Mvcmovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü düzeni
Görünümler/Shared/_Layout. cshtml dosyasında uygulanır. Görünümler/paylaşılan/_Layout. cshtml dosyasını açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden çok
sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm görünüme özgü
sayfaların, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını seçerseniz,
Görünümler/Home/privacy. cshtml görünümü RenderBody yöntemi içinde işlenir.

Düzen dosyasındaki başlık, altbilgi ve menü bağlantısını değiştirme


Görünümler/paylaşılan/_Layout. cshtml dosyasının içeriğini aşağıdaki biçimlendirme ile değiştirin. Değişiklikler
vurgulanır:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie App</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow
mb-3">
<div class="container">
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>

Yukarıdaki biçimlendirme aşağıdaki değişiklikleri yaptı:


MvcMovie Movie App için 3 oluşum.
Tutturucu öğe
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>``<a class="navbar-brand"
asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a>
.
Yukarıdaki biçimlendirmede, bu uygulama alankullandığından asp-area="" tutturucu etiketi Yardımcısı özniteliği ve
öznitelik değeri atlandı.
Not: Movies denetleyicisi uygulanmadı. Bu noktada, Movie App bağlantısı işlevsel değildir.
Değişikliklerinizi kaydedin ve Gizlilik bağlantısını seçin. Tarayıcı sekmesindeki başlığın Gizlilik ilkesi yerine bir film
uygulaması (Gizlilik ilkesi değil) nasıl görüntülediğini fark edin -MVC filmi:

Giriş bağlantısını seçin ve başlık ve bağlantı metninin film uygulamasınıda görüntülediğine dikkat edin. Düzen
şablonunda değişikliği bir kez yapabildik ve sitedeki tüm sayfalar yeni bağlantı metnini ve yeni başlığı
yansıtmaktadır.
Views/_ViewStart. cshtml dosyasını inceleyin:

@{
Layout = "_Layout";
}

Views/_ViewStart. cshtml dosyası her bir görünüm için views/Shared/_Layout. cshtml dosyasını getirir. Layout
özelliği, farklı bir düzen görünümü ayarlamak veya null olarak ayarlamak için kullanılabilir; Bu nedenle hiçbir
düzen dosyası kullanılmayacak.
Views/HelloWorld/Index. cshtml görünüm dosyasının başlığını ve <h2> öğesini değiştirin:

@{
ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

Başlık ve <h2> öğesi biraz farklıdır, bu sayede kodun hangi bitini görüntülemesini görebilirsiniz.
yukarıdaki koddaki ViewData["Title"] = "Movie List"; , ViewData sözlüğün Title özelliğini "film listesi" olarak
ayarlar. Title özelliği, Düzen sayfasındaki <title> HTML öğesinde kullanılır:

<title>@ViewData["Title"] - Movie App</title>

Değişikliği kaydedin ve https://localhost:{PORT}/HelloWorld gidin. Tarayıcı başlığı, birincil başlık ve ikincil


başlıkların değiştirildiğini unutmayın. (Tarayıcıda değişiklik görmüyorsanız, önbelleğe alınmış içeriği görüntülüyor
olabilirsiniz. Sunucudan gelen yanıtı zorlamak için tarayıcınızda CTRL + F5 tuşlarına basın.) Tarayıcı başlığı, Index.
cshtml görünüm şablonunda belirlediğimiz ViewData["Title"] ve düzen dosyasına eklenen ek "-film uygulaması"
ile oluşturulur.
Index. cshtml görünüm şablonundaki içerik views/Shared/_Layout. cshtml görünüm şablonuyla birleştirilir.
Tarayıcıya tek bir HTML yanıtı gönderilir. Düzen şablonları, bir uygulamadaki tüm sayfalara uygulanan değişiklikler
yapmayı kolaylaştırır. Daha fazla bilgi için bkz. Düzen.

"Data" (Bu durumda "Görünümümüzden Merhaba!") çok az. ileti) sabit kodludur, ancak. MVC uygulamasında bir
"V" (görünüm) var ve bir "C" (denetleyici) var, ancak henüz "M" (model) yok.

Denetleyiciden görünüme veri geçirme


Gelen URL isteğine yanıt olarak denetleyici eylemleri çağrılır. Bir denetleyici sınıfı, gelen tarayıcı isteklerini işleyen
kodun yazıldığı yerdir. Denetleyici verileri bir veri kaynağından alır ve tarayıcıya ne tür bir yanıt gönderileceğini
belirler. Görünüm şablonları bir denetleyiciden, tarayıcıya HTML yanıtı oluşturmak ve biçimlendirmek için
kullanılabilir.
Bir görünüm şablonunun yanıt işlemesi için gereken verileri sağlamaktan denetleyiciler sorumludur. En iyi yöntem:
Görünüm şablonları iş mantığı gerçekleştirmemelidir veya doğrudan bir veritabanıyla etkileşime girmemelidir.
Bunun yerine, bir görünüm şablonu yalnızca denetleyici tarafından sunulan verilerle birlikte çalışmalıdır. Bu
"kaygıları ayrımı", kodun temiz, test edilebilir ve sürdürülebilir kalmasına yardımcı olur.
Şu anda, HelloWorldController sınıfındaki Welcome yöntemi bir name ve ID parametresi alır ve sonra değerleri
doğrudan tarayıcıya çıkarır. Denetleyicinin bu yanıtı bir dize olarak işlemesini sağlamak yerine, denetleyiciyi bir
görünüm şablonu kullanacak şekilde değiştirin. Görünüm şablonu dinamik bir yanıt üretir, bu, yanıtı oluşturmak için
denetleyiciden görünüme uygun veri bitlerinin geçirilmesi gereken anlamına gelir. Bu, denetleyicinin görünüm
şablonu tarafından daha sonra erişebileceği bir ViewData sözlüğünde bulunan dinamik verileri (parametreler)
yerleştirerek bunu yapın.
HelloWorldController.cs' de, ViewData sözlüğüne bir Message ve NumTimes değeri eklemek için Welcome yöntemini
değiştirin. ViewData sözlüğü dinamik bir nesnedir, yani herhangi bir tür kullanılabilir; ViewData nesnenin içine bir
öğe yerleştirene kadar tanımlanmış özellikleri yok. MVC modeli bağlama sistemi , adlandırılmış parametreleri (
name ve numTimes ), adres çubuğundaki sorgu dizesinden yöntemdeki parametrelere otomatik olarak eşler. Tüm
HelloWorldController.cs dosyası şuna benzer:

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Welcome(string name, int numTimes = 1)


{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;

return View();
}
}
}

ViewData Dictionary nesnesi görünüme geçirilecek verileri içerir.


Görünümler/HelloWorld/Welcome. cshtmladlı bir hoş geldiniz görünüm şablonu oluşturun.
Welcome. cshtml görünüm şablonunda "Hello" NumTimes görüntüleyen bir döngü oluşturacaksınız.
Views/HelloWorld/Welcome. cshtml içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>

Değişikliklerinizi kaydedin ve aşağıdaki URL 'ye gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

Veriler URL 'den alınır ve MVC model Bağlayıcısı kullanılarak denetleyiciye geçirilir. Denetleyici, verileri bir
ViewData sözlüğüne paketler ve bu nesneyi görünüme geçirir. Daha sonra Görünüm, verileri tarayıcıda HTML
olarak işler.
Yukarıdaki örnekte ViewData sözlüğü denetleyiciden bir görünüme veri geçirmek için kullanılmıştır. Öğreticide
daha sonra bir görünüm modeli, bir denetleyicideki verileri bir görünüme geçirmek için kullanılır. Veri geçirme
yaklaşımına yönelik görünüm modeli, ViewData sözlük yaklaşımına göre genel olarak çok tercih edilir. Daha fazla
bilgi için bkz. ViewBag, ViewData veya TempData kullanma .
Sonraki öğreticide, bir film veritabanı oluşturulur.

ÖN CEKI İL E R I

Bu bölümde, bir istemciye HTML yanıtları oluşturma işlemini düzgün bir şekilde kapsüllemek için
HelloWorldController sınıfını Razor görünümü dosyalarını kullanacak şekilde değiştirirsiniz.

Razor kullanarak bir görünüm şablonu dosyası oluşturursunuz. Razor tabanlı görünüm şablonlarının . cshtml dosya
uzantısı vardır. Bu kişiler ile C#HTML çıktısı oluşturmanın zarif bir yolunu sağlarlar.
Şu anda Indexyöntemi, denetleyici sınıfında sabit kodlanmış bir ileti içeren bir dize döndürür.
HelloWorldController sınıfında, Index yöntemini aşağıdaki kodla değiştirin:

public IActionResult Index()


{
return View();
}

Yukarıdaki kod denetleyicinin View yöntemini çağırır. HTML yanıtı oluşturmak için bir görünüm şablonu kullanır.
Yukarıdaki Index yöntemi gibi denetleyici Yöntemleri ( eylem yöntemleriolarak da bilinir), genellikle, string gibi
bir tür değil, genellikle bir IActionResult (veya ActionResulttüretilen bir sınıf) döndürür.

Görünüm ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Görünümler klasörüne sağ tıklayın ve ardından Yeni > klasör ekleyin ve HelloWorldklasörünü adlandırın.
Görünümler/HelloWorld klasörüne sağ tıklayın ve ardından > yeni öğe ekleyin.
Yeni öğe Ekle-Mvcfilmi iletişim kutusunda
Sağ üst köşedeki arama kutusuna Görünüm girin
Razor görünümü seçin
Index. cshtml adlı ad kutusu değerini saklayın.
Ekle 'yi seçin

Views/HelloWorld/Index. cshtml Razor görünüm dosyasının içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://test-cors.org sayfasına gidin. HelloWorldController Index yöntemi çok bitmedi; Bu, yönteminin tarayıcıya
yanıt işlemek için bir görünüm şablonu dosyası kullanması gerektiğini belirten return View(); ifadesini çalıştırdı.
Bir görünüm şablonu dosya adı belirtilmediğinden, MVC varsayılan görünüm dosyasını kullanmaya göre varsayılan
olarak ayarlanmış. Varsayılan görünüm dosyası yöntemiyle aynı ada sahiptir ( Index ), bu nedenle
/views/HelloWorld/Index.cshtml kullanılır. Aşağıdaki görüntüde "görünüm Şablonumuzdan Merhaba!" dizesi
gösterilmektedir görünümde sabit kodlanmış.
Görünümleri ve düzen sayfalarını değiştirme
Menü bağlantılarını (Mvcmovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü düzeni
Görünümler/Shared/_Layout. cshtml dosyasında uygulanır. Görünümler/paylaşılan/_Layout. cshtml dosyasını açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden çok
sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm görünüme özgü
sayfaların, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını seçerseniz,
Görünümler/Home/privacy. cshtml görünümü RenderBody yöntemi içinde işlenir.

Düzen dosyasındaki başlık, altbilgi ve menü bağlantısını değiştirme


Başlık ve altbilgi öğelerinde MvcMovie Movie App olarak değiştirin.
Tutturucu öğe <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a>
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a> olarak değiştirin.

Aşağıdaki biçimlendirme vurgulanan değişiklikleri göstermektedir:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie App</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.1.3/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute"
crossorigin="anonymous"
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
</environment>
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow
mb-3">
<div class="container">
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<partial name="_CookieConsentPartial" />
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>

<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
</script>
</environment>
<script src="~/js/site.js" asp-append-version="true"></script>

@RenderSection("Scripts", required: false)


</body>
</html>

Yukarıdaki biçimlendirmede, bu uygulama alankullandığından asp-area tutturucu etiketi yardımcı özniteliği


atlandı.
Not: Movies denetleyicisi uygulanmadı. Bu noktada, Movie App bağlantısı işlevsel değildir.
Değişikliklerinizi kaydedin ve Gizlilik bağlantısını seçin. Tarayıcı sekmesindeki başlığın Gizlilik ilkesi yerine bir film
uygulaması (Gizlilik ilkesi değil) nasıl görüntülediğini fark edin -MVC filmi:

Giriş bağlantısını seçin ve başlık ve bağlantı metninin film uygulamasınıda görüntülediğine dikkat edin. Düzen
şablonunda değişikliği bir kez yapabildik ve sitedeki tüm sayfalar yeni bağlantı metnini ve yeni başlığı
yansıtmaktadır.
Views/_ViewStart. cshtml dosyasını inceleyin:

@{
Layout = "_Layout";
}

Views/_ViewStart. cshtml dosyası her bir görünüm için views/Shared/_Layout. cshtml dosyasını getirir. Layout
özelliği, farklı bir düzen görünümü ayarlamak veya null olarak ayarlamak için kullanılabilir; Bu nedenle hiçbir
düzen dosyası kullanılmayacak.
Views/HelloWorld/Index. cshtml görünüm dosyasının başlığını ve <h2> öğesini değiştirin:

@{
ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

Başlık ve <h2> öğesi biraz farklıdır, bu sayede kodun hangi bitini görüntülemesini görebilirsiniz.
yukarıdaki koddaki ViewData["Title"] = "Movie List"; , ViewData sözlüğün Title özelliğini "film listesi" olarak
ayarlar. Title özelliği, Düzen sayfasındaki <title> HTML öğesinde kullanılır:

<title>@ViewData["Title"] - Movie App</title>

Değişikliği kaydedin ve https://localhost:{PORT}/HelloWorld gidin. Tarayıcı başlığı, birincil başlık ve ikincil


başlıkların değiştirildiğini unutmayın. (Tarayıcıda değişiklik görmüyorsanız, önbelleğe alınmış içeriği görüntülüyor
olabilirsiniz. Sunucudan gelen yanıtı zorlamak için tarayıcınızda CTRL + F5 tuşlarına basın.) Tarayıcı başlığı, Index.
cshtml görünüm şablonunda belirlediğimiz ViewData["Title"] ve düzen dosyasına eklenen ek "-film uygulaması"
ile oluşturulur.
Ayrıca, Index. cshtml görünüm şablonundaki içeriğin Görünümler/paylaşılan/_Layout. cshtml görünüm şablonuyla
nasıl birleştirildiğini ve tarayıcıya tek bir HTML yanıtı gönderildiğini de unutmayın. Düzen şablonları,
uygulamanızdaki tüm sayfalara uygulanan değişiklikler yapmayı gerçekten kolaylaştırır. Daha fazla bilgi için bkz.
Düzen.

"Data" (Bu durumda "Görünümümüzden Merhaba!") çok az. ileti) sabit kodludur, ancak. MVC uygulamasında bir
"V" (görünüm) var ve bir "C" (denetleyici) var, ancak henüz "M" (model) yok.

Denetleyiciden görünüme veri geçirme


Gelen URL isteğine yanıt olarak denetleyici eylemleri çağrılır. Bir denetleyici sınıfı, gelen tarayıcı isteklerini işleyen
kodun yazıldığı yerdir. Denetleyici verileri bir veri kaynağından alır ve tarayıcıya ne tür bir yanıt gönderileceğini
belirler. Görünüm şablonları bir denetleyiciden, tarayıcıya HTML yanıtı oluşturmak ve biçimlendirmek için
kullanılabilir.
Bir görünüm şablonunun yanıt işlemesi için gereken verileri sağlamaktan denetleyiciler sorumludur. En iyi yöntem:
Görünüm şablonları iş mantığı gerçekleştirmemelidir veya doğrudan bir veritabanıyla etkileşime girmemelidir.
Bunun yerine, bir görünüm şablonu yalnızca denetleyici tarafından sunulan verilerle birlikte çalışmalıdır. Bu
"kaygıları ayrımı", kodun temiz, test edilebilir ve sürdürülebilir kalmasına yardımcı olur.
Şu anda, HelloWorldController sınıfındaki Welcome yöntemi bir name ve ID parametresi alır ve sonra değerleri
doğrudan tarayıcıya çıkarır. Denetleyicinin bu yanıtı bir dize olarak işlemesini sağlamak yerine, denetleyiciyi bir
görünüm şablonu kullanacak şekilde değiştirin. Görünüm şablonu dinamik bir yanıt üretir, bu, yanıtı oluşturmak için
denetleyiciden görünüme uygun veri bitlerinin geçirilmesi gereken anlamına gelir. Bu, denetleyicinin görünüm
şablonu tarafından daha sonra erişebileceği bir ViewData sözlüğünde bulunan dinamik verileri (parametreler)
yerleştirerek bunu yapın.
HelloWorldController.cs' de, ViewData sözlüğüne bir Message ve NumTimes değeri eklemek için Welcome yöntemini
değiştirin. ViewData sözlüğü dinamik bir nesnedir, yani herhangi bir tür kullanılabilir; ViewData nesnenin içine bir
öğe yerleştirene kadar tanımlanmış özellikleri yok. MVC modeli bağlama sistemi , adlandırılmış parametreleri (
name ve numTimes ), adres çubuğundaki sorgu dizesinden yöntemdeki parametrelere otomatik olarak eşler. Tüm
HelloWorldController.cs dosyası şuna benzer:

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Welcome(string name, int numTimes = 1)


{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;

return View();
}
}
}

ViewData Dictionary nesnesi görünüme geçirilecek verileri içerir.


Görünümler/HelloWorld/Welcome. cshtmladlı bir hoş geldiniz görünüm şablonu oluşturun.
Welcome. cshtml görünüm şablonunda "Hello" NumTimes görüntüleyen bir döngü oluşturacaksınız.
Views/HelloWorld/Welcome. cshtml içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>

Değişikliklerinizi kaydedin ve aşağıdaki URL 'ye gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

Veriler URL 'den alınır ve MVC model Bağlayıcısı kullanılarak denetleyiciye geçirilir. Denetleyici, verileri bir
ViewData sözlüğüne paketler ve bu nesneyi görünüme geçirir. Daha sonra Görünüm, verileri tarayıcıda HTML
olarak işler.
Yukarıdaki örnekte ViewData sözlüğü denetleyiciden bir görünüme veri geçirmek için kullanılmıştır. Öğreticide
daha sonra bir görünüm modeli, bir denetleyicideki verileri bir görünüme geçirmek için kullanılır. Veri geçirme
yaklaşımına yönelik görünüm modeli, ViewData sözlük yaklaşımına göre genel olarak çok tercih edilir. Daha fazla
bilgi için bkz. ViewBag, ViewData veya TempData kullanma .
Sonraki öğreticide, bir film veritabanı oluşturulur.

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına model ekleme
23.11.2019 • 43 minutes to read • Edit Online

Rick Anderson ve Tom Dykstra tarafından


Bu bölümde, bir veritabanında film yönetmeye yönelik sınıflar eklersiniz. Bu sınıflar, dVC uygulamasının "dodel"
parçası olacaktır.
Bu sınıfları bir veritabanıyla çalışmak için Entity Framework Core (EF Core) ile birlikte kullanırsınız. EF Core,
yazmanız gereken veri erişim kodunu kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
Oluşturduğunuz model sınıfları, EF Core hiçbir bağımlılığı olmadığından, POCO sınıfları olarak bilinir ( PLain O ).
Yalnızca veritabanında depolanacak verilerin özelliklerini tanımlar.
Bu öğreticide, önce model sınıflarını yazdığınızda EF Core veritabanını oluşturur. Burada kapsanmayan alternatif bir
yaklaşım var olan bir veritabanından model sınıfları oluşturmaktır. Bu yaklaşım hakkında daha fazla bilgi için bkz.
ASP.NET Core-var olan veritabanı.

Veri modeli sınıfı ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
> sınıf eklemek > modeller klasörüne sağ tıklayın. Dosyayı Movie.csolarak adlandırın.
Movie.cs dosyasını aşağıdaki kodla güncelleştirin:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı, birincil anahtar için veritabanı için gerekli olan bir Id alanı içerir.
ReleaseDate veri türü özniteliği, verilerin türünü belirtir ( Date ). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.

NuGet paketleri Ekle


Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.

PMC 'de şu komutu çalıştırın:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Yukarıdaki komut, EF Core SQL Server sağlayıcısını ekler. Sağlayıcı paketi, EF Core paketini bir bağımlılık olarak
yüklüyor. Ek paketler, öğreticinin sonraki bölümlerinde bulunan yapı iskelesi adımında otomatik olarak yüklenir.

Veritabanı bağlamı sınıfı oluşturma


Movie modeli için EF Core işlevselliği (oluşturma, okuma, güncelleştirme, silme) koordine etmek için bir veritabanı
bağlamı sınıfı gerekir. Veritabanı bağlamı Microsoft. EntityFrameworkCore. DbContext öğesinden türetilir ve veri
modeline dahil edilecek varlıkları belirtir.
Bir veri klasörü oluşturun.
Aşağıdaki kodla bir Data/MvcMovieContext. cs dosyası ekleyin:

using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;

namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}

public DbSet<Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Veritabanı bağlamı Kaydet
ASP.NET Core, bağımlılık ekleme (dı)ile oluşturulmuştur. Hizmetlerin (EF Core DB bağlamı gibi) uygulama
başlatma sırasında DI ile kayıtlı olması gerekir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu
hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin
ilerleyen bölümlerinde gösterilmektedir. Bu bölümde, veritabanı bağlamını dı kapsayıcısına kaydedersiniz.
Aşağıdaki using deyimlerini Startup.csüst kısmına ekleyin:

using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;

Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:


Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddControllersWithViews();

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.

Veritabanı bağlantı dizesi Ekle


AppSettings. JSON dosyasına bir bağlantı dizesi ekleyin:
Visual Studio
Visual Studio Code/Mac için Visual Studio

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Projeyi derleyici hatalarına yönelik bir denetim olarak derleyin.

Yapı iskelesi film sayfaları


Film modeli için oluşturma, okuma, güncelleştirme ve silme (CRUD ) sayfaları üretmek için scafkatlama aracını
kullanın.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler klasörüne sağ tıklayıp yeni > yapı iskelesi > öğesi ekleyin.

Yapı Ekle iletişim kutusunda, Entity Framework > Ekle ' yi kullanarak views ile MVC denetleyicisi ' ni seçin.

Denetleyici Ekle iletişim kutusunu doldurun:


Model sınıfı: Film (mvcmovie. modeller )
Veri bağlamı sınıfı: mvcmoviecontext (mvcmovie. Data )
Görünümler: Her seçeneğin varsayılan kısmını işaretli tut
Denetleyici adı: Varsayılan MoviesController tut
Ekle 'yi seçin
Visual Studio şunları oluşturur:
Bir filmler denetleyicisi (denetleyiciler/MoviesController. cs)
Razor oluşturma, silme, ayrıntılar, düzenleme ve dizin sayfaları için dosyaları görüntüleme
(Görünümler/filmler/*. cshtml)

Bu dosyaların otomatik olarak oluşturulması, Yapı iskelesiolarak bilinir.


Veritabanı mevcut olmadığından, scafkatmış sayfaları henüz kullanamazsınız. Uygulamayı çalıştırır ve film
uygulaması bağlantısına tıklarsanız, bir veritabanı açılamıyor veya böyle bir tablo yok: film hata iletisi.

İlk geçiş
Veritabanını oluşturmak için EF Core geçişleri özelliğini kullanın. Geçişler, veri modelinizle eşleşecek bir veritabanı
oluşturmanıza ve güncelleştirmenize olanak sağlayan bir araç kümesidir.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.
PMC'de aşağıdaki komutları girin:

Add-Migration InitialCreate
Update-Database

Add-Migration InitialCreate : bir geçişler/{timestamp } _InitialCreate. cs geçiş dosyası oluşturuyor.


InitialCreate bağımsız değişkeni geçiş adıdır. Herhangi bir ad kullanılabilir, ancak kurala göre, geçişi
açıklayan bir ad seçilidir. Bu ilk geçiş olduğundan, oluşturulan sınıf veritabanı şemasını oluşturmak için kod
içerir. Veritabanı şeması, MvcMovieContext sınıfında belirtilen modeli temel alır.
Update-Database : veritabanını, önceki komutun oluşturulduğu en son geçişe güncelleştirir. Bu komut,
veritabanını oluşturan geçişler/{Time-damga } _InitialCreate. cs dosyasında Up yöntemini çalıştırır.
Database Update komutu aşağıdaki uyarıyı üretir:

' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür belirtilmedi. Bu, varsayılan duyarlık ve ölçeğe
uygun olmadıkları takdirde değerlerin sessizce kesilmesine neden olur. ' Hasccolumntype () ' kullanarak
tüm değerleri barındırabilecek SQL Server sütun türünü açıkça belirtin.

Bu uyarıyı yoksayabilirsiniz, daha sonraki bir öğreticide düzeltilecektir.


EF Core için PMC araçları hakkında daha fazla bilgi için bkz. Visual Studio 'da EF Core araçları başvurusu-PMC.
Initialcreate sınıfı
Geçişleri/{timestamp } _InitialCreate. cs geçiş dosyasını inceleyin:

public partial class Initial : Migration


{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Title = table.Column<string>(nullable: true),
ReleaseDate = table.Column<DateTime>(nullable: false),
Genre = table.Column<string>(nullable: true),
Price = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}

protected override void Down(MigrationBuilder migrationBuilder)


{
migrationBuilder.DropTable(
name: "Movie");
}
}

Up yöntemi, film tablosunu oluşturur ve Id birincil anahtar olarak yapılandırır. Down yöntemi, Up geçişi
tarafından yapılan şema değişikliklerini geri alır.

Uygulamayı test etme


Uygulamayı çalıştırın ve film uygulaması bağlantısına tıklayın.
Aşağıdakilerden birine benzer bir özel durum alırsanız:
Visual Studio
Visual Studio Code/Mac için Visual Studio

SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Muhtemelen geçişler adımınıkaçırdınız.
Oluştur sayfasını test edin. Veri girin ve gönderebilirsiniz.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül İngilizce
olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer gerekir.
Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Düzenleme, Ayrıntılarve silme sayfalarını test edin.

Denetleyiciye bağımlılık ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
Controllers/MoviesController. cs dosyasını açın ve oluşturucuyu inceleyin:

public class MoviesController : Controller


{
private readonly MvcMovieContext _context;

public MoviesController(MvcMovieContext context)


{
_context = context;
}

Oluşturucu, veritabanı bağlamını ( MvcMovieContext ) denetleyiciye eklemek için bağımlılık ekleme işlemini kullanır.
Her bir veritabanı bağlamı kullanılan CRUD denetleyici yöntemleri.

Türü kesin belirlenmiş modeller ve @model anahtar sözcüğü


Bu öğreticide daha önce, bir denetleyicinin ViewData sözlüğünü kullanarak bir görünüme nasıl veri veya nesne
geçirekullanabileceğinizi gördünüz. ViewData sözlüğü bir görünüme bilgi geçirmek için uygun, geç bağlanan bir yol
sağlayan dinamik bir nesnedir.
MVC Ayrıca, kesin olarak belirlenmiş model nesnelerini bir görünüme geçirmeye olanak tanır. Bu kesin türü
belirtilmiş yaklaşım derleme zamanı kodu denetimini sunar. Yapı iskelesi mekanizması, MoviesController sınıfı ve
görünümleriyle bu yaklaşımı (türü kesin belirlenmiş bir modeli geçirerek) kullandı.
Controllers/MoviesController. cs dosyasında oluşturulan Details yöntemini inceleyin:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

id parametresi genellikle rota verileri olarak geçirilir. Örneğin https://localhost:5001/movies/details/1 kümeler:


movies denetleyicisine denetleyici (ilk URL segmenti).
details eylemi (ikinci URL segmenti).
Kimliği 1 ' e (son URL segmenti).
Aşağıdaki gibi bir sorgu dizesiyle id de geçirebilirsiniz:
https://localhost:5001/movies/details?id=1

KIMLIK değeri sağlanmazsa id parametresi null yapılabilir bir tür ( int? ) olarak tanımlanır.
Bir lambda ifadesi , rota verileriyle veya sorgu dizesi değeriyle eşleşen film varlıklarını seçmek üzere
FirstOrDefaultAsync ' A geçirilir.

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);

Bir film bulunursa, Movie modelinin bir örneği Details görünümüne geçirilir:

return View(movie);

Görünümler/filmler/ayrıntılar. cshtml dosyasının içeriğini inceleyin:


@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Movie</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Genre)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Görünüm dosyasının en üstündeki @model ifade, görünümün beklediği nesne türünü belirtir. Film denetleyicisi
oluşturulduğunda, aşağıdaki @model deyimleri eklenmiştir:

@model MvcMovie.Models.Movie

Bu @model yönergesi, denetleyicinin görünüme geçirildiği filme erişimine izin verir. Model nesne kesin olarak
belirlenmiş. Örneğin, details. cshtml görünümünde, kod her bir film alanını DisplayNameFor DisplayFor ve HTML
yardımcılarını türü kesin belirlenmiş Model nesnesiyle geçirir. Create ve Edit yöntemleri ve görünümleri bir
Movie model nesnesi de iletir.

Dizin. cshtml görünümünü ve film denetleyicisindeki Index yöntemini inceleyin. List , View yöntemini
çağırdığında kodun bir nesne nasıl oluşturduğunu fark edin. Kod, Index eylem yönteminden bu Movies listesini
görünüme geçirir:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}

Film denetleyicisi oluşturulduğunda, yapı iskelesi Index. cshtml dosyasının en üstüne aşağıdaki @model ifadesini
içeriyordu:

@model IEnumerable<MvcMovie.Models.Movie>

@model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak, denetleyicinin görünüme geçirildiği film
listesine erişmenizi sağlar. Örneğin, Index. cshtml görünümünde, kod kesin türü belirtilmiş Model nesnesi üzerinde
foreach bir ifadesiyle filmlerle döngü yapılır:
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Model nesne kesin olarak yazıldığı için (bir IEnumerable<Movie> nesnesi olarak), döngüdeki her öğe Movie olarak
yazılır. Diğer avantajların yanı sıra, kodu derleme zaman denetimini alacağınız anlamına gelir.

Ek kaynaklar
Etiket Yardımcıları
Genelleştirme ve yerelleştirme
Daha Ö N C E B IR G Ö R Ü N Ü M D A H A S O N R A S Q L IL E
EKLEM E Ç A L IŞ M A

Veri modeli sınıfı ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
> sınıf eklemek > modeller klasörüne sağ tıklayın. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfı:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie Sınıfı içerir:


Id Alanı ve veritabanı için birincil anahtarı gereklidir.
[DataType(DataType.Date)] : DataType özniteliği veri türünü belirtir ( Date ). Bu öznitelik ile:
Kullanıcının tarih alanı saat bilgilerini girmek için gerekli değildir.
Yalnızca tarih görüntülenen, olmayan zaman bilgilerdir.
DataAnnotations bir sonraki öğreticide ele alınmaktadır.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler klasörüne sağ tıklayıp yeni > yapı iskelesi > öğesi ekleyin.
Yapı Ekle iletişim kutusunda, Entity Framework > Ekle ' yi kullanarak views ile MVC denetleyicisi ' ni seçin.

Denetleyici Ekle iletişim kutusunu doldurun:


Model sınıfı: Film (mvcmovie. modeller )
Veri bağlamı sınıfı: + simgesini seçin ve varsayılan Mvcmovie. modeller. MvcMovieContext öğesini
ekleyin
Görünümler: Her seçeneğin varsayılan kısmını işaretli tut
Denetleyici adı: Varsayılan MoviesController tut
Ekle 'yi seçin

Visual Studio şunları oluşturur:


Entity Framework Core veritabanı bağlam sınıfı (Data/MvcMovieContext. cs)
Bir filmler denetleyicisi (denetleyiciler/MoviesController. cs)
Razor oluşturma, silme, ayrıntılar, düzenleme ve dizin sayfaları için dosyaları görüntüleme
(Görünümler/filmler/*. cshtml)

Veritabanı bağlamı ve CRUD (oluşturma, okuma, güncelleştirme ve silme) eylem yöntemlerinin ve görünümlerinin
otomatik olarak oluşturulması, Yapı iskelesiolarak bilinir.
Uygulamayı çalıştırır ve MVC filmi bağlantısına tıklarsanız aşağıdakine benzer bir hata alırsınız:
Visual Studio
Visual Studio Code/Mac için Visual Studio
An unhandled exception occurred while processing the request.

SqlException: Cannot open database "MvcMovieContext-<GUID removed>" requested by the login. The login failed.
Login failed for user 'Rick'.

System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString

Veritabanını oluşturmanız ve bunu yapmak için EF Core geçişleri özelliğini kullanmanız gerekir. Geçişler veri
modelinize uyan bir veritabanı oluşturmanıza ve veri modeliniz değiştiğinde veritabanı şemasını güncelleştirmenize
olanak tanır.

İlk geçiş
Bu bölümde, aşağıdaki görevler tamamlanır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Visual Studio
Visual Studio Code/Mac için Visual Studio
1. Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.

2. PMC'de aşağıdaki komutları girin:

Add-Migration Initial
Update-Database

Add-Migration Komut, ilk veritabanı şeması oluşturmak için kod oluşturur.


Veritabanı şeması, MvcMovieContext sınıfında belirtilen modeli temel alır. Initial bağımsız değişkeni geçiş
adıdır. Herhangi bir ad kullanılabilir, ancak kurala göre, geçişi açıklayan bir ad kullanılır.Daha fazla bilgi için
bkz. Öğretici: EF Core ile geçiş özelliğini kullanma-ASP.NET MVC.
Update-Database Komutu çalıştırmaları Up yöntemi geçişleri / {zaman damgası} _InitialCreate.cs dosyasını
veritabanı oluşturur.
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core, bağımlılık ekleme (dı)ile oluşturulmuştur. Hizmetler (EF Core DB bağlamı gibi) uygulama başlatma
sırasında dı ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler Oluşturucu
parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin ilerleyen bölümlerinde
gösterilmektedir.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Scafkatlama aracı otomatik olarak bir DB bağlamı oluşturup dı kapsayıcısına kaydetti.
Aşağıdaki Startup.ConfigureServices yöntemini inceleyin. Vurgulanan satırı iskele kurucu tarafından eklendi:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

MvcMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları Movie modeli.
Veri bağlamı ( MvcMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı, veri modeline
hangi varlıkların ekleneceğini belirtir:

// Unused usings removed.


using Microsoft.EntityFrameworkCore;
using MvcMovie.Models; // Enables public DbSet<Movie> Movie

namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}

public DbSet<Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Aşağıdakine benzer bir veritabanı özel durumu alırsanız:

SqlException: Cannot open database "MvcMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı. Veri girin ve gönderebilirsiniz.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül İngilizce
olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer gerekir.
Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Startup sınıfını inceleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Önceki vurgulanan kod, bağımlılık ekleme kapsayıcısına eklenen film veritabanı bağlamını gösterir:
services.AddDbContext<MvcMovieContext>(options => kullanılacak veritabanını ve bağlantı dizesini belirtir.
=> lambda operatörü

Controllers/MoviesController. cs dosyasını açın ve oluşturucuyu inceleyin:

public class MoviesController : Controller


{
private readonly MvcMovieContext _context;

public MoviesController(MvcMovieContext context)


{
_context = context;
}

Oluşturucu, veritabanı bağlamını ( MvcMovieContext ) denetleyiciye eklemek için bağımlılık ekleme işlemini kullanır.
Her bir veritabanı bağlamı kullanılan CRUD denetleyici yöntemleri.

Türü kesin belirlenmiş modeller ve @model anahtar sözcüğü


Bu öğreticide daha önce, bir denetleyicinin ViewData sözlüğünü kullanarak bir görünüme nasıl veri veya nesne
geçirekullanabileceğinizi gördünüz. ViewData sözlüğü bir görünüme bilgi geçirmek için uygun, geç bağlanan bir yol
sağlayan dinamik bir nesnedir.
MVC Ayrıca, kesin olarak belirlenmiş model nesnelerini bir görünüme geçirmeye olanak tanır. Bu kesin türü
belirtilmiş yaklaşım, kodunuzun daha iyi derleme zaman denetimini sunar. Yapı iskelesi mekanizması, yöntem ve
görünümleri oluştururken MoviesController sınıfı ve görünümleriyle bu yaklaşımı (türü kesin belirlenmiş bir model
geçirme) kullanır.
Controllers/MoviesController. cs dosyasında oluşturulan Details yöntemini inceleyin:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

id parametresi genellikle rota verileri olarak geçirilir. Örneğin https://localhost:5001/movies/details/1 kümeler:


movies denetleyicisine denetleyici (ilk URL segmenti).
details eylemi (ikinci URL segmenti).
Kimliği 1 ' e (son URL segmenti).
Aşağıdaki gibi bir sorgu dizesiyle id de geçirebilirsiniz:
https://localhost:5001/movies/details?id=1

KIMLIK değeri sağlanmazsa id parametresi null yapılabilir bir tür ( int? ) olarak tanımlanır.
Bir lambda ifadesi , rota verileriyle veya sorgu dizesi değeriyle eşleşen film varlıklarını seçmek üzere
FirstOrDefaultAsync ' A geçirilir.

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);

Bir film bulunursa, Movie modelinin bir örneği Details görünümüne geçirilir:

return View(movie);

Görünümler/filmler/ayrıntılar. cshtml dosyasının içeriğini inceleyin:


@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Movie</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Genre)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Görünüm dosyasının üst kısmına bir @model ifadesini ekleyerek, görünümün beklediği nesne türünü
belirtebilirsiniz. Film denetleyicisini oluştururken, Ayrıntılar. cshtml dosyasının en üstüne aşağıdaki @model
deyimleri otomatik olarak eklenmiştir:

@model MvcMovie.Models.Movie

Bu @model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak denetleyicinin görünüme geçirildiği
filme erişmenizi sağlar. Örneğin, details. cshtml görünümünde, kod her bir film alanını DisplayNameFor DisplayFor
ve HTML yardımcılarını türü kesin belirlenmiş Model nesnesiyle geçirir. Create ve Edit yöntemleri ve
görünümleri bir Movie model nesnesi de iletir.
Dizin. cshtml görünümünü ve film denetleyicisindeki Index yöntemini inceleyin. List , View yöntemini
çağırdığında kodun bir nesne nasıl oluşturduğunu fark edin. Kod, Index eylem yönteminden bu Movies listesini
görünüme geçirir:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}

Film denetleyicisini oluştururken, yapı iskelesi Index. cshtml dosyasının en üstüne aşağıdaki @model ifadesini
otomatik olarak dahil edin:

@model IEnumerable<MvcMovie.Models.Movie>

@model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak, denetleyicinin görünüme geçirildiği film
listesine erişmenizi sağlar. Örneğin, Index. cshtml görünümünde, kod kesin türü belirtilmiş Model nesnesi üzerinde
foreach bir ifadesiyle filmlerle döngü yapılır:
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Model nesne kesin olarak yazıldığı için (bir IEnumerable<Movie> nesnesi olarak), döngüdeki her öğe Movie olarak
yazılır. Diğer avantajların yanı sıra, kodun derleme zaman denetimini alacağınız anlamına gelir:

Ek kaynaklar
Etiket Yardımcıları
Genelleştirme ve yerelleştirme
Daha Ö N C E B IR G Ö R Ü N Ü M D A H A S O N R A S Q L IL E
EKLEM E Ç A L IŞ M A
ASP.NET Core 'de SQL ile çalışma
23.11.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


MvcMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini işler.
Veritabanı bağlamı, Startup.cs dosyasındaki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddControllersWithViews();

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON dosyasından
bağlantı dizesini alır:

"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
2;Trusted_Connection=True;MultipleActiveResultSets=true"
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini bir üretim SQL Server ayarlamak için
bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür. LocalDB,
isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak,
LocalDB veritabanı C:/Users/{User } dizininde . mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.
Movie tablo > görünüm tasarımcısına sağ tıklayın
ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar ID adlı bir özellik
oluşturacak.
Movie tabloya sağ tıklayarak verileri görüntüleyin >
Veritabanının çekirdeğini oluşturma
Modeller klasöründe SeedData adlı yeni bir sınıf oluşturun. Oluşturulan kodu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MvcMovie.Data;
using System;
using System.Linq;

namespace MvcMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


Program.cs içeriğini aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MvcMovie.Data;
using MvcMovie.Models;
using System;

namespace MvcMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Uygulamayı test etme


Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya SSOX 'ten silme bağlantılarıyla yapabilirsiniz.
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur ' a
dokunun

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 'e basın
VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir.

ÖN CEKI İL E R I

Tarafından Rick Anderson


MvcMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini işler.
Veritabanı bağlamı, Startup.cs dosyasındaki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON dosyasından
bağlantı dizesini alır:

"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
2;Trusted_Connection=True;MultipleActiveResultSets=true"
}

Uygulamayı bir test veya üretim sunucusuna dağıtırken, bağlantı dizesini gerçek bir SQL Server ayarlamak için bir
ortam değişkeni veya başka bir yaklaşım kullanabilirsiniz. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür. LocalDB,
isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak,
LocalDB veritabanı C:/Users/{User } dizininde . mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.
Movie tablo > görünüm tasarımcısına sağ tıklayın
ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar ID adlı bir özellik
oluşturacak.
Movie tabloya sağ tıklayarak verileri görüntüleyin >
Veritabanının çekirdeğini oluşturma
Modeller klasöründe SeedData adlı yeni bir sınıf oluşturun. Oluşturulan kodu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace MvcMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


Program.cs içeriğini aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
using MvcMovie;

namespace MvcMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<MvcMovieContext>();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

Uygulamayı test etme


Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya SSOX 'ten silme bağlantılarıyla yapabilirsiniz.
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur ' a
dokunun

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 'e basın
VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir.

ÖN CEKI İL E R I
Denetleyici metotları ve görünümleri ASP.NET Core
11.07.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Film uygulaması için iyi bir başlangıç sahibiz ancak sunu Örneğin, ideal olarak, değildir ReleaseDate iki kelimeye
olmalıdır.

Açık Models/Movie.cs dosya ve aşağıda vurgulanan satırları ekleyin:


using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

Biz karşılarız DataAnnotations sonraki öğreticide. Görüntüleme öznitelik adı (Bu durumda "ReleaseDate" yerine
"yayın tarihi") bir alan için görüntülenecek öğeleri belirtir. DataType öznitelik alanında depolanan saat bilgilerini
görüntülenmediğini şekilde (tarih), veri türünü belirtir.
[Column(TypeName = "decimal(18, 2)")] Veri ek açıklama, Entity Framework Core doğru şekilde eşleyebilirsiniz
biçimde gereklidir Price veritabanında para birimi. Daha fazla bilgi için veri türleri.
Gözat Movies denetleyicisi ve fare işaretçisini tutun bir Düzenle hedef URL'ye görmek için bağlantıyı.

Düzenle, ayrıntıları, ve Sil bağlantıları Core MVC yer işareti etiketi Yardımcısı tarafından üretilen
Views/Movies/Index.cshtml dosya.
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper dinamik olarak HTML oluşturan href denetleyici eylem
yöntemi ve rota kimliğinden öznitelik değeri. Kullandığınız kaynağı görüntüle sık kullandığınız tarayıcıyı ya da
kullanım oluşturulan biçimlendirme incelemek için geliştirici araçları. Oluşturulan HTML değerinin bir bölümü
aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>

Biçim için geri çağırma yönlendirme kümesinde Startup.cs dosyası:

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

ASP.NET Core çevirir https://localhost:5001/Movies/Edit/4 bir istek halinde Edit eylem yöntemi Movies
denetleyicisi parametresiyle Id 4. (Denetleyici olarak da bilinen eylem yöntemleri yöntemlerdir.)
Etiket Yardımcıları ASP.NET Core en popüler yeni özellikler biridir. Daha fazla bilgi için ek kaynaklar.
Açık Movies denetleyicisi ve iki inceleyin Edit eylem yöntemleri. Aşağıdaki kodda gösterildiği HTTP GET Edit film
getirir ve tarafından oluşturulan düzenleme formu dolduran yöntemi Edit.cshtml Razor dosya.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.FindAsync(id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Aşağıdaki kodda gösterildiği HTTP POST Edit gönderilen film değerleri işleyen yöntemi:
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Aşağıdaki kodda gösterildiği HTTP POST Edit gönderilen film değerleri işleyen yöntemi:
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

[Bind] Özniteliktir karşı korumak için bir yol aşırı yayınlayarak. Özellikler yalnızca içermelidir [Bind] değiştirmek
istediğiniz özniteliği. Daha fazla bilgi için denetleyicinizin atlayarak nakil korumak. Viewmodel'lar atlayarak önlemek
için alternatif bir yaklaşım sağlar.
İkinci fark Edit eylem yöntemine öncesinde [HttpPost] özniteliği.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

HttpPost Özniteliği belirtir bu Edit yöntemi çağrılacak yalnızca için POST istekleri. Geçerli olabilir [HttpGet] ilk
özniteliği Düzenle yöntemi, ancak gerekli değildir çünkü [HttpGet] varsayılandır.
ValidateAntiForgeryToken Özniteliktir için kullanılan istek sahteciliğini önleme ve düzenleme görünümü dosyasında
oluşturulan bir sahteciliğe karşı koruma belirteci ile eşleştirilmiş (Views/Movies/Edit.cshtml). Sahteciliğe karşı
koruma belirteci ile düzenleme görünüm dosyası oluşturur Form etiketi Yardımcısı.

<form asp-action="Edit">

Form etiketi Yardımcısı eşleşmelidir gizli bir sahteciliğe karşı koruma belirteci oluşturan
[ValidateAntiForgeryToken] oluşturulan sahteciliğe karşı koruma belirtecine Edit denetleyici filmler yöntemi.
Daha fazla bilgi için istek sahteciliğinden koruma.
HttpGet EditYöntemi alır film ID parametresini arar Entity Framework kullanarak filmi FindAsync yöntemi ve
düzenleme görünümü seçili film döndürür. Bir filmi bulunamazsa NotFound (HTTP 404) döndürülür.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.FindAsync(id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Yapı iskelesi sistem düzenleme görünümü oluşturduğunuzda, onu incelenirken Movie sınıfı ve işlemek için
oluşturulan kodu <label> ve <input> sınıfın her bir özellik için öğeleri. Aşağıdaki örnek, Visual Studio yapı iskelesi
sistem tarafından oluşturulan düzenleme görünümünü gösterir:
@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-action="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Şablonu Görüntüle nasıl olduğunu fark bir @model MvcMovie.Models.Movie deyimini dosyanın üst.
@model MvcMovie.Models.Movie Görünüm model görünüm şablonu türünde olmasını bekliyor belirtir Movie .
İskele kurulan kodu birkaç etiketi Yardımcısı yöntemleri HTML biçimlendirmeyi kolaylaştırmak için kullanır. Etiket
etiketi Yardımcısı ("Title", "ReleaseDate", "Tarzı" veya "Price") alanın adını görüntüler. Giriş etiketi Yardımcısı bir
HTML işleyen <input> öğesi. Doğrulama etiketi Yardımcısı bu özellikle ilişkili herhangi bir doğrulama iletisi
görüntüler.
Uygulamayı çalıştırmak ve gidin /Movies URL'si. ' A tıklayın bir Düzenle bağlantı. Tarayıcıda, sayfa için kaynağı
görüntüleyin. İçin oluşturulan HTML <form> öğesi aşağıda gösterilmektedir.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID"
value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-
replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must
be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-
replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-
MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

<input> Öğeler içinde bir HTML <form> öğesi olan action özniteliğinin ayarlanmış gönderinin yayımlanacağı
/Movies/Edit/id URL'si. Form verileri sunucuya yayımlanacak olduğunda Save düğmesine tıklandığında. Son
satırı kapatmadan önce </form> öğenin gizli gösterir XSRF tarafından oluşturulan belirteç Form etiketi Yardımcısı.

POST isteğini işleme


Aşağıdaki liste gösterildiği [HttpPost] sürümünü Edit eylem yöntemi.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

[ValidateAntiForgeryToken] Özniteliği gizli doğrular XSRF içinde sahteciliğe karşı koruma belirteci Oluşturucu
tarafından oluşturulan belirteç Form etiketi Yardımcısı
Model bağlama sistem gönderilen form değerlerini alır ve oluşturan bir Movie olarak geçirilen nesne movie
parametresi. ModelState.IsValid Yöntemi doğrular (düzenleme veya güncelleştirme) değiştirileceğini biçiminde
gönderilen veriler kullanılabilir bir Movie nesne. Veriler geçerliyse kaydedilir. Güncelleştirilmiş (düzenlenen) film
verileri çağırarak veritabanına kaydedilir SaveChangesAsync veritabanı bağlamının yöntemi. Verileri kaydettikten
sonra kodu kullanıcı için yönlendiren Index eylem yöntemi MoviesController yaptığınız değişiklikleri içeren film
koleksiyonu görüntüleyen sınıfı.
Form, sunucuya gönderilen önce istemci tarafı doğrulama alanlarda tüm doğrulama kurallarını denetler. Herhangi
bir doğrulama hatası varsa, bir hata iletisi görüntülenir ve form gönderilen değil. JavaScript devre dışı bırakılırsa,
istemci tarafı doğrulama olmaz ancak sunucu, geçerli olmayan gönderilen değerlerden algılar ve form değerleri,
hata iletileri ile yeniden. Öğreticinin ilerleyen bölümlerinde inceleyeceğiz Model doğrulama daha ayrıntılı bir
şekilde. Doğrulama etiketi Yardımcısı içinde Views/Movies/Edit.cshtml görünüm şablonu uygun hata iletilerini
görüntüleme üstlenir.
Tüm HttpGet film denetleyici yöntemleri benzer bir desen uygulayın. Bir film nesnesi aldıkları (veya durumunda
nesnelerin listesini Index ) ve ' % s'nesne (modeli) görünümüne geçirin. Create Boş film nesneye yöntemi geçirir
Create görünümü. Bu nedenle, oluşturmak, düzenlemek, silmek veya aksi halde verileri değiştiren tüm yöntemler
yapmak [HttpPost] yöntemi aşırı yüklemesi. Verileri değiştirme bir HTTP GET bir güvenlik riski yöntemidir. Verileri
değiştirme bir HTTP GET yöntemi de ihlal HTTP en iyi yöntemler ve mimari REST desen, GET istekleri,
uygulamanızın durumunu değiştirmemeniz belirtir. Diğer bir deyişle, bir GET işlemi gerçekleştirilirken yan etkileri
olan ve verilerinizi kalıcı değiştirmez güvenli bir işlem olmalıdır.

Ek kaynaklar
Genelleştirme ve yerelleştirme
Etiket Yardımcıları giriş
Yazma etiketi Yardımcıları
İstek Sahteciliğinden Koruma
Denetleyicinizden korumak aşırı gönderme
Viewmodel'lar
Form Etiketi Yardımcısı
Giriş Etiketi Yardımcısı
Etiket Etiketi Yardımcısı
Seçim Etiketi Yardımcısı
Doğrulama etiketi Yardımcısı

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına arama ekleme
13.08.2019 • 10 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, film metoduna tarz veya adagöre arama Index özelliği ekleyebilirsiniz.
Controllers/MoviesController. cs içinde bulunan yöntemiaşağıdakikodlagüncelleştirin: Index

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}

Index Eylem yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

var movies = from m in _context.Movie


select m;

Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.


searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtrelenecek şekilde
değiştirilir:

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

Yukarıdaki kod bir lambda ifadesidir. s => s.Title.Contains() Lambdalar, Yöntem tabanlı LINQ sorgularında
WHERE yöntemi veya Contains (Yukarıdaki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız
değişkenler olarak kullanılır. LINQ sorguları tanımlandıklarında veya Where , Contains ya OrderBy da gibi bir
yöntem çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir
ifadenin değerlendirmesi, gerçekleştirilmiş değeri gerçekten yineleneceği veya ToListAsync Yöntem çağrılana kadar
geciktirilen anlamına gelir. Ertelenmiş sorgu yürütme hakkında daha fazla bilgi için bkz. sorgu yürütme.
Not: Contains yöntemi yukarıda gösterilen c# kodunda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük harf
duyarlılığı veritabanına ve harmanlamaya bağlıdır. SQL Server üzerinde SQL gibieşlemeler içerir , büyük/küçük
harfe duyarsız olur. SQLite ' da, varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.
/Movies/Index sayfasına gidin. URL 'ye gibi ?searchString=Ghost bir sorgu dizesi ekleyin. Filtrelenmiş filmler
görüntülenir.
Index Yönteminin imzasını adlı id bir parametreye sahip olacak şekilde değiştirirseniz, id parametresi
Startup.csiçinde ayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuya eşleşir.

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Parametresini id ve searchString değişikliğin tümoluşumlarınıolarakdeğiştirin. id


Önceki Index Yöntem:

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}

Parametresi ile Index id güncelleştirilmiş Yöntem:


public async Task<IActionResult> Index(string id)
{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title.Contains(id));
}

return View(await movies.ToListAsync());


}

Artık arama başlığını sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak geçirebilirsiniz.

Ancak, kullanıcıların bir filmi her arayışınızda URL 'YI değiştirmesini beklemeniz gerekmez. Böylece, filmlerin
filtrelemesine yardımcı olmak için UI öğeleri ekleyeceğiz. Yol ile bağlantılı ID parametrenin nasıl geçirileceğini test
Index etmek için yönteminin imzasını değiştirdiyseniz, adlı searchString bir parametre alması için geri değiştirin:

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}

Views/filmler/Index. cshtml dosyasını açın ve aşağıda vurgulanan <form> biçimlendirmeyi ekleyin:


ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-action="Create">Create New</a>
</p>

<form asp-controller="Movies" asp-action="Index">


<p>
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>

HTML <form> etiketi, form etiketi yardımcısınıkullanır, bu nedenle formu gönderdiğinizde, filtre dizesi film
denetleyicisinin Index eylemine gönderilir. Değişikliklerinizi kaydedin ve sonra filtreyi test edin.

Bekleneceğiniz gibi [HttpPost] Index metodun aşırı yüklemesi yoktur. Bunun için gerekli değildir, çünkü yöntem
uygulamanın durumunu değiştirmediğinden verileri filtrelememeniz yeterlidir.
Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
notUsed Parametresi , Index yöntemi için bir aşırı yükleme oluşturmak için kullanılır. Öğreticide daha sonra
konuşacağız.
Bu yöntemi eklerseniz, Invoker [HttpPost] Index yöntemi yöntemiyle eşleşir [HttpPost] Index ve yöntemi
aşağıdaki görüntüde gösterildiği gibi çalışır.

Ancak, bu [HttpPost] Index yöntemin bu sürümünü eklemeseniz bile, tümünün nasıl uygulandığını gösteren bir
sınırlama vardır. Belirli bir arama için yer işareti koymak istediğinizi veya aynı film filtrelenmiş listesini görmek için
onlara tıklabilecekleri bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL 'SI GET isteğinin
URL 'siyle (localhost: {PORT}/filmler/dizin) aynı olduğunu fark edin; URL 'de arama bilgisi yok. Arama dizesi
bilgileri sunucuya form alanı değeriolarak gönderilir. Tarayıcı geliştirici araçları veya harika Fiddler
aracınınolduğunu doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı geliştirici araçları gösterilmektedir:
Arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Bu şekilde, önceki öğreticide bahsedildiği
gibi, form etiketi Yardımcısı , bir XSRF Anti-forgery belirteci oluşturur. Verileri değiştiriyoruz, bu nedenle
denetleyiciyi denetleyici yönteminde doğrulamamız gerekmiyor.
Arama parametresi, URL değil, istek gövdesinde olduğundan, bu arama bilgilerini, yer işareti veya başkalarıyla
paylaşmak için yakalayamazsınız. İsteğin, HTTP GET Görünümler/filmler/Index. cshtml dosyasında bulunması
gerektiğini belirterek bunu düzeltemedi.
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)

Artık bir arama gönderdiğinizde, URL arama sorgu dizesini içerir. HttpGet Index Bir HttpPost Index yönteminiz
olsa da, arama eylem yöntemine de gidecektir.

Aşağıdaki biçimlendirme form etiketine olan değişikliği gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre arama Ekle


Aşağıdaki MovieGenreViewModel sınıfının modelleri klasörü:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
public List<Movie> Movies { get; set; }
public SelectList Genres { get; set; }
public string MovieGenre { get; set; }
public string SearchString { get; set; }
}
}

Film tarzı görünüm modeli şunları içerir:


Bir film listesi.
Tarzlar listesini içeren bir SelectList . Bu, kullanıcının listeden bir tarz seçmesine olanak sağlar.
MovieGenre , seçilen tarzı içeren.
SearchString , kullanıcılar arama metin kutusuna girdiğiniz metni içerir.

Index İçindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}

var movieGenreVM = new MovieGenreViewModel


{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};

return View(movieGenreVM);
}

Aşağıdaki kod, veritabanından tüm LINQ tarzları alan bir sorgudur.

// Use LINQ to get list of genres.


IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
SelectList Tarzlar ayrı tarzlar yansıtıyor (Select listenizin yinelenen tarzlar olmasını istemiyorum).
Kullanıcı öğeyi aradığında arama değeri arama kutusuna tutulur.

Tarzı, dizin görünümüne göre ara ekleme


Şu Index.cshtml şekilde görünümlerde/filmlerde bulunan güncelleştirme:
@model MvcMovie.Models.MovieGenreViewModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>

<select asp-for="MovieGenre" asp-items="Model.Genres">


<option value="">All</option>
</select>

Title: <input type="text" asp-for="SearchString" />


<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movies[0].Title)

Yukarıdaki kodda, DisplayNameFor HTML Yardımcısı, görünen adı belirlemede Lambda Title ifadesinde
başvurulan özelliği inceler. Lambda model ifadesi değerlendirilmek yerine incelenebileceğinden,, model.Movies ,
veya model.Movies[0] null boş olduğunda bir erişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde
(örneğin, @Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.
Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin:

ÖN CEKI İleri
ASP.NET Core MVC uygulamasına yeni bir alan
ekleme
23.11.2019 • 8 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alanı veritabanına geçirin.
EF Code First otomatik olarak bir veritabanı oluşturmak için kullanıldığında, Code First:
Veritabanının şemasını izlemek için veritabanına tablo ekler.
Veritabanının oluşturulduğu model sınıflarıyla eşitlenmiş olduğunu doğrular. Bunlar eşitlenmiş değilse EF bir
özel durum oluşturur. Bu, tutarsız veritabanı/kod sorunlarını bulmayı kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleyin


Modeller/film. cs' ye bir Rating özelliği ekleyin:

public class Movie


{
public int Id { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulama oluşturma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Ctrl+Shift+B
Movie sınıfına yeni bir alan eklediyseniz, bu yeni özellik dahil edilecek şekilde bağlama beyaz listesini
güncelleştirmeniz gerekir. MoviesController.cs' de, Rating özelliği dahil etmek için hem Create hem de Edit
eylem yöntemlerinin [Bind] özniteliğini güncelleştirin:

[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]

Yeni Rating özelliğini tarayıcı görünümünde görüntülemek, oluşturmak ve düzenlemek için görünüm şablonlarını
güncelleştirin.
/Views/movies/Index.cshtml dosyasını düzenleyin ve bir Rating alanı ekleyin:

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |

Bir Rating alanla /views/movies/Create.cshtml güncelleştirin.


Visual Studio/Mac için Visual Studio
Visual Studio Code
Önceki "form grubunu kopyalayabilir/yapıştırabilir" ve IntelliSense 'in alanları güncelleştirmenize yardımcı
olmasına izin verebilirsiniz. IntelliSense, Etiket Yardımcılarıile birlikte çalışmaktadır.
Kalan şablonları güncelleştirin.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie için bu değişikliği yapmak isteyeceksiniz.

new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "R",
Price = 7.99M
},

VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Şimdi çalıştırıldığında, aşağıdaki
SqlException atılır:

SqlException: Invalid column name 'Rating'.

Bu hata, güncelleştirilmiş film modeli sınıfı varolan veritabanının film tablosunun şemasından farklı olduğu için
oluşur. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Entity Framework yeni model sınıfı şemasına göre otomatik olarak veritabanını bırakıp yeniden oluşturmayı
sağlayabilirsiniz. Bu yaklaşım, bir test veritabanı üzerinde etkin geliştirme yaparken geliştirme döngüsünün
başlarında çok daha kolay. modeli ve veritabanı şemasını birlikte hızla gelişmenize olanak tanır. Bunun
yanında, bu yaklaşımı bir üretim veritabanında kullanmak istemezsiniz, ancak bu, veritabanında var olan
verileri kaybetmeniz olur. Bir veritabanının test verileriyle otomatik olarak çekirdeği oluşturmak için bir
başlatıcı kullanılması, genellikle bir uygulama geliştirmenin üretken bir yoludur. Bu, erken geliştirme ve
SQLite kullanılırken iyi bir yaklaşımdır.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın avantajı,
verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği oluşturarak
yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanılır.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.

PMC'de aşağıdaki komutları girin:

Add-Migration Rating
Update-Database

komutu, geçiş çerçevesinin geçerli Movie modelini geçerli Movie DB şemasıyla incelemesini ve
Add-Migration
VERITABANıNı yeni modele geçirmek için gerekli kodu oluşturmasını söyler.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir ad
kullanılması yararlı olur.
VERITABANıNDAKI tüm kayıtlar silinirse, Initialize yöntemi VERITABANıNı temel alır ve Rating alanını içerir.
Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi
doğrulayın. Edit , Details ve Delete görünüm şablonlarına Rating alanı eklemeniz gerekir.

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına doğrulama ekleme
23.11.2019 • 15 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde:
Doğrulama mantığı Movie modeline eklenir.
Bir Kullanıcı bir filmi oluşturduğunda veya düzenleişinizde doğrulama kurallarının uygulanmasını
sağlayabilirsiniz.

İşleri güncel tutma


MVC 'nin tasarımdan biri (" kendini tekrarlama"). ASP.NET Core MVC, işlevselliği veya davranışı yalnızca bir kez
belirtmenizi ve bir uygulamada her yerde yansıtıldığını önerir. Bu, yazmanız gereken kod miktarını azaltır ve daha az
hata yazmanızı, daha kolay test yapmayı ve bakımını daha kolay hale getirir.
MVC ve Entity Framework Core Code First tarafından sunulan doğrulama desteği, işlem içindeki kuru ilkeye uygun
bir örnektir. Doğrulama kurallarını tek bir yerde (model sınıfında) bildirimli olarak belirtebilir ve kurallar
uygulamada her yerde zorlanır.

Film modeline doğrulama kuralları ekleme


Dataaçıklamalarda ad alanı, bir sınıfa veya özelliğe bildirimli olarak uygulanan bir yerleşik doğrulama öznitelikleri
kümesi sağlar. Dataaçıklamalarda, biçimlendirme ile ilgili Yardım DataType ve herhangi bir doğrulama sağlamayan
gibi biçimlendirme öznitelikleri de bulunur.
Yerleşik Required , , RegularExpression vedoğrulama özniteliklerinden yararlanmak için sınıfıgüncelleştirin. Movie
StringLength Range
public class Movie
{
public int Id { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}

Doğrulama öznitelikleri, uygulanan model özellikleri üzerinde zorlamak istediğiniz davranışı belirtir:
Required Ve MinimumLength öznitelikleri bir özelliğin bir değere sahip olması gerektiğini belirtir; ancak hiçbir
şey, bir kullanıcının bu doğrulamayı karşılamak için boşluk girmesini engeller.
RegularExpression Öznitelik, hangi karakterlerin girişi yapabileceğini sınırlamak için kullanılır. Yukarıdaki
kodda, "tarz":
Yalnızca harfler kullanılmalıdır.
İlk harfin büyük harfle olması gerekir. Boşluk, sayı ve özel karakterlere izin verilmez.
RegularExpression "Derecelendirme":

İlk karakterin büyük harf olmasını gerektirir.


Sonraki boşlukların içindeki özel karakter ve sayılara izin verir. "PG -13" bir derecelendirme için geçerlidir,
ancak bir "tarz" için başarısız olur.
Range Özniteliği bir değeri belirtilen bir Aralık içinde kısıtlar.

StringLengthÖzniteliği, bir dize özelliğinin en büyük uzunluğunu ve isteğe bağlı olarak en düşük
uzunluğunu ayarlamanıza olanak sağlar.
Değer türleri (örneğin, decimal , int , float DateTime ), doğal olarak gereklidir ve [Required] özniteliğe
gerek kalmaz.
Doğrulama kurallarının otomatik olarak uygulanmasını ASP.NET Core uygulamanızın daha sağlam olmasına
yardımcı olur. Ayrıca, bir şeyi doğrulamayı unutmanızı ve veritabanına yanlışlıkla veri vermemesini de sağlar.

Doğrulama hatası Kullanıcı arabirimi


Uygulamayı çalıştırın ve filmler denetleyicisine gidin.
Yeni bir film eklemek için Yeni oluştur bağlantısına dokunun. Formu, bazı geçersiz değerlerle doldurun. JQuery
istemci tarafı doğrulaması hatayı algıladıktan hemen sonra bir hata iletisi görüntüler.
NOTE
Ondalık alanlara ondalık virgüller giremeyebilirsiniz. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih biçimleri için virgül (",")
kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı globalize için adımlar
uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .
Formun, geçersiz bir değer içeren her bir alanda uygun bir doğrulama hata iletisini nasıl otomatik olarak
oluşturduğuna dikkat edin. Hatalar hem istemci tarafında (JavaScript ve jQuery kullanılarak) hem de sunucu
tarafında (kullanıcının JavaScript devre dışı bırakılmış olması durumunda) zorlanır.
Önemli bir avantaj, bu doğrulama kullanıcı arabirimini etkinleştirmek için MoviesController sınıfında veya Create.
cshtml görünümündeki tek bir kod satırını değiştirmeniz gerekmez. Bu öğreticide daha önce oluşturduğunuz
denetleyici ve görünümler, Movie model sınıfının özelliklerinde doğrulama özniteliklerini kullanarak belirttiğiniz
doğrulama kurallarını otomatik olarak çekti. Edit Action yöntemini kullanarak test doğrulaması ve aynı doğrulama
uygulanır.
Form verileri, istemci tarafı doğrulama hatası kalmayana kadar sunucuya gönderilmez. Bunu, Fiddler aracını veya
F12 geliştirici araçlarınıkullanarak HTTP Post yöntemine bir kesme noktası koyarak doğrulayabilirsiniz.

Doğrulamanın çalışması
Doğrulama Kullanıcı arabiriminin denetleyici veya görünümlerde kodda herhangi bir güncelleştirme yapmadan
nasıl oluşturulduğunu merak edebilirsiniz. Aşağıdaki kod iki Create yöntemini gösterir.

// GET: Movies/Create
public IActionResult Create()
{
return View();
}

// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("ID,Title,ReleaseDate,Genre,Price, Rating")] Movie movie)
{
if (ModelState.IsValid)
{
_context.Add(movie);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(movie);
}

İlk (HTTP GET) Create Action yöntemi ilk oluşturma formunu görüntüler. İkinci ( [HttpPost] ) sürüm, form
gönderisini işler. İkinci Create yöntemi ( [HttpPost] sürümü), filmin herhangi bir doğrulama hatası olup
olmadığını denetlemek için ModelState.IsValid çağırır. Bu yöntemi çağırmak, nesnesine uygulanmış olan tüm
doğrulama özniteliklerini değerlendirir. Nesnede doğrulama hataları varsa Create yöntemi formu yeniden
görüntüler. Hata yoksa, yöntemi yeni filmi veritabanına kaydeder. Film örneğimizde, istemci tarafında algılanan
doğrulama hataları olduğunda form sunucuya nakledilmez; istemci tarafı doğrulama hataları olduğunda ikinci
Create yöntemi hiçbir zaman çağrılmaz. Tarayıcınızda JavaScript 'i devre dışı bırakırsanız, istemci doğrulaması
devre dışıdır ve herhangi bir doğrulama hatasını tespit ModelState.IsValid HTTP POST Create yöntemini test
edebilirsiniz.
[HttpPost] Create yönteminde bir kesme noktası ayarlayabilir ve yöntemin hiçbir zaman çağrılmadığını
doğrulayabilirsiniz, doğrulama hataları algılandığında istemci tarafı doğrulaması form verilerini göndermez.
Tarayıcınızda JavaScript 'i devre dışı bırakır, ardından formu hatalarla gönderirseniz, kesme noktası isabet eder.
JavaScript olmadan tam doğrulama almaya devam edersiniz.
Aşağıdaki görüntüde, FireFox tarayıcısında JavaScript 'In nasıl devre dışı bırakılacağı gösterilmektedir.
Aşağıdaki görüntüde, Chrome tarayıcısında JavaScript 'In nasıl devre dışı bırakılacağı gösterilmektedir.

JavaScript 'i devre dışı bıraktıktan sonra, geçersiz veri gönderin ve hata ayıklayıcıda adım adım ilerleyin.
Create. cshtml görünüm şablonunun bölümü aşağıdaki biçimlendirmede gösterilmiştir:

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>

@*Markup removed for brevity.*@

Yukarıdaki biçimlendirme eylem yöntemleri tarafından ilk formu görüntülemek ve bir hata durumunda onu
yeniden görüntülemek için kullanılır.
Giriş etiketi Yardımcısı , dataaçıklamaların özniteliklerini kullanır ve istemci tarafında jQuery doğrulaması için
gerekli HTML özniteliklerini üretir. Doğrulama etiketi Yardımcısı doğrulama hatalarını görüntüler. Daha fazla bilgi
için bkz. doğrulama .
Bu yaklaşım ne kadar iyi bir şeydir, denetleyicinin ne de Create görünüm şablonunun zorlanmakta olan gerçek
doğrulama kuralları ya da görüntülenen belirli hata iletileri hakkında herhangi bir şeyi biliyor olması önemlidir.
Doğrulama kuralları ve hata dizeleri yalnızca Movie sınıfında belirtilmiştir. Aynı doğrulama kuralları Edit
görünümüne ve modelinizi düzenleyebilecek oluşturabileceğiniz diğer tüm görünümler şablonlarına otomatik
olarak uygulanır.
Doğrulama mantığını değiştirmeniz gerektiğinde, modele doğrulama öznitelikleri ekleyerek tam olarak bir yerde
bunu yapabilirsiniz (Bu örnekte, Movie sınıfı). Kuralların nasıl zorlandığından, uygulamanın farklı bölümlerinin
tutarsız olması konusunda endişelenmeniz gerekmez; tüm doğrulama mantığı tek bir yerde tanımlanır ve her yerde
kullanılır. Bu, kodun temiz kalmasını sağlar ve bakımını ve gelişmesini kolaylaştırır. Ayrıca, KURULAMA ilkesini tam
olarak sunabileceksiniz anlamına gelir.

DataType özniteliklerini kullanma


Movie.cs dosyasını açın ve Movie sınıfını inceleyin. System.ComponentModel.DataAnnotations ad alanı, yerleşik
doğrulama öznitelikleri kümesine ek olarak biçimlendirme öznitelikleri sağlar. Yayın tarihine ve fiyat alanlarına
DataType bir numaralandırma değeri zaten uyguladık. Aşağıdaki kod, uygun DataType özniteliğiyle ReleaseDate
ve Price özelliklerini gösterir.

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

DataType öznitelikleri yalnızca görünüm altyapısının verileri biçimlendirmek için ipuçları sağlar (ve URL 'ler için
<a> gibi öğeleri/öznitelikleri ve e-posta için <a href="mailto:EmailAddress.com"> sağlar. RegularExpression
özniteliğini kullanarak verilerin biçimini doğrulayabilirsiniz. DataType özniteliği, veritabanı iç türünden daha özel bir
veri türü belirtmek için kullanılır, bunlar doğrulama öznitelikleri değildir. Bu durumda, zamanı değil yalnızca tarihi
izlemek istiyoruz. DataType numaralandırması, tarih, saat, PhoneNumber, para birimi, Emaadresi ve daha fazlası
gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin, DataType.EmailAddress için mailto: bir bağlantı oluşturulabilir ve HTML5 'i
destekleyen tarayıcılarda DataType.Date için bir tarih seçici sağlaneklenebilir. DataType öznitelikleri HTML 5
tarayıcıların anlayabilmesi için HTML 5 data- (bir veri Dash) öznitelikleri yayar. DataType öznitelikleri herhangi bir
doğrulama sağlamaz.
DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, veri alanı, sunucunun CultureInfo göre
varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]


public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode ayarı, bir metin kutusunda değer görüntülenmek üzere görüntülendiğinde


biçimlendirmenin de uygulanacağını belirtir. (Örneğin, para birimi değerleri için, büyük olasılıkla, metin kutusundaki
para birimi sembolünü, bazı alanlar için istemiyor olabilirsiniz.)
DisplayFormat özniteliğini kendisi kullanabilirsiniz, ancak bu genellikle DataType özniteliğini kullanmak iyi bir fikir
olabilir. DataType özniteliği, bir ekranda nasıl işlenirim aksine verilerin semantiğini sunar ve DisplayFormat ile elde
olmadığınız aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını vb. göstermek için)
Varsayılan olarak tarayıcı, verileri yerel ayarınızı temel alarak doğru biçimi kullanarak işleyebilir.
DataType özniteliği, verileri işlemek için doğru alan şablonunu seçmek üzere MVC 'yi etkinleştirebilir
(kendisi tarafından kullanılırsa, dize şablonunu kullanıyorsa DisplayFormat ).

NOTE
jQuery doğrulaması, Range özniteliğiyle ve DateTime birlikte çalışmaz. Örneğin, aşağıdaki kod, tarih belirtilen aralıkta
olduğunda bile her zaman bir istemci tarafı doğrulama hatası görüntüler:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

DateTime``Range özniteliğini kullanmak için jQuery Tarih doğrulamasını devre dışı bırakmanız gerekir.
Modellerinizde sabit tarihleri derlemek genellikle iyi bir uygulamadır, bu nedenle Range özniteliği ve DateTime
kullanılması önerilmez.
Aşağıdaki kod, öznitelikleri tek bir satırda birleştirmeyi gösterir:

public class Movie


{
public int Id { get; set; }

[StringLength(60, MinimumLength = 3)]


public string Title { get; set; }

[Display(Name = "Release Date"), DataType(DataType.Date)]


public DateTime ReleaseDate { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$"), Required, StringLength(30)]


public string Genre { get; set; }

[Range(1, 100), DataType(DataType.Currency)]


[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; }
}

Serinin bir sonraki bölümünde, uygulamayı gözden geçiririz ve otomatik olarak oluşturulan Details ve Delete
yöntemlerinde bazı geliştirmeler yaparsınız.

Ek kaynaklar
Formlarla Çalışma
Genelleştirme ve yerelleştirme
Etiket yardımcılarına giriş
Yazar etiketi yardımcıları

ÖN CEKI İL E R I
ASP.NET Core uygulamasının Ayrıntılar ve silme
yöntemlerini inceleyin
4.12.2019 • 4 minutes to read • Edit Online

Tarafından Rick Anderson


Film denetleyicisini açın ve Details yöntemi inceleyin:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

Bu eylem yöntemini oluşturan MVC yapı iskelesi altyapısı, yöntemi çağıran bir HTTP isteğini gösteren bir açıklama
ekler. Bu durumda, üç URL segmentine sahip bir GET isteği, Movies denetleyicisi, Details yöntemi ve bir id
değeri. Bu kesimleri geri çağır Startup.csiçinde tanımlanmıştır.

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

EF, FirstOrDefaultAsync yöntemini kullanarak verileri aramanızı kolaylaştırır. Yöntemi içinde yerleşik olarak
bulunan önemli bir güvenlik özelliği, kodun, onunla herhangi bir şey yapmayı denemeden önce arama yönteminin
bir filmi buldığını doğrulamasından kaynaklanmaktadır. Örneğin, bir korsan
http://localhost:{PORT}/Movies/Details/1 bağlantıları tarafından oluşturulan URL 'yi
http://localhost:{PORT}/Movies/Details/12345 (veya gerçek bir filmi temsil eden başka bir değer ) gibi bir şeye
değiştirerek siteye hata verebilir. Null bir filmi denetmediyseniz, uygulama bir özel durum oluşturur.
Delete ve DeleteConfirmed yöntemlerini inceleyin.
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var movie = await _context.Movie.FindAsync(id);
_context.Movie.Remove(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}

HTTP GET Delete yöntemi belirtilen filmi silmediğini unutmayın. Bu, silme işlemini gönderebileceğiniz (HttpPost)
filmin bir görünümünü döndürür. Bir GET isteğine yanıt olarak silme işlemi gerçekleştirme (veya bu konuyla ilgili
olarak, düzenleme işlemi gerçekleştirme, oluşturma işlemi yapma veya verileri değiştiren başka bir işlem) bir
güvenlik deliği açılır.
Verileri silen [HttpPost] yöntemi, HTTP POST yöntemine benzersiz bir imza veya ad vermek için DeleteConfirmed
olarak adlandırılır. İki yöntem imzası aşağıda gösterilmiştir:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Ortak dil çalışma zamanı (CLR ), aşırı yüklenmiş yöntemlerin benzersiz bir parametre imzasına sahip olmasını
gerektirir (aynı yöntem adı ancak farklı parametre listesi). Bununla birlikte, her ikisi de aynı parametre imzasına
sahip olmak üzere iki Delete yöntemi (GET için bir tane ve diğeri) gerekir. (Her ikisi de parametre olarak tek bir
tamsayıyı kabul etmelidir.)
Bu sorunun iki yaklaşımı vardır, biri yöntemlere farklı adlar vermektir.Bu, önceki örnekte bulunan yapı iskelesi
mekanizmasına göre yapılır. Ancak, bu küçük bir sorun ortaya çıkarır: ASP.NET bir URL 'nin segmentlerini ada göre
eylem yöntemlerine eşler ve bir yöntemi yeniden adlandırırsanız, yönlendirme normalde bu yöntemi bulamaz.
Çözüm, örnekte gördüğünüz şeydir. Bu, DeleteConfirmed yöntemine ActionName("Delete") özniteliğini eklemektir.
Bu öznitelik, yönlendirme sistemi için eşleme gerçekleştirerek, bir POST isteği için/Delete/içeren bir URL 'nin
DeleteConfirmed yöntemi bulacaktır.
Özdeş adlara ve imzalara sahip yöntemler için bir diğer yaygın çalışma yapay, POST yönteminin imzasını bir ek
(kullanılmamış) parametre içerecek şekilde değiştirecek. Bu, notUsed parametresini eklediğimiz sırada önceki bir
gönderimiz tarafından yaptığımız şeydir. [HttpPost] Delete yöntemi için burada aynı şeyi yapabilirsiniz:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Azure'a Yayımlama
Azure 'a dağıtma hakkında bilgi için bkz. öğretici: Azure App Service .NET Core ve SQL veritabanı Web uygulaması
oluşturma.

ÖN CEKI
İlk Blazor uygulamanızı oluşturma
9.12.2019 • 12 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Bu öğreticide bir Blazor uygulamasının nasıl oluşturulacağı ve değiştirileceği gösterilmektedir.


Bu öğreticide bir Blazor projesi oluşturmak için ASP.NET Core Blazor kullanmaya başlama makalesindeki
yönergeleri izleyin. Projeyi ToDoListolarak adlandırın.

Derleme bileşenleri
1. Sayfalar klasöründe uygulamanın üç sayfasının her birine gidin: giriş, sayaç ve veri getirme. Bu sayfalar,
Razor bileşen dosyaları dizini. Razor, Counter. Razorve fetchdata. Razortarafından uygulanır.
2. Sayaç sayfasında, bir sayfa yenilemesi olmadan sayacı artırmak için bana tıklama düğmesini seçin. Bir Web
sayfasında normal olarak bir sayacı artırma, JavaScript yazmayı gerektirir. Blazor, bunun yerine yazabilirsiniz
C# .
3. Counter. Razor dosyasındaki Counter bileşeninin uygulamasını inceleyin.
Pages/Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()


{
currentCount++;
}
}

Counter bileşenin kullanıcı arabirimi HTML kullanılarak tanımlanır. Dinamik işleme mantığı (örneğin,
döngüler, koşullar, ifadeler) C# Razoradlı gömülü bir sözdizimi kullanılarak eklenir. HTML biçimlendirme ve
C# işleme mantığı, derleme zamanında bir bileşen sınıfına dönüştürülür. Oluşturulan .NET sınıfının adı dosya
adıyla eşleşir.
Bileşen sınıfının üyeleri bir @code bloğunda tanımlanmıştır. @code bloğunda, bileşen durumu (özellikler,
alanlar) ve yöntemler olay işleme için veya diğer bileşen mantığını tanımlamak için belirtilir. Bu Üyeler daha
sonra bileşenin işleme mantığının bir parçası olarak ve olayları işlemek için kullanılır.
Bana tıklama düğmesi seçildiğinde:
Counterbileşenin kayıtlı onclick işleyicisine ( IncrementCount yöntemi) denir.
Counter bileşeni, işleme ağacını yeniden oluşturur.
Yeni işleme ağacı öncekiyle karşılaştırılır.
Yalnızca Belge Nesne Modeli (DOM ) üzerinde yapılan değişiklikler uygulanır. Görünen sayı
güncelleştirildi.
4. Sayıyı bir C# yerine iki ile artırmak için Counter bileşenin mantığını değiştirin.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()


{
currentCount += 2;
}
}

5. Değişiklikleri görmek için uygulamayı yeniden derleyin ve çalıştırın. Ben tıklama düğmesini seçin. Sayaç iki
olarak artar.

Bileşenleri kullanma
Bir bileşeni, bir HTML söz dizimini kullanarak başka bir bileşene ekleyin.
1. Index bileşenine bir <Counter /> öğesi ekleyerek uygulamanın Index bileşenine Counter bileşenini
ekleyin (Index. Razor).
Bu deneyim için Blazor WebAssembly kullanıyorsanız, Index bileşeni tarafından SurveyPrompt bir bileşen
kullanılır. <SurveyPrompt> öğesini bir <Counter /> öğesiyle değiştirin. Bu deneyim için bir Blazor sunucusu
uygulaması kullanıyorsanız, Index bileşenine <Counter /> öğesini ekleyin:
Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter />

2. Uygulamayı yeniden derleyin ve çalıştırın. Index bileşeni kendi sayacıdır.

Bileşen parametreleri
Bileşenler de parametrelere sahip olabilir. Bileşen parametreleri, bileşen sınıfında [Parameter] özniteliğiyle ortak
özellikler kullanılarak tanımlanır. Biçimlendirme içindeki bir bileşenin bağımsız değişkenlerini belirtmek için
öznitelikleri kullanın.
1. Bileşenin @code C# kodunu güncelleştirin:
[Parameter] özniteliğiyle ortak bir IncrementAmount özelliği ekleyin.
currentCount değerini artırdığınızda IncrementAmount kullanmak için IncrementCount yöntemini
değiştirin.
Pages/Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

[Parameter]
public int IncrementAmount { get; set; } = 1;

private void IncrementCount()


{
currentCount += IncrementAmount;
}
}

1. Özniteliği kullanarak Index bileşeninin <Counter> öğesinde bir IncrementAmount parametresi belirtin.
Sayacı on olarak artırmak için değeri ayarlayın.
Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter IncrementAmount="10" />

2. Index bileşenini yeniden yükleyin. Beni tıklama düğmesi seçildiğinde sayaç on bir kez artar. Counter
bileşenindeki sayaç bir artış ile devam eder.

Bileşenlere yönlendir
Counter. Razor dosyasının en üstündeki @page yönergesi, Counter bileşeninin bir yönlendirme uç noktası
olduğunu belirtir. Counter bileşeni /counter gönderilen istekleri işler. @page yönergesi olmadan, bileşen
yönlendirilmiş istekleri işlemez, ancak bileşen diğer bileşenler tarafından hala kullanılabilir.

Bağımlılık ekleme
Blazor sunucusu deneyimi
Blazor sunucu uygulamasıyla çalışıyorsanız, WeatherForecastService hizmeti bir tek Startup.ConfigureServices
olarak kaydedilir. Uygulamanın tamamında bağımlılık ekleme (dı)yoluyla hizmetin bir örneği mevcuttur:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}

@inject yönergesi, WeatherForecastService hizmetinin örneğini FetchData bileşenine eklemek için kullanılır.
Pages/FetchData. Razor:

@page "/fetchdata"
@using ToDoList.Data
@inject WeatherForecastService ForecastService

FetchData bileşeni, WeatherForecast nesnelerinin bir dizisini almak için, ForecastService olarak eklenen hizmeti
kullanır:

@code {
private WeatherForecast[] forecasts;

protected override async Task OnInitializedAsync()


{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}

Blazor Weelsembly deneyimi


Blazor WebAssembly uygulamasıyla çalışıyorsanız, Wwwroot/Sample-Data klasöründeki Hava durumu. JSON
dosyasından Hava durumu tahmin verileri almak için HttpClient eklenir.
Pages/FetchData. Razor:

@inject HttpClient Http

...

protected override async Task OnInitializedAsync()


{
forecasts =
await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}

@foreach döngüsü, her tahmin örneğini Hava durumu verileri tablosunda bir satır olarak işlemek için kullanılır:
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>

Yapılacaklar listesi oluşturma


Uygulamaya basit bir yapılacaklar listesi uygulayan yeni bir bileşen ekleyin.
1. Uygulamalar klasörüne Todo. Razor adlı boş bir dosya ekleyin:
2. Bileşen için ilk biçimlendirmeyi belirtin:

@page "/todo"

<h1>Todo</h1>

3. Gezinti çubuğuna Todo bileşenini ekleyin.


NavMenu bileşeni (Shared/NavMenu. Razor) uygulamanın düzeninde kullanılır. Düzenler, uygulamadaki
içeriğin çoğaltılmasını önlemenize olanak sağlayan bileşenlerdir.
Aşağıdaki liste öğesi işaretlemesini paylaşılan/NavMenu. Razor dosyasında var olan liste öğelerinin altına
ekleyerek Todo bileşeni için bir <NavLink> öğesi ekleyin:

<li class="nav-item px-3">


<NavLink class="nav-link" href="todo">
<span class="oi oi-list-rich" aria-hidden="true"></span> Todo
</NavLink>
</li>

4. Uygulamayı yeniden derleyin ve çalıştırın. Todo bileşeni bağlantısının çalıştığından emin olmak için yeni
Todo sayfasını ziyaret edin.
5. Bir Todo öğesini temsil eden bir sınıfı tutmak için projenin köküne bir TodoItem.cs dosyası ekleyin. TodoItem
sınıfı için C# aşağıdaki kodu kullanın:
public class TodoItem
{
public string Title { get; set; }
public bool IsDone { get; set; }
}

6. Todo bileşenine geri dönün (Pages/Todo. Razor):


@code bloğundaki Todo öğeleri için bir alan ekleyin. Todo bileşeni, Todo listesinin durumunu korumak
için bu alanı kullanır.
Her Todo öğesini bir liste öğesi ( <li> ) olarak işlemek için sıralanmamış liste işaretlemesi ve bir foreach
döngüsü ekleyin.

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
}

7. Uygulama, listeye Todo öğeleri eklemek için Kullanıcı arabirimi öğeleri gerektirir. Sıralanmamış listenin (
<ul>...</ul> ) altına bir metin girişi ( <input> ) ve bir düğme ( <button> ) ekleyin:

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

<input placeholder="Something todo" />


<button>Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
}

8. Uygulamayı yeniden derleyin ve çalıştırın. Todo Ekle düğmesi seçildiğinde, bir olay işleyicisi düğmeye
kablolu olmadığı için hiçbir şey olmaz.
9. Todo bileşenine bir AddTodo yöntemi ekleyin ve @onclick özniteliğini kullanarak düğme seçimleri için
kaydedin. Düğme seçildiğinde C# AddTodo yöntemi çağrılır:
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();

private void AddTodo()


{
// Todo: Add the todo
}
}

10. Yeni Todo öğesinin başlığını almak için, @code bloğunun üst kısmına bir newTodo dize alanı ekleyin ve
<input> öğesindeki bind özniteliğini kullanarak metin girişinin değerine bağlayın:

private IList<TodoItem> todos = new List<TodoItem>();


private string newTodo;

<input placeholder="Something todo" @bind="newTodo" />

11. AddTodo yöntemini, belirtilen başlığa sahip TodoItem listeye eklemek için güncelleştirin. newTodo boş bir
dizeye ayarlayarak metin girişinin değerini temizleyin:

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

<input placeholder="Something todo" @bind="newTodo" />


<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
private string newTodo;

private void AddTodo()


{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}

12. Uygulamayı yeniden derleyin ve çalıştırın. Yeni kodu test etmek için Todo listesine bazı Todo öğeleri ekleyin.
13. Her Todo öğesi için başlık metni düzenlenebilir hale getirilebilir ve bir onay kutusu kullanıcının tamamlanmış
öğeleri izlemesine yardımcı olabilir. Her Todo öğesi için bir onay kutusu girişi ekleyin ve değerini IsDone
özelliğine bağlayın. @todo.Title , @todo.Title bağlantılı <input> bir öğe olarak değiştirin:
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>

14. Bu değerlerin bağlandığını doğrulamak için <h1> üst bilgisini, tamamlanmamış olan Todo öğelerinin
sayısının sayısını gösterecek şekilde güncelleştirin ( IsDone false ).

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

15. Tamamlanan Todo bileşeni (Sayfalar/Todo. Razor):

@page "/todo"

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>

<input placeholder="Something todo" @bind="newTodo" />


<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
private string newTodo;

private void AddTodo()


{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}

16. Uygulamayı yeniden derleyin ve çalıştırın. Yeni kodu test etmek için Todo öğeleri ekleyin.
ASP.NET Core Razor bileşenleri oluşturma ve kullanma
Öğretici: ASP.NET Core bir Web API 'SI oluşturma
10.12.2019 • 47 minutes to read • Edit Online

Tarafından Rick Anderson ve Mike Wasson


Bu öğretici, bir web API ASP.NET Core ile oluşturmaya ilişkin temel bilgileri öğretir.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
Bir Web API projesi oluşturun.
Bir model sınıfı ve bir veritabanı bağlamı ekleyin.
CRUD yöntemleriyle bir denetleyiciyi dolandırın.
Yönlendirmeyi, URL yollarını ve dönüş değerlerini yapılandırın.
Web API'si Postman ile çağırın.
Sonunda, bir veritabanında depolanan "yapılacaklar" öğelerini yönetebilmek için bir Web API 'SI vardır.

Genel bakış
Bu öğretici yandaki API oluşturur:

API AÇIKLAMA İSTEK GÖVDESI YANIT GÖVDESI

/Api/TodoItems al Tüm yapılacak iş öğeleri al Yok. Yapılacaklar öğelerinin bir


dizisi

/Api/TodoItems/{id} al Bir öğeyi Kimliğine göre Al Yok. Yapılacak iş öğesi

POST/api/TodoItems Yeni Öğe Ekle Yapılacak iş öğesi Yapılacak iş öğesi

/Api/TodoItems/{id} koy Mevcut öğeyi güncelleştirin Yapılacak iş öğesi Yok.

/Api/TodoItems/{id} SIL Öğeyi Sil Yok. Yok.

Aşağıdaki diyagramda, bu uygulamanın tasarımını gösterir.


Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019 16,4 veya üzeri
.NET Core 3,1 SDK veya üzeri

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması şablonunu seçin ve İleri' ye tıklayın.
Projeyi TodoApi olarak adlandırın ve Oluştur' a tıklayın.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda, .net Core ve ASP.NET Core 3,1 ' un
seçili olduğunu doğrulayın. API şablonunu seçin ve Oluştur' a tıklayın.

API'yi test etme


Proje şablonu oluşturur bir WeatherForecast API. Çağrı Get uygulamayı test etmek için bir tarayıcıdan yöntemi.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı çalıştırmak için CTRL + F5 tuşlarına basın. Visual Studio bir tarayıcı ile başlatarak
https://localhost:<port>/WeatherForecast burada <port> bir rastgele seçilen bağlantı noktası numarasıdır.
IIS Express sertifika güven varsa soran bir iletişim kutusu alırsanız seçin Evet. İçinde Güvenlik Uyarısı ardından,
görüntülenen iletişim seçin Evet.
Aşağıdakine benzer bir JSON döndürülür:

[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]

Bir model sınıfı ekleme


A modeli uygulamayı yöneten verilerini temsil eden sınıflar kümesidir. Tek bir modeldir bu uygulama için TodoItem
sınıfı.
Visual Studio
Visual Studio Code
Mac için Visual Studio
İçinde Çözüm Gezgini, projeye sağ tıklayın. Seçin ekleme > yeni klasör. Klasör adı modelleri.
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı Todoıtem seçip Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
}

Id Özelliği işlevlerinin bir ilişkisel veritabanında benzersiz anahtar.


Model sınıfları herhangi bir projede gidip ancak modelleri klasörü, kural olarak kullanılır.

Veritabanı bağlamı Ekle


Veritabanı bağlamı koordine eden bir veri modeli için Entity Framework işlevsellik ana sınıftır. Bu sınıf türetme
tarafından oluşturulan Microsoft.EntityFrameworkCore.DbContext sınıfı.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Microsoft. EntityFrameworkCore. SqlServer ekleyin
Araçlar menüsünde nuget Paket Yöneticisi > çözüm Için NuGet Paketlerini Yönet' i seçin.
Araştır sekmesini seçin ve arama kutusuna Microsoft. Entityframeworkcore. SqlServer yazın.
Sol bölmedeki Microsoft. EntityFrameworkCore. SqlServer öğesini seçin.
Sağ bölmedeki Proje onay kutusunu seçin ve ardından Install' ı seçin.
Microsoft.EntityFrameworkCore.InMemory NuGet paketini eklemek için yukarıdaki yönergeleri kullanın.
TodoContext veritabanı bağlamını ekleme
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı TodoContext tıklatıp Ekle.
Aşağıdaki kodu girin:

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}

public DbSet<TodoItem> TodoItems { get; set; }


}
}

Veritabanı bağlamı Kaydet


ASP.NET Core DB bağlamı gibi hizmetler ile kaydedilmelidir bağımlılık ekleme (dı) kapsayıcı. Kapsayıcı hizmeti
denetleyicilerine sağlar.
Güncelleştirme Startup.cs aşağıdaki vurgulanmış kodu:
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

Yukarıdaki kod:
Kullanılmayan kaldırır using bildirimleri.
Veritabanı bağlamı DI kapsayıcıya ekler.
Veritabanı bağlamı bir bellek içi veritabanına kullanacağını belirtir.

Denetleyiciyi bir denetleyiciye katlama


Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ denetleyicileri klasör.
> yeni yapı Iskelesi öğesi Ekle ' yi seçin.
Entity Framework kullanarak ve eylemler Içeren API denetleyicisi' ni seçin ve ardından Ekle' yi seçin.
API denetleyiciyi eylemler Ile Ekle ' de Entity Framework iletişim kutusunu kullanarak:
Model sınıfında TodoItem (TodoApi. modeller) öğesini seçin.
Veri bağlamı sınıfında TodoContext (TodoApi. modeller) öğesini seçin.
Add (Ekle) seçeneğini belirleyin.
Oluşturulan kod:
Bir API denetleyicisi sınıfı yöntemleri olmadan tanımlar.
Sınıfı [ApiController] özniteliğiyle işaretler. Bu öznitelik, denetleyicinin web API'si isteklerine yanıt verdiğini
gösterir. Özniteliğin izin aldığı belirli davranışlar hakkında daha fazla bilgi için bkz. ASP.NET Core ile Web API
'Leri oluşturma.
Veritabanı bağlamı eklemesine DI kullanır ( TodoContext ) içine denetleyici. Her bir veritabanı bağlamı kullanılan
CRUD denetleyici yöntemleri.

PostTodoItem Create metodunu inceleyin


PostTodoItem ' deki return ifadesini, NameOf işlecini kullanacak şekilde değiştirin:

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();

//return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);


return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

Yukarıdaki kod, [HttpPost] özniteliğiyle gösterildiği gıbı bır http post yöntemidir. Yöntemi, HTTP isteği
gövdesinden Yapılacaklar öğenin değerini alır.
CreatedAtAction Yöntemi:
Başarılı olursa bir HTTP 201 durum kodu döndürür. HTTP 201 sunucuda yeni bir kaynak oluşturan bir HTTP
POST yöntemi için standart yanıttır.
Yanıta bir konum üst bilgisi ekler. Location üstbilgisi, yeni oluşturulan Yapılacaklar öğesinin URI 'sini belirtir.
Daha fazla bilgi için 10.2.2 201 oluşturuldu.
Location üst bilgisinin URI 'sini oluşturmak için GetTodoItem eyleme başvurur. C# nameof anahtar sözcüğü,
CreatedAtAction çağrısında eylem adının sabit kodlanmasını önlemek için kullanılır.

Postman yükleme
Bu öğreticide Postman web API'si test etmek için kullanılır.
Yükleme Postman
Web uygulaması başlatın.
Postman'i başlatın.
Devre dışı SSL sertifika doğrulama
Dosya > ayarları ' ndan (genel sekmesinden) SSL sertifikası doğrulamasınıdevre dışı bırakın.

WARNING
Test denetleyicisi sonra SSL sertifika doğrulamasını yeniden etkinleştirin.
Postman ile test PostTodoItem
Yeni bir istek oluşturun.
HTTP yöntemini POST olarak ayarlayın.
Seçin gövdesi sekmesi.
Seçin ham radyo düğmesi.
Tür kümesine JSON (application/json) .
İstek gövdesinde bir yapılacak iş öğesi için JSON girin:

{
"name":"walk dog",
"isComplete":true
}

Gönder’i seçin.

Konum üst bilgisi URI test


Seçin üstbilgileri sekmesinde yanıt bölmesi.
Kopyalama konumu üst bilgi değeri:
Yöntemini GET öğesine Ayarla.
URI 'yi yapıştırın (örneğin, https://localhost:5001/api/TodoItems/1 ).
Gönder’i seçin.

GET yöntemlerini inceleyin


İki GET uç noktası bu yöntemleri uygulayın:
GET /api/TodoItems
GET /api/TodoItems/{id}

Tarayıcıdan veya Postman 'dan iki uç noktayı çağırarak uygulamayı test edin. Örneğin:
https://localhost:5001/api/TodoItems
https://localhost:5001/api/TodoItems/1
Aşağıdakine benzer bir yanıt, GetTodoItems çağrısı tarafından üretilir:

[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]

Postman ile test al


Yeni bir istek oluşturun.
HTTP yöntemi kümesine alma.
İstek URL'si kümesine https://localhost:<port>/api/TodoItems . Örneğin: https://localhost:5001/api/TodoItems .
Ayarlama iki bölme görünümü postman'deki.
Gönder’i seçin.
Bu uygulama, bellek içi bir veritabanını kullanır. Uygulama durdurulup başlatılırsa, önceki GET isteği herhangi bir
veri döndürmez. Hiçbir veri döndürülmezse, verileri uygulamaya gönderin .

URL Yönlendirme ve yolları


[HttpGet] Özniteliği bir HTTP GET isteğine yanıt vermeden bir yöntemi gösterir. Her yöntem için URL yolu şu
şekilde oluşturulur:
Denetleyicinin şablonu dizesi ile başlayıp Route özniteliği:

[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;

public TodoItemsController(TodoContext context)


{
_context = context;
}

Değiştirin [controller] denetleyicinin adı ile kural tarafından olduğu "Controller" soneki eksi denetleyici
sınıfı adı. Bu örnek için denetleyici sınıfı adı todoıtemsdenetleyicisidir, bu nedenle denetleyicinin adı
"todoıtems" olur. ASP.NET Core yönlendirme büyük/küçük harfe duyarlıdır.
[HttpGet] özniteliğinin bir yol şablonu varsa (örneğin, [HttpGet("products")] ), yola ekleyin. Bu örnek, bir
şablon kullanmaz. Daha fazla bilgi için özniteliği Http [eylem] özniteliği ile yönlendirme.
Aşağıdaki GetTodoItem yöntemi "{id}" yapılacak iş öğesi benzersiz tanımlayıcısı için bir yer tutucu değişkendir.
GetTodoItem çağrıldığında, URL 'deki "{id}" değeri id parametresindeki yöntemine sağlanır.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Döndürülen değerler
Dönüş türünü GetTodoItems ve GetTodoItem yöntemler actionresult öğesini<T > türü. ASP.NET Core, nesneyi
otomatik olarak serileştiren JSON ve yanıt iletisinin gövdesine JSON yazar. Yanıt kodu 200 bu dönüş türü için
olduğu varsayılırsa işlenmeyen özel durumlar vardır. İşlenmeyen özel durumları 5xx hatalarla karşılaşırsanız çevrilir.
ActionResult dönüş türleri, geniş HTTP durum kodları temsil edebilir. Örneğin, GetTodoItem iki farklı durum
değerleri döndürebilir:
Öğe istenen kimliği eşleşirse, yöntem bir 404 döndürür NotFound hata kodu.
Aksi takdirde yöntem bir JSON yanıt gövdesine 200 döndürür. Döndüren item sonuçları bir HTTP 200 yanıtı.

PutTodoItem yöntemi
PutTodoItem yöntemini inceleyin:

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}

_context.Entry(todoItem).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}

return NoContent();
}

PutTodoItem benzer PostTodoItem , HTTP PUT kullanır. Yanıt 204 (içerik yok). HTTP belirtimine göre bir PUT İsteği
tüm güncelleştirilmiş varlık yalnızca değişiklikler değil göndermek istemci gerektirir. Kısmi güncelleştirmeleri
desteklemek için kullanma HTTP PATCH.
PutTodoItem çağırırken bir hata alırsanız, veritabanında bir öğe olduğundan emin olmak için GET çağırın.
Test PutTodoItem yöntemi
Bu örnek, uygulama her başlatıldığında başlatılmış olması gereken bellek içi bir veritabanını kullanır. Bir PUT çağrısı
yapmadan önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan
emin olmak için GET çağrısı yapın.
ID = 1 olan Yapılacaklar öğesini güncelleştirin ve adını "Feed balık" olarak ayarlayın:

{
"ID":1,
"name":"feed fish",
"isComplete":true
}

Aşağıdaki görüntüde, Postman güncelleştirme gösterilmektedir:


DeleteTodoItem yöntemi
DeleteTodoItem yöntemini inceleyin:

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}

_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();

return todoItem;
}

DeleteTodoItem Yanıt 204 (içerik yok).


Test DeleteTodoItem yöntemi
Postman bir yapılacak iş öğesini silmek için kullanın:
Yöntem kümesine DELETE .
Silinecek nesnenin URI 'sini ayarlayın (örneğin https://localhost:5001/api/TodoItems/1 ).
Gönder’i seçin.

JavaScript ile Web API 'sini çağırma


Bkz. öğretici: JavaScript ile ASP.NET Core Web API 'Si çağırma.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
Bir Web API projesi oluşturun.
Bir model sınıfı ve bir veritabanı bağlamı ekleyin.
Bir denetleyici ekleyeceksiniz.
CRUD yöntemleri ekleyin.
Yönlendirmeyi Yapılandırma ve URL yolu.
Dönüş değerleri belirtin.
Web API'si Postman ile çağırın.
JavaScript ile Web API 'sini çağırın.
Sonunda, web API'si "Yapılacaklar" öğelerini ilişkisel bir veritabanında depolanan yönetebileceği sahip.

Genel bakış
Bu öğretici yandaki API oluşturur:

API AÇIKLAMA İSTEK GÖVDESI YANIT GÖVDESI

/Api/TodoItems al Tüm yapılacak iş öğeleri al Yok. Yapılacaklar öğelerinin bir


dizisi

/Api/TodoItems/{id} al Bir öğeyi Kimliğine göre Al Yok. Yapılacak iş öğesi

POST/api/TodoItems Yeni Öğe Ekle Yapılacak iş öğesi Yapılacak iş öğesi

/Api/TodoItems/{id} koy Mevcut öğeyi güncelleştirin Yapılacak iş öğesi Yok.

/Api/TodoItems/{id} SIL Öğeyi Sil Yok. Yok.

Aşağıdaki diyagramda, bu uygulamanın tasarımını gösterir.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri
WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması şablonunu seçin ve İleri' ye tıklayın.
Projeyi TodoApi olarak adlandırın ve Oluştur' a tıklayın.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda, .net Core ve ASP.NET Core 2,2 ' un
seçili olduğunu doğrulayın. API şablonunu seçin ve Oluştur' a tıklayın. Docker desteğini etkinleştir ' i
seçmeyin .

API'yi test etme


Proje şablonu oluşturur bir values API. Çağrı Get uygulamayı test etmek için bir tarayıcıdan yöntemi.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı çalıştırmak için CTRL + F5 tuşlarına basın. Visual Studio bir tarayıcı ile başlatarak
https://localhost:<port>/api/values burada <port> bir rastgele seçilen bağlantı noktası numarasıdır.

IIS Express sertifika güven varsa soran bir iletişim kutusu alırsanız seçin Evet. İçinde Güvenlik Uyarısı ardından,
görüntülenen iletişim seçin Evet.
Aşağıdaki JSON döndürülür:

["value1","value2"]

Bir model sınıfı ekleme


A modeli uygulamayı yöneten verilerini temsil eden sınıflar kümesidir. Tek bir modeldir bu uygulama için TodoItem
sınıfı.
Visual Studio
Visual Studio Code
Mac için Visual Studio
İçinde Çözüm Gezgini, projeye sağ tıklayın. Seçin ekleme > yeni klasör. Klasör adı modelleri.
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı Todoıtem seçip Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:

namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
}

Id Özelliği işlevlerinin bir ilişkisel veritabanında benzersiz anahtar.


Model sınıfları herhangi bir projede gidip ancak modelleri klasörü, kural olarak kullanılır.

Veritabanı bağlamı Ekle


Veritabanı bağlamı koordine eden bir veri modeli için Entity Framework işlevsellik ana sınıftır. Bu sınıf türetme
tarafından oluşturulan Microsoft.EntityFrameworkCore.DbContext sınıfı.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı TodoContext tıklatıp Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}

public DbSet<TodoItem> TodoItems { get; set; }


}
}

Veritabanı bağlamı Kaydet


ASP.NET Core DB bağlamı gibi hizmetler ile kaydedilmelidir bağımlılık ekleme (dı) kapsayıcı. Kapsayıcı hizmeti
denetleyicilerine sağlar.
Güncelleştirme Startup.cs aşağıdaki vurgulanmış kodu:
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the
//container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

// This method gets called by the runtime. Use this method to configure the HTTP
//request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseMvc();
}
}
}

Yukarıdaki kod:
Kullanılmayan kaldırır using bildirimleri.
Veritabanı bağlamı DI kapsayıcıya ekler.
Veritabanı bağlamı bir bellek içi veritabanına kullanacağını belirtir.

Denetleyici ekleme
Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ denetleyicileri klasör.
> Yeni öğe Ekle ' yi seçin.
İçinde Yeni Öğe Ekle iletişim kutusunda API denetleyici sınıfı şablonu.
Sınıf adı TodoControllerseçip Ekle.

Şablon kodunu aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TodoApi.Models;

namespace TodoApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

public TodoController(TodoContext context)


{
_context = context;

if (_context.TodoItems.Count() == 0)
{
// Create a new TodoItem if collection is empty,
// which means you can't delete all TodoItems.
_context.TodoItems.Add(new TodoItem { Name = "Item1" });
_context.SaveChanges();
}
}
}
}

Yukarıdaki kod:
Bir API denetleyicisi sınıfı yöntemleri olmadan tanımlar.
Sınıfı [ApiController] özniteliğiyle işaretler. Bu öznitelik, denetleyicinin web API'si isteklerine yanıt verdiğini
gösterir. Özniteliğin izin aldığı belirli davranışlar hakkında daha fazla bilgi için bkz. ASP.NET Core ile Web API
'Leri oluşturma.
Veritabanı bağlamı eklemesine DI kullanır ( TodoContext ) içine denetleyici. Her bir veritabanı bağlamı kullanılan
CRUD denetleyici yöntemleri.
Adlı bir öğe ekler Item1 veritabanı boşsa veritabanı. Her çalıştığında bu kod oluşturucusunun içinde yeni bir
HTTP isteği olduğundan. Tüm öğeleri silerseniz, oluşturucu oluşturur Item1 API yöntemi çağrıldığında tekrar
başlattığınızda. Bu nedenle, gerçekten işe yaradı silme işlemi işe yaramadı gibi görünebilir.

Get yöntemleri ekleyin


Yapılacak iş öğeleri alır bir API sağlamak için aşağıdaki yöntemi ekleyin. TodoController sınıfı:

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

İki GET uç noktası bu yöntemleri uygulayın:


GET /api/todo
GET /api/todo/{id}

Hala çalışıyorsa uygulamayı durdurun. Ardından, en son değişiklikleri dahil etmek için yeniden çalıştırın.
Bir tarayıcıdan iki uç nokta çağırarak uygulamayı test edin. Örneğin:
https://localhost:<port>/api/todo
https://localhost:<port>/api/todo/1

Şu HTTP yanıtı çağrısı tarafından üretilen GetTodoItems :

[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
URL Yönlendirme ve yolları
[HttpGet] Özniteliği bir HTTP GET isteğine yanıt vermeden bir yöntemi gösterir. Her yöntem için URL yolu şu
şekilde oluşturulur:
Denetleyicinin şablonu dizesi ile başlayıp Route özniteliği:

namespace TodoApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

Değiştirin [controller] denetleyicinin adı ile kural tarafından olduğu "Controller" soneki eksi denetleyici
sınıfı adı. Bu örnek, denetleyici sınıfı adı olan TodoDenetleyici adı "todo" Bu nedenle denetleyicisi. ASP.NET
Core yönlendirme büyük/küçük harfe duyarlıdır.
[HttpGet] özniteliğinin bir yol şablonu varsa (örneğin, [HttpGet("products")] ), yola ekleyin. Bu örnek, bir
şablon kullanmaz. Daha fazla bilgi için özniteliği Http [eylem] özniteliği ile yönlendirme.
Aşağıdaki GetTodoItem yöntemi "{id}" yapılacak iş öğesi benzersiz tanımlayıcısı için bir yer tutucu değişkendir.
Zaman GetTodoItem çağrılır, değerini "{id}" yöntemine URL'de sağlanan kendi id parametresi.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Döndürülen değerler
Dönüş türünü GetTodoItems ve GetTodoItem yöntemler actionresult öğesini<T > türü. ASP.NET Core, nesneyi
otomatik olarak serileştiren JSON ve yanıt iletisinin gövdesine JSON yazar. Yanıt kodu 200 bu dönüş türü için
olduğu varsayılırsa işlenmeyen özel durumlar vardır. İşlenmeyen özel durumları 5xx hatalarla karşılaşırsanız çevrilir.
ActionResult dönüş türleri, geniş HTTP durum kodları temsil edebilir. Örneğin, GetTodoItem iki farklı durum
değerleri döndürebilir:
Öğe istenen kimliği eşleşirse, yöntem bir 404 döndürür NotFound hata kodu.
Aksi takdirde yöntem bir JSON yanıt gövdesine 200 döndürür. Döndüren item sonuçları bir HTTP 200 yanıtı.

Test GetTodoItems yöntemi


Bu öğreticide Postman web API'si test etmek için kullanılır.
Postman'yi yükleme.
Web uygulaması başlatın.
Postman'i başlatın.
SSL sertifikası doğrulamasınıdevre dışı bırakın.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Dosya > ayarları ' ndan (genel sekmesinden) SSL sertifikası doğrulamasınıdevre dışı bırakın.

WARNING
Test denetleyicisi sonra SSL sertifika doğrulamasını yeniden etkinleştirin.

Yeni bir istek oluşturun.


HTTP yöntemi kümesine alma.
İstek URL'si kümesine https://localhost:<port>/api/todo . Örneğin: https://localhost:5001/api/todo .
Ayarlama iki bölme görünümü postman'deki.
Gönder’i seçin.

Create yöntemi ekleme


Aşağıdaki PostTodoItem yöntemini Controllers/TodoController. csiçine ekleyin:

// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
_context.TodoItems.Add(item);
await _context.SaveChangesAsync();

return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);


}
Yukarıdaki kod, [HttpPost] özniteliğiyle gösterildiği gıbı bır http post yöntemidir. Yöntemi, HTTP isteği
gövdesinden Yapılacaklar öğenin değerini alır.
CreatedAtAction Yöntemi:
Başarılı olursa bir HTTP 201 durum kodu döndürür. HTTP 201 sunucuda yeni bir kaynak oluşturan bir HTTP
POST yöntemi için standart yanıttır.
Yanıta bir Location üst bilgisi ekler. Location üstbilgisi, yeni oluşturulan Yapılacaklar öğesinin URI 'sini
belirtir. Daha fazla bilgi için 10.2.2 201 oluşturuldu.
Location üst bilgisinin URI 'sini oluşturmak için GetTodoItem eyleme başvurur. C# nameof anahtar sözcüğü,
CreatedAtAction çağrısında eylem adının sabit kodlanmasını önlemek için kullanılır.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Test PostTodoItem yöntemi


Projeyi oluşturun.
Postman HTTP yöntemi kümesine POST .
Seçin gövdesi sekmesi.
Seçin ham radyo düğmesi.
Tür kümesine JSON (application/json) .
İstek gövdesinde bir yapılacak iş öğesi için JSON girin:

{
"name":"walk dog",
"isComplete":true
}

Gönder’i seçin.
Bir 405 yöntemine Izin verilmiyor hatası alırsanız, PostTodoItem yöntemi eklendikten sonra projenin
derlenmesinin sonucu büyük olasılıkla oluşur.
Konum üst bilgisi URI test
Seçin üstbilgileri sekmesinde yanıt bölmesi.
Kopyalama konumu üst bilgi değeri:

Yöntemini GET öğesine Ayarla.


URI 'yi yapıştırın (örneğin, https://localhost:5001/api/Todo/2 ).
Gönder’i seçin.

PutTodoItem yöntemi ekleme


Aşağıdaki PutTodoItem yöntemi:

// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
if (id != item.Id)
{
return BadRequest();
}

_context.Entry(item).State = EntityState.Modified;
await _context.SaveChangesAsync();

return NoContent();
}

PutTodoItem benzer PostTodoItem , HTTP PUT kullanır. Yanıt 204 (içerik yok). HTTP belirtimine göre bir PUT İsteği
tüm güncelleştirilmiş varlık yalnızca değişiklikler değil göndermek istemci gerektirir. Kısmi güncelleştirmeleri
desteklemek için kullanma HTTP PATCH.
PutTodoItem çağırırken bir hata alırsanız, veritabanında bir öğe olduğundan emin olmak için GET çağırın.
Test PutTodoItem yöntemi
Bu örnek, uygulama her başlatıldığında başlatılmış olması gereken bellek içi bir veritabanını kullanır. Bir PUT çağrısı
yapmadan önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan
emin olmak için GET çağrısı yapın.
Kimliğine sahip bir yapılacak iş öğesi güncelleştirme = 1 ve "balık akış için" adını girin:

{
"ID":1,
"name":"feed fish",
"isComplete":true
}

Aşağıdaki görüntüde, Postman güncelleştirme gösterilmektedir:


DeleteTodoItem yöntemi ekleme
Aşağıdaki DeleteTodoItem yöntemi:

// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();

return NoContent();
}

DeleteTodoItem Yanıt 204 (içerik yok).


Test DeleteTodoItem yöntemi
Postman bir yapılacak iş öğesini silmek için kullanın:
Yöntem kümesine DELETE .
Silinecek nesnenin URI 'sini ayarlayın (örneğin https://localhost:5001/api/todo/1 ).
Gönder’i seçin.
Örnek uygulama, tüm öğeleri silmenizi sağlar. Ancak, son öğe silindiğinde, API 'nin bir sonraki çağrılışında model
sınıfı Oluşturucu tarafından yeni bir tane oluşturulur.

JavaScript ile Web API 'sini çağırma


Bu bölümde, Web API 'sini çağırmak için JavaScript kullanan bir HTML sayfası eklenir.jQuery isteği başlatır.
JavaScript, sayfayı Web API 'sinin yanıtından alınan ayrıntılarla güncelleştirir.
Uygulamayı statik dosyalara sunacak şekilde yapılandırın ve aşağıdaki vurgulanmış kodla Startup.cs
güncelleştirerek varsayılan dosya eşlemesini etkinleştirin :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseMvc();
}
Oluşturma bir wwwroot proje dizininde klasör.
Adlı bir HTML dosyası ekleyin index.html için wwwroot dizin. Dosyanın içeriğini aşağıdaki biçimlendirme ile
değiştirin:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>To-do CRUD</title>
<style>
input[type='submit'], button, [aria-label] {
cursor: pointer;
}

#spoiler {
display: none;
}

table {
font-family: Arial, sans-serif;
border: 1px solid;
border-collapse: collapse;
}

th {
background-color: #0066CC;
color: white;
}

td {
border: 1px solid;
padding: 5px;
}
</style>
</head>
<body>
<h1>To-do CRUD</h1>
<h3>Add</h3>
<form action="javascript:void(0);" method="POST" onsubmit="addItem()">
<input type="text" id="add-name" placeholder="New to-do">
<input type="submit" value="Add">
</form>

<div id="spoiler">
<h3>Edit</h3>
<form class="my-form">
<input type="hidden" id="edit-id">
<input type="checkbox" id="edit-isComplete">
<input type="text" id="edit-name">
<input type="submit" value="Save">
<a onclick="closeInput()" aria-label="Close">&#10006;</a>
</form>
</div>

<p id="counter"></p>

<table>
<tr>
<th>Is Complete</th>
<th>Name</th>
<th></th>
<th></th>
</tr>
<tbody id="todos"></tbody>
</table>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="site.js"></script>
</body>
</html>

Adlı bir JavaScript dosyası ekleyin site.js için wwwroot dizin. Dosyanın içeriğini aşağıdaki kodla değiştirin:

const uri = "api/todo";


let todos = null;
function getCount(data) {
const el = $("#counter");
let name = "to-do";
if (data) {
if (data > 1) {
name = "to-dos";
}
el.text(data + " " + name);
} else {
el.text("No " + name);
}
}

$(document).ready(function() {
getData();
});

function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
success: function(data) {
const tBody = $("#todos");

$(tBody).empty();

getCount(data.length);

$.each(data, function(key, item) {


const tr = $("<tr></tr>")
.append(
$("<td></td>").append(
$("<input/>", {
type: "checkbox",
disabled: true,
checked: item.isComplete
})
)
)
.append($("<td></td>").text(item.name))
.append(
$("<td></td>").append(
$("<button>Edit</button>").on("click", function() {
editItem(item.id);
})
)
)
.append(
$("<td></td>").append(
$("<button>Delete</button>").on("click", function() {
deleteItem(item.id);
})
)
);

tr.appendTo(tBody);
tr.appendTo(tBody);
});

todos = data;
}
});
}

function addItem() {
const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}

function deleteItem(id) {
$.ajax({
url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});
}

function editItem(id) {
$.each(todos, function(key, item) {
if (item.id === id) {
$("#edit-name").val(item.name);
$("#edit-id").val(item.id);
$("#edit-isComplete")[0].checked = item.isComplete;
}
});
$("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
const item = {
name: $("#edit-name").val(),
isComplete: $("#edit-isComplete").is(":checked"),
id: $("#edit-id").val()
};

$.ajax({
url: uri + "/" + $("#edit-id").val(),
type: "PUT",
accepts: "application/json",
contentType: "application/json",
data: JSON.stringify(item),
success: function(result) {
getData();
}
});

closeInput();
closeInput();
return false;
});

function closeInput() {
$("#spoiler").css({ display: "none" });
}

ASP.NET Core proje başlatma ayarlarında bir değişiklik HTML sayfasını yerel olarak test etmek için gerekli:
Açık Properties\launchSettings.json.
Kaldırma launchUrl , açmak için uygulamayı zorlamak için özellik index.html—projenin varsayılan dosya.

Bu örnek, Web API 'sinin tüm CRUD yöntemlerini çağırır. API çağrıları açıklamaları aşağıda verilmiştir.
Yapılacaklar öğelerinin bir listesini alın
jQuery, bir to-do öğesi dizisini temsil eden JSON döndüren Web API 'sine bir HTTP GET isteği gönderir. success
İstek başarılı olursa geri çağırma işlevi çağrılır. Geri çağırma içinde DOM Yapılacaklar bilgilerle güncelleştirilir.
$(document).ready(function() {
getData();
});

function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
success: function(data) {
const tBody = $("#todos");

$(tBody).empty();

getCount(data.length);

$.each(data, function(key, item) {


const tr = $("<tr></tr>")
.append(
$("<td></td>").append(
$("<input/>", {
type: "checkbox",
disabled: true,
checked: item.isComplete
})
)
)
.append($("<td></td>").text(item.name))
.append(
$("<td></td>").append(
$("<button>Edit</button>").on("click", function() {
editItem(item.id);
})
)
)
.append(
$("<td></td>").append(
$("<button>Delete</button>").on("click", function() {
deleteItem(item.id);
})
)
);

tr.appendTo(tBody);
});

todos = data;
}
});
}

Yapılacak İş Öğesi Ekle


jQuery, istek gövdesinde Yapılacaklar öğesiyle bir HTTP POST isteği gönderir. accepts Ve contentType
seçeneklerini ayarlamak application/json gönderilen ve alınan medya türü belirtmek için. Yapılacak iş öğesi
kullanarak JSON'a dönüştürülür JSON.stringify. API'yi bir başarılı durum kodu döndürdüğünde getData işlevi
HTML tablosu güncelleştirmek için çağrılır.
function addItem() {
const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}

Yapılacak iş öğesini güncelleştirme


Yapılacak iş öğesi güncelleştirilirken bir eklemeye benzerdir. url Öğenin benzersiz tanıtıcısı eklemek için
değişiklikleri ve type olduğu PUT .

$.ajax({
url: uri + "/" + $("#edit-id").val(),
type: "PUT",
accepts: "application/json",
contentType: "application/json",
data: JSON.stringify(item),
success: function(result) {
getData();
}
});

Yapılacak iş öğesi silme


Yapılacak iş öğesi silme gerçekleştirilir ayarlayarak type AJAX çağrısı hedefi üzerinde DELETE ve öğenin benzersiz
tanıtıcısı URL'yi belirterek.

$.ajax({
url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});

Web API 'sine kimlik doğrulama desteği ekleme


ASP.NET Core kimlik, ASP.NET Core Web uygulamalarına Kullanıcı arabirimi (UI) oturum açma işlevselliği ekler.
Web API 'Leri ve maça 'ları güvenli hale getirmek için aşağıdakilerden birini kullanın:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C )]
Identityserver4
Identityserver4, ASP.NET Core 3,0 için bir OpenID Connect ve OAuth 2,0 çerçevesidir. Identityserver4 aşağıdaki
güvenlik özelliklerini sunar:
Hizmet olarak kimlik doğrulaması (AaaS )
Birden çok uygulama türü üzerinde çoklu oturum açma/kapatma (SSO )
API 'Ler için erişim denetimi
Federasyon ağ geçidi
Daha fazla bilgi için bkz. ıdentityserver4 to Welcome.

Ek kaynaklar
Görüntülemek veya Bu öğretici için örnek kodu indirdikten. Bkz: nasıl indirileceğini.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
ASP.NET Core ile Web API 'Leri oluşturma
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core - Öğreticisi 1. 8'de Entity Framework Core ile Razor sayfaları
ASP.NET Core denetleyici eylemlerine yönlendirme
ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri
ASP.NET Core uygulamalarını Azure App Service dağıtma
ASP.NET Core barındırma ve dağıtma
Bu öğreticinin YouTube sürümü
MongoDB ile ASP.NET Core ile web API'si oluşturma
6.12.2019 • 33 minutes to read • Edit Online

Tarafından Pratik Khandelwal ve Scott Addie


Bu öğreticide web API'si temel oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemleri gerçekleştiren
oluşturur bir MongoDB NoSQL veritabanı.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
MongoDB yapılandırın
MongoDB veritabanı oluşturma
MongoDB koleksiyonu ve şema tanımlayın
Bir web API'sini MongoDB CRUD işlemleri gerçekleştirme
JSON serileştirmesini özelleştirme
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core SDK 3.0 veya üzeri
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
MongoDB

MongoDB yapılandırın
Windows kullanıyorsanız MongoDB, varsayılan olarak mongodb\C:\Program Files 'a yüklenir. \Program
Files\MongoDB\Server\ <Version_Number >\ Path ) ortam değişkenine ekleyin. Bu değişiklik yerden MongoDB
erişim sağlar, geliştirme makinenizde.
Mongo kabuğunu veritabanı oluşturma, koleksiyonları yapın ve belgeleri depolamak için aşağıdaki adımları
kullanın. Mongo Kabuğu komutları hakkında daha fazla bilgi için bkz. mongo kabuğunu çalışma.
1. Geliştirme makinenizde verilerin depolanması için bir dizin seçin. Örneğin, C: Windows üzerinde\BooksData
. Yoksa dizini oluşturun. Mongo kabuğunu yeni dizinleri oluşturmaz.
2. Bir komut kabuğunu açın. Varsayılan bağlantı noktası 27017 mongodb'ye bağlanmak için aşağıdaki komutu
çalıştırın. Değiştirmeyi unutmayın <data_directory_path> önceki adımda seçtiğiniz dizini.

mongod --dbpath <data_directory_path>

3. Başka bir komut kabuğu örneği açın. Aşağıdaki komutu çalıştırarak varsayılan test veritabanı'na bağlanma:

mongo

4. Bir komut kabuğu'nda aşağıdaki komutu çalıştırın:


use BookstoreDb

Adlı bir veritabanı zaten mevcut olmayan halinde BookstoreDb oluşturulur. Veritabanı mevcut değilse,
bağlantı işlemleri için açılır.
5. Oluşturma bir Books koleksiyon aşağıdaki komutu kullanarak:

db.createCollection('Books')

Aşağıdaki sonucu görüntülenir:

{ "ok" : 1 }

6. İçin bir şema tanımlayabilir Books toplama ve ekleme iki belge aşağıdaki komutu kullanarak:

db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph
Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])

Aşağıdaki sonucu görüntülenir:

{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5bfd996f7b8e48dc15ff215d"),
ObjectId("5bfd996f7b8e48dc15ff215e")
]
}

NOTE
Bu makalede gösterilen KIMLIK, bu örneği çalıştırdığınızda kimliklerle eşleşmeyecektir.

7. Aşağıdaki komutu kullanarak veritabanında belgelerini görüntüleyin:

db.Books.find({}).pretty()

Aşağıdaki sonucu görüntülenir:

{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
"Name" : "Design Patterns",
"Price" : 54.93,
"Category" : "Computers",
"Author" : "Ralph Johnson"
}
{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
"Name" : "Clean Code",
"Price" : 43.15,
"Category" : "Computers",
"Author" : "Robert C. Martin"
}
Şema girmiş ekler _id türünün özelliği ObjectId her belge için.

Veritabanı hazırdır. ASP.NET Core web API'si oluşturmaya başlayabilirsiniz.

ASP.NET Core web API projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
1. Dosya > Yeni > projesi' ne gidin.
2. ASP.NET Core Web uygulaması proje türünü seçin ve İleri' yi seçin.
3. Projeyi Booksapıolarak adlandırın ve Oluştur' u seçin.
4. .NET Core hedef çerçevesini ve 3,0 ASP.NET Coreseçin. API proje şablonunu seçin ve Oluştur' u seçin.
5. MongoDB için .NET sürücüsünün en son kararlı sürümünü öğrenmek üzere NuGet galerisini ziyaret edin:
MongoDB. Driver . İçinde Paket Yöneticisi Konsolu penceresinde proje kök dizinine gidin. MongoDB için
.NET sürücüsünü yüklemek için aşağıdaki komutu çalıştırın:

Install-Package MongoDB.Driver -Version {VERSION}

Varlık modeli ekleme


1. Ekleme bir modelleri proje kök dizini.
2. Ekleme bir Book sınıfının modelleri aşağıdaki kod ile dizin:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models
{
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

[BsonElement("Name")]
public string BookName { get; set; }

public decimal Price { get; set; }

public string Category { get; set; }

public string Author { get; set; }


}
}

Önceki sınıfta Id özelliği:


Ortak dil çalışma zamanı (CLR ) nesnesini MongoDB koleksiyonuna eşlemek için gereklidir.
, Bu özelliği belgenin birincil anahtarı olarak belirlemek için [BsonId] ile açıklama eklenir.
, Parametreyi ObjectID yapısı yerine tür string olarak geçirmeyi sağlayan
[BsonRepresentation(BsonType.ObjectId)] ile açıklama eklenir. Mongo, string dönüştürmeyi ObjectId
olarak işler.
BookName özelliğine [BsonElement] özniteliğiyle açıklama eklenir. Özniteliğin Name değeri, MongoDB
koleksiyonundaki özellik adını temsil eder.

Yapılandırma modeli ekleme


1. Aşağıdaki veritabanı yapılandırma değerlerini appSettings. JSONöğesine ekleyin:

{
"BookstoreDatabaseSettings": {
"BooksCollectionName": "Books",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookstoreDb"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}

2. Modeller dizinine aşağıdaki kodla bir BookstoreDatabaseSettings.cs dosyası ekleyin:

namespace BooksApi.Models
{
public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
{
public string BooksCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}

public interface IBookstoreDatabaseSettings


{
string BooksCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
}

Yukarıdaki BookstoreDatabaseSettings sınıfı, appSettings. JSON dosyasının BookstoreDatabaseSettings


özellik değerlerini depolamak için kullanılır. JSON ve C# Özellik adları, eşleme sürecini kolaylaştırmak için
aynı şekilde adlandırılır.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:
public void ConfigureServices(IServiceCollection services)
{
// requires using Microsoft.Extensions.Options
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddControllers();
}

Yukarıdaki kodda:
AppSettings. JSON dosyasının BookstoreDatabaseSettings bölüm bağlandığı yapılandırma örneği,
bağımlılık ekleme (dı) kapsayıcısına kaydedilir. Örneğin, bir BookstoreDatabaseSettings nesnesinin
ConnectionString özelliği appSettings. JSONiçindeki BookstoreDatabaseSettings:ConnectionString özelliği
ile doldurulur.
IBookstoreDatabaseSettings arabirimi, tek bir hizmet ömrüile dı 'ye kaydedilir. Eklerken, arabirim örneği
bir BookstoreDatabaseSettings nesnesine çözümlenir.
4. BookstoreDatabaseSettings ve IBookstoreDatabaseSettings başvurularını çözümlemek için aşağıdaki kodu en
üst kısmına ekleyin :

using BooksApi.Models;

CRUD işlemleri hizmeti ekleme


1. Ekleme bir Hizmetleri proje kök dizini.
2. Ekleme bir BookService sınıfının Hizmetleri aşağıdaki kod ile dizin:
using BooksApi.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;

namespace BooksApi.Services
{
public class BookService
{
private readonly IMongoCollection<Book> _books;

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

public List<Book> Get() =>


_books.Find(book => true).ToList();

public Book Get(string id) =>


_books.Find<Book>(book => book.Id == id).FirstOrDefault();

public Book Create(Book book)


{
_books.InsertOne(book);
return book;
}

public void Update(string id, Book bookIn) =>


_books.ReplaceOne(book => book.Id == id, bookIn);

public void Remove(Book bookIn) =>


_books.DeleteOne(book => book.Id == bookIn.Id);

public void Remove(string id) =>


_books.DeleteOne(book => book.Id == id);
}
}

Yukarıdaki kodda, Oluşturucu ekleme yoluyla dı 'den bir IBookstoreDatabaseSettings örneği alınır. Bu teknik,
yapılandırma modeli ekleme bölümüne eklenen appSettings. JSON yapılandırma değerlerine erişim sağlar.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddControllers();
}

Önceki kodda, BookService sınıfı, tüketen sınıflarda Oluşturucu ekleme işlemini desteklemek için DI ile
kaydedilir. BookService , MongoClient doğrudan bağımlılığı sağladığından, tek hizmet ömrü en uygundur.
Resmi Mongo istemci yeniden kullanım yönergeleritemelinde MongoClient , tek bir hizmet ömrü ile birlikte
kaydedilmelidir.
4. BookService başvurusunu çözümlemek için aşağıdaki kodu Startup.cs 'un en üstüne ekleyin:

using BooksApi.Services;

BookService Sınıfını kullanan aşağıdaki MongoDB.Driver veritabanında CRUD işlemleri gerçekleştirmek için üyeleri:
Mongoclient –, veritabanı işlemlerini gerçekleştirmek için sunucu örneğini okur. Bu sınıfın oluşturucusu,
MongoDB bağlantı dizesini sağlanır:

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

Imongodatabase – işlemleri gerçekleştirmek Için Mongo veritabanını temsil eder. Bu öğretici, belirli bir
koleksiyondaki verilere erişim kazanmak için arabirimindeki genel GetCollection<TDocument > (koleksiyon)
yöntemini kullanır. Bu yöntem çağrıldıktan sonra, koleksiyonda CRUD işlemleri gerçekleştirin. İçinde
GetCollection<TDocument>(collection) yöntem çağrısı:

collection Koleksiyon adını temsil eder.


TDocument Bir koleksiyonda depolanan CLR nesne türünü temsil eder.

GetCollection<TDocument>(collection) , koleksiyonu temsil eden bir Mongocollection nesnesi döndürür. Bu


öğreticide, aşağıdaki yöntemlerden koleksiyonunda çağrılır:
Deleteone –, belirtilen arama ölçütleriyle eşleşen tek bir belgeyi siler.
<TDocument > bul –, koleksiyonda belirtilen arama ölçütleriyle eşleşen tüm belgeleri döndürür.
Insertone –, belirtilen nesneyi koleksiyondaki yeni bir belge olarak ekler.
Replaceone –, belirtilen arama ölçütleriyle eşleşen tek belgeyi, belirtilen nesneyle değiştirir.

Denetleyici ekleme
Ekleme bir BooksController sınıfının denetleyicileri aşağıdaki kod ile dizin:

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;

public BooksController(BookService bookService)


{
_bookService = bookService;
}

[HttpGet]
public ActionResult<List<Book>> Get() =>
public ActionResult<List<Book>> Get() =>
_bookService.Get();

[HttpGet("{id:length(24)}", Name = "GetBook")]


public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

return book;
}

[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);

return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);


}

[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Update(id, bookIn);

return NoContent();
}

[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Remove(book.Id);

return NoContent();
}
}
}

Önceki web API denetleyicisi:


Kullanan BookService CRUD işlemleri gerçekleştirmek için sınıf.
GET, POST, PUT ve DELETE HTTP isteklerini desteklemek için eylem yöntemleri içerir.
Bir HTTP 201 yanıtı döndürmek için Create eylemi yönteminde CreatedAtRoute çağırır. Durum kodu 201,
sunucuda yeni bir kaynak oluşturan HTTP POST yöntemi için standart yanıttır. CreatedAtRoute Ayrıca yanıta bir
Location üst bilgisi ekler. Location üstbilgisi yeni oluşturulan kitabın URI 'sini belirtir.

Web API 'sini test etme


1. Uygulamayı derleyin ve çalıştırın.
2. Denetleyicinin parametresiz Get eylem yöntemini sınamak için http://localhost:<port>/api/books gidin.
Aşağıdaki JSON yanıtı gösterilir:

[
{
"id":"5bfd996f7b8e48dc15ff215d",
"bookName":"Design Patterns",
"price":54.93,
"category":"Computers",
"author":"Ralph Johnson"
},
{
"id":"5bfd996f7b8e48dc15ff215e",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}
]

3. Denetleyicinin aşırı yüklenmiş eylem yöntemini sınamak için


Get
http://localhost:<port>/api/books/{id here} gidin. Aşağıdaki JSON yanıtı gösterilir:

{
"id":"{ID}",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}

JSON serileştirme seçeneklerini yapılandırma


Web API 'Sini test etme bölümünde döndürülen JSON yanıtları hakkında iki ayrıntı vardır:
' Varsayılan ortası büyük/küçük harf özelliği, CLR nesnesinin özellik adlarının Pascal büyük küçük harfleriyle
eşleşecek şekilde değiştirilmelidir.
bookName özelliği Name olarak döndürülmelidir.

Önceki gereksinimleri karşılamak için aşağıdaki değişiklikleri yapın:


1. JSON.NET, ASP.NET paylaşılan çerçevesinden kaldırılmıştır. Microsoft. AspNetCore. Mvc.
NewtonsoftJsonöğesine bir paket başvurusu ekleyin.
2. Startup.ConfigureServices ' de, aşağıdaki vurgulanmış kodu AddMvc yöntemi çağrısına zincirle:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddControllers()
.AddNewtonsoftJson(options => options.UseMemberCasing());
}

Önceki değişiklik ile, Web API 'sinin seri hale getirilmiş JSON yanıtındaki Özellik adları CLR nesne türündeki
ilgili özellik adlarıyla eşleşir. Örneğin, Book sınıfının Author özelliği Author olarak serileştirir.
3. Modeller/Book. cs' de, BookName özelliğine aşağıdaki [JsonProperty] özniteliğiyle açıklama ekleyin:

[BsonElement("Name")]
[JsonProperty("Name")]
public string BookName { get; set; }

[JsonProperty] özniteliğinin değeri Name , Web API 'sinin serileştirilmiş JSON yanıtında özellik adını temsil
eder.
4. [JsonProperty] öznitelik başvurusunu çözümlemek için modeller/Book. cs ' nin en üstüne aşağıdaki kodu
ekleyin:

using Newtonsoft.Json;

5. Web API 'Sini test etme bölümünde tanımlanan adımları yineleyin. JSON Özellik adlarındaki farka dikkat
edin.
Bu öğreticide web API'si temel oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemleri gerçekleştiren
oluşturur bir MongoDB NoSQL veritabanı.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
MongoDB yapılandırın
MongoDB veritabanı oluşturma
MongoDB koleksiyonu ve şema tanımlayın
Bir web API'sini MongoDB CRUD işlemleri gerçekleştirme
JSON serileştirmesini özelleştirme
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core SDK 2,2
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
MongoDB
MongoDB yapılandırın
Windows kullanıyorsanız MongoDB, varsayılan olarak mongodb\C:\Program Files 'a yüklenir. \Program
Files\MongoDB\Server\ <Version_Number >\ Path ) ortam değişkenine ekleyin. Bu değişiklik yerden MongoDB
erişim sağlar, geliştirme makinenizde.
Mongo kabuğunu veritabanı oluşturma, koleksiyonları yapın ve belgeleri depolamak için aşağıdaki adımları
kullanın. Mongo Kabuğu komutları hakkında daha fazla bilgi için bkz. mongo kabuğunu çalışma.
1. Geliştirme makinenizde verilerin depolanması için bir dizin seçin. Örneğin, C: Windows üzerinde\BooksData
. Yoksa dizini oluşturun. Mongo kabuğunu yeni dizinleri oluşturmaz.
2. Bir komut kabuğunu açın. Varsayılan bağlantı noktası 27017 mongodb'ye bağlanmak için aşağıdaki komutu
çalıştırın. Değiştirmeyi unutmayın <data_directory_path> önceki adımda seçtiğiniz dizini.

mongod --dbpath <data_directory_path>

3. Başka bir komut kabuğu örneği açın. Aşağıdaki komutu çalıştırarak varsayılan test veritabanı'na bağlanma:

mongo

4. Bir komut kabuğu'nda aşağıdaki komutu çalıştırın:

use BookstoreDb

Adlı bir veritabanı zaten mevcut olmayan halinde BookstoreDb oluşturulur. Veritabanı mevcut değilse,
bağlantı işlemleri için açılır.
5. Oluşturma bir Books koleksiyon aşağıdaki komutu kullanarak:

db.createCollection('Books')

Aşağıdaki sonucu görüntülenir:

{ "ok" : 1 }

6. İçin bir şema tanımlayabilir Books toplama ve ekleme iki belge aşağıdaki komutu kullanarak:

db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph
Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])

Aşağıdaki sonucu görüntülenir:

{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5bfd996f7b8e48dc15ff215d"),
ObjectId("5bfd996f7b8e48dc15ff215e")
]
}
NOTE
Bu makalede gösterilen KIMLIK, bu örneği çalıştırdığınızda kimliklerle eşleşmeyecektir.

7. Aşağıdaki komutu kullanarak veritabanında belgelerini görüntüleyin:

db.Books.find({}).pretty()

Aşağıdaki sonucu görüntülenir:

{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
"Name" : "Design Patterns",
"Price" : 54.93,
"Category" : "Computers",
"Author" : "Ralph Johnson"
}
{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
"Name" : "Clean Code",
"Price" : 43.15,
"Category" : "Computers",
"Author" : "Robert C. Martin"
}

Şema girmiş ekler _id türünün özelliği ObjectId her belge için.
Veritabanı hazırdır. ASP.NET Core web API'si oluşturmaya başlayabilirsiniz.

ASP.NET Core web API projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
1. Dosya > Yeni > projesi' ne gidin.
2. ASP.NET Core Web uygulaması proje türünü seçin ve İleri' yi seçin.
3. Projeyi Booksapıolarak adlandırın ve Oluştur' u seçin.
4. .NET Core hedef çerçevesini ve 2,2 ASP.NET Coreseçin. API proje şablonunu seçin ve Oluştur' u seçin.
5. MongoDB için .NET sürücüsünün en son kararlı sürümünü öğrenmek üzere NuGet galerisini ziyaret edin:
MongoDB. Driver . İçinde Paket Yöneticisi Konsolu penceresinde proje kök dizinine gidin. MongoDB için
.NET sürücüsünü yüklemek için aşağıdaki komutu çalıştırın:

Install-Package MongoDB.Driver -Version {VERSION}

Varlık modeli ekleme


1. Ekleme bir modelleri proje kök dizini.
2. Ekleme bir Book sınıfının modelleri aşağıdaki kod ile dizin:
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models
{
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

[BsonElement("Name")]
public string BookName { get; set; }

public decimal Price { get; set; }

public string Category { get; set; }

public string Author { get; set; }


}
}

Önceki sınıfta Id özelliği:


Ortak dil çalışma zamanı (CLR ) nesnesini MongoDB koleksiyonuna eşlemek için gereklidir.
, Bu özelliği belgenin birincil anahtarı olarak belirlemek için [BsonId] ile açıklama eklenir.
, Parametreyi ObjectID yapısı yerine tür string olarak geçirmeyi sağlayan
[BsonRepresentation(BsonType.ObjectId)] ile açıklama eklenir. Mongo, string dönüştürmeyi ObjectId
olarak işler.
BookName özelliğine [BsonElement] özniteliğiyle açıklama eklenir. Özniteliğin Name değeri, MongoDB
koleksiyonundaki özellik adını temsil eder.

Yapılandırma modeli ekleme


1. Aşağıdaki veritabanı yapılandırma değerlerini appSettings. JSONöğesine ekleyin:

{
"BookstoreDatabaseSettings": {
"BooksCollectionName": "Books",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookstoreDb"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}

2. Modeller dizinine aşağıdaki kodla bir BookstoreDatabaseSettings.cs dosyası ekleyin:


namespace BooksApi.Models
{
public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
{
public string BooksCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}

public interface IBookstoreDatabaseSettings


{
string BooksCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
}

Yukarıdaki BookstoreDatabaseSettings sınıfı, appSettings. JSON dosyasının BookstoreDatabaseSettings


özellik değerlerini depolamak için kullanılır. JSON ve C# Özellik adları, eşleme sürecini kolaylaştırmak için
aynı şekilde adlandırılır.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Yukarıdaki kodda:
AppSettings. JSON dosyasının BookstoreDatabaseSettings bölüm bağlandığı yapılandırma örneği,
bağımlılık ekleme (dı) kapsayıcısına kaydedilir. Örneğin, bir BookstoreDatabaseSettings nesnesinin
ConnectionString özelliği appSettings. JSONiçindeki BookstoreDatabaseSettings:ConnectionString özelliği
ile doldurulur.
IBookstoreDatabaseSettings arabirimi, tek bir hizmet ömrüile dı 'ye kaydedilir. Eklerken, arabirim örneği
bir BookstoreDatabaseSettings nesnesine çözümlenir.
4. BookstoreDatabaseSettings ve IBookstoreDatabaseSettings başvurularını çözümlemek için aşağıdaki kodu en
üst kısmına ekleyin :

using BooksApi.Models;

CRUD işlemleri hizmeti ekleme


1. Ekleme bir Hizmetleri proje kök dizini.
2. Ekleme bir BookService sınıfının Hizmetleri aşağıdaki kod ile dizin:
using BooksApi.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;

namespace BooksApi.Services
{
public class BookService
{
private readonly IMongoCollection<Book> _books;

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

public List<Book> Get() =>


_books.Find(book => true).ToList();

public Book Get(string id) =>


_books.Find<Book>(book => book.Id == id).FirstOrDefault();

public Book Create(Book book)


{
_books.InsertOne(book);
return book;
}

public void Update(string id, Book bookIn) =>


_books.ReplaceOne(book => book.Id == id, bookIn);

public void Remove(Book bookIn) =>


_books.DeleteOne(book => book.Id == bookIn.Id);

public void Remove(string id) =>


_books.DeleteOne(book => book.Id == id);
}
}

Yukarıdaki kodda, Oluşturucu ekleme yoluyla dı 'den bir IBookstoreDatabaseSettings örneği alınır. Bu teknik,
yapılandırma modeli ekleme bölümüne eklenen appSettings. JSON yapılandırma değerlerine erişim sağlar.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Önceki kodda, BookService sınıfı, tüketen sınıflarda Oluşturucu ekleme işlemini desteklemek için DI ile
kaydedilir. BookService , MongoClient doğrudan bağımlılığı sağladığından, tek hizmet ömrü en uygundur.
Resmi Mongo istemci yeniden kullanım yönergeleritemelinde MongoClient , tek bir hizmet ömrü ile birlikte
kaydedilmelidir.
4. BookService başvurusunu çözümlemek için aşağıdaki kodu Startup.cs 'un en üstüne ekleyin:

using BooksApi.Services;

BookService Sınıfını kullanan aşağıdaki MongoDB.Driver veritabanında CRUD işlemleri gerçekleştirmek için üyeleri:
Mongoclient –, veritabanı işlemlerini gerçekleştirmek için sunucu örneğini okur. Bu sınıfın oluşturucusu,
MongoDB bağlantı dizesini sağlanır:

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

Imongodatabase – işlemleri gerçekleştirmek Için Mongo veritabanını temsil eder. Bu öğretici, belirli bir
koleksiyondaki verilere erişim kazanmak için arabirimindeki genel GetCollection<TDocument > (koleksiyon)
yöntemini kullanır. Bu yöntem çağrıldıktan sonra, koleksiyonda CRUD işlemleri gerçekleştirin. İçinde
GetCollection<TDocument>(collection) yöntem çağrısı:

collection Koleksiyon adını temsil eder.


TDocument Bir koleksiyonda depolanan CLR nesne türünü temsil eder.

GetCollection<TDocument>(collection) , koleksiyonu temsil eden bir Mongocollection nesnesi döndürür. Bu


öğreticide, aşağıdaki yöntemlerden koleksiyonunda çağrılır:
Deleteone –, belirtilen arama ölçütleriyle eşleşen tek bir belgeyi siler.
<TDocument > bul –, koleksiyonda belirtilen arama ölçütleriyle eşleşen tüm belgeleri döndürür.
Insertone –, belirtilen nesneyi koleksiyondaki yeni bir belge olarak ekler.
Replaceone –, belirtilen arama ölçütleriyle eşleşen tek belgeyi, belirtilen nesneyle değiştirir.

Denetleyici ekleme
Ekleme bir BooksController sınıfının denetleyicileri aşağıdaki kod ile dizin:

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;

public BooksController(BookService bookService)


{
_bookService = bookService;
}

[HttpGet]
[HttpGet]
public ActionResult<List<Book>> Get() =>
_bookService.Get();

[HttpGet("{id:length(24)}", Name = "GetBook")]


public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

return book;
}

[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);

return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);


}

[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Update(id, bookIn);

return NoContent();
}

[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Remove(book.Id);

return NoContent();
}
}
}

Önceki web API denetleyicisi:


Kullanan BookService CRUD işlemleri gerçekleştirmek için sınıf.
GET, POST, PUT ve DELETE HTTP isteklerini desteklemek için eylem yöntemleri içerir.
Bir HTTP 201 yanıtı döndürmek için Create eylemi yönteminde CreatedAtRoute çağırır. Durum kodu 201,
sunucuda yeni bir kaynak oluşturan HTTP POST yöntemi için standart yanıttır. CreatedAtRoute Ayrıca yanıta bir
Location üst bilgisi ekler. Location üstbilgisi yeni oluşturulan kitabın URI 'sini belirtir.
Web API 'sini test etme
1. Uygulamayı derleyin ve çalıştırın.
2. Denetleyicinin parametresiz Get eylem yöntemini sınamak için http://localhost:<port>/api/books gidin.
Aşağıdaki JSON yanıtı gösterilir:

[
{
"id":"5bfd996f7b8e48dc15ff215d",
"bookName":"Design Patterns",
"price":54.93,
"category":"Computers",
"author":"Ralph Johnson"
},
{
"id":"5bfd996f7b8e48dc15ff215e",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}
]

3. Denetleyicinin aşırı yüklenmiş eylem yöntemini sınamak için


Get
http://localhost:<port>/api/books/{id here} gidin. Aşağıdaki JSON yanıtı gösterilir:

{
"id":"{ID}",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}

JSON serileştirme seçeneklerini yapılandırma


Web API 'Sini test etme bölümünde döndürülen JSON yanıtları hakkında iki ayrıntı vardır:
' Varsayılan ortası büyük/küçük harf özelliği, CLR nesnesinin özellik adlarının Pascal büyük küçük harfleriyle
eşleşecek şekilde değiştirilmelidir.
bookName özelliği Name olarak döndürülmelidir.

Önceki gereksinimleri karşılamak için aşağıdaki değişiklikleri yapın:


1. Startup.ConfigureServices ' de, aşağıdaki vurgulanmış kodu AddMvc yöntemi çağrısına zincirle:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddMvc()
.AddJsonOptions(options => options.UseMemberCasing())
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Önceki değişiklik ile, Web API 'sinin seri hale getirilmiş JSON yanıtındaki Özellik adları CLR nesne türündeki
ilgili özellik adlarıyla eşleşir. Örneğin, Book sınıfının Author özelliği Author olarak serileştirir.
2. Modeller/Book. cs' de, BookName özelliğine aşağıdaki [JsonProperty] özniteliğiyle açıklama ekleyin:

[BsonElement("Name")]
[JsonProperty("Name")]
public string BookName { get; set; }

[JsonProperty] özniteliğinin değeri Name , Web API 'sinin serileştirilmiş JSON yanıtında özellik adını temsil
eder.
3. [JsonProperty] öznitelik başvurusunu çözümlemek için modeller/Book. cs ' nin en üstüne aşağıdaki kodu
ekleyin:

using Newtonsoft.Json;

4. Web API 'Sini test etme bölümünde tanımlanan adımları yineleyin. JSON Özellik adlarındaki farka dikkat
edin.

Web API 'sine kimlik doğrulama desteği ekleme


ASP.NET Core kimlik, ASP.NET Core Web uygulamalarına Kullanıcı arabirimi (UI) oturum açma işlevselliği ekler.
Web API 'Leri ve maça 'ları güvenli hale getirmek için aşağıdakilerden birini kullanın:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C )]
Identityserver4
Identityserver4, ASP.NET Core 3,0 için bir OpenID Connect ve OAuth 2,0 çerçevesidir. Identityserver4 aşağıdaki
güvenlik özelliklerini sunar:
Hizmet olarak kimlik doğrulaması (AaaS )
Birden çok uygulama türü üzerinde çoklu oturum açma/kapatma (SSO )
API 'Ler için erişim denetimi
Federasyon ağ geçidi
Daha fazla bilgi için bkz. ıdentityserver4 to Welcome.

Sonraki adımlar
ASP.NET Core web API'leri oluşturmaya daha fazla bilgi için aşağıdaki kaynaklara bakın:
Bu makalenin YouTube sürümü
ASP.NET Core ile Web API 'Leri oluşturma
ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri
Öğretici: JavaScript ile ASP.NET Core Web API 'SI
çağırma
3.12.2019 • 7 minutes to read • Edit Online

Rick Anderson tarafından


Bu öğreticide, Fetch APIkullanılarak JavaScript ile ASP.NET Core Web API 'sinin nasıl çağrılacağını
gösterilmektedir.
ASP.NET Core 2,2 için, JavaScript ile Web API 'Sini çağırma2,2 sürümüne bakın.

Prerequisites
Tüm öğreticiyi: Web API 'Si oluşturma
CSS, HTML ve JavaScript ile benzerlik

JavaScript ile Web API 'sini çağırma


Bu bölümde, Yapılacaklar öğeleri oluşturmak ve yönetmek için form içeren bir HTML sayfası ekleyeceksiniz. Olay
işleyicileri sayfadaki öğelere iliştirilir. Olay işleyicileri, Web API 'sinin eylem yöntemlerine HTTP istekleri sonucu
vermez. Fetch API 'sinin fetch işlevi her HTTP isteğini başlatır.
fetch işlevi, bir Response nesnesi olarak temsil edilen bir HTTP yanıtı içeren bir Promise nesnesi döndürür.
Ortak bir model, Response nesnesinde json işlevini çağırarak JSON yanıt gövdesini ayıklamaya yönelik bir
modeldir. JavaScript, sayfayı Web API 'sinin yanıtından alınan ayrıntılarla güncelleştirir.
En basit fetch çağrısı, yolu temsil eden tek bir parametreyi kabul eder. init nesnesi olarak bilinen ikinci bir
parametre isteğe bağlıdır. init HTTP isteğini yapılandırmak için kullanılır.
1. Uygulamayı statik dosyaları sunacak ve varsayılan dosya eşlemesini etkinleştirecekşekilde yapılandırın.
Aşağıdaki vurgulanan kod Startup.cs Configure yönteminde gereklidir:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
2. Proje kökünde bir Wwwroot klasörü oluşturun.
3. Wwwroot klasörü içinde bir js klasörü oluşturun.
4. Wwwroot klasörüne index. HTML adlı bir HTML dosyası ekleyin. İndex. html içeriğini aşağıdaki
biçimlendirme ile değiştirin:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>To-do CRUD</title>
<link rel="stylesheet" href="css/site.css" />
</head>
<body>
<h1>To-do CRUD</h1>
<h3>Add</h3>
<form action="javascript:void(0);" method="POST" onsubmit="addItem()">
<input type="text" id="add-name" placeholder="New to-do">
<input type="submit" value="Add">
</form>

<div id="editForm">
<h3>Edit</h3>
<form action="javascript:void(0);" onsubmit="updateItem()">
<input type="hidden" id="edit-id">
<input type="checkbox" id="edit-isComplete">
<input type="text" id="edit-name">
<input type="submit" value="Save">
<a onclick="closeInput()" aria-label="Close">&#10006;</a>
</form>
</div>

<p id="counter"></p>

<table>
<tr>
<th>Is Complete?</th>
<th>Name</th>
<th></th>
<th></th>
</tr>
<tbody id="todos"></tbody>
</table>

<script src="js/site.js" asp-append-version="true"></script>


<script type="text/javascript">
getItems();
</script>
</body>
</html>

5. Wwwroot/js klasörüne site. js adlı bir JavaScript dosyası ekleyin. Site. js içeriğini aşağıdaki kodla değiştirin:

const uri = 'api/TodoItems';


let todos = [];

function getItems() {
fetch(uri)
.then(response => response.json())
.then(data => _displayItems(data))
.catch(error => console.error('Unable to get items.', error));
}

function addItem() {
const addNameTextbox = document.getElementById('add-name');
const addNameTextbox = document.getElementById('add-name');

const item = {
isComplete: false,
name: addNameTextbox.value.trim()
};

fetch(uri, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item)
})
.then(response => response.json())
.then(() => {
getItems();
addNameTextbox.value = '';
})
.catch(error => console.error('Unable to add item.', error));
}

function deleteItem(id) {
fetch(`${uri}/${id}`, {
method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));
}

function displayEditForm(id) {
const item = todos.find(item => item.id === id);

document.getElementById('edit-name').value = item.name;
document.getElementById('edit-id').value = item.id;
document.getElementById('edit-isComplete').checked = item.isComplete;
document.getElementById('editForm').style.display = 'block';
}

function updateItem() {
const itemId = document.getElementById('edit-id').value;
const item = {
id: parseInt(itemId, 10),
isComplete: document.getElementById('edit-isComplete').checked,
name: document.getElementById('edit-name').value.trim()
};

fetch(`${uri}/${itemId}`, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item)
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));

closeInput();

return false;
}

function closeInput() {
document.getElementById('editForm').style.display = 'none';
}

function _displayCount(itemCount) {
const name = (itemCount === 1) ? 'to-do' : 'to-dos';
const name = (itemCount === 1) ? 'to-do' : 'to-dos';

document.getElementById('counter').innerText = `${itemCount} ${name}`;


}

function _displayItems(data) {
const tBody = document.getElementById('todos');
tBody.innerHTML = '';

_displayCount(data.length);

const button = document.createElement('button');

data.forEach(item => {
let isCompleteCheckbox = document.createElement('input');
isCompleteCheckbox.type = 'checkbox';
isCompleteCheckbox.disabled = true;
isCompleteCheckbox.checked = item.isComplete;

let editButton = button.cloneNode(false);


editButton.innerText = 'Edit';
editButton.setAttribute('onclick', `displayEditForm(${item.id})`);

let deleteButton = button.cloneNode(false);


deleteButton.innerText = 'Delete';
deleteButton.setAttribute('onclick', `deleteItem(${item.id})`);

let tr = tBody.insertRow();

let td1 = tr.insertCell(0);


td1.appendChild(isCompleteCheckbox);

let td2 = tr.insertCell(1);


let textNode = document.createTextNode(item.name);
td2.appendChild(textNode);

let td3 = tr.insertCell(2);


td3.appendChild(editButton);

let td4 = tr.insertCell(3);


td4.appendChild(deleteButton);
});

todos = data;
}

HTML sayfasını yerel olarak test etmek için ASP.NET Core projesinin başlatma ayarlarındaki bir değişikliğin
yapılması gerekebilir:
1. Properties\launchSettings.JSON'i açın.
2. Uygulamayı, projenin varsayılan dosyası—Dizin. html ' de açmaya zorlamak için launchUrl özelliğini kaldırın.

Bu örnek, Web API 'sinin tüm CRUD yöntemlerini çağırır. Web API isteklerinin açıklamaları aşağıda verilmiştir.
Yapılacaklar öğelerinin bir listesini alın
Aşağıdaki kodda, API/todoıtems yoluna BIR http get isteği gönderilir:

fetch(uri)
.then(response => response.json())
.then(data => _displayItems(data))
.catch(error => console.error('Unable to get items.', error));

Web API 'SI başarılı bir durum kodu döndürdüğünde _displayItems işlevi çağrılır. _displayItems tarafından
kabul edilen dizi parametresindeki her Yapılacaklar öğesi, Düzenle ve Sil düğmeleriyle bir tabloya eklenir. Web
API isteği başarısız olursa, tarayıcının konsoluna bir hata kaydedilir.
Yapılacaklar öğesi ekleme
Aşağıdaki kodda:
item değişken, yapılacaklar öğesinin nesne sabit gösterimini oluşturmak için bildirilmiştir.
Aşağıdaki seçeneklerle bir getirme isteği yapılandırılır:
method — HTTP eyleminin SONRASı fiilini belirtir.
body —, istek gövdesinin JSON temsilini belirtir. JSON, item ' de depolanan nesne sabit değeri JSON.
stringbelirt işlevine geçirilerek oluşturulur.
headers — Accept ve Content-Type HTTP istek üst bilgilerini belirtir. Her iki üst bilgi de
application/json olarak ayarlanır ve sırasıyla, alınan ve gönderilen medya türünü belirtir.
API/todoıtems yoluna BIR http post isteği gönderilir.

function addItem() {
const addNameTextbox = document.getElementById('add-name');

const item = {
isComplete: false,
name: addNameTextbox.value.trim()
};

fetch(uri, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item)
})
.then(response => response.json())
.then(() => {
getItems();
addNameTextbox.value = '';
})
.catch(error => console.error('Unable to add item.', error));
}

Web API 'SI başarılı bir durum kodu döndürdüğünde, getItems işlevi HTML tablosunu güncelleştirmek için
çağrılır. Web API isteği başarısız olursa, tarayıcının konsoluna bir hata kaydedilir.
Yapılacaklar öğesini güncelleştirme
Bir yapılacaklar öğesinin güncelleştirilmesi bir tane eklemeye benzer; Ancak, iki önemli fark vardır:
Yol, güncelleştirilecek öğenin benzersiz tanımlayıcısı ile sone düzeltildi. Örneğin, api/todoıtems/1.
HTTP eylemi fiili, method seçeneği tarafından belirtilen şekilde konur.

fetch(`${uri}/${itemId}`, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item)
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));

Bir yapılacaklar öğesini silme


Bir yapılacaklar öğesini silmek için, isteğin method seçeneğini DELETE olarak ayarlayın ve URL 'de öğenin
benzersiz tanımlayıcısını belirtin.

fetch(`${uri}/${id}`, {
method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));

Web API 'SI yardım sayfaları oluşturmayı öğrenmek için bir sonraki öğreticiye ilerleyin:
Swashbuckle ve ASP.NET Core kullanmaya başlayın
ASP.NET Core ile yerel mobil uygulamalar için arka uç
hizmetleri oluşturma
6.12.2019 • 12 minutes to read • Edit Online

Steve Smith tarafından


Mobil uygulamalar ASP.NET Core arka uç hizmetleriyle iletişim kurabilir. İOS simülatörleri ve Android
öykünücülerinden yerel Web hizmetlerini bağlama yönergeleri için bkz. IOS simülatörleri ve Android
Öykünücülerinden yerel Web hizmetlerine bağlanma.
Örnek arka uç hizmetleri kodunu görüntüle veya indir

Örnek yerel mobil uygulama


Bu öğreticide, yerel mobil uygulamaları desteklemek üzere ASP.NET Core MVC kullanarak arka uç hizmetleri
oluşturma gösterilmektedir. Android, iOS, Windows Evrensel ve Windows Phone cihazları için ayrı yerel istemciler
içeren, Xamarin Forms ToDoRest uygulamasını yerel istemcisi olarak kullanır. Yerel uygulamayı oluşturmak (ve
gerekli ücretsiz Xamarin araçlarını yüklemek) ve Xamarin örnek çözümünü indirmek için bağlantılı öğreticiyi
izleyebilirsiniz. Xamarin örneği, bu makalenin ASP.NET Core uygulamasının yerini aldığı bir ASP.NET Web API 2
Services projesi içerir (istemci tarafından gerekli olmayan değişiklikler olmadan).
Özellikler
ToDoRest uygulaması, yapılacaklar öğelerini listelemeyi, eklemeyi, silmeyi ve güncellemeyi destekler. Her öğe bir
KIMLIĞE, bir ada, notlara ve henüz gerçekleştirilip yapılmadığını gösteren bir özelliğe sahiptir.
Öğelerin ana görünümü yukarıda gösterildiği gibi, her öğenin adını listeler ve bir onay işaretiyle gerçekleştirilip
yapılmadığını gösterir.
+ simgesine dokunarak öğe Ekle iletişim kutusu açılır:
Ana liste ekranındaki bir öğeye dokunduğunuzda, öğenin adı, notları ve bitti ayarlarının değiştirilebilmesi veya
öğenin silinebileceği bir düzenleme iletişim kutusu açılır.
Bu örnek varsayılan olarak, salt okuma işlemlerine izin veren developer.xamarin.com adresinde barındırılan arka uç
hizmetlerini kullanacak şekilde yapılandırılmıştır. Bilgisayarınızı bilgisayarınızda çalışan bir sonraki bölümde
oluşturulan ASP.NET Core uygulamasına karşı test etmek için uygulamanın RestUrl sabitini güncelleştirmeniz
gerekir. ToDoREST projesine gidin ve Constants.cs dosyasını açın. RestUrl , makinenizin IP adresini (localhost veya
127.0.0.1 değil) içeren bir URL ile değiştirin. bu adres, makineden değil cihaz öykünücüsünde kullanılıyor. Bağlantı
noktası numarasını da (5000) dahil edin. Hizmetlerinizin bir cihazla birlikte çalıştığını test etmek için, bu bağlantı
noktasına erişimi engelleyen etkin bir güvenlik duvarı olmadığından emin olun.

// URL of REST service (Xamarin ReadOnly Service)


//public static string RestUrl = "http://developer.xamarin.com:8081/api/todoitems{0}";

// use your machine's IP address


public static string RestUrl = "http://192.168.1.207:5000/api/todoitems/{0}";

ASP.NET Core projesi oluşturma


Visual Studio 'da yeni bir ASP.NET Core Web uygulaması oluşturun. Web API şablonunu ve kimlik doğrulaması
yok ' ı seçin. Projeyi ToDoApiolarak adlandırın.
Uygulama, 5000 numaralı bağlantı noktasına yapılan tüm isteklere yanıt vermelidir. Bunu başarmak için program.cs
'i .UseUrls("http://*:5000") ekleyin:

var host = new WebHostBuilder()


.UseKestrel()
.UseUrls("http://*:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

NOTE
Varsayılan olarak yerel olmayan istekleri yok sayan IIS Express arkasında değil, uygulamayı doğrudan çalıştırdığınızdan emin
olun. Bir komut isteminden DotNet Run komutunu çalıştırın veya Visual Studio araç çubuğunda hata ayıklama hedefi açılır
listesinden uygulama adı profilini seçin.

Yapılacaklar öğelerini temsil etmek için bir model sınıfı ekleyin. Gerekli alanları [Required] özniteliğiyle işaretleyin:
using System.ComponentModel.DataAnnotations;

namespace ToDoApi.Models
{
public class ToDoItem
{
[Required]
public string ID { get; set; }

[Required]
public string Name { get; set; }

[Required]
public string Notes { get; set; }

public bool Done { get; set; }


}
}

API yöntemleri, verilerle çalışmak için bir yol gerektirir. Özgün Xamarin örneğinde kullanılan IToDoRepository
arabirimini kullanın:

using System.Collections.Generic;
using ToDoApi.Models;

namespace ToDoApi.Interfaces
{
public interface IToDoRepository
{
bool DoesItemExist(string id);
IEnumerable<ToDoItem> All { get; }
ToDoItem Find(string id);
void Insert(ToDoItem item);
void Update(ToDoItem item);
void Delete(string id);
}
}

Bu örnek için, uygulama yalnızca özel bir öğe koleksiyonu kullanır:

using System.Collections.Generic;
using System.Linq;
using ToDoApi.Interfaces;
using ToDoApi.Models;

namespace ToDoApi.Services
{
public class ToDoRepository : IToDoRepository
{
private List<ToDoItem> _toDoList;

public ToDoRepository()
{
InitializeData();
}

public IEnumerable<ToDoItem> All


{
get { return _toDoList; }
}

public bool DoesItemExist(string id)


{
return _toDoList.Any(item => item.ID == id);
return _toDoList.Any(item => item.ID == id);
}

public ToDoItem Find(string id)


{
return _toDoList.FirstOrDefault(item => item.ID == id);
}

public void Insert(ToDoItem item)


{
_toDoList.Add(item);
}

public void Update(ToDoItem item)


{
var todoItem = this.Find(item.ID);
var index = _toDoList.IndexOf(todoItem);
_toDoList.RemoveAt(index);
_toDoList.Insert(index, item);
}

public void Delete(string id)


{
_toDoList.Remove(this.Find(id));
}

private void InitializeData()


{
_toDoList = new List<ToDoItem>();

var todoItem1 = new ToDoItem


{
ID = "6bb8a868-dba1-4f1a-93b7-24ebce87e243",
Name = "Learn app development",
Notes = "Attend Xamarin University",
Done = true
};

var todoItem2 = new ToDoItem


{
ID = "b94afb54-a1cb-4313-8af3-b7511551b33b",
Name = "Develop apps",
Notes = "Use Xamarin Studio/Visual Studio",
Done = false
};

var todoItem3 = new ToDoItem


{
ID = "ecfa6f80-3671-4911-aabe-63cc442c1ecf",
Name = "Publish apps",
Notes = "All app stores",
Done = false,
};

_toDoList.Add(todoItem1);
_toDoList.Add(todoItem2);
_toDoList.Add(todoItem3);
}
}
}

Startup.cs'de uygulamayı yapılandırın:


public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();

services.AddSingleton<IToDoRepository,ToDoRepository>();
}

Bu noktada, ToDoItemsControlleroluşturmak için hazırsınız demektir.

TIP
ASP.NET Core MVC ve Visual Studio ile Ilk Web API 'Nizi derlemebölümünde Web API 'leri oluşturma hakkında daha fazla bilgi
edinin.

Denetleyici oluşturma
Projeye yeni bir denetleyici ekleyin, ToDoItemsController. Microsoft. AspNetCore. Mvc. Controller öğesinden
devralması gerekir. Denetleyicinin api/todoitems başlayan yollara yapılan istekleri işleyeceğini göstermek için bir
Route özniteliği ekleyin. Yoldaki [controller] belirteci denetleyicinin adıyla ( Controller sonekini atlayarak)
değiştirilmiştir ve özellikle genel yollar için yararlıdır. Yönlendirmehakkında daha fazla bilgi edinin.
Denetleyici bir IToDoRepository işlevini gerektirir; denetleyicinin Oluşturucusu aracılığıyla bu türde bir örnek
isteyin. Çalışma zamanında bu örnek, çerçevenin bağımlılık eklemedesteği kullanılarak sağlanacaktır.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ToDoApi.Interfaces;
using ToDoApi.Models;

namespace ToDoApi.Controllers
{
[Route("api/[controller]")]
public class ToDoItemsController : Controller
{
private readonly IToDoRepository _toDoRepository;

public ToDoItemsController(IToDoRepository toDoRepository)


{
_toDoRepository = toDoRepository;
}

Bu API, veri kaynağında CRUD (oluşturma, okuma, güncelleştirme, silme) işlemleri gerçekleştirmek için dört farklı
HTTP fiillerini destekler. Bunların en basit yolu, bir HTTP GET isteğine karşılık gelen okuma işlemidir.
Öğeleri okuma
Öğelerin bir listesini istemek List metoduna yönelik GET isteğiyle yapılır. List yönteminde [HttpGet] özniteliği,
bu eylemin yalnızca GET isteklerini işleyeceği anlamına gelir. Bu eylemin yolu, denetleyicide belirtilen yoldur. Yolun
bir parçası olarak eylem adını kullanmanız gerekmez. Her bir eylemin benzersiz ve belirsiz bir yol içerdiğinden emin
olmanız yeterlidir. Yönlendirme öznitelikleri, belirli yolları oluşturmak için hem denetleyiciye hem de Yöntem
düzeylerine uygulanabilir.
[HttpGet]
public IActionResult List()
{
return Ok(_toDoRepository.All);
}

List yöntemi, JSON olarak serileştirilmiş bir 200 Tamam yanıt kodu ve tüm ToDo öğelerini döndürür.
Yeni API yönteminizi, Postmangibi çeşitli araçlar kullanarak test edebilirsiniz:

Öğe oluşturma
Kurala göre, yeni veri öğeleri oluşturmak HTTP POST fiili ile eşleştirilir. Create yöntemine uygulanan bir
[HttpPost] özniteliği vardır ve bir ToDoItem örneği kabul eder. item bağımsız değişkeni POST gövdesinde
geçirildiğinden, bu parametre [FromBody] özniteliğini belirtir.
Yöntemi içinde, öğe geçerliliği için denetlenir ve veri deposunda daha önce bulunur ve herhangi bir sorun oluşursa,
depo kullanılarak eklenir. ModelState.IsValid , model doğrulamasıgerçekleştirir ve Kullanıcı girişini kabul eden her
API yönteminde yapılmalıdır.
[HttpPost]
public IActionResult Create([FromBody] ToDoItem item)
{
try
{
if (item == null || !ModelState.IsValid)
{
return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
}
bool itemExists = _toDoRepository.DoesItemExist(item.ID);
if (itemExists)
{
return StatusCode(StatusCodes.Status409Conflict, ErrorCode.TodoItemIDInUse.ToString());
}
_toDoRepository.Insert(item);
}
catch (Exception)
{
return BadRequest(ErrorCode.CouldNotCreateItem.ToString());
}
return Ok(item);
}

Örnek, mobil istemciye geçirilen hata kodlarını içeren bir Enum kullanır:

public enum ErrorCode


{
TodoItemNameAndNotesRequired,
TodoItemIDInUse,
RecordNotFound,
CouldNotCreateItem,
CouldNotUpdateItem,
CouldNotDeleteItem
}

İsteğin gövdesinde JSON biçiminde yeni nesne sağlayan POST fiilini kullanarak yeni öğe ekleme işlemini test edin.
Ayrıca, application/json``Content-Type belirten bir istek üst bilgisi de eklemeniz gerekir.
Yöntemi, yanıtta yeni oluşturulan öğeyi döndürür.
Öğeler güncelleştiriliyor
Kayıtları değiştirme HTTP PUT istekleri kullanılarak yapılır. Bu değişiklik dışında Edit yöntemi neredeyse Create
ile aynıdır. Kayıt bulunmazsa Edit eyleminin bir NotFound (404) yanıtı dönebileceğini unutmayın.

[HttpPut]
public IActionResult Edit([FromBody] ToDoItem item)
{
try
{
if (item == null || !ModelState.IsValid)
{
return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
}
var existingItem = _toDoRepository.Find(item.ID);
if (existingItem == null)
{
return NotFound(ErrorCode.RecordNotFound.ToString());
}
_toDoRepository.Update(item);
}
catch (Exception)
{
return BadRequest(ErrorCode.CouldNotUpdateItem.ToString());
}
return NoContent();
}
Postman ile test etmek için fiili ' i koymak için değiştirin. İsteğin gövdesinde güncelleştirilmiş nesne verilerini
belirtin.

Bu yöntem, başarılı olduğunda, önceden var olan API ile tutarlılık için NoContent (204) yanıtı döndürür.
Öğeleri silme
Kayıtları silme işlemi, hizmete SILME istekleri yapılarak ve silinecek öğenin KIMLIĞI geçirilerek gerçekleştirilir.
Güncelleştirmelerde olduğu gibi, mevcut olmayan öğelere yönelik istekler NotFound yanıtlarını alacaktır. Aksi
takdirde, başarılı bir istek NoContent (204) yanıtı alır.
[HttpDelete("{id}")]
public IActionResult Delete(string id)
{
try
{
var item = _toDoRepository.Find(id);
if (item == null)
{
return NotFound(ErrorCode.RecordNotFound.ToString());
}
_toDoRepository.Delete(id);
}
catch (Exception)
{
return BadRequest(ErrorCode.CouldNotDeleteItem.ToString());
}
return NoContent();
}

Silme işlevinin test edilirken, isteğin gövdesinde hiçbir şey gerekmediği unutulmamalıdır.

Ortak Web API kuralları


Uygulamanız için arka uç hizmetlerini geliştirirken, çapraz kesme sorunlarını işlemeye yönelik tutarlı bir kural veya
ilke kümesiyle birlikte çalışmak isteyeceksiniz. Örneğin, yukarıda gösterilen hizmette, bulunamayan belirli kayıtlara
yönelik istekler BadRequest bir yanıt yerine NotFound yanıtı aldı. Benzer şekilde, bu hizmete uygulanan ve model
bağlantılı türlerde geçen komutlar ModelState.IsValid her zaman denetlenir ve geçersiz model türleri için bir
BadRequest döndürülür.
API 'leriniz için ortak bir ilke tanımladıktan sonra, genellikle bunu bir filtredekapsülleyebilirsiniz. ASP.NET Core
MVC uygulamalarında ortak API ilkelerini kapsüllemekhakkında daha fazla bilgi edinin.

Ek kaynaklar
Kimlik Doğrulaması ve Yetkilendirme
Öğretici: ASP.NET Core SignalR ile çalışmaya başlama
26.11.2019 • 21 minutes to read • Edit Online

Bu öğreticide SignalRkullanarak gerçek zamanlı bir uygulama oluşturmanın temelleri öğretilir. Aşağıdakileri nasıl
yapacağınızı öğrenirsiniz:
Web projesi oluşturun.
SignalR istemci kitaplığı ekleyin.
SignalR hub 'ı oluşturun.
Projeyi SignalRkullanacak şekilde yapılandırın.
Herhangi bir istemciden tüm bağlı istemcilere ileti gönderen kodu ekleyin.
Sonunda, çalışan bir sohbet uygulamanız olacaktır:

Önkoşullar
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Web uygulaması projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Menüden dosya > yeni proje' yi seçin.
Yeni proje oluştur iletişim kutusunda ASP.NET Core Web uygulaması' nı seçin ve ardından İleri' yi
seçin.
Yeni projenizi yapılandırın iletişim kutusunda, proje signalrchatadını adlandırın ve ardından Oluştur' u
seçin.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda .net Core ve ASP.NET Core 3,0' i
seçin.
Razor Pages kullanan bir proje oluşturmak için Web uygulaması ' nı seçin ve ardından Oluştur' u seçin.

SignalR istemci kitaplığı ekleme


SignalR sunucusu kitaplığı, ASP.NET Core 3,0 paylaşılan çerçevesine dahildir. JavaScript istemci kitaplığı projeye
otomatik olarak dahil değildir. Bu öğreticide, istemci kitaplığını unpkg'den almak Için kitaplık Yöneticisi 'Ni (Libman)
kullanacaksınız. unpkg, Node. js Paket Yöneticisi NPM 'de bulunan her şeyi teslim edebilen bir içerik teslim ağı
(CDN )).
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, projeye sağ tıklayın ve > Istemci tarafı kitaplığı Ekle ' yi seçin.
Istemci tarafı kitaplığı Ekle Iletişim kutusunda sağlayıcı için unpkgseçeneğini belirleyin.
Kitaplıkiçin @microsoft/signalr@latest girin.
Belirli dosyaları seç' i seçin, dağ/Browser klasörünü genişletin ve SignalR. js ve SignalR. min. js' yi seçin.
Hedef konumu Wwwroot/js/SignalR/ olarak ayarlayın ve yüklemeyiseçin.
LibMan, bir Wwwroot/js/SignalR klasörü oluşturur ve seçilen dosyaları buna kopyalar.

SignalR hub 'ı oluşturma


Hub , istemci-sunucu iletişimini işleyen yüksek düzeyli bir işlem hattı görevi gören bir sınıftır.
SignalRChat proje klasöründe bir hub klasörü oluşturun.
Hub 'lar klasöründe, aşağıdaki kodla bir ChatHub.cs dosyası oluşturun:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}

ChatHub sınıfı SignalR Hub sınıfından devralır. Hub sınıfı bağlantıları, grupları ve mesajlaşmayı yönetir.
SendMessage yöntemi, tüm istemcilere ileti göndermek için bağlı bir istemci tarafından çağrılabilir. Yöntemi
çağıran JavaScript istemci kodu Öğreticinin ilerleyen kısımlarında gösterilmektedir. SignalR kod, en fazla
ölçeklenebilirlik sağlamak için zaman uyumsuzdur.

SignalR Yapılandır
SignalR sunucusu, SignalRSignalR istekleri geçirilecek şekilde yapılandırılmalıdır.
Aşağıdaki Vurgulanan kodu Startup.cs dosyasına ekleyin.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;

namespace SignalRChat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSignalR();
}

// This method gets called by the runtime. Use this method to configure the HTTP request
pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production
scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chatHub");
});
}
}
}

Bu değişiklikler, ASP.NET Core bağımlılığı ekleme ve yönlendirme sistemlerine SignalR ekler.

SignalR istemci kodu ekle


Pages\ındex.cshtml içindeki içeriği şu kodla değiştirin:

@page
<div class="container">
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-2">User</div>
<div class="col-4"><input type="text" id="userInput" /></div>
</div>
<div class="row">
<div class="col-2">Message</div>
<div class="col-4"><input type="text" id="messageInput" /></div>
</div>
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-6">
<input type="button" id="sendButton" value="Send Message" />
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-6">
<ul id="messagesList"></ul>
</div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

Yukarıdaki kod:
Ad ve ileti metni ve Gönder düğmesi için metin kutuları oluşturur.
SignalR hub 'ından alınan iletileri görüntülemek için id="messagesList" içeren bir liste oluşturur.
Bir sonraki adımda oluşturduğunuz SignalR ve sohbet. js uygulama koduna yönelik betik başvurularını
içerir.
Wwwroot/js klasöründe, aşağıdaki kodla bir chat. js dosyası oluşturun:
"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established


document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {


var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});

connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {


var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});

Yukarıdaki kod:
Bir bağlantı oluşturur ve başlatır.
, Hub 'a ileti gönderen bir işleyiciye Gönder düğmesine ekler.
, Hub 'dan iletileri alan ve bunları listeye ekleyen bir işleyici olan bağlantı nesnesine ekler.

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamadan çalıştırmak için CTRL + F5 tuşlarına basın.
Adres çubuğundan URL 'yi kopyalayın, başka bir tarayıcı örneği veya sekme açın ve adres çubuğuna URL 'YI
yapıştırın.
Tarayıcı ' yı seçin, bir ad ve ileti girin ve Ileti gönder düğmesini seçin.
Ad ve ileti anında her iki sayfada da görüntülenir.
TIP
Uygulama işe yaramazsa, tarayıcı geliştirici araçlarınızı (F12) açın ve konsola gidin. HTML ve JavaScript kodunuzla ilgili
hatalarla karşılaşabilirsiniz. Örneğin, SignalR. js ' yi yönlendirenden farklı bir klasöre yerleştirdiğinizi varsayalım. Bu
durumda, bu dosyaya başvuru çalışmaz ve konsolunda 404 hatası görürsünüz.

Chrome 'da hata ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY alırsanız, geliştirme sertifikanızı güncelleştirmek için


şu komutları çalıştırın:

dotnet dev-certs https --clean


dotnet dev-certs https --trust

Bu öğreticide SignalRkullanarak gerçek zamanlı bir uygulama oluşturmanın temelleri öğretilir. Aşağıdakileri nasıl
yapacağınızı öğrenirsiniz:
Web projesi oluşturun.
SignalR istemci kitaplığı ekleyin.
SignalR hub 'ı oluşturun.
Projeyi SignalRkullanacak şekilde yapılandırın.
Herhangi bir istemciden tüm bağlı istemcilere ileti gönderen kodu ekleyin.
Sonunda, çalışan bir sohbet uygulamasına sahipsiniz:
Önkoşullar
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2017 sürüm 15,9 veya üzeri ile ASP.NET ve web geliştirme iş yükü. Kullanabileceğiniz Visual
Studio 2019, ancak bazı proje oluşturma adımlarını öğreticide gösterilen öğesinden farklı.
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Menüden dosya > yeni proje' yi seçin.
Yeni proje iletişim kutusunda, yüklü > Visual C# > Web > ASP.NET Core Web uygulaması' nı seçin.
Projeyi Signalrchatolarak adlandırın.
Razor Pages kullanan bir proje oluşturmak için Web uygulaması ' nı seçin.
.NET Core'un hedef çerçevesini seçin, ASP.NET Core 2,2' i seçin ve Tamam' ı tıklatın.

SignalR istemci kitaplığı ekleme


SignalR sunucusu kitaplığı, Microsoft.AspNetCore.App metapackage 'e dahildir. JavaScript istemci kitaplığı projeye
otomatik olarak dahil değildir. Bu öğreticide, istemci kitaplığını unpkg'den almak Için kitaplık Yöneticisi 'Ni (Libman)
kullanacaksınız. unpkg, Node. js Paket Yöneticisi NPM 'de bulunan her şeyi teslim edebilen bir içerik teslim ağı
(CDN )).
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, projeye sağ tıklayın ve > Istemci tarafı kitaplığı Ekle ' yi seçin.
Istemci tarafı kitaplığı Ekle Iletişim kutusunda sağlayıcı için unpkgseçeneğini belirleyin.
Kitaplıkiçin @microsoft/signalr@3 girin ve Önizleme olmayan en son sürümü seçin.

Belirli dosyaları seç' i seçin, dağ/Browser klasörünü genişletin ve SignalR. js ve SignalR. min. js' yi seçin.
Hedef konumu Wwwroot/lib/SignalR/ olarak ayarlayın ve yüklemeyiseçin.

LibMan, bir Wwwroot/LIB/SignalR klasörü oluşturur ve seçilen dosyaları buna kopyalar.


SignalR hub 'ı oluşturma
Hub , istemci-sunucu iletişimini işleyen yüksek düzeyli bir işlem hattı görevi gören bir sınıftır.
SignalRChat proje klasöründe bir hub klasörü oluşturun.
Hub 'lar klasöründe, aşağıdaki kodla bir ChatHub.cs dosyası oluşturun:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}

ChatHub sınıfı SignalR Hub sınıfından devralır. Hub sınıfı bağlantıları, grupları ve mesajlaşmayı yönetir.
SendMessage yöntemi, tüm istemcilere ileti göndermek için bağlı bir istemci tarafından çağrılabilir. Yöntemi
çağıran JavaScript istemci kodu Öğreticinin ilerleyen kısımlarında gösterilmektedir. SignalR kod, en fazla
ölçeklenebilirlik sağlamak için zaman uyumsuzdur.

SignalR Yapılandır
SignalR sunucusu, SignalRSignalR istekleri geçirilecek şekilde yapılandırılmalıdır.
Aşağıdaki Vurgulanan kodu Startup.cs dosyasına ekleyin.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SignalRChat.Hubs;

namespace SignalRChat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a
given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddSignalR();
}

// This method gets called by the runtime. Use this method to configure the HTTP request
pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
app.UseMvc();
}
}
}

Bu değişiklikler, ASP.NET Core bağımlılık ekleme sistemine ve ara yazılım ardışık düzenine SignalR ekler.

SignalR istemci kodu ekle


Pages\ındex.cshtml içindeki içeriği şu kodla değiştirin:

@page
<div class="container">
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-6">&nbsp;</div>
<div class="col-6">
User..........<input type="text" id="userInput" />
<br />
Message...<input type="text" id="messageInput" />
<input type="button" id="sendButton" value="Send Message" />
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-6">&nbsp;</div>
<div class="col-6">
<ul id="messagesList"></ul>
</div>
</div>
</div>
<script src="~/lib/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

Yukarıdaki kod:
Ad ve ileti metni ve Gönder düğmesi için metin kutuları oluşturur.
SignalR hub 'ından alınan iletileri görüntülemek için id="messagesList" içeren bir liste oluşturur.
Bir sonraki adımda oluşturduğunuz SignalR ve sohbet. js uygulama koduna yönelik betik başvurularını
içerir.
Wwwroot/js klasöründe, aşağıdaki kodla bir chat. js dosyası oluşturun:
"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established


document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {


var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});

connection.start().then(function(){
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {


var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});

Yukarıdaki kod:
Bir bağlantı oluşturur ve başlatır.
, Hub 'a ileti gönderen bir işleyiciye Gönder düğmesine ekler.
, Hub 'dan iletileri alan ve bunları listeye ekleyen bir işleyici olan bağlantı nesnesine ekler.

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamadan çalıştırmak için CTRL + F5 tuşlarına basın.
Adres çubuğundan URL 'yi kopyalayın, başka bir tarayıcı örneği veya sekme açın ve adres çubuğuna URL 'YI
yapıştırın.
Tarayıcı ' yı seçin, bir ad ve ileti girin ve Ileti gönder düğmesini seçin.
Ad ve ileti anında her iki sayfada da görüntülenir.
TIP
Uygulama işe yaramazsa, tarayıcı geliştirici araçlarınızı (F12) açın ve konsola gidin. HTML ve JavaScript kodunuzla ilgili hatalarla
karşılaşabilirsiniz. Örneğin, SignalR. js ' yi yönlendirenden farklı bir klasöre yerleştirdiğinizi varsayalım. Bu durumda, bu dosyaya
başvuru çalışmaz ve konsolunda 404 hatası görürsünüz.

Ek kaynaklar
Bu öğreticinin YouTube sürümü
TypeScript ve WebPack ile ASP.NET Core SignalR
kullanma
26.11.2019 • 34 minutes to read • Edit Online

, Sébastien Sougnez ve Scott Ade tarafından


WebPack , geliştiricilerin bir Web uygulamasının istemci tarafı kaynaklarını paketleyip oluşturmalarına olanak
sağlar. Bu öğretici, istemcisinin TypeScript'te yazıldığı bir ASP.NET Core SignalR Web uygulamasında WebPack 'in
kullanımını gösterir.
Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:
Bir başlatıcı ASP.NET Core SignalR uygulama için yapı iskelesi
SignalR TypeScript istemcisini yapılandırma
WebPack kullanarak derleme işlem hattı yapılandırma
SignalR sunucusunu yapılandırma
İstemci ve sunucu arasındaki iletişimi etkinleştir
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Önkoşullar
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core SDK 3,0 veya üzeri
NPM ile Node. js

ASP.NET Core Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio 'Yu, Path ortam değişkeninde NPM için arama yapmak üzere yapılandırın. Varsayılan olarak, Visual
Studio yükleme dizininde bulunan NPM sürümünü kullanır. Visual Studio 'da şu yönergeleri izleyin:
1. Web Paket Yönetimi > dış web araçları> > > Araçlar ve Seçenekler ' e gidin.
2. Listeden $ (yol) girişini seçin. Girdiyi listedeki ikinci konuma taşımak için yukarı oka tıklayın.
Visual Studio yapılandırması tamamlandı. Projeyi oluşturma zamanı.
1. Dosya > Yeni > projesi menü seçeneğini kullanın ve ASP.NET Core Web uygulaması şablonunu seçin.
2. Projeyi Signalrwebpackolarak adlandırın ve Oluştur' u seçin.
3. Hedef çerçeve açılır listesinden .NET Core ' u seçin ve çerçeve Seçicisi açılır listesinden ASP.NET Core 3,0 ' ı
seçin. Boş şablonu seçin ve Oluştur' u seçin.

WebPack ve TypeScript yapılandırma


Aşağıdaki adımlar, TypeScript 'in JavaScript 'e dönüştürülmesini ve istemci tarafı kaynaklarını paketlemeyi
yapılandırır.
1. Bir Package. JSON dosyası oluşturmak için proje kökünde aşağıdaki komutu yürütün:

npm init -y

2. Vurgulanan özelliği Package. JSON dosyasına ekleyin:

{
"name": "SignalRWebPack",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

private özelliğinin true olarak ayarlanması, sonraki adımda paket yükleme uyarılarını önler.
3. Gerekli NPM paketlerini yükler. Proje kökünden aşağıdaki komutu yürütün:
npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-
extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3

Aklınızda bazı komut ayrıntıları:


Sürüm numarası, her paket adı için @ işaretini izler. NPM bu özel paket sürümlerini yüklüyor.
-E seçeneği, NPM 'nin semantik sürüm aralığı işleçlerini Package. JSONöğesine yazmanın varsayılan
davranışını devre dışı bırakır. Örneğin, "webpack": "^4.29.3" yerine "webpack": "4.29.3" kullanılır. Bu
seçenek, daha yeni paket sürümlerine istenmeden yükseltme yapılmasını engeller.
Daha ayrıntılı bilgi için resmi NPM -Install docs bölümüne bakın.
4. Package. JSON dosyasının scripts özelliğini aşağıdaki kod parçacığıyla değiştirin:

"scripts": {
"build": "webpack --mode=development --watch",
"release": "webpack --mode=production",
"publish": "npm run release && dotnet publish -c Release"
},

Betiklerin bazı açıklamaları:


build : istemci tarafı kaynaklarınızı geliştirme modunda paketler ve dosya değişikliklerini izler. Dosya
izleyici, bir proje dosyası her değiştiğinde paketin yeniden oluşturulmasına neden olur. mode seçeneği,
Tree gerçekleşmesi ve minbirleşme gibi üretim iyileştirmeleri devre dışı bırakır. Yalnızca geliştirmede
build kullanın.
release : istemci tarafı kaynaklarınızı üretim modunda Paketlayın.
publish : release betiği, istemci tarafı kaynaklarını üretim modunda paketleyip çalıştırır. Uygulamayı
yayımlamak için .NET Core CLI Publish komutunu çağırır.
5. Aşağıdaki içeriğe sahip proje kökünde WebPack. config. jsadlı bir dosya oluşturun:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "wwwroot"),
filename: "[name].[chunkhash].js",
publicPath: "/"
},
resolve: {
extensions: [".js", ".ts"]
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new CleanWebpackPlugin(["wwwroot/*"]),
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css"
})
]
};

Yukarıdaki dosya Web paketi derlemesini yapılandırır. Aklınızda bazı yapılandırma ayrıntıları:
output özelliği, dağ'ın varsayılan değerini geçersiz kılar. Paket, Wwwroot dizininde yayınlanır.
resolve.extensions dizisi, SignalR istemci JavaScript 'ı içeri aktarmak için . js içerir.
6. Proje kökünde yeni bir src dizini oluşturun. Amaç, projenin istemci tarafı varlıklarını depolardır.
7. Aşağıdaki içerikle src/index.html oluşturun.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core SignalR</title>
</head>
<body>
<div id="divMessages" class="messages">
</div>
<div class="input-zone">
<label id="lblMessage" for="tbMessage">Message:</label>
<input id="tbMessage" class="input-zone-input" type="text" />
<button id="btnSend">Send</button>
</div>
</body>
</html>
Önceki HTML, giriş sayfasının ortak işaretlemesini tanımlar.
8. Yeni bir src/CSS dizini oluşturun. Amacı, projenin . css dosyalarını depolamadır.
9. Aşağıdaki içerikle src/CSS/Main. css oluşturun:

*, *::before, *::after {
box-sizing: border-box;
}

html, body {
margin: 0;
padding: 0;
}

.input-zone {
align-items: center;
display: flex;
flex-direction: row;
margin: 10px;
}

.input-zone-input {
flex: 1;
margin-right: 10px;
}

.message-author {
font-weight: bold;
}

.messages {
border: 1px solid #000;
margin: 10px;
max-height: 300px;
min-height: 300px;
overflow-y: auto;
padding: 5px;
}

Önceki Main. css dosyası uygulamayı stiller.


10. Şu içerikle src/tsconfig. JSON oluşturun:

{
"compilerOptions": {
"target": "es5"
}
}

Yukarıdaki kod, TypeScript derleyicisini ECMAScript 5 uyumlu JavaScript üretecek şekilde yapılandırır.
11. Aşağıdaki içeriğe sahip src/index. TS oluşturun:
import "./css/main.css";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Önceki TypeScript, DOM öğelerine başvuruları alır ve iki olay işleyicisini ekler:
keyup : Bu olay Kullanıcı metin kutusuna tbMessage olarak tanımlanan bir şeyi yazdığında ateşlenir. send
işlevi, Kullanıcı ENTER tuşuna bastığında çağrılır.
click : Kullanıcı Gönder düğmesine tıkladığında bu olay ateşlenir. send işlevi çağırılır.

ASP.NET Core uygulamasını yapılandırma


1. Startup.Configure yönteminde, Usedefaultfiles ve usestaticfilesöğesine çağrılar ekleyin.

app.UseRouting();
app.UseDefaultFiles();
app.UseStaticFiles();

Yukarıdaki kod, kullanıcının tam URL 'sini veya Web uygulamasının kök URL 'sini girmeksizin Dizin. html
dosyasını bulmasını ve sunmasını sağlar.
2. Startup.Configure yönteminin sonunda, bir /hub yolunu ChatHub hub 'ına eşleyin. Merhaba Dünya
görüntülenen kodu değiştirin ! Aşağıdaki satırla:

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/hub");
});

3. Startup.ConfigureServices yönteminde Addsignalröğesini çağırın. SignalR hizmetlerini projenize ekler.

services.AddSignalR();

4. Proje kökünde hubolarak adlandırılan yeni bir dizin oluşturun. Amacı, bir sonraki adımda oluşturulan
SignalR hub 'ını deposağlamaktır.
5. Aşağıdaki kodla hub hub 'ları/ChatHub. cs oluşturun:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
}
}

6. ChatHub başvurusunu çözümlemek için, Startup.cs dosyasının en üstüne aşağıdaki kodu ekleyin:

using SignalRWebPack.Hubs;

İstemci ve sunucu iletişimini etkinleştir


Uygulama Şu anda ileti göndermek için basit bir form görüntülüyor. Bunu yapmayı denediğinizde hiçbir şey olmaz.
Sunucu belirli bir yolu dinliyor, ancak gönderilen iletilerle hiçbir şey yapmıyor.
1. Proje kökünde aşağıdaki komutu yürütün:

npm install @microsoft/signalr

Yukarıdaki komut, istemcinin sunucuya ileti göndermesini sağlayan SignalR TypeScript istemcisiniyüklüyor.
2. Vurgulanan kodu src/index. TS dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@microsoft/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let m = document.createElement("div");

m.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Yukarıdaki kod, sunucudan ileti almayı destekler. HubConnectionBuilder sınıfı, sunucu bağlantısını
yapılandırmak için yeni bir Oluşturucu oluşturur. withUrl işlevi hub URL 'sini yapılandırır.
SignalR, istemci ile sunucu arasında ileti alışverişi yapılmasını mümkün. Her ileti belirli bir ada sahiptir.
Örneğin, ileti bölgesindeki yeni iletiyi görüntülemekten sorumlu mantığı çalıştıran messageReceived adına
sahip iletilere sahip olabilirsiniz. Belirli bir iletiyi dinlemek on işlevi aracılığıyla yapılabilir. Herhangi bir
sayıda ileti adını dinleyebilmeniz gerekir. Ayrıca, yazarın adı ve alınan iletinin içeriği gibi parametreleri iletiye
geçirmek da mümkündür. İstemci bir ileti aldıktan sonra yazarın adı ve innerHTML özniteliğinde ileti içeriğiyle
yeni bir div öğesi oluşturulur. Bu, iletileri görüntüleyen ana div öğesine eklenir.
3. Artık istemci bir ileti aldığına göre, ileti gönderecek şekilde yapılandırın. Vurgulanan kodu src/index. TS
dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let messageContainer = document.createElement("div");

messageContainer.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(messageContainer);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => tbMessage.value = "");
}

WebSockets bağlantısı aracılığıyla bir ileti gönderildiğinde send yönteminin çağrılması gerekir. Yöntemin ilk
parametresi ileti adıdır. İleti verileri diğer parametreleri geçersiz kılar. Bu örnekte, newMessage sunucusuna
gönderildiği gibi bir ileti gönderilir. İleti, bir metin kutusundan Kullanıcı adından ve Kullanıcı girişinden
oluşur. Gönderme işlemi çalışırsa metin kutusu değeri temizlenir.
4. Vurgulanan yöntemi ChatHub sınıfına ekleyin:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
public async Task NewMessage(long username, string message)
{
await Clients.All.SendAsync("messageReceived", username, message);
}
}
}

Yukarıdaki kod, sunucu onları aldıktan sonra tüm bağlı kullanıcılara ileti almış iletileri yayınlar. Tüm iletileri
almak için genel bir on yöntemi olması gereksizdir. İleti adından sonra adlandırılmış bir yöntem.
Bu örnekte, TypeScript istemcisi newMessage olarak tanımlanan bir ileti gönderir. C# NewMessage yöntemi,
istemci tarafından gönderilen verileri bekler. Istemcilerdeki sendadsync yöntemine bir çağrı yapılır. Alınan
iletiler, hub 'a bağlı tüm istemcilere gönderilir.

Uygulamayı test etme


Uygulamanın aşağıdaki adımlarla çalıştığından emin olun.
Visual Studio
Visual Studio Code
1. Web paketini yayın modunda çalıştırın. Paket Yöneticisi konsol penceresini kullanarak, proje kökünde
aşağıdaki komutu yürütün. Proje kökünde değilseniz, komutu girmeden önce cd SignalRWebPack girin.

npm run release

Bu komut, uygulamayı çalıştırırken alınacağı istemci-tarafı varlıkları verir. Varlıkları yerleştirilir wwwroot
klasör.
Web, aşağıdaki görevleri tamamlandı:
İçeriğini temizleneceği wwwroot dizin.
JavaScript için TypeScript dönüştürülen—olarak da bilinen bir işlem transpilation.
Dosya boyutunu küçültmek için oluşturulan JavaScript karıştırılmış—olarak da bilinen bir işlem küçültme.
İşlenen JavaScript, CSS ve HTML dosyalarından kopyalanan src için wwwroot dizin.
Aşağıdaki öğeleri içine eklenen wwwroot/index.html dosyası:
A <link> başvuran etiketi wwwroot/main.< karma>.css dosya. Bu etiket kapatılmadan hemen
önce yerleştirilir </head> etiketi.
A <script> küçültülmüş başvuran etiketi wwwroot/main.< karma>.js dosya. Bu etiket
kapatılmadan hemen önce yerleştirilir </body> etiketi.
2. Hata ayıklayıcıyı eklemeden uygulamayı bir tarayıcıda başlatmak **için hata ayıklama > ** Başlat ' ı seçin.
Wwwroot/index.html dosyası http://localhost:<port_number> olarak sunulur.
Derleme hataları alırsanız, çözümü kapatıp yeniden açmayı deneyin.
3. Başka bir tarayıcı örneği (herhangi bir tarayıcı) açın. URL 'YI adres çubuğuna yapıştırın.
4. Tarayıcı seçin, ileti metin kutusuna bir şey yazın ve Gönder düğmesine tıklayın. Benzersiz Kullanıcı adı ve
ileti anında her iki sayfada da görüntülenir.
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core SDK 2,2 veya üzeri
NPM ile Node. js

ASP.NET Core Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio 'Yu, Path ortam değişkeninde NPM için arama yapmak üzere yapılandırın. Varsayılan olarak, Visual
Studio yükleme dizininde bulunan NPM sürümünü kullanır. Visual Studio 'da şu yönergeleri izleyin:
1. Web Paket Yönetimi > dış web araçları> > > Araçlar ve Seçenekler ' e gidin.
2. Listeden $ (yol) girişini seçin. Girdiyi listedeki ikinci konuma taşımak için yukarı oka tıklayın.
Visual Studio yapılandırması tamamlandı. Projeyi oluşturma zamanı.
1. Dosya > Yeni > projesi menü seçeneğini kullanın ve ASP.NET Core Web uygulaması şablonunu seçin.
2. Projeyi Signalrwebpackolarak adlandırın ve Oluştur' u seçin.
3. Hedef çerçeve açılır listesinden .NET Core ' u seçin ve çerçeve Seçicisi açılır listesinden ASP.NET Core 2,2 ' ı
seçin. Boş şablonu seçin ve Oluştur' u seçin.

WebPack ve TypeScript yapılandırma


Aşağıdaki adımlar, TypeScript 'in JavaScript 'e dönüştürülmesini ve istemci tarafı kaynaklarını paketlemeyi
yapılandırır.
1. Bir Package. JSON dosyası oluşturmak için proje kökünde aşağıdaki komutu yürütün:

npm init -y

2. Vurgulanan özelliği Package. JSON dosyasına ekleyin:

{
"name": "SignalRWebPack",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

private özelliğinin true olarak ayarlanması, sonraki adımda paket yükleme uyarılarını önler.
3. Gerekli NPM paketlerini yükler. Proje kökünden aşağıdaki komutu yürütün:
npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-
extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3

Aklınızda bazı komut ayrıntıları:


Sürüm numarası, her paket adı için @ işaretini izler. NPM bu özel paket sürümlerini yüklüyor.
-E seçeneği, NPM 'nin semantik sürüm aralığı işleçlerini Package. JSONöğesine yazmanın varsayılan
davranışını devre dışı bırakır. Örneğin, "webpack": "^4.29.3" yerine "webpack": "4.29.3" kullanılır. Bu
seçenek, daha yeni paket sürümlerine istenmeden yükseltme yapılmasını engeller.
Daha ayrıntılı bilgi için resmi NPM -Install docs bölümüne bakın.
4. Package. JSON dosyasının scripts özelliğini aşağıdaki kod parçacığıyla değiştirin:

"scripts": {
"build": "webpack --mode=development --watch",
"release": "webpack --mode=production",
"publish": "npm run release && dotnet publish -c Release"
},

Betiklerin bazı açıklamaları:


build : istemci tarafı kaynaklarınızı geliştirme modunda paketler ve dosya değişikliklerini izler. Dosya
izleyici, bir proje dosyası her değiştiğinde paketin yeniden oluşturulmasına neden olur. mode seçeneği,
Tree gerçekleşmesi ve minbirleşme gibi üretim iyileştirmeleri devre dışı bırakır. Yalnızca geliştirmede
build kullanın.
release : istemci tarafı kaynaklarınızı üretim modunda Paketlayın.
publish : release betiği, istemci tarafı kaynaklarını üretim modunda paketleyip çalıştırır. Uygulamayı
yayımlamak için .NET Core CLI Publish komutunu çağırır.
5. Aşağıdaki içeriğe sahip proje kökünde WebPack. config. jsadlı bir dosya oluşturun:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "wwwroot"),
filename: "[name].[chunkhash].js",
publicPath: "/"
},
resolve: {
extensions: [".js", ".ts"]
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new CleanWebpackPlugin(["wwwroot/*"]),
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css"
})
]
};

Yukarıdaki dosya Web paketi derlemesini yapılandırır. Aklınızda bazı yapılandırma ayrıntıları:
output özelliği, dağ'ın varsayılan değerini geçersiz kılar. Paket, Wwwroot dizininde yayınlanır.
resolve.extensions dizisi, SignalR istemci JavaScript 'ı içeri aktarmak için . js içerir.
6. Proje kökünde yeni bir src dizini oluşturun. Amaç, projenin istemci tarafı varlıklarını depolardır.
7. Aşağıdaki içerikle src/index.html oluşturun.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core SignalR</title>
</head>
<body>
<div id="divMessages" class="messages">
</div>
<div class="input-zone">
<label id="lblMessage" for="tbMessage">Message:</label>
<input id="tbMessage" class="input-zone-input" type="text" />
<button id="btnSend">Send</button>
</div>
</body>
</html>
Önceki HTML, giriş sayfasının ortak işaretlemesini tanımlar.
8. Yeni bir src/CSS dizini oluşturun. Amacı, projenin . css dosyalarını depolamadır.
9. Aşağıdaki içerikle src/CSS/Main. css oluşturun:

*, *::before, *::after {
box-sizing: border-box;
}

html, body {
margin: 0;
padding: 0;
}

.input-zone {
align-items: center;
display: flex;
flex-direction: row;
margin: 10px;
}

.input-zone-input {
flex: 1;
margin-right: 10px;
}

.message-author {
font-weight: bold;
}

.messages {
border: 1px solid #000;
margin: 10px;
max-height: 300px;
min-height: 300px;
overflow-y: auto;
padding: 5px;
}

Önceki Main. css dosyası uygulamayı stiller.


10. Şu içerikle src/tsconfig. JSON oluşturun:

{
"compilerOptions": {
"target": "es5"
}
}

Yukarıdaki kod, TypeScript derleyicisini ECMAScript 5 uyumlu JavaScript üretecek şekilde yapılandırır.
11. Aşağıdaki içeriğe sahip src/index. TS oluşturun:
import "./css/main.css";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Önceki TypeScript, DOM öğelerine başvuruları alır ve iki olay işleyicisini ekler:
keyup : Bu olay Kullanıcı metin kutusuna tbMessage olarak tanımlanan bir şeyi yazdığında ateşlenir. send
işlevi, Kullanıcı ENTER tuşuna bastığında çağrılır.
click : Kullanıcı Gönder düğmesine tıkladığında bu olay ateşlenir. send işlevi çağırılır.

ASP.NET Core uygulamasını yapılandırma


1. Startup.Configure yönteminde belirtilen kod Merhaba Dünya! görüntülüyor. app.Run yöntemi çağrısını,
Usedefaultfiles ve usestaticfilesçağrılarıyla değiştirin.

app.UseDefaultFiles();
app.UseStaticFiles();

Yukarıdaki kod, kullanıcının tam URL 'sini veya Web uygulamasının kök URL 'sini girmeksizin Dizin. html
dosyasını bulmasını ve sunmasını sağlar.
2. Startup.ConfigureServices yönteminde Addsignalr öğesini çağırın. SignalR hizmetlerini projenize ekler.

services.AddSignalR();

3. Bir /hub yolunu ChatHub hub 'ına eşleyin. Startup.Configure yönteminin sonuna aşağıdaki satırları ekleyin:

app.UseSignalR(options =>
{
options.MapHub<ChatHub>("/hub");
});

4. Proje kökünde hubolarak adlandırılan yeni bir dizin oluşturun. Amacı, bir sonraki adımda oluşturulan
SignalR hub 'ını deposağlamaktır.
5. Aşağıdaki kodla hub hub 'ları/ChatHub. cs oluşturun:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
}
}

6. ChatHub başvurusunu çözümlemek için, Startup.cs dosyasının en üstüne aşağıdaki kodu ekleyin:

using SignalRWebPack.Hubs;

İstemci ve sunucu iletişimini etkinleştir


Uygulama Şu anda ileti göndermek için basit bir form görüntülüyor. Bunu yapmayı denediğinizde hiçbir şey olmaz.
Sunucu belirli bir yolu dinliyor, ancak gönderilen iletilerle hiçbir şey yapmıyor.
1. Proje kökünde aşağıdaki komutu yürütün:

npm install @microsoft/signalr

Yukarıdaki komut, istemcinin sunucuya ileti göndermesini sağlayan SignalR TypeScript istemcisiniyüklüyor.
2. Vurgulanan kodu src/index. TS dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let m = document.createElement("div");

m.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Yukarıdaki kod, sunucudan ileti almayı destekler. HubConnectionBuilder sınıfı, sunucu bağlantısını
yapılandırmak için yeni bir Oluşturucu oluşturur. withUrl işlevi hub URL 'sini yapılandırır.
SignalR, istemci ile sunucu arasında ileti alışverişi yapılmasını mümkün. Her ileti belirli bir ada sahiptir.
Örneğin, ileti bölgesindeki yeni iletiyi görüntülemekten sorumlu mantığı çalıştıran messageReceived adına
sahip iletilere sahip olabilirsiniz. Belirli bir iletiyi dinlemek on işlevi aracılığıyla yapılabilir. Herhangi bir
sayıda ileti adını dinleyebilmeniz gerekir. Ayrıca, yazarın adı ve alınan iletinin içeriği gibi parametreleri iletiye
geçirmek da mümkündür. İstemci bir ileti aldıktan sonra yazarın adı ve innerHTML özniteliğinde ileti içeriğiyle
yeni bir div öğesi oluşturulur. Bu, iletileri görüntüleyen ana div öğesine eklenir.
3. Artık istemci bir ileti aldığına göre, ileti gönderecek şekilde yapılandırın. Vurgulanan kodu src/index. TS
dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let messageContainer = document.createElement("div");

messageContainer.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(messageContainer);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => tbMessage.value = "");
}

WebSockets bağlantısı aracılığıyla bir ileti gönderildiğinde send yönteminin çağrılması gerekir. Yöntemin ilk
parametresi ileti adıdır. İleti verileri diğer parametreleri geçersiz kılar. Bu örnekte, newMessage sunucusuna
gönderildiği gibi bir ileti gönderilir. İleti, bir metin kutusundan Kullanıcı adından ve Kullanıcı girişinden
oluşur. Gönderme işlemi çalışırsa metin kutusu değeri temizlenir.
4. Vurgulanan yöntemi ChatHub sınıfına ekleyin:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
public async Task NewMessage(long username, string message)
{
await Clients.All.SendAsync("messageReceived", username, message);
}
}
}

Yukarıdaki kod, sunucu onları aldıktan sonra tüm bağlı kullanıcılara ileti almış iletileri yayınlar. Tüm iletileri
almak için genel bir on yöntemi olması gereksizdir. İleti adından sonra adlandırılmış bir yöntem.
Bu örnekte, TypeScript istemcisi newMessage olarak tanımlanan bir ileti gönderir. C# NewMessage yöntemi,
istemci tarafından gönderilen verileri bekler. Istemcilerdeki sendadsync yöntemine bir çağrı yapılır. Alınan
iletiler, hub 'a bağlı tüm istemcilere gönderilir.

Uygulamayı test etme


Uygulamanın aşağıdaki adımlarla çalıştığından emin olun.
Visual Studio
Visual Studio Code
1. Web paketini yayın modunda çalıştırın. Paket Yöneticisi konsol penceresini kullanarak, proje kökünde
aşağıdaki komutu yürütün. Proje kökünde değilseniz, komutu girmeden önce cd SignalRWebPack girin.

npm run release

Bu komut, uygulamayı çalıştırırken alınacağı istemci-tarafı varlıkları verir. Varlıkları yerleştirilir wwwroot
klasör.
Web, aşağıdaki görevleri tamamlandı:
İçeriğini temizleneceği wwwroot dizin.
JavaScript için TypeScript dönüştürülen—olarak da bilinen bir işlem transpilation.
Dosya boyutunu küçültmek için oluşturulan JavaScript karıştırılmış—olarak da bilinen bir işlem küçültme.
İşlenen JavaScript, CSS ve HTML dosyalarından kopyalanan src için wwwroot dizin.
Aşağıdaki öğeleri içine eklenen wwwroot/index.html dosyası:
A <link> başvuran etiketi wwwroot/main.< karma>.css dosya. Bu etiket kapatılmadan hemen
önce yerleştirilir </head> etiketi.
A <script> küçültülmüş başvuran etiketi wwwroot/main.< karma>.js dosya. Bu etiket
kapatılmadan hemen önce yerleştirilir </body> etiketi.
2. Hata ayıklayıcıyı eklemeden uygulamayı bir tarayıcıda başlatmak **için hata ayıklama > ** Başlat ' ı seçin.
Wwwroot/index.html dosyası http://localhost:<port_number> olarak sunulur.
3. Başka bir tarayıcı örneği (herhangi bir tarayıcı) açın. URL 'YI adres çubuğuna yapıştırın.
4. Tarayıcı seçin, ileti metin kutusuna bir şey yazın ve Gönder düğmesine tıklayın. Benzersiz Kullanıcı adı ve
ileti anında her iki sayfada da görüntülenir.
Ek kaynaklar
ASP.NET Core SignalR JavaScript istemcisi
ASP.NET Core SignalR hub 'ları kullanma
Öğretici: ASP.NET Core bir gRPC istemcisi ve
sunucusu oluşturma
6.12.2019 • 15 minutes to read • Edit Online

John Luo tarafından


Bu öğreticide, bir .NET Core GRPC istemcisinin ve bir ASP.NET Core GRPC sunucusunun nasıl oluşturulacağı
gösterilmektedir.
Sonda, gRPC Greeter hizmeti ile iletişim kuran bir gRPC istemcisine sahip olacaksınız.
Örnek kodu görüntüleyin veya indirin (nasıl indirilir).
Bu öğreticide şunları yaptınız:
GRPC sunucusu oluşturun.
GRPC istemcisi oluşturun.
GRPC istemci hizmetini gRPC Greeter hizmeti ile test edin.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

GRPC hizmeti oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'Yu başlatın ve Yeni proje oluştur' u seçin. Alternatif olarak, Visual Studio Dosya
menüsünden Yeni > projesi' ni seçin.
Yeni proje oluştur Iletişim kutusunda GRPC hizmeti ' ni seçin ve İleri' yi seçin:

Projeyi Grpcgreeterolarak adlandırın. Kodu kopyalayıp yapıştırdığınızda ad alanlarının eşleşmesi için, proje
Grpcgreeter adında bir ad vermek önemlidir.
Seçin oluşturma.
Yeni bir gRPC hizmeti oluştur iletişim kutusunda:
GRPC hizmeti şablonu seçilidir.
Seçin oluşturma.
Hizmeti çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:

Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.


Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve example.com
gibi bir şey görüntülenir. Bunun nedeni, localhost yerel bilgisayar için Standart ana bilgisayar adıdır.
Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual Studio bir Web projesi
oluşturduğunda, Web sunucusu için rastgele bir bağlantı noktası kullanılır.
Günlükler, https://localhost:5001 üzerinde dinleme hizmetini gösterir.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development

NOTE
GRPC şablonu, Aktarım Katmanı Güvenliği (TLS)kullanmak üzere yapılandırılmıştır. gRPC istemcilerinin, sunucuyu çağırmak için
HTTPS kullanması gerekir.
macOS, TLS ile ASP.NET Core gRPC 'yi desteklemez. MacOS 'ta gRPC hizmetlerini başarıyla çalıştırmak için ek yapılandırma
gerekir. Daha fazla bilgi için bkz. macOS üzerinde gRPC uygulaması ASP.NET Core başlatılamıyor.

Proje dosyalarını inceleyin


Grpcgreeter proje dosyaları:
Greet. proto – prototips/Greet. proto dosyası Greeter GRPC 'Yi tanımlar ve GRPC sunucu varlıklarını
oluşturmak için kullanılır. Daha fazla bilgi için bkz. gRPC 'ye giriş.
Hizmetler klasörü: Greeter hizmetinin uygulamasını içerir.
appSettings. json –, Kestrel tarafından kullanılan protokol gibi yapılandırma verilerini içerir. Daha fazla bilgi için
bkz. ASP.NET Core yapılandırma.
Program.cs –, GRPC hizmetinin giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs – uygulama davranışını yapılandıran kodu içerir. Daha fazla bilgi için bkz. uygulama başlatma.

Bir .NET konsol uygulamasında gRPC istemcisini oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'nun ikinci bir örneğini açın ve Yeni proje oluştur' u seçin.
Yeni proje oluştur Iletişim kutusunda konsol uygulaması (.NET Core) öğesini seçin ve İleri' yi seçin.
Ad metin kutusuna Grpcgreeterclient girin ve Oluştur' u seçin.
Gerekli paketleri Ekle
GRPC istemci projesi aşağıdaki paketleri gerektirir:
.NET Core istemcisini içeren GRPC .net. Client.
İçin C#prototipsiz Ileti API 'Leri içeren Google. protoarabellek.
Prototipleme dosyaları için araç desteğini C# Içeren GRPC. Tools. Araç, çalışma zamanında gerekli değildir, bu
nedenle bağımlılık PrivateAssets="All" olarak işaretlenir.

Visual Studio
Visual Studio Code
Mac için Visual Studio
Paket Yöneticisi Konsolu (PMC ) veya NuGet Paketlerini Yönet ' i kullanarak paketleri yükler.
Paket yüklemek için PMC seçeneği
Visual Studio 'da araçlar > NuGet Paket Yöneticisi > Paket Yöneticisi konsolu ' nu seçin.
Paket Yöneticisi konsol penceresinde, Grpcgreeterclient. csproj dosyalarını içeren klasöre Dizin
değiştirmek için cd GrpcGreeterClient çalıştırın.
Aşağıdaki komutları çalıştırın:

Install-Package Grpc.Net.Client
Install-Package Google.Protobuf
Install-Package Grpc.Tools

Paket yüklemek için NuGet Paketlerini Yönet seçeneği


NuGet paketlerini yönetmek > Çözüm Gezgini ' de projeye sağ tıklayın
Gözat sekmesini seçin.
Arama kutusuna GRPC .net. Client girin.
Araştır sekmesinden GRPC .net. Client paketini seçin ve ardından Install' ı seçin.
Google.Protobuf ve Grpc.Tools için yineleyin.

Greet. proto Ekle


GRPC istemci projesinde bir Prototips klasörü oluşturun.
Protos\bilgisem. proto dosyasını GRPC Greeter hizmetinden GRPC istemci projesine kopyalayın.
Grpcgreeterclient. csproj proje dosyasını düzenleyin:
Visual Studio
Visual Studio Code
Mac için Visual Studio
Projeye sağ tıklayın ve Proje dosyasını Düzenle' yi seçin.

Greet. proto dosyasına başvuran <Protobuf> öğesi olan bir öğe grubu ekleyin:

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Greeter istemcisini oluşturma


GrpcGreeter ad alanındaki türleri oluşturmak için projeyi derleyin. GrpcGreeter türleri yapı işlemi tarafından
otomatik olarak oluşturulur.
GRPC Client program.cs dosyasını aşağıdaki kodla güncelleştirin:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using GrpcGreeter;
using Grpc.Net.Client;

namespace GrpcGreeterClient
{
class Program
{
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}

Program.cs , GRPC istemcisinin giriş noktasını ve mantığını içerir.


Greeter istemcisi şu şekilde oluşturulur:
GRPC hizmetine bağlantı oluşturma bilgilerini içeren bir GrpcChannel örnekleniyor.
Greeter istemcisini oluşturmak için GrpcChannel kullanma:

static async Task Main(string[] args)


{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}

Greeter istemcisi zaman uyumsuz SayHello yöntemini çağırır. SayHello çağrısının sonucu görüntülenir:

static async Task Main(string[] args)


{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}

GRPC istemcisini gRPC Greeter hizmeti ile test etme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Greeter hizmetinde, hata ayıklayıcı olmadan sunucuyu başlatmak için Ctrl+F5 ' a basın.
GrpcGreeterClient projede, hata ayıklayıcı olmadan istemcisini başlatmak için Ctrl+F5 ' a basın.

İstemci, adı Greeterclientolan bir iletiyle hizmete bir tebrik gönderir. Hizmet, "Hello GreeterClient" iletisini yanıt
olarak gönderir. Komut isteminde "Hello GreeterClient" yanıtı görüntülenir:

Greeting: Hello GreeterClient


Press any key to exit...

GRPC hizmeti, komut istemine yazılan günlüklerde başarılı çağrının ayrıntılarını kaydeder:

info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\GH\aspnet\docs\4\Docs\aspnetcore\tutorials\grpc\grpc-start\sample\GrpcGreeter
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 POST https://localhost:5001/Greet.Greeter/SayHello application/grpc
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 78.32260000000001ms 200 application/grpc

NOTE
Bu makaledeki kod, gRPC hizmetini güvenli hale getirmek için ASP.NET Core HTTPS geliştirme sertifikası gerektirir. İstemci
The remote certificate is invalid according to the validation procedure. ileti ile başarısız olursa, geliştirme
sertifikası güvenilir değildir. Bu sorunu gidermeye yönelik yönergeler için bkz. Windows ve macOS 'ta ASP.NET Core https
geliştirme sertifikasına güvenin.

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub sorunu.

Sonraki adımlar
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
GRPC hizmetlerini C Core 'dan ASP.NET Core geçirme
ASP.NET Core - Öğreticisi 1. 8'de Entity Framework
Core ile Razor sayfaları
23.11.2019 • 53 minutes to read • Edit Online

Tarafından Tom Dykstra ve Rick Anderson


Bu, bir ASP.NET Core Razor Pages uygulamasında ENTITY Framework (EF ) çekirdeğini nasıl kullanacağınızı
gösteren bir öğretici serisinin ilkisidir. Öğreticiler, kurgusal bir Contoso Üniversitesi için bir Web sitesi oluşturur.
Site, öğrenci giriş, kurs oluşturma ve eğitmen atamaları gibi işlevleri içerir.
İndirme veya tamamlanmış uygulamayı görüntüleyin. Yükleme yönergeleri.

Önkoşullar
Razor Pages yeni başladıysanız, bu duruma başlamadan önce Razor Pages öğretici serisini kullanmaya başlayın.
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Veritabanı altyapıları
Visual Studio yönergeleri, yalnızca Windows üzerinde çalışan bir SQL Server Express sürümü olan SQL Server
LocalDB'yi kullanır.
Visual Studio Code yönergeler, platformlar arası bir veritabanı altyapısı olan SQLitekullanır.
SQLite kullanmayı seçerseniz, SQLite Için DB tarayıcısıgibi bir SQLite veritabanını yönetmek ve görüntülemek için
üçüncü taraf bir araç indirip yükleyin.

Sorun giderme
Giderebileceğiniz bir sorunla karşılaşırsanız, kodunuzu Tamamlanan projeylekarşılaştırın. Yardım almanın iyi bir
yolu, ASP.NET Core etiketi veya EF Core etiketikullanılarak StackOverflow.com 'e bir soru göndererek.

Örnek uygulama
Aşağıdaki öğreticilerde oluşturulan bir uygulamayı bir temel university web sitesidir. Kullanıcılar görüntüleyebilir ve
Öğrenci, kurs ve Eğitmen bilgileri güncelleştirin. Öğreticide oluşturulan ekranlar birkaçını aşağıda verilmiştir.
Bu sitenin kullanıcı arabirimi stili yerleşik proje şablonlarına dayalıdır. Öğreticinin odağı, Kullanıcı arabirimini nasıl
özelleştireceğinizi değil EF Core kullanma konusunda yer alır.
Tamamlanan projenin kaynak kodunu almak için sayfanın üst kısmındaki bağlantıyı izleyin. Cu30 klasörü,
öğreticinin ASP.NET Core 3,0 sürümü için kod içerir. 1-7 öğreticileri için kodun durumunu yansıtan dosyalar
cu30snapshots klasöründe bulunabilir.
Visual Studio
Visual Studio Code
Tamamlanmış projeyi indirdikten sonra uygulamayı çalıştırmak için:
Üç dosyayı ve ad içinde SQLite içeren bir klasörü silin.
Projeyi oluşturun.
Paket Yöneticisi konsolu 'nda (PMC ) aşağıdaki komutu çalıştırın:

Update-Database

Veritabanını temel alarak projeyi çalıştırın.

Web uygulaması projesi oluşturma


Visual Studio
Visual Studio Code
Visual Studio'dan dosya menüsünde yeni > proje.
Seçin ASP.NET Core Web uygulaması.
Projeyi adlandırın ContosoUniversity. Büyük harfler de dahil olmak üzere bu tam adı kullanmak önemlidir, bu
nedenle kod kopyalanıp yapıştırılırken ad alanları eşleşir.
Açılan menüden .NET Core ve 3,0 ASP.NET Core seçin ve ardından Web uygulaması' nı seçin.

Site stili Ayarla


Sayfa/paylaşılan/_Layout. cshtml'yi güncelleştirerek site üst bilgisini, alt bilgisini ve menüsünü ayarlayın:
"Contoso Üniversitesi" için "ContosoUniversity" her örneğini değiştirin. Üç örnekleri vardır.
Giriş ve Gizlilik menü girişlerini silin ve hakkında, öğrenciler, Kurslar, eğitmenlerve Departmanlariçin
girişler ekleyin.
Değişiklikler vurgulanır.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Contoso University</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow
mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">Contoso University</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/About">About</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Instructors/Index">Instructors</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Departments/Index">Departments</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Contoso University - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>

@RenderSection("Scripts", required: false)


</body>
</html>

Pages/Index. cshtmldosyasında, ASP.NET Core hakkındaki metni bu uygulamayla ilgili metinle değiştirmek için
dosyanın içeriğini aşağıdaki kodla değiştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="row mb-auto">


<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 mb-4 ">
<p class="card-text">
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core Razor Pages web app.
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 d-flex flex-column position-static">
<p class="card-text mb-auto">
You can build the application by following the steps in a series of tutorials.
</p>
<p>
<a href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro" class="stretched-
link">See the tutorial</a>
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 d-flex flex-column">
<p class="card-text mb-auto">
You can download the completed project from GitHub.
</p>
<p>
<a href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-
rp/intro/samples" class="stretched-link">See project source code</a>
</p>
</div>
</div>
</div>
</div>

Giriş sayfasının göründüğünü doğrulamak için uygulamayı çalıştırın.

Veri modeli
Aşağıdaki bölümler bir veri modeli oluşturur:
Bir öğrenci herhangi bir sayıda kursa kaydolabilir ve bir kurs, kayıtlı sayıda öğrenciye sahip olabilir.

Öğrenci varlık

Proje klasöründe bir modeller klasörü oluşturun.


Aşağıdaki kodla modeller/öğrenci. cs oluşturun:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

ID özelliği, bu sınıfa karşılık gelen veritabanı tablosunun birincil anahtar sütunu olur. Varsayılan olarak EF Core adlı
bir özellik yorumlar ID veya classnameID birincil anahtar olarak. Bu nedenle, Student sınıfı birincil anahtarı için
otomatik olarak tanınan ad StudentID .
Enrollments Özelliği bir gezinti özelliği. Gezinti özellikleri, bu varlıkla ilgili diğer varlıkları tutar. Bu durumda, bir
Student varlığının Enrollments özelliği söz konusu öğrenci ile ilgili Enrollment varlıkların tümünü barındırır.
Örneğin, veritabanındaki bir öğrenci satırında iki ilişkili kayıt satırı varsa, Enrollments gezinti özelliği bu iki kayıt
varlığını içerir.
Veritabanında, bir kayıt satırı, Studentitıd sütunu öğrencinin ID değerini içeriyorsa bir öğrenci satırıyla ilgilidir.
Örneğin, bir öğrenci satırının ID = 1 olduğunu varsayalım. İlgili kayıt satırları Studentitıd = 1 olacaktır. Studentitıd,
kayıt tablosundaki bir yabancı anahtardır .
Birden çok ilgili kayıt varlığı olabileceğinden Enrollments özelliği ICollection<Enrollment> olarak tanımlanır.
List<Enrollment> veya HashSet<Enrollment> gibi başka koleksiyon türleri de kullanabilirsiniz. Zaman
ICollection<Enrollment> olduğu EF Core kullanıldığında, oluşturur bir HashSet<Enrollment> varsayılan olarak
koleksiyon.

Kayıt varlık
Aşağıdaki kodla modeller/kayıt. cs oluşturun:

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

EnrollmentID özelliği birincil anahtardır; Bu varlık, ID yerine classnameID modelini kullanır. Bir üretim veri modeli
için bir model seçin ve bunu tutarlı bir şekilde kullanın. Bu öğretici her ikisinin de yalnızca bir iş olduğunu
göstermek için kullanır. classname olmadan ID kullanmak, bazı veri modeli değişikliklerinin uygulanmasını
kolaylaştırır.
Grade Özelliği bir enum . Grade türü bildiriminden sonraki soru işareti, Grade özelliğinin null yapılabilirolduğunu
gösterir. Null olan bir sınıf sıfır bir sınıfa göre farklılık gösterir—null, henüz bir sınıf bilinmediğini veya henüz
atanmadığını belirtir.
StudentID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Student . Bir Enrollment
varlıktır biriyle ilişkili Student tek bir özellik içerecek şekilde varlık Student varlık.
CourseID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Course . Bir Enrollment varlıktır
biriyle ilişkili Course varlık.
EF Core adlandırılmışsa, bu özellik bir yabancı anahtar olarak yorumlar
<navigation property name><primary key property name> . Örneğin, Student varlığın birincil anahtarı ID
olduğundan, Student gezinti özelliği için StudentID yabancı anahtardır. Yabancı anahtar özellikleri de adı
<primary key property name> . Örneğin, CourseID beri Course varlığın birincil anahtarı CourseID .

Kurs varlık
Aşağıdaki kodla modeller/kurs. cs oluşturun:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Enrollments Özelliktir bir gezinme özelliği. A Course varlık dilediğiniz sayıda ilgili olabileceğini Enrollment
varlıklar.
DatabaseGenerated özniteliği, uygulamanın veritabanını oluşturmak yerine birincil anahtarı belirtmesini sağlar.
Derleyici hatası olmadığını doğrulamak için projeyi derleyin.

Yapı iskelesi öğrenci sayfaları


Bu bölümde, oluşturmak için ASP.NET Core scafkatlama aracını kullanırsınız:
EF Core bağlamı sınıfı. Bağlam, belirli bir veri modeli için Entity Framework işlevselliği koordine eden ana
sınıftır. Microsoft.EntityFrameworkCore.DbContext sınıfından türetilir.
Student varlık için oluşturma, okuma, güncelleştirme ve silme ( CRUD ) işlemlerini işleyen Razor sayfaları.

Visual Studio
Visual Studio Code
Sayfalar klasöründe bir öğrenciler klasörü oluşturun.
Çözüm Gezgini, Sayfalar/öğrenciler klasörüne sağ tıklayın ve > yeni yapı iskelesi öğesi Ekle ' yi seçin.
İçinde İskele Ekle iletişim kutusunda Entity Framework (CRUD ) kullanarak Razor sayfaları > ekleme.
Entity Framework kullanarak Razor Pages Ekle (CRUD ) iletişim kutusunda:
İçinde Model sınıfı açılan listesinde, select Öğrenci (ContosoUniversity.Models) .
Veri bağlamı sınıfı satırında + (artı) işaretini seçin.
Contosouniversity. modeller. Contosoüniversıtycontext olan veri bağlamı adını Contosouniversity. Data.
SchoolContextolarak değiştirin.
Add (Ekle) seçeneğini belirleyin.
Aşağıdaki paketler otomatik olarak yüklenir:
Microsoft.VisualStudio.Web.CodeGeneration.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.Extensions.Logging.Debug
Microsoft.EntityFrameworkCore.Tools

Önceki adımla ilgili bir sorununuz varsa, projeyi derleyin ve yapı iskelesi adımını yeniden deneyin.
Yapı iskelesi işlemi:
Sayfalar/öğrenciler klasöründe Razor sayfaları oluşturur:
. Cshtml ve Create.cshtml.cs oluşturma
Delete. cshtml ve delete.cshtml.cs
Details. cshtml ve details.cshtml.cs
. Cshtml ve Edit.cshtml.cs Düzenle
Index. cshtml ve Index.cshtml.cs
Data/SchoolContext. csoluşturur.
Startup.csiçinde bağımlılık eklenmesine bağlam ekler.
AppSettings. JSONöğesine bir veritabanı bağlantı dizesi ekler.

Veritabanı bağlantı dizesi


Visual Studio
Visual Studio Code
Bağlantı dizesini belirtir SQL Server LocalDB.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"SchoolContext": "Server=
(localdb)\\mssqllocaldb;Database=SchoolContext;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

LocalDB, SQL Server Express veritabanı Motoru'nu hafif bir sürümüdür ve uygulama geliştirme, üretim kullanımı
için tasarlanmıştır. Varsayılan olarak, LocalDB C:/Users/<user> dizininde . mdf dosyaları oluşturur.

Veritabanı bağlam sınıfını Güncelleştir


Belirli bir veri modeli için EF Core işlevselliğini koordine eden ana sınıf veritabanı bağlamı sınıfıdır. Bağlam
Microsoft. EntityFrameworkCore. DbContextöğesinden türetilir. Bağlam, veri modeline hangi varlıkların
ekleneceğini belirtir. Bu projede adlı sınıfı SchoolContext .
Güncelleştirme SchoolContext.cs aşağıdaki kod ile:
using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext (DbContextOptions<SchoolContext> options)
: base(options)
{
}

public DbSet<Student> Students { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}

Vurgulanan kod oluşturur bir olan DB<TEntity > her varlık kümesi özelliği. EF Core terminolojisinde:
Bir varlık kümesi, genellikle bir veritabanı tablosuna karşılık gelir.
Bir varlık tablosunda bir satıra karşılık gelir.
Bir varlık kümesi birden çok varlık içerdiğinden, DBSet özellikleri çoğul adlar olmalıdır. Scafkatlama aracı bir
Student DBSet oluşturduğundan, bu adım bunu plural Students olarak değiştirir.

Razor Pages kodun yeni DBSet adıyla eşleşmesini sağlamak için, tüm _context.Student projesi genelinde
_context.Students için genel bir değişiklik yapın. 8 oluşum vardır.

Derleyici hatası olmadığını doğrulamak için projeyi derleyin.

Startup.cs
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (EF Core veritabanı bağlamı gibi) uygulama başlatma
sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler
Oluşturucu parametresi üzerinden sağlanır. Bir veritabanı bağlamı örneğini alan Oluşturucu kodu öğreticide daha
sonra gösterilmiştir.
Scafkatlama Aracı, bağlam sınıfını bağımlılık ekleme kapsayıcısına otomatik olarak kaydetti.
Visual Studio
Visual Studio Code
ConfigureServices , vurgulanan satırlar scaffolder tarafından eklenmiştir:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
}
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.

Veritabanını oluşturma
Mevcut değilse veritabanını oluşturmak için program.cs güncelleştirin:

using ContosoUniversity.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

CreateDbIfNotExists(host);

host.Run();
}

private static void CreateDbIfNotExists(IHost host)


{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Bağlam için bir veritabanı varsa, Ensuyeniden oluşturma yöntemi hiçbir eylemde bulunmaz. Veritabanı yoksa,
veritabanını ve şemayı oluşturur. EnsureCreated , veri modeli değişikliklerini işlemek için aşağıdaki iş akışına izin
vermez:
Veritabanını silin. Mevcut veriler kaybolur.
Veri modelini değiştirin. Örneğin, bir EmailAddress alanı ekleyin.
Uygulamayı çalıştırın.
EnsureCreated yeni şemaya sahip bir veritabanı oluşturur.
Bu iş akışı, verileri korumanıza gerek olmadığı sürece, şema hızlı bir şekilde gelişen zaman geliştirme aşamasında
iyi bir şekilde gerçekleştirilir. Veritabanına girilen verilerin korunması gerektiğinde bu durum farklıdır. Bu durumda,
geçişleri kullanın.
Öğretici serisinde daha sonra, EnsureCreated tarafından oluşturulan veritabanını silin ve bunun yerine geçişleri
kullanın. EnsureCreated tarafından oluşturulan bir veritabanı, geçişler kullanılarak güncelleştirilemiyor.
Uygulamayı test etme
Uygulamayı çalıştırın.
Seçin Öğrenciler bağlantısını ve ardından Yeni Oluştur.
Ayrıntılar, düzenleme, test edin ve bağlantılarını silin.

Veritabanının çekirdeğini oluşturma


EnsureCreated yöntemi boş bir veritabanı oluşturur. Bu bölüm, veritabanını test verileriyle dolduran kodu ekler.
Aşağıdaki kodla veri/Dbınizer. cs oluşturun:

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();

// Look for any students.


if (context.Students.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-
01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-
01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-
01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-
01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-
01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-
01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-
01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();

var courses = new Course[]


{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}

Kod, veritabanında herhangi bir öğrenci olup olmadığını denetler. Öğrenci yoksa, veritabanına test verileri ekler.
Performansı iyileştirmek için List<T> koleksiyonları yerine diziler halinde test verileri oluşturur.
Program.cs' de EnsureCreated çağrısını DbInitializer.Initialize çağrısıyla değiştirin:

// context.Database.EnsureCreated();
DbInitializer.Initialize(context);

Visual Studio
Visual Studio Code
Çalışıyorsa uygulamayı durdurun ve Paket Yöneticisi konsolunda (PMC ) aşağıdaki komutu çalıştırın:

Drop-Database

Uygulamayı yeniden başlatın.


Sağlanan verileri görmek için öğrenciler sayfasını seçin.

Veritabanını görüntüleme
Visual Studio
Visual Studio Code
Açık SQL Server Nesne Gezgini (SSOX) öğesinden görünümü Visual Studio'daki menü.
SSOX 'te, (LocalDB ) \MSSQLLocalDB > veritabanları > SchoolContext-{GUID } öğesini seçin. Veritabanı
adı, daha önce belirttiğiniz bağlam adından ve bir tire ve bir GUID ile oluşturulur.
Genişletin tabloları düğümü.
Sağ Öğrenci tablosu ve'ı tıklatın görünüm verilerini oluşturulan sütunları ve tabloya eklenen satırları
görebilirsiniz.
Student modelinin Student tablo şemasına nasıl eşlendiğini görmek için öğrenci tablosuna sağ tıklayın ve
kodu görüntüle ' ye tıklayın.

Zaman uyumsuz kod


Zaman uyumsuz programlama, ASP.NET Core ve EF Core için varsayılan moddur.
Sınırlı sayıda iş parçacığı kullanılabilir bir web sunucusuna sahip ve yüksek yük durumlarda tüm kullanılabilir iş
parçacıklarının kullanımda olabilir. Bu durum oluştuğunda, sunucunun iş parçacıklarının serbest bırakılana kadar
yeni istekleri işleyemiyor. G/ç tamamlanması bekleniyor çünkü bunlar herhangi bir iş gerçekten yapmamanız
sırasında eş zamanlı kod ile birçok iş parçacığı bağlanması. İşlemi tamamlamak, g/ç için beklerken zaman uyumsuz
kod ile diğer istekleri işlemek için kullanılacak sunucuyu için kendi iş parçacığı serbest bırakılır. Sonuç olarak, zaman
uyumsuz kod sunucu kaynaklarının daha verimli kullanılmasını sağlar ve sunucu gecikmeksizin daha fazla trafiği
işleyebilir.
Zaman uyumsuz kod, çalışma zamanında az miktarda bir ek yükü sunar. Düşük trafiğe durumlar, performans
düşüşüne yüksek trafik durumlar için göz ardı edilebilir, çalışırken, olası performans geliştirmesi önemli.
Aşağıdaki kodda, zaman uyumsuz anahtar sözcüğü, Task<T> dönüş değeri, await anahtar sözcüğü ve
ToListAsync yöntemi zaman uyumsuz yürütülen kod olun.

public async Task OnGetAsync()


{
Students = await _context.Students.ToListAsync();
}

async Anahtar sözcüğü, derleyiciye bildirir:


Yöntem gövdesini bölümleri için geri çağırmaları oluşturur.
Döndürülen görev nesnesini oluşturun.
Task<T> dönüş türü devam eden çalışmayı temsil eder.
await Anahtar sözcüğü, derleyicinin yöntemin iki parçalara bölmek neden olur. İlk bölüm ile zaman uyumsuz
olarak başlatıldığında işlemi sonlandırır. İkinci bölümü, işlemi tamamlandıktan sonra çağrılan bir geri çağırma
yöntemi yerleştirilir.
ToListAsync zaman uyumsuz sürümüdür ToList genişletme yöntemi.

EF Core kullanan zaman uyumsuz kodu yazarken dikkat edilmesi gereken bazı noktalar şunlardır:
Yalnızca sorguları veya komutlarının veritabanına gönderilmesine neden olan deyimler zaman uyumsuz olarak
yürütülür. Bu ToListAsync , SingleOrDefaultAsync , FirstOrDefaultAsync ve SaveChangesAsync içerir. Yalnızca
değiştirmek deyimleri içermeyen bir IQueryable , gibi
var students = context.Students.Where(s => s.LastName == "Davolio") .
EF Core bağlam iş parçacığı güvenli olmayan: paralel birden çok işlem yapmak yeniden denemeyin.
Zaman uyumsuz kodun performans avantajlarından yararlanmak için, veritabanına sorgu gönderen EF Core
yöntemleri çağırıyorsa kitaplık paketlerinin (örneğin, sayfalama için) zaman uyumsuz olarak kullanılacağını
doğrulayın.
. NET'te zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman uyumsuz genel bakış ve zaman
uyumsuz programlama ile async ve await.

Sonraki adımlar

SON RA KI
Ö Ğ R E T IC I

Contoso University örnek web uygulamasını, Entity Framework (EF ) çekirdek kullanarak bir ASP.NET Core Razor
sayfalar uygulamasının nasıl oluşturulacağını gösterir.
Örnek uygulama, kurgusal Contoso üniversite için bir web sitesidir. Öğrenci giriş, kurs oluşturma ve Eğitmen
atamaları gibi işlevleri içerir. Contoso University örnek uygulamasının nasıl oluşturulacağını açıklayan öğreticileri
serisinin ilk sayfadır.
İndirme veya tamamlanmış uygulamayı görüntüleyin. Yükleme yönergeleri.

Önkoşullar
Visual Studio
Visual Studio Code
Visual Studio 2019 aşağıdaki iş yükleri ile:
ASP.NET ve web geliştirme
.NET core platformlar arası geliştirme
.NET core 2.1 SDK veya üzeri
Konusunda Razor sayfaları. Yeni programcılar tamamlamanız gereken Razor sayfaları kullanmaya başlama Bu seriyi
başlatmadan önce.

Sorun giderme
Bir sorunla karşılaşırsanız, çözümleyemiyor çalıştırırsanız, genel olarak çözüm kodunuzda karşılaştırarak
bulabilirsiniz projeyi. Soru göndererek Yardım almak için en iyi yolu olan StackOverflow.com için ASP.NET Core
veya EF Core.

Contoso University web uygulaması


Aşağıdaki öğreticilerde oluşturulan bir uygulamayı bir temel university web sitesidir.
Kullanıcılar görüntüleyebilir ve Öğrenci, kurs ve Eğitmen bilgileri güncelleştirin. Öğreticide oluşturulan ekranlar
birkaçını aşağıda verilmiştir.
Bu sitenin UI Stili yerleşik şablonları tarafından üretilen yakın ' dir. EF çekirdekli Razor sayfaları, UI ile öğretici odağı
açıktır.

ContosoUniversity Razor sayfaları web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun. Projeyi adlandırın ContosoUniversity. Projeyi adlandırın
önemlidir ContosoUniversity kod kopyalanıp/yapıştırılmış ad alanları eşleştirmek için.
Seçin ASP.NET Core 2.1 açılır ve ardından Web uygulaması.
Önceki adımlarda görüntüleri için bkz: Razor web uygulaması oluşturma. Uygulamayı çalıştırın.

Site stili Ayarla


Birkaç değişiklik site menü, Düzen ve giriş sayfası ayarlayın. Güncelleştirme Pages/Shared/_Layout.cshtml
aşağıdaki değişikliklerle birlikte:
"Contoso Üniversitesi" için "ContosoUniversity" her örneğini değiştirin. Üç örnekleri vardır.
Menü girdileri eklemek Öğrenciler, kursları, Eğitmenler, ve Departmanlarve silme başvurun menüsü
girişi.
Değişiklikler vurgulanır. (Tüm biçimlendirme değil görüntülenir.)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] : Contoso University</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-
collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">Contoso University</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Students/Index">Students</a></li>
<li><a asp-page="/Courses/Index">Courses</a></li>
<li><a asp-page="/Instructors/Index">Instructors</a></li>
<li><a asp-page="/Departments/Index">Departments</a></li>
</ul>
</div>
</div>
</nav>

<partial name="_CookieConsentPartial" />

<div class="container body-content">


@RenderBody()
<hr />
<footer>
<p>&copy; 2018 : Contoso University</p>
</footer>
</div>

@*Remaining markup not shown for brevity.*@

İçinde sayfalar/dizin.cshtml, dosyanın içeriğini ASP.NET ve MVC hakkında metnin bu uygulama hakkında metinle
değiştirmek için aşağıdaki kodla değiştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core Razor Pages web app.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p>
<a class="btn btn-default"
href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro">
See the tutorial &raquo;
</a>
</p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p>
<a class="btn btn-default"
href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-
rp/intro/samples/">
See project source code &raquo;
</a>
</p>
</div>
</div>

Veri modeli oluşturma


Varlık sınıflarının Contoso University uygulama oluşturun. Aşağıdaki üç varlıklarla başlayın:

Bir-çok ilişkisi arasında Student ve Enrollment varlıklar. Bir-çok ilişkisi arasında Course ve Enrollment varlıklar.
Bir öğrenci herhangi bir sayıda kursları kaydedebilirsiniz. Bir kurs herhangi bir sayıda Öğrenciler içinde kayıtlı
olabilir.
Aşağıdaki bölümlerde, bu varlıkların her biri için bir sınıf oluşturulur.
Öğrenci varlık
Oluşturma bir modelleri klasör. İçinde modelleri klasöründe adlı bir sınıf dosyası oluşturma Student.cs aşağıdaki
kod ile:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

ID Özelliği bu sınıfa karşılık gelen veritabanı (DB ) tablosunun birincil anahtar sütunu duruma gelir. Varsayılan
olarak EF Core adlı bir özellik yorumlar ID veya classnameID birincil anahtar olarak. İçinde classnameID ,
classname sınıf adıdır. Alternatif birincil anahtarı otomatik olarak kabul edilen StudentID önceki örnekte.

Enrollments Özelliği bir gezinti özelliği. Gezinti özellikleri bu varlıkla ilgili diğer varlıkları bağlayın. Bu durumda,
Enrollments özelliği bir Student entity tüm tutan Enrollment olarak ilişkili varlıkları Student . Örneğin, bir
öğrenci satır DB'de iki kayıt satırları ilgili olan Enrollments gezinti özelliği içerir, bu iki Enrollment varlıklar. İlgili
Enrollment satırdır bu öğrencinin birincil anahtar değerini içeren bir satır StudentID sütun. Örneğin, Öğrenci
kimlikli varsayalım = 1 olan iki satır Enrollment tablo. Enrollment Tablosunda var olan iki satır StudentID = 1.
StudentID içinde bir yabancı anahtar Enrollment içinde Öğrenci belirten tablo Student tablo.

Bir gezinme özelliği birden çok varlık tutarsanız gezinme özelliğini bir liste türü gibi olmalıdır ICollection<T> .
ICollection<T> belirtilebilir, ya da bir tür gibi List<T> veya HashSet<T> . Zaman ICollection<T> olduğu EF Core
kullanıldığında, oluşturur bir HashSet<T> varsayılan olarak koleksiyon. Birden çok varlık tutun Gezinti özellikleri
çoktan çoğa ve bire çok ilişkileri gelir.
Kayıt varlık

İçinde modelleri klasör oluşturma Enrollment.cs aşağıdaki kod ile:


namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

EnrollmentID Birincil anahtar özelliğidir. Bu varlığı kullanan classnameID yerine desen ID gibi Student varlık.
Genellikle geliştiriciler bir düzen seçin ve veri modelini kullanın. Bir sonraki öğreticide, classname Kimliğini
kullanarak, veri modelinde aktarma uygulamak daha kolay hale getirmek için gösterilir.
Grade Özelliği bir enum . Sonra soru işareti Grade türü bildirimi gösterir Grade özelliği boş değer atanabilir. Boş
bir sınıf bir sıfır sınıf farklı--null anlamına gelir bir sınıf bilinen değil veya henüz atanmamış.
StudentID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Student . Bir Enrollment
varlıktır biriyle ilişkili Student tek bir özellik içerecek şekilde varlık Student varlık. Student Varlık farklıdır
Student.Enrollments içeren birden çok gezinti özelliği Enrollment varlıklar.

CourseID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Course . Bir Enrollment varlıktır
biriyle ilişkili Course varlık.
EF Core adlandırılmışsa, bu özellik bir yabancı anahtar olarak yorumlar
<navigation property name><primary key property name> . Örneğin, StudentID için Student gezinti özelliği bu yana
Student varlığın birincil anahtarı ID . Yabancı anahtar özellikleri de adı <primary key property name> . Örneğin,
CourseID beri Course varlığın birincil anahtarı CourseID .

Kurs varlık

İçinde modelleri klasör oluşturma Course.cs aşağıdaki kod ile:


using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Enrollments Özelliktir bir gezinme özelliği. A Course varlık dilediğiniz sayıda ilgili olabileceğini Enrollment
varlıklar.
DatabaseGenerated DB sahip, oluşturmak, yerine özniteliği birincil anahtarı belirtmek için uygulamayı sağlar.

İskele Öğrenci modeli


Bu bölümde, Öğrenci modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik Öğrenci modeli oluşturur.
Projeyi oluşturun.
Oluşturma sayfaları/Öğrenciler klasör.
Visual Studio
Visual Studio Code
İçinde Çözüm Gezgini, sağ tıklayın sayfaları/Öğrenciler klasör > Ekle > yeni iskele kurulmuş öğe.
İçinde İskele Ekle iletişim kutusunda Entity Framework (CRUD ) kullanarak Razor sayfaları > ekleme.
Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:
İçinde Model sınıfı açılan listesinde, select Öğrenci (ContosoUniversity.Models) .
İçinde veri bağlamı sınıfının satır, select + (artı) oturum açın ve oluşturulan bir adla değiştirin
ContosoUniversity.Models.SchoolContext.
İçinde veri bağlamı sınıfının açılan listesinde, select ContosoUniversity.Models.SchoolContext
Add (Ekle) seçeneğini belirleyin.
Bkz: film modeli iskelesini önceki adımı ile ilgili bir sorun varsa.
İskele işlem oluşturulur ve aşağıdaki dosya değişti:
Oluşturulan dosyalar
Sayfa/Öğrenciler oluşturma, silme, Ayrıntılar, düzenleme, dizin.
Data/SchoolContext.cs
Dosya güncelleştirmeleri
Startup.cs : Bu dosyada yapılan değişiklikler sonraki bölümde ayrıntılı.
appSettings.JSON : yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi eklenir.

Bağımlılık ekleme ile kayıtlı bağlamını İnceleme


ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı), uygulama başlatma
sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler
Oluşturucu parametresi üzerinden sağlanır. Bir db bağlamı örneği alır Oluşturucu kodu öğreticinin ilerleyen
bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme kapsayıcısını ile
kayıtlı.
İnceleme ConfigureServices yönteminde Startup.cs. Vurgulanan satırı iskele kurucu tarafından eklendi:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for
//non -essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
}

Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.

Ana güncelleştir
İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Çağrı EnsureCreated.
Bağlam dispose olduğunda EnsureCreated yöntemi tamamlar.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.
using ContosoUniversity.Models; // SchoolContext
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; // CreateScope
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

EnsureCreated Veritabanı bağlamının var olmasını sağlar. Varsa, hiçbir işlem yapılmaz. Yoksa, veritabanı ve tüm
şema oluşturulur. EnsureCreated veritabanı oluşturmaya geçişleri kullanmaz. İle oluşturulmuş bir veritabanı
EnsureCreated daha sonra geçişleri kullanılarak güncelleştirilemez.

EnsureCreated Aşağıdaki iş akışı sağlayan uygulama Başlat menüsünde çağrılır:


DB silin.
DB şema değiştirme (örneğin, bir EmailAddress alan).
Uygulamayı çalıştırın.
EnsureCreated bir DB ile oluşturur EmailAddress sütun.

EnsureCreated Şema hızla gelişirken erken geliştirme uygundur. Daha sonra öğreticide DB silinir ve geçişler
kullanılır.
Uygulamayı test etme
Uygulamayı çalıştırın ve tanımlama bilgisi ilkesini kabul edin. Bu uygulama, kişisel bilgileri tutmak değil. Tanımlama
bilgisi ilkesi hakkında bilgi edinebilirsiniz AB genel veri koruma yönetmeliği (GDPR ) Destek.
Seçin Öğrenciler bağlantısını ve ardından Yeni Oluştur.
Ayrıntılar, düzenleme, test edin ve bağlantılarını silin.
SchoolContext DB bağlamını İnceleme
Verilen veri modeli için EF Core işlevselliği koordine eden ana DB bağlamı sınıfının sınıftır. Veri bağlamı türetilir
Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı, hangi varlıkları veri modelinde yer alan belirtir. Bu
projede adlı sınıfı SchoolContext .
Güncelleştirme SchoolContext.cs aşağıdaki kod ile:

using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Models
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options)
: base(options)
{
}

public DbSet<Student> Student { get; set; }


public DbSet<Enrollment> Enrollment { get; set; }
public DbSet<Course> Course { get; set; }
}
}

Vurgulanan kod oluşturur bir olan DB<TEntity > her varlık kümesi özelliği. EF Core terminolojisinde:
Bir varlık kümesini genellikle DB tabloya karşılık gelir.
Bir varlık tablosunda bir satıra karşılık gelir.
DbSet<Enrollment> ve atlanmış. EF Core içeren bunları örtük olarak çünkü Student varlık
DbSet<Course>
başvuruları Enrollment varlığı ve Enrollment varlık başvuruları Course varlık. Bu öğretici için tutmak
DbSet<Enrollment> ve DbSet<Course> içinde SchoolContext .

SQL Server Express LocalDB


Bağlantı dizesini belirtir SQL Server LocalDB. LocalDB, SQL Server Express veritabanı Motoru'nu hafif bir
sürümüdür ve uygulama geliştirme, üretim kullanımı için tasarlanmıştır. LocalDB, isteğe bağlı olarak başlar ve
karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak LocalDB oluşturur .mdf DB
dosyaları C:/Users/<user> dizin.

Bir veritabanı test verileri ile başlatmak için kod ekleyin


EF Core boş bir veritabanı oluşturur. Bu bölümde, bir Initialize yöntemi test verileriyle doldurma işlemine yazılır.
İçinde veri klasöründe adlı yeni bir sınıf dosyası oluşturma DbInitializer.cs ve aşağıdaki kodu ekleyin:

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Models
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();

// Look for any students.


if (context.Student.Any())
{
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-
01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Student.Add(s);
}
context.SaveChanges();

var courses = new Course[]


{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Course.Add(c);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollment.Add(e);
}
context.SaveChanges();
}
}
}

Note: Yukarıdaki kod Data yerine ad alanı ( namespace ContosoUniversity.Models ) için Models kullanır. Models ,
scaffolder tarafından oluşturulan kodla tutarlıdır. Daha fazla bilgi için bkz. GitHub yapı iskelesi sorunu.
Kod DB'de tüm Öğrenciler olup olmadığını denetler. DB'de Öğrenci varsa, bir veritabanı test verileri ile başlatılır.
Diziye test verileri yükler yerine List<T> performansını iyileştirmek için koleksiyonları.
EnsureCreated Yöntemi DB bağlamı için bir veritabanı otomatik olarak oluşturur. Veritabanı varsa, EnsureCreated
DB değiştirmeden döndürür.
İçinde Program.cs, değişiklik Main çağrılacak yöntem Initialize :

public class Program


{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
// using ContosoUniversity.Data;
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

Visual Studio
Visual Studio Code
Çalışıyorsa uygulamayı durdurun ve Paket Yöneticisi konsolunda (PMC ) aşağıdaki komutu çalıştırın:

Drop-Database

DB görüntüleyin
Veritabanı adı, daha önce belirttiğiniz bağlam adından ve bir tire ve bir GUID ile oluşturulur. Bu nedenle, veritabanı
adı "SchoolContext-{GUID }" olacaktır. GUID her kullanıcı için farklı olacaktır. Açık SQL Server Nesne Gezgini
(SSOX) öğesinden görünümü Visual Studio'daki menü. SSOX 'te, (LocalDB ) \MSSQLLocalDB > veritabanları
> SchoolContext-{GUID } ' a tıklayın.
Genişletin tabloları düğümü.
Sağ Öğrenci tablosu ve'ı tıklatın görünüm verilerini oluşturulan sütunları ve tabloya eklenen satırları
görebilirsiniz.

Zaman uyumsuz kod


Zaman uyumsuz programlama, ASP.NET Core ve EF Core için varsayılan moddur.
Sınırlı sayıda iş parçacığı kullanılabilir bir web sunucusuna sahip ve yüksek yük durumlarda tüm kullanılabilir iş
parçacıklarının kullanımda olabilir. Bu durum oluştuğunda, sunucunun iş parçacıklarının serbest bırakılana kadar
yeni istekleri işleyemiyor. G/ç tamamlanması bekleniyor çünkü bunlar herhangi bir iş gerçekten yapmamanız
sırasında eş zamanlı kod ile birçok iş parçacığı bağlanması. İşlemi tamamlamak, g/ç için beklerken zaman uyumsuz
kod ile diğer istekleri işlemek için kullanılacak sunucuyu için kendi iş parçacığı serbest bırakılır. Sonuç olarak,
sunucu kaynaklarının daha etkin kullanılması zaman uyumsuz kod sağlar ve sunucu gecikmeler olmadan daha fazla
trafik işlemek için etkinleştirilir.
Zaman uyumsuz kod, çalışma zamanında az miktarda bir ek yükü sunar. Düşük trafiğe durumlar, performans
düşüşüne yüksek trafik durumlar için göz ardı edilebilir, çalışırken, olası performans geliştirmesi önemli.
Aşağıdaki kodda, zaman uyumsuz anahtar sözcüğü, Task<T> dönüş değeri, await anahtar sözcüğü ve
ToListAsync yöntemi zaman uyumsuz yürütülen kod olun.

public async Task OnGetAsync()


{
Student = await _context.Student.ToListAsync();
}

async Anahtar sözcüğü, derleyiciye bildirir:


Yöntem gövdesini bölümleri için geri çağırmaları oluşturur.
Otomatik olarak oluşturmasını görev döndürülen nesne. Daha fazla bilgi için görev dönüş türü.
Örtük dönüş türü Task devam eden çalışmayı temsil eder.
await Anahtar sözcüğü, derleyicinin yöntemin iki parçalara bölmek neden olur. İlk bölüm ile zaman
uyumsuz olarak başlatıldığında işlemi sonlandırır. İkinci bölümü, işlemi tamamlandıktan sonra çağrılan bir
geri çağırma yöntemi yerleştirilir.
ToListAsync zaman uyumsuz sürümüdür ToList genişletme yöntemi.
EF Core kullanan zaman uyumsuz kodu yazarken dikkat edilmesi gereken bazı noktalar şunlardır:
Sorguları veya Veritabanına gönderilecek komutları neden deyimleri zaman uyumsuz olarak yürütülür. İçeren,
ToListAsync , SingleOrDefaultAsync , FirstOrDefaultAsync , ve SaveChangesAsync . Yalnızca değiştirmek deyimleri
içermeyen bir IQueryable , gibi var students = context.Students.Where(s => s.LastName == "Davolio") .
EF Core bağlam iş parçacığı güvenli olmayan: paralel birden çok işlem yapmak yeniden denemeyin.
Zaman uyumsuz kodun performans avantajlarından yararlanmak için bunlar için bir veritabanı sorguları
göndermek EF Core yöntemleri çağırırsanız kitaplığı paketlerinin (disk belleği sunamıyoruz gibi) zaman
uyumsuz kullandığını doğrulayın.
. NET'te zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman uyumsuz genel bakış ve zaman
uyumsuz programlama ile async ve await.
Sonraki öğreticide, temel CRUD (oluşturma, okuma, güncelleştirme ve silme) işlemleri incelenir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

NEXT
ASP.NET Core-CRUD-2 ' de EF Core ile Razor Pages
20.08.2019 • 34 minutes to read • Edit Online

, Tom Dykstra, Jon P Smithve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, scafkatan CRUD (oluşturma, okuma, güncelleştirme, silme) kodu incelenir ve özelleştirilir.

Depo yok
Bazı geliştiriciler, Kullanıcı arabirimi (Razor Pages) ve veri erişim katmanı arasında bir soyutlama katmanı
oluşturmak için bir hizmet katmanı veya depo deseninin kullanılmasını sağlar. Bu öğretici bunu yapmaz.
Karmaşıklığı en aza indirmek ve öğreticiyi EF Core odaklanmasını sağlamak için EF Core kodu doğrudan sayfa
modeli sınıflarına eklenir.

Ayrıntılar sayfasını Güncelleştir


Öğrenciler sayfaları için yapı iskelesi kodu kayıt verilerini içermez. Bu bölümde, ayrıntılar sayfasına kayıtları
eklersiniz.
Kayıtları oku
Sayfada öğrenciye ait kayıt verilerini göstermek için, onu okumanız gerekir. Pages/öğrenciler/details. cshtml. cs
içindeki scafkatlama kodu, kayıt verileri olmadan yalnızca öğrenci verilerini okur:

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Students.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

OnGetAsync Yöntemi, seçili öğrenci için kayıt verilerini okumak üzere aşağıdaki kodla değiştirin. Değişiklikler
vurgulanır.
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Students


.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

Include ve thenınclude yöntemleri, içeriğin Student.Enrollments gezinti özelliğini yüklemesine ve her


Enrollment.Course kaydın gezinti özelliği içine olmasına neden olur. Bu yöntemler, okuma ilgili verileri öğreticisinde
ayrıntılı olarak incelendi.
Asnotracking yöntemi, döndürülen varlıkların geçerli bağlamda güncelleştirilmediği senaryolarda performansı
geliştirir. AsNoTracking Bu öğreticinin ilerleyen kısımlarında ele alınmıştır.
Kayıtları görüntüle
Sayfalar/öğrenciler/details. cshtml içindeki kodu aşağıdaki kodla değiştirin ve kayıtlar listesini görüntüleyin.
Değişiklikler vurgulanır.
@page
@model ContosoUniversity.Pages.Students.DetailsModel

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Student</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.Enrollments)
</dt>
<dd class="col-sm-10">
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Student.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Student.ID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>

Yukarıdaki kod, Enrollments Gezinti özelliğindeki varlıklar aracılığıyla döngü başlatır. Her kayıt için kurs başlığını ve
sınıfı görüntüler. Kurs başlığı, kayıt varlığının Course gezinti özelliğinde depolanan kurs varlığından alınır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir öğrenci için Ayrıntılar bağlantısına tıklayın. Seçili öğrenci
için Kurslar ve notlar listesi görüntülenir.
Bir varlığı okuma yolları
Oluşturulan kod, bir varlığı okumak için Firstordefaultasync kullanır. Bu yöntem, hiçbir şey bulunamazsa null
değerini döndürür; Aksi takdirde, sorgu filtresi ölçütlerine uyan bulunan ilk satırı döndürür. FirstOrDefaultAsync
genellikle aşağıdaki alternatiflere göre daha iyi bir seçimdir:
Singleordefaultasync -sorgu filtresini karşılayan birden fazla varlık varsa bir özel durum oluşturur. Sorgu
tarafından birden fazla satır döndürülüp döndürülmeyeceğini anlamak için birden çok satır getirmeyi
SingleOrDefaultAsync dener. Sorgu yalnızca bir varlık döndürebiliyorsanız ve benzersiz bir anahtarda arama
yaptığında bu ek çalışma gereksizdir.
Findadsync -birincil ANAHTARLA (PK) bir varlık bulur. PK 'ye sahip bir varlık bağlam tarafından izleniyorsa,
veritabanına bir istek olmadan döndürülür. Bu yöntem tek bir varlık aramak için en iyi duruma getirilmiştir, ancak
ile Include FindAsync çağrılamaz. Bu nedenle, ilgili veriler gerekliyse, FirstOrDefaultAsync daha iyi bir seçimdir.
Veri yönlendirme ve sorgu dizesi karşılaştırması
Ayrıntılar sayfasının https://localhost:<port>/Students/Details?id=1 URL 'si. Varlığın birincil anahtar değeri, sorgu
dizesinde bulunur. Bazı geliştiriciler anahtar değerini rota verilerinde geçirmeye tercih eder:
https://localhost:<port>/Students/Details/1 . Daha fazla bilgi için bkz. oluşturulan kodu güncelleştirme.

Oluştur sayfasını Güncelleştir


Oluşturma sayfası için yapı OnPostAsync İskelesi kodu, aşırı nakmeaçıktır. Pages/öğrenciler/Create. cshtml. cs
içindeki yöntemiaşağıdakikodladeğiştirin. OnPostAsync

public async Task<IActionResult> OnPostAsync()


{
var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
_context.Students.Add(emptyStudent);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}

TryUpdateModelAsync
Yukarıdaki kod bir öğrenci nesnesi oluşturur ve ardından, öğrenci nesnesinin özelliklerini güncelleştirmek için,
postalanan form alanlarını kullanır. Tryupdatemodelasync yöntemi:
PagemodelIçindeki pagecontext özelliğinden gönderilen form değerlerini kullanır.
Yalnızca listelenen ( s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate ) özellikleri güncelleştirir.
"Öğrenci" ön ekine sahip form alanlarını arar. Örneğin: Student.FirstMidName . Büyük/küçük harfe duyarlı
değildir.
, Dizelerdeki form değerlerini Student modeldeki türlere dönüştürmek için model bağlama sistemini kullanır.
Örneğin, EnrollmentDate DateTime 'a dönüştürülmesi gerekir.

Uygulamayı çalıştırın ve oluştur sayfasını test etmek için bir öğrenci varlığı oluşturun.

Fazla nakil
Deftere TryUpdateModel nakledilen değerler içeren alanları güncelleştirmek için kullanmak, aşırı nakletmeyi önlediği
için en iyi güvenlik yöntemidir. Örneğin, öğrenci varlığının bu Web sayfasının güncelleştirmesi veya Secret
eklemesi gereken bir özelliği içerdiğini varsayalım:

public class Student


{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}

Uygulama, oluşturma veya güncelleştirme Razor sayfasında Secret bir alana sahip olmasa da, bir korsan Secret
değeri aşırı nakme ile ayarlayabilir. Bir korsan, Fiddler gibi bir araç kullanabilir veya bir Secret form değeri
göndermek için bazı JavaScript yazabilir. Özgün kod, bir öğrenci örneği oluştururken model cildin kullandığı
alanları sınırlamaz.
Secret Form alanı için belirtilen korsanın hangi değeri veritabanında güncelleştirildiği. Aşağıdaki görüntüde, alanı
("overpost" değeri ile Secret ), postalanan form değerlerine ekleyen Fiddler aracı gösterilmektedir.

"Overpost" değeri eklenen satırın Secret özelliğine başarıyla eklendi. Bu durum, Uygulama Tasarımcısı hiçbir
şekilde Secret özelliği oluştur sayfasıyla ayarlamaya yönelik değildir.
Modeli görüntüle
Model görüntüleme, fazla nakletmeyi önlemenin alternatif bir yolunu sağlar.
Uygulama modeli genellikle etki alanı modeli olarak adlandırılır. Etki alanı modeli genellikle veritabanında ilgili
varlık için gereken tüm özellikleri içerir. Görünüm modeli yalnızca için kullanılan Kullanıcı arabirimi için gereken
özellikleri içerir (örneğin, oluşturma sayfası).
Görünüm modeline ek olarak, bazı uygulamalar Razor Pages sayfa modeli sınıfı ve tarayıcı arasında veri geçirmek
için bir bağlama modeli veya giriş modeli kullanır.
Aşağıdaki Student görünüm modelini göz önünde bulundurun:
using System;

namespace ContosoUniversity.Models
{
public class StudentVM
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}

Aşağıdaki kod, yeni bir StudentVM öğrenci oluşturmak için görünüm modelini kullanır:

[BindProperty]
public StudentVM StudentVM { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var entry = _context.Add(new Student());


entry.CurrentValues.SetValues(StudentVM);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

SetValues yöntemi, başka bir PropertyValues nesnesinden değerleri okuyarak bu nesnenin değerlerini ayarlar.
SetValues Özellik adı eşleştirme kullanır. Görünüm modeli türünün model türüyle ilgili olması gerekmez, yalnızca
eşleşen özellikleri olması gerekir.
Kullanılması StudentVM için StudentVM Create . cshtml kullanılması gerekir. Student

Güncelleştirme düzenleme sayfası


Sayfalar/öğrenciler/Edit. cshtml. cs' de, OnGetAsync ve OnPostAsync yöntemlerini aşağıdaki kodla değiştirin.
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Students.FindAsync(id);

if (Student == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
var studentToUpdate = await _context.Students.FindAsync(id);

if (studentToUpdate == null)
{
return NotFound();
}

if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}

Kod değişiklikleri, birkaç özel durum dışında oluşturma sayfasına benzerdir:


FirstOrDefaultAsync , Findadsyncile değiştirilmiştir. İlgili verileri dahil etmeniz gerekmiyorsa, FindAsync daha
etkilidir.
OnPostAsyncbir id parametreye sahiptir.
Geçerli öğrenci boş bir öğrenci oluşturmak yerine veritabanından getirilir.
Uygulamayı çalıştırın ve bir öğrenci oluşturup düzenleyerek test edin.

Varlık durumları
Veritabanı bağlamı, bellekteki varlıkların veritabanında karşılık gelen satırlarıyla eşitlenmiş olup olmadığını izler. Bu
izleme bilgileri, Savechangesasync çağrıldığında ne olacağını belirler. Örneğin, yeni bir varlık Addadsync yöntemine
geçirildiğinde, bu varlığın durumu eklendiolarak ayarlanır. SaveChangesAsync Çağrıldığında, veritabanı bağlamı bir
SQL INSERT komutu yayınlar.
Bir varlık aşağıdaki durumlardanbirinde olabilir:
Added : Varlık veritabanında henüz yok. SaveChanges Yöntemi bir INSERT ifadesini yayınlar.
: Bu varlıkla birlikte hiçbir değişiklik kaydedilmesi gerekmiyor. Bir varlık veritabanından okurken
Unchanged
bu durumu içerir.
Modified : Varlığın özellik değerlerinin bazıları veya tümü değiştirildi. SaveChanges Yöntemi bir Update
ifadesini yayınlar.
Deleted : Varlık silinmek üzere işaretlendi. SaveChanges Yöntemi bir DELETE ifadesini yayınlar.
Detached : Varlık, veritabanı bağlamı tarafından izlenmiyor.

Bir masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlık okundu,
değişiklikler yapılır ve varlık durumu otomatik olarak olarak değiştirilir Modified . Çağıran SaveChanges yalnızca
değiştirilen özellikleri güncelleştiren bir SQL Update bildirisi oluşturur.
Bir Web uygulamasında, DbContext bir varlığı okur ve bir sayfa işlendikten sonra verileri görüntüler. Bir sayfanın
OnPostAsync yöntemi çağrıldığında, yeni bir Web isteği oluşturulur ve yeni bir örneğine DbContext sahiptir.
Okuyarak bu yeni bağlamdaki varlığı, masaüstü işlemesini benzetir.

Silme sayfası
Bu bölümde, çağrısı SaveChanges başarısız olduğunda özel bir hata iletisi uygulayacağınızı görürsünüz.
Pages/öğrenciler/delete. cshtml. cs dosyasındaki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır ( using
deyimler temizliği dışında).

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }
public string ErrorMessage { get; set; }

public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Students


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}

if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}

return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}

var student = await _context.Students.FindAsync(id);

if (student == null)
{
return NotFound();
}

try
{
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("./Delete",
new { id, saveChangesError = true });
}
}
}
}

Yukarıdaki kod, isteğe bağlı parametresini saveChangesError OnGetAsync Yöntem imzasına ekler. saveChangesError
öğrenci nesnesini silme hatasından sonra yöntemin çağrılıp çağrılmadığını gösterir. Geçici ağ sorunları nedeniyle
silme işlemi başarısız olabilir. Geçici ağ hataları, veritabanı bulutta olduğunda daha olasıdır. Sil sayfası OnGetAsync
kullanıcı arabiriminden çağrıldığında parametrefalse'tur. saveChangesError Tarafından çağrıldığında ( silme
saveChangesError işlemi başarısız olduğundan), parametresi true olur. OnGetAsync OnPostAsync

Yöntemi seçili varlığı alır, ardından varlığın durumunu olarak Deleted ayarlamak için Remove yöntemini çağırır.
OnPostAsync SaveChanges Çağrıldığında, bir SQL DELETE komutu oluşturulur. Remove Başarısız olursa:

Veritabanı özel durumu yakalandı.


Sayfaları OnGetAsync Sil yöntemi ile saveChangesError=true çağırılır.

Razor silme sayfasına bir hata iletisi ekleyin (Sayfalar/öğrenciler/delete. cshtml):


@page
@model ContosoUniversity.Pages.Students.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h1>Delete</h1>

<p class="text-danger">@Model.ErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Student</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Student.ID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>

Uygulamayı çalıştırın ve Sil sayfasını test etmek için bir öğrenci silin.

Sonraki adımlar

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide, scafkatan CRUD (oluşturma, okuma, güncelleştirme, silme) kodu incelenir ve özelleştirilir.
Karmaşıklığı en aza indirmek ve bu öğreticilerin EF Core odaklanmasını sağlamak için, EF Core kod sayfa
modellerinde kullanılır. Bazı geliştiriciler, Kullanıcı arabirimi (Razor Pages) ve veri erişim katmanı arasında bir
soyutlama katmanı oluşturmak için bir hizmet katmanını veya depo modelini kullanır.
Bu öğreticide, öğrenciler klasöründeki oluşturma, düzenleme, silme ve Ayrıntılar Razor Pages incelenir.
Scafkatlanmış kod, sayfa oluşturma, düzenleme ve silme için aşağıdaki kalıbı kullanır:
HTTP GET yöntemiyle OnGetAsync istenen verileri alın ve görüntüleyin.
HTTP POST yöntemiyle OnPostAsync verilerde yapılan değişiklikleri kaydedin.

Dizin ve ayrıntı sayfaları, HTTP GET yöntemiyle istenen verileri alır ve görüntüler OnGetAsync

SingleOrDefaultAsync ile FirstOrDefaultAsync


Oluşturulan kod, genellikle Singleordefaultasyncüzerinden tercih edilen firstordefaultasynckullanır.
FirstOrDefaultAsync , bir varlık getirenden SingleOrDefaultAsync daha verimlidir:
Kodun sorgudan döndürülen birden fazla varlık olmadığını doğrulaması gerekmiyorsa.
SingleOrDefaultAsync daha fazla veri getirir ve gereksiz işler.
SingleOrDefaultAsync Filtre bölümüne uyan birden fazla varlık varsa bir özel durum oluşturur.
FirstOrDefaultAsync Filtre bölümüne uyan birden fazla varlık varsa oluşturmaz.

Findadsync
Yapı iskelesi kodunun büyük bir kısmında, yerine Findadsync kullanılabilir FirstOrDefaultAsync .
FindAsync :
Birincil anahtarla (PK) bir varlık bulur. PK 'ye sahip bir varlık bağlam tarafından izleniyorsa, VERITABANıNA bir
istek olmadan döndürülür.
Basittir ve kısadır.
Tek bir varlığı aramak için iyileştirilmiştir.
Bazı durumlarda performans avantajlarına sahip olabilir, ancak tipik Web uygulamaları için nadiren meydana
gelir.
, Maleasyncyerine dolaylı olarak firstasync kullanır.
Ancak Include başka varlıklar FindAsync istiyorsanız artık uygun değildir. Bu, uygulamanız ilerledikçe bir sorguyu
iptal FindAsync etmeniz ve bir sorguya taşımanız gerekebileceği anlamına gelir.

Ayrıntılar sayfasını özelleştirme


Pages/Students Sayfaya gidin. Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/öğrenciler/Index. cshtml
dosyasındaki tutturucu etiketi Yardımcısı tarafından oluşturulur.

<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>

Uygulamayı çalıştırın ve bir Ayrıntılar bağlantısı seçin. URL, formundadır


http://localhost:5000/Students/Details?id=2 . Öğrenci KIMLIĞI bir sorgu dizesi ( ?id=2 ) kullanılarak geçirilir.

"{id:int}" Yol şablonunu kullanmak için düzenleme, Ayrıntılar ve silme Razor Pages güncelleştirin. Bu sayfaların
her biri için Page yönergesini ' den @page ' e @page "{id:int}" değiştirin.
Bir tamsayı yol değeri içermeyen "{id: Int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404 (bulunamadı)
hatası döndürüyor. Örneğin, http://localhost:5000/Students/Details 404 hatası döndürür. Kimliği isteğe bağlı
yapmak için yol kısıtlamasına ? ekleyin:

@page "{id:int?}"

Uygulamayı çalıştırın, Ayrıntılar bağlantısına tıklayın ve URL 'nin KIMLIĞI yönlendirme verileri (
http://localhost:5000/Students/Details/2 ) olarak geçirdiğini doğrulayın.
' I genel @page olarak değiştirmeyin, bunu yaparak giriş bağlantılarını keser ve sayfa oluşturabilirsiniz.
@page "{id:int}"

İlgili verileri ekleme


Öğrenciler dizin sayfasının yapı iskelesi kodu Enrollments özelliği içermez. Bu bölümde, Enrollments koleksiyonun
içeriği ayrıntılar sayfasında görüntülenir.
Pages/ öğrenciler/details. cshtml. FirstOrDefaultAsync CS yöntemi, tek Student bir varlığı almak için yöntemini
kullanır. OnGetAsync Aşağıdaki vurgulanmış kodu ekleyin:

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Student


.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

Include ve thenınclude yöntemleri, içeriğin Student.Enrollments gezinti özelliğini yüklemesine ve her


Enrollment.Course kaydın gezinti özelliği içine olmasına neden olur. Bu yöntemler, okuma ile ilgili veri öğreticisinde
ayrıntılı olarak incelenmelidir.
Asnotracking yöntemi, döndürülen varlıkların geçerli bağlamda güncelleştirilmediği durumlarda, senaryolarda
performansı geliştirir. AsNoTracking Bu öğreticinin ilerleyen kısımlarında ele alınmıştır.
Ayrıntılar sayfasında ilgili kayıtları görüntüleme
Sayfaları/öğrencileri/ayrıntıları. cshtml'yi açın. Kayıtlar listesini göstermek için aşağıdaki vurgulanmış kodu ekleyin:
@page "{id:int}"
@model ContosoUniversity.Pages.Students.DetailsModel

@{
ViewData["Title"] = "Details";
}

<h2>Details</h2>

<div>
<h4>Student</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.Enrollments)
</dt>
<dd>
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Student.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Student.ID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>

Kod yapıştırıldıktan sonra kod girintisi yanlışsa, düzeltmek için CTRL -K-D ' a basın.
Yukarıdaki kod, Enrollments Gezinti özelliğindeki varlıklar aracılığıyla döngü başlatır. Her kayıt için kurs başlığını ve
sınıfı görüntüler. Kurs başlığı, kayıt varlığının Course gezinti özelliğinde depolanan kurs varlığından alınır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir öğrenci için Ayrıntılar bağlantısına tıklayın. Seçili öğrenci
için Kurslar ve notlar listesi görüntülenir.

Oluştur sayfasını Güncelleştir


Pages/öğrenciler/Create. cshtml. cs dosyasındaki yöntemiaşağıdakikodlagüncelleştirin: OnPostAsync

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
_context.Student.Add(emptyStudent);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return null;
}

TryUpdateModelAsync
Tryupdatemodelasync kodunu inceleyin:

var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{

TryUpdateModelAsync<Student> Önceki kodda, pagemodeliçindeki pagecontext özelliğinden emptyStudent


gönderilen form değerlerini kullanarak nesneyi güncelleştirmeye çalışır. TryUpdateModelAsync yalnızca listelenen (
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate ) özellikleri güncelleştirir.

Yukarıdaki örnekte:
İkinci bağımsız değişken ( "student", // Prefix ), ön ek değerleri aramak için kullanılır. Büyük/küçük harfe
duyarlı değildir.
Postalanan form değerleri model Student bağlamakullanılarak modeldeki türlere dönüştürülür.
Fazla nakil
Deftere TryUpdateModel nakledilen değerler içeren alanları güncelleştirmek için kullanmak, aşırı nakletmeyi önlediği
için en iyi güvenlik yöntemidir. Örneğin, öğrenci varlığının bu Web sayfasının güncelleştirmesi veya Secret
eklemesi gereken bir özelliği içerdiğini varsayalım:
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}

Uygulama, oluşturma/güncelleştirme Razor sayfasında Secret bir alana sahip olmasa da, bir korsan Secret
değeri aşırı nakme ile ayarlayabilir. Bir korsan, Fiddler gibi bir araç kullanabilir veya bir Secret form değeri
göndermek için bazı JavaScript yazabilir. Özgün kod, bir öğrenci örneği oluştururken model cildin kullandığı
alanları sınırlamaz.
Secret Form alanı için belirtilen korsanın hangi değeri veritabanında güncelleştirildiği. Aşağıdaki görüntüde, alanı
("overpost" değeri ile Secret ), postalanan form değerlerine ekleyen Fiddler aracı gösterilmektedir.

"Overpost" değeri eklenen satırın Secret özelliğine başarıyla eklendi. Uygulama Tasarımcısı hiçbir şekilde hiçbir
Secret özelliği oluştur sayfasıyla ayarlamaya yönelik değildir.

Modeli görüntüle
Bir görünüm modeli, genellikle uygulama tarafından kullanılan modelde bulunan özelliklerin bir alt kümesini içerir.
Uygulama modeli genellikle etki alanı modeli olarak adlandırılır. Etki alanı modeli genellikle VERITABANıNDAKI
karşılık gelen varlık için gereken tüm özellikleri içerir. Görünüm modeli yalnızca UI katmanı için gereken özellikleri
içerir (örneğin, Oluştur sayfası). Görünüm modeline ek olarak, bazı uygulamalar Razor Pages sayfa modeli sınıfı ve
tarayıcı arasında veri geçirmek için bir bağlama modeli veya giriş modeli kullanır. Aşağıdaki Student görünüm
modelini göz önünde bulundurun:
using System;

namespace ContosoUniversity.Models
{
public class StudentVM
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}

Model görüntüleme, fazla nakletmeyi önlemenin alternatif bir yolunu sağlar. Görünüm modeli yalnızca
görüntüleme (görüntüleme) veya güncelleştirme özelliklerini içerir.
Aşağıdaki kod, yeni bir StudentVM öğrenci oluşturmak için görünüm modelini kullanır:

[BindProperty]
public StudentVM StudentVM { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var entry = _context.Add(new Student());


entry.CurrentValues.SetValues(StudentVM);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

SetValues yöntemi, başka bir PropertyValues nesnesinden değerleri okuyarak bu nesnenin değerlerini ayarlar.
SetValues Özellik adı eşleştirme kullanır. Görünüm modeli türünün model türüyle ilgili olması gerekmez, yalnızca
eşleşen özellikleri olması gerekir.
Kullanmak StudentVM için createvm gerekir. cshtml , yerine kullanılmak StudentVM üzere güncelleştirilir. Student

Razor Pages, PageModel türetilmiş sınıf görünüm modelidir.

Güncelleştirme düzenleme sayfası


Düzenleme sayfasının sayfa modelini güncelleştirin. Büyük değişiklikler vurgulanır:
public class EditModel : PageModel
{
private readonly SchoolContext _context;

public EditModel(SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Student.FindAsync(id);

if (Student == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (!ModelState.IsValid)
{
return Page();
}

var studentToUpdate = await _context.Student.FindAsync(id);

if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}
}

Kod değişiklikleri, birkaç özel durum dışında oluşturma sayfasına benzerdir:


OnPostAsync isteğe bağlı id bir parametreye sahiptir.
Geçerli öğrenci boş bir öğrenci oluşturmak yerine DB 'den getirilir.
FirstOrDefaultAsync , Findadsyncile değiştirilmiştir. FindAsync birincil anahtardan bir varlık seçerken iyi bir
seçimdir. Daha fazla bilgi için bkz. Findadsync .
Düzenleme ve oluşturma sayfalarını test etme
Birkaç öğrenci varlığı oluşturun ve düzenleyin.

Varlık durumları
DB bağlamı, bellekteki varlıkların VERITABANıNDA karşılık gelen satırlarıyla eşitlenmiş olup olmadığını izler.
VERITABANı bağlamı eşitleme bilgileri, Savechangesasync çağrıldığında ne olacağını belirler. Örneğin, yeni bir
varlık Addadsync yöntemine geçirildiğinde, bu varlığın durumu eklendiolarak ayarlanır. SaveChangesAsync
Çağrıldığında, DB bağlamı bir SQL INSERT komutu yayınlar.
Bir varlık aşağıdaki durumlardanbirinde olabilir:
Added : Varlık, VERITABANıNDA henüz yok. SaveChanges Yöntemi bir INSERT ifadesini yayınlar.
: Bu varlıkla birlikte hiçbir değişiklik kaydedilmesi gerekmiyor. Bir varlık, DB 'den okurken bu
Unchanged
duruma sahip olur.
Modified : Varlığın özellik değerlerinin bazıları veya tümü değiştirildi. SaveChanges Yöntemi bir Update
ifadesini yayınlar.
Deleted : Varlık silinmek üzere işaretlendi. SaveChanges Yöntemi bir DELETE ifadesini yayınlar.
Detached : Varlık DB bağlamı tarafından izlenmiyor.
Bir masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlık okundu,
değişiklikler yapılır ve varlık durumu otomatik olarak olarak değiştirilecek Modified . Çağıran SaveChanges yalnızca
değiştirilen özellikleri güncelleştiren bir SQL Update bildirisi oluşturur.
Bir Web uygulamasında, DbContext bir varlığı okur ve bir sayfa işlendikten sonra verileri görüntüler. Bir sayfanın
OnPostAsync yöntemi çağrıldığında, yeni bir Web isteği oluşturulur ve yeni bir örneğine DbContext sahiptir. Yeni
bağlamdaki varlığı yeniden okumak masaüstü işlemesini benzetir.

Silme sayfası
Bu bölümde, çağrı SaveChanges başarısız olduğunda özel bir hata iletisi uygulamak için kod eklenir. Olası hata
iletilerini içeren bir dize ekleyin:

public class DeleteModel : PageModel


{
private readonly SchoolContext _context;

public DeleteModel(SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }
public string ErrorMessage { get; set; }

OnGetAsync Yöntemini aşağıdaki kodla değiştirin:


public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Student


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}

if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}

return Page();
}

Önceki kod isteğe bağlı parametresini saveChangesError içerir. saveChangesError öğrenci nesnesini silme hatasından
sonra yöntemin çağrılıp çağrılmadığını gösterir. Geçici ağ sorunları nedeniyle silme işlemi başarısız olabilir. Geçici
ağ hataları, bulutta daha olasıdır. saveChangesError , silme sayfası OnGetAsync kullanıcı arabiriminden çağrıldığında
false 'tur. Tarafından çağrıldığında ( silme saveChangesError işlemi başarısız olduğundan), parametresi true olur.
OnGetAsync OnPostAsync

Sayfaları sil OnPostAsync yöntemi


OnPostAsync Öğesini aşağıdaki kodla değiştirin:

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

var student = await _context.Student


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (student == null)
{
return NotFound();
}

try
{
_context.Student.Remove(student);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("./Delete",
new { id, saveChangesError = true });
}
}
Önceki kod seçili varlığı alır, ardından varlığın durumunu olarak Deleted ayarlamak için Remove yöntemini çağırır.
SaveChanges Çağrıldığında, bir SQL DELETE komutu oluşturulur. Remove Başarısız olursa:

DB özel durumu yakalandı.


Sayfaları OnGetAsync Sil yöntemi ile saveChangesError=true çağırılır.
Razor Sil sayfasını Güncelleştir
Aşağıdaki Vurgulanan hata iletisini Razor Sil sayfasına ekleyin.

@page "{id:int}"
@model ContosoUniversity.Pages.Students.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<p class="text-danger">@Model.ErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>

Test silme.

Sık karşılaşılan hatalar


Öğrenciler/dizin veya diğer bağlantılar çalışmaz:
Razor sayfasının doğru @page yönergeyi içerdiğini doğrulayın. Örneğin, öğrenciler/Dizin Razor sayfası bir yol
şablonu içermemelidir:

@page "{id:int}"

Her Razor sayfası @page yönergesini içermelidir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

ÖN CEKI İleri A S P. N E T C O R E S IR A L A M A , F IL T R E L E M E , S A Y F A L A M A -3 / 8 ' D E E F C O R E R A Z O R


PAGES
ASP.NET Core sıralama, filtreleme, sayfalama-3/8 ' de
EF Core Razor Pages
20.08.2019 • 44 minutes to read • Edit Online

By Tom Dykstra, Rick Andersonve Jon P Smith


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğretici, öğrenciler sayfalarına sıralama, filtreleme ve sayfalama işlevselliği ekler.
Aşağıdaki çizimde tamamlanmış bir sayfa gösterilmektedir. Sütun başlıkları sütunu sıralamak için tıklatılabilir
bağlantılardır. Artan ve azalan sıralama düzeni arasında geçiş yapmak için bir sütun başlığına tekrar tekrar tıklayın.

Sıralama Ekle
Pages/öğrenciler/Index. cshtml. cs içindeki kodu, sıralama eklemek için aşağıdaki kodla değiştirin.
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public IList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentsIQ = from s in _context.Students


select s;

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();


}
}
}

Yukarıdaki kod:
Sıralama parametrelerini içeren özellikleri ekler.
Student Özelliğin adını olarak Students değiştirir.
OnGetAsync Yöntemindeki kodu değiştirir.

Yöntemi, URL 'deki sortOrder sorgu dizesinden bir parametre alır. OnGetAsync URL (sorgu dizesi dahil), tutturucu
etiketi Yardımcısıtarafından oluşturulur.
sortOrder Parametre "ad" ya da "Tarih" dır. Parametre sortOrder , isteğe bağlı olarak azalan sıra belirtmek için
"_DESC" tarafından izlenir. Varsayılan sıralama düzeni artan.
Öğrenciler bağlantısından Dizin sayfası istendiğinde sorgu dizesi yoktur. Öğrenciler, son ada göre artan sırada
görüntülenir. Son ada göre artan sıralama, switch deyimindeki varsayılan (gelen durumdur). Kullanıcı bir sütun
başlığı bağlantısına tıkladığında, sorgu dizesi değerinde uygun sortOrder değer sağlanır.
NameSort ve DateSort Razor sayfası tarafından sütun başlığı köprülerini uygun sorgu dizesi değerleriyle
yapılandırmak için kullanılır:

NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";


DateSort = sortOrder == "Date" ? "date_desc" : "Date";

Kod, C# koşullu işleci kullanıyor ?:. ?: İşleci üçlü bir işleçtir (üç işlenen alır). İlk satır, null veya boş sortOrder
olduğunu belirtir, NameSort "name_desc" olarak ayarlanır. Null veya boş değilseboşbirdizeolarak NameSort ayarlanır.
sortOrder

Bu iki deyim, sayfanın sütun başlığı köprülerini şu şekilde ayarlamanızı sağlar:

GEÇERLI SIRALAMA DÜZENI SON AD KÖPRÜSÜ TARIH KÖPRÜSÜ

Artan son ad descending ascending

Azalan son ad ascending ascending

Artan Tarih ascending descending

Azalan Tarih ascending ascending

Yöntemi, sıralama yapılacak sütunu belirtmek için LINQ to Entities kullanır. Kod, Switch ifadesinden
IQueryable<Student> önce bir başlatır ve Switch ifadesinde onu değiştirir:

IQueryable<Student> studentsIQ = from s in _context.Students


select s;

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();

Bir IQueryable oluşturulduğunda veya değiştirildiğinde, veritabanına hiçbir sorgu gönderilmez. IQueryable Nesne
bir koleksiyona dönüştürülene kadar sorgu yürütülmez. IQueryable , gibi bir yöntemi ToListAsync çağırarak bir
koleksiyona dönüştürülür. Bu nedenle, IQueryable kod, aşağıdaki deyime kadar yürütülemeyen tek bir sorgu ile
sonuçlanır:
Students = await studentsIQ.AsNoTracking().ToListAsync();

OnGetAsync çok sayıda sıralanabilir sütunla ayrıntı alabilir. Bu işlevi kodun alternatif bir yolu hakkında daha fazla
bilgi için, bu öğretici serisinin MVC sürümünde kodu basitleştirmek için dınamık LINQ kullanma konusuna bakın.
Öğrenci dizini sayfasına sütun başlığı köprüleri ekleme
Öğrenciler/Index. cshtmliçindeki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>
<p>
<a asp-page="Create">Create New</a>
</p>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yukarıdaki kod:
LastName Ve EnrollmentDate sütun başlıklarına köprüler ekler.
, Ve NameSort DateSort içindeki bilgileri kullanarak geçerli sıralama düzeni değerleriyle köprüler ayarlar.
Sayfa başlığını dizinden öğrencilerle değiştirir.
Üzerinde yapılan değişiklikler Model.Student . Model.Students

Sıralamanın çalıştığını doğrulamak için:


Uygulamayı çalıştırın ve öğrenciler sekmesini seçin.
Sütun başlıklarına tıklayın.

Filtre ekleme
Öğrenciler dizin sayfasına filtre eklemek için:
Razor sayfasına bir metin kutusu ve bir Gönder düğmesi eklenir. Metin kutusu, ad veya soyadı üzerinde bir
arama dizesi sağlar.
Sayfa modeli metin kutusu değerini kullanacak şekilde güncelleştirilir.
OnGetAsync yöntemini güncelleştirme
Öğrenciler/Index. cshtml. cs dosyasındaki kodu, filtreleme eklemek için aşağıdaki kodla değiştirin:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public IList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder, string searchString)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

CurrentFilter = searchString;

IQueryable<Student> studentsIQ = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentsIQ = studentsIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();


}
}
}

Yukarıdaki kod:
Yöntemine parametresini ekler ve parametre değerini CurrentFilter özelliğine kaydeder. searchString
OnGetAsync Arama dizesi değeri bir sonraki bölüme eklenen bir metin kutusundan alınır.
LINQ deyimi a Where yan tümcesine ekler. Where Yan tümce yalnızca adı veya soyadı arama dizesini içeren
öğrencileri seçer. LINQ deyimleri yalnızca aranacak bir değer varsa yürütülür.
IQueryable vs. IEnumerable
Kod, Where yöntemi bir IQueryable nesne üzerinde çağırır ve filtre sunucuda işlenir. Bazı senaryolarda, uygulama
bir bellek içi koleksiyonda bir genişletme Where yöntemi olarak yöntemi çağırıyor olabilir. Örneğin, EF Core DbSet
'den _context.Students bir IEnumerable koleksiyonu döndüren bir depo yöntemine yapılan değişiklikleri varsayın.
Sonuç normalde aynı olur, ancak bazı durumlarda farklı olabilir.
Örneğin, uygulamasının Contains .NET Framework uygulanması varsayılan olarak büyük/küçük harfe duyarlı bir
karşılaştırma gerçekleştirir. SQL Server, Contains büyük/küçük harf duyarlılığı SQL Server örneğinin harmanlama
ayarına göre belirlenir. SQL Server varsayılan olarak büyük/küçük harfe duyarlı değildir. SQLite, büyük/küçük harfe
duyarlı olur. ToUpper testi açık büyük/küçük harfe duyarsız hale getirmek için çağrılabilir:

Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())`

Yukarıdaki kod, Where yöntemin bir veya bir IEnumerable SQLite üzerinde çağrılması durumunda bile filtrenin
büyük/küçük harf duyarsız olmasını güvence altına alır.
Contains Bir IEnumerable koleksiyon üzerinde çağrıldığında .NET Core uygulamasını kullanır. Contains Bir
IQueryable nesne üzerinde çağrıldığında, veritabanı uygulamasını kullanır.

Contains Bir IQueryable üzerinde çağırmak, genellikle performans nedenleriyle tercih edilir. İle IQueryable ,
filtreleme veritabanı sunucusu tarafından yapılır. Önce bir IEnumerable oluşturulduysa, tüm satırların veritabanı
sunucusundan döndürülmesi gerekir.
Çağırmak ToUpper için bir performans cezası vardır. ToUpper Kod, TSQL SELECT ifadesinin WHERE yan tümcesine
bir işlev ekler. Eklenen işlev, iyileştiricinin bir dizin kullanmasını önler. SQL, büyük/küçük harfe duyarsız olarak
yüklendiği için, gerekli olmadığında ToUpper çağrının önüne geçmek en iyisidir.
Daha fazla bilgi için bkz. SQLite sağlayıcı ile büyük/küçük harfe duyarsız sorgu kullanma.
Razor sayfasını güncelleştirme
Sayfalar/öğrenciler/Index. cshtml içindeki kodu, bir arama düğmesi ve assıralanan Chrome oluşturmak için
değiştirin.
@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-primary" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Yukarıdaki kod, arama metin <form> kutusu ve düğme eklemek için etiket yardımcısını kullanır. Varsayılan olarak,
<form> etiket Yardımcısı form verilerini bir gönderiyle gönderir. POST ile parametreler, URL 'de değil HTTP ileti
gövdesine geçirilir. HTTP GET kullanıldığında, form verileri URL 'ye sorgu dizeleri olarak geçirilir. Verilerin sorgu
dizelerine geçirilmesi, kullanıcıların URL 'YI yer işaretine eklemesini sağlar. W3C yönergeleri , eylem bir
güncelleştirme ile SONUÇLANMAZSA, Get 'in kullanılması önerilir.
Uygulamayı test edin:
Öğrenciler sekmesini seçin ve bir arama dizesi girin. SQLite kullanıyorsanız, filtre yalnızca daha önce
gösterilen isteğe bağlı ToUpper kodu uyguladıysanız, büyük/küçük harfe duyarlıdır.
Ara' yı seçin.
URL 'nin arama dizesini içerdiğine dikkat edin. Örneğin:

https://localhost:<port>/Students?SearchString=an

Sayfa yer işaretiyle, yer işareti sayfanın URL 'sini ve SearchString sorgu dizesini içerir. method="get" Etiketi,sorgu
form dizesinin oluşturulmasına neden oldu.

Şu anda, bir sütun başlığı sıralama bağlantısı seçildiğinde, arama kutusundaki filtre değeri kaybedilir. Kayıp filtre
değeri bir sonraki bölümde düzeltilir.

Sayfalama Ekle
Bu bölümde, sayfalama desteği PaginatedList için bir sınıf oluşturulur. Sınıfı, tablodaki tüm Take satırları almak
yerine, sunucudaki verileri filtrelemek için ve deyimlerini kullanır Skip . PaginatedList Aşağıdaki çizimde
sayfalama düğmeleri gösterilmektedir.

Sayfalı liste sınıfını oluşturma


Proje klasöründe aşağıdaki kodla oluşturun PaginatedList.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)


{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);

this.AddRange(items);
}

public bool HasPreviousPage


{
get
{
return (PageIndex > 1);
}
}

public bool HasNextPage


{
get
{
return (PageIndex < TotalPages);
}
}

public static async Task<PaginatedList<T>> CreateAsync(


IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip(
(pageIndex - 1) * pageSize)
.Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}

Yukarıdaki koddaki Skip Take IQueryable yöntemi sayfa boyutunu ve sayfa numarasını alır ve ' a uygun ve
deyimlerini uygular. CreateAsync ToListAsync Üzerindeçağrıldığında,yalnızcaistenensayfayı IQueryable içeren bir
liste döndürür. Özellikler HasPreviousPage ve HasNextPage önceki ve sonraki sayfalama düğmelerini
etkinleştirmek veya devre dışı bırakmak için kullanılır.
Yöntemi oluşturmak için kullanılır. PaginatedList<T> CreateAsync Oluşturucu PaginatedList<T> nesneyi
oluşturamıyor; oluşturucular zaman uyumsuz kod çalıştıramıyor.
PageModel sınıfına sayfalama ekleme
Öğrenciler/Index. cshtml. cs ' deki kodu, sayfalama eklemek için değiştirin.

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public PaginatedList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)
{
CurrentSort = sortOrder;
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

CurrentFilter = searchString;

IQueryable<Student> studentsIQ = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentsIQ = studentsIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

int pageSize = 3;
Students = await PaginatedList<Student>.CreateAsync(
studentsIQ.AsNoTracking(), pageIndex ?? 1, pageSize);
}
}
}
}

Yukarıdaki kod:
Students Özelliğinin türünü PaginatedList<Student> olarak değiştirir. IList<Student>
Sayfa dizinini, geçerli sortOrder currentFilter ve OnGetAsync öğesini Yöntem imzasına ekler.
Sıralama düzenini CurrentSort özelliğine kaydeder.
Yeni bir arama dizesi olduğunda sayfa dizinini 1 olarak sıfırlar.
Öğrenci varlıklarını almak için sınıfınıkullanır. PaginatedList

Şu durumlarda OnGetAsync alan tüm parametreler null:


Sayfa öğrenciler bağlantısından çağrılır.
Kullanıcı bir sayfalama veya sıralama bağlantısına tıklamadı.
Bir sayfalama bağlantısına tıklandığında, sayfa dizin değişkeni görüntülenecek sayfa numarasını içerir.
CurrentSort Özelliği, geçerli sıralama düzeni ile Razor sayfasını sağlar. Disk belleği sırasında sıralama düzenini
korumak için geçerli sıralama düzeni, sayfalama bağlantılarına eklenmelidir.
CurrentFilter Özelliği, Razor sayfasını geçerli filtre dizesiyle birlikte sağlar. CurrentFilter Değer:
Disk belleği sırasında filtre ayarlarını korumak için disk belleği bağlantılarına eklenmelidir.
Sayfa yeniden görüntülendiğinde metin kutusuna geri yüklenmelidir.
Sayfalama sırasında arama dizesi değiştirilirse sayfa 1 ' e sıfırlanır. Yeni filtre farklı verilerin görüntülenmesini
sağladığından sayfanın 1 olarak sıfırlanması. Bir arama değeri girildiğinde ve Gönder seçildiğinde:
Arama dizesi değiştirildi.
searchString Parametre null değil.

Yöntemi PaginatedList.CreateAsync , öğrenci sorgusunu, sayfalama destekleyen bir koleksiyon türündeki tek bir
öğrenci sayfasına dönüştürür. Bu tek öğrenci sayfası Razor sayfasına geçirilir.
Çağrıdan PaginatedList.CreateAsync sonraki pageIndex iki soru işareti, null birleşim işlecinitemsil eder. Null
birleşim işleci, null yapılabilir bir tür için varsayılan değeri tanımlar. İfade (pageIndex ?? 1) , bir değer pageIndex
içeriyorsa değerini döndürür anlamına gelir. pageIndex Değer yoksa 1 döndürün.
Razor sayfasına sayfalama bağlantıları ekleme
Öğrenciler/Index. cshtml içindeki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-primary" /> |
<a asp-page="./Index">Back to full List</a>
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@{
var prevDisabled = !Model.Students.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.Students.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @nextDisabled">
Next
</a>
Sütun üst bilgisi bağlantıları, geçerli arama dizesini OnGetAsync yönteme geçirmek için sorgu dizesini kullanır:

<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"


asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>

Sayfalama düğmeleri etiket yardımcıları tarafından görüntülenir:

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @nextDisabled">
Next
</a>

Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.


Sayfalama 'nin çalıştığından emin olmak için, farklı sıralama emirlerindeki disk belleği bağlantılarına tıklayın.
Disk belleğinin sıralama ve filtreleme ile düzgün çalıştığını doğrulamak için bir arama dizesi girin ve sayfalama
yapmayı deneyin.

Gruplandırma Ekle
Bu bölüm, her kayıt tarihi için kaç öğrenciye kaydolduğunu görüntüleyen bir hakkında sayfası oluşturur.
Güncelleştirme gruplamayı kullanır ve aşağıdaki adımları içerir:
Hakkında sayfasında kullanılan veriler için bir görünüm modeli oluşturun.
Görünüm modelini kullanmak için hakkında sayfasını güncelleştirin.
Görünüm modeli oluşturma
Modeller/SchoolViewModels klasörü oluşturun.
Aşağıdaki kodla SchoolViewModels/kayıtlarını Mentdategroup. cs oluşturun:

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; }

public int StudentCount { get; set; }


}
}

Razor sayfasını oluşturma


Aşağıdaki kodla bir Pages/about. cshtml dosyası oluşturun:

@page
@model ContosoUniversity.Pages.AboutModel

@{
ViewData["Title"] = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
<tr>
<th>
Enrollment Date
</th>
<th>
Students
</th>
</tr>

@foreach (var item in Model.Students)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

Sayfa modelini oluşturma


Aşağıdaki kodla bir Pages/about. cshtml. cs dosyası oluşturun:
using ContosoUniversity.Models.SchoolViewModels;
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ContosoUniversity.Models;

namespace ContosoUniversity.Pages
{
public class AboutModel : PageModel
{
private readonly SchoolContext _context;

public AboutModel(SchoolContext context)


{
_context = context;
}

public IList<EnrollmentDateGroup> Students { get; set; }

public async Task OnGetAsync()


{
IQueryable<EnrollmentDateGroup> data =
from student in _context.Students
group student by student.EnrollmentDate into dateGroup
select new EnrollmentDateGroup()
{
EnrollmentDate = dateGroup.Key,
StudentCount = dateGroup.Count()
};

Students = await data.AsNoTracking().ToListAsync();


}
}
}

LINQ beyanı, öğrenci varlıklarını kayıt tarihine göre gruplandırır, her bir gruptaki varlıkların sayısını hesaplar ve
sonuçları bir EnrollmentDateGroup görünüm modeli nesneleri koleksiyonunda depolar.
Uygulamayı çalıştırın ve hakkında sayfasına gidin. Her kayıt tarihi için öğrenci sayısı bir tabloda görüntülenir.
Sonraki adımlar
Sonraki öğreticide, uygulama, veri modelini güncelleştirmek için geçişleri kullanır.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide sıralama, filtreleme, gruplama ve sayfalama işlevleri eklenmiştir.


Aşağıdaki çizimde tamamlanmış bir sayfa gösterilmektedir. Sütun başlıkları sütunu sıralamak için tıklatılabilir
bağlantılardır. Sütun başlığına tıklanması, artan ve azalan sıralama düzeni arasında sürekli olarak geçiş yapar.

Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.

Dizin sayfasına sıralama Ekle


Sıralama parametrelerini içerecek şekilde öğrenciler/Index. cshtml. cs PageModel öğesine dizeler ekleyin:

public class IndexModel : PageModel


{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:


public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Yukarıdaki kod, URL 'deki sortOrder sorgu dizesinden bir parametre alır. URL (sorgu dizesi dahil), tutturucu etiketi
Yardımcısı tarafından oluşturulur
sortOrder Parametre "ad" ya da "Tarih" dır. Parametre sortOrder , isteğe bağlı olarak azalan sıra belirtmek için
"_DESC" tarafından izlenir. Varsayılan sıralama düzeni artan.
Öğrenciler bağlantısından Dizin sayfası istendiğinde sorgu dizesi yoktur. Öğrenciler, son ada göre artan sırada
görüntülenir. Son ada göre artan sıralama, switch deyimindeki varsayılan (gelen durumdur). Kullanıcı bir sütun
başlığı bağlantısına tıkladığında, sorgu dizesi değerinde uygun sortOrder değer sağlanır.
NameSort ve DateSort Razor sayfası tarafından sütun başlığı köprülerini uygun sorgu dizesi değerleriyle
yapılandırmak için kullanılır:
public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Aşağıdaki kod, C# koşullu ?: işleciniiçerir:

NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";


DateSort = sortOrder == "Date" ? "date_desc" : "Date";

İlk satır, null veya boş sortOrder olduğunu belirtir, NameSort "name_desc" olarak ayarlanır. Null veya boş
değilseboşbirdizeolarak NameSort ayarlanır. sortOrder
, ?: operator Üçlü işleç olarak da bilinir.
Bu iki deyim, sayfanın sütun başlığı köprülerini şu şekilde ayarlamanızı sağlar:

GEÇERLI SIRALAMA DÜZENI SON AD KÖPRÜSÜ TARIH KÖPRÜSÜ

Artan son ad descending ascending

Azalan son ad ascending ascending

Artan Tarih ascending descending

Azalan Tarih ascending ascending

Yöntemi, sıralama yapılacak sütunu belirtmek için LINQ to Entities kullanır. Kod, Switch ifadesinden
IQueryable<Student> önce bir başlatır ve Switch ifadesinde onu değiştirir:
public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Bir IQueryable oluşturulduğunda veya değiştirildiğinde, veritabanına hiçbir sorgu gönderilmez. IQueryable Nesne
bir koleksiyona dönüştürülene kadar sorgu yürütülmez. IQueryable , gibi bir yöntemi ToListAsync çağırarak bir
koleksiyona dönüştürülür. Bu nedenle, IQueryable kod, aşağıdaki deyime kadar yürütülemeyen tek bir sorgu ile
sonuçlanır:

Student = await studentIQ.AsNoTracking().ToListAsync();

OnGetAsync çok sayıda sıralanabilir sütunla ayrıntı alabilir.


Öğrenci dizini sayfasına sütun başlığı köprüleri ekleme
Öğrenciler/Index. cshtmliçindeki kodu aşağıdaki vurgulanmış kodla değiştirin:
@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>
<p>
<a asp-page="Create">Create New</a>
</p>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Student)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yukarıdaki kod:
LastName Ve EnrollmentDate sütun başlıklarına köprüler ekler.
, Ve NameSort DateSort içindeki bilgileri kullanarak geçerli sıralama düzeni değerleriyle köprüler ayarlar.
Sıralamanın çalıştığını doğrulamak için:
Uygulamayı çalıştırın ve öğrenciler sekmesini seçin.
Son ad' a tıklayın.
Kayıt tarihi' ne tıklayın.
Kodu daha iyi anlamak için:
Öğrenciler/Index. cshtml. csdosyasında, üzerinde switch (sortOrder) bir kesme noktası ayarlayın.
NameSort Ve DateSort için bir izleme ekleyin.
Öğrenciler/Index. cshtml'de, üzerinde @Html.DisplayNameFor(model => model.Student[0].LastName) bir kesme
noktası ayarlayın.
Hata ayıklayıcıda adım adım.

Öğrenciler dizin sayfasına bir arama kutusu ekleyin


Öğrenciler dizin sayfasına filtre eklemek için:
Razor sayfasına bir metin kutusu ve bir Gönder düğmesi eklenir. Metin kutusu, ad veya soyadı üzerinde bir
arama dizesi sağlar.
Sayfa modeli metin kutusu değerini kullanacak şekilde güncelleştirilir.
Dizin yöntemine filtreleme işlevi ekleme
Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync(string sortOrder, string searchString)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
CurrentFilter = searchString;

IQueryable<Student> studentIQ = from s in _context.Student


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentIQ = studentIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Yukarıdaki kod:
OnGetAsync Yöntemine searchString parametresini ekler. Arama dizesi değeri bir sonraki bölüme eklenen bir
metin kutusundan alınır.
LINQ deyimi bir Where yan tümcesine eklendi. Where Yan tümce yalnızca adı veya soyadı arama dizesini içeren
öğrencileri seçer. LINQ deyimleri yalnızca aranacak bir değer varsa yürütülür.
Not: Yukarıdaki kod, Where metodu bir IQueryable nesne üzerinde çağırır ve filtre sunucuda işlenir. Bazı
senaryolarda, uygulama bir bellek içi koleksiyonda bir genişletme Where yöntemi olarak yöntemi çağırıyor olabilir.
Örneğin, EF Core DbSet 'den _context.Students bir IEnumerable koleksiyonu döndüren bir depo yöntemine
yapılan değişiklikleri varsayın. Sonuç normalde aynı olur, ancak bazı durumlarda farklı olabilir.
Örneğin, uygulamasının Contains .NET Framework uygulanması varsayılan olarak büyük/küçük harfe duyarlı bir
karşılaştırma gerçekleştirir. SQL Server, Contains büyük/küçük harf duyarlılığı SQL Server örneğinin harmanlama
ayarına göre belirlenir. SQL Server varsayılan olarak büyük/küçük harfe duyarlı değildir. ToUpper testi açık
büyük/küçük harfe duyarsız hale getirmek için çağrılabilir:
Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())

Yukarıdaki kod, kodun kullanım IEnumerable için değişiklik yaptığı durumlarda sonuçların büyük/küçük harf
duyarsız olmasını sağlar. Contains Bir IEnumerable koleksiyon üzerinde çağrıldığında .NET Core uygulamasını
kullanır. Contains Bir IQueryable nesne üzerinde çağrıldığında, veritabanı uygulamasını kullanır. IEnumerable Bir
depodan döndürmek önemli bir performans cezasına sahip olabilir:
1. Tüm satırlar DB sunucusundan döndürülür.
2. Filtre, uygulamadaki tüm döndürülen satırlara uygulanır.
Çağırmak ToUpper için bir performans cezası vardır. ToUpper Kod, TSQL SELECT ifadesinin WHERE yan tümcesine
bir işlev ekler. Eklenen işlev, iyileştiricinin bir dizin kullanmasını önler. SQL, büyük/küçük harfe duyarsız olarak
yüklendiği için, gerekli olmadığında ToUpper çağrının önüne geçmek en iyisidir.
Öğrenci dizin sayfasına bir arama kutusu ekleyin
Sayfalar/öğrenciler/Index. cshtml' de, bir arama düğmesi ve asi grafik Chrome oluşturmak için aşağıdaki
vurgulanmış kodu ekleyin.

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">

Yukarıdaki kod, arama metin <form> kutusu ve düğme eklemek için etiket yardımcısını kullanır. Varsayılan olarak,
<form> etiket Yardımcısı form verilerini bir gönderiyle gönderir. POST ile parametreler, URL 'de değil HTTP ileti
gövdesine geçirilir. HTTP GET kullanıldığında, form verileri URL 'ye sorgu dizeleri olarak geçirilir. Verilerin sorgu
dizelerine geçirilmesi, kullanıcıların URL 'YI yer işaretine eklemesini sağlar. W3C yönergeleri , eylem bir
güncelleştirme ile SONUÇLANMAZSA, Get 'in kullanılması önerilir.
Uygulamayı test edin:
Öğrenciler sekmesini seçin ve bir arama dizesi girin.
Ara' yı seçin.
URL 'nin arama dizesini içerdiğine dikkat edin.

http://localhost:5000/Students?SearchString=an

Sayfa yer işaretiyle, yer işareti sayfanın URL 'sini ve SearchString sorgu dizesini içerir. method="get" Etiketi,sorgu
form dizesinin oluşturulmasına neden oldu.

Şu anda, bir sütun başlığı sıralama bağlantısı seçildiğinde, arama kutusundaki filtre değeri kaybedilir. Kayıp filtre
değeri bir sonraki bölümde düzeltilir.

Öğrenciler dizin sayfasına sayfalama işlevselliği ekleme


Bu bölümde, sayfalama desteği PaginatedList için bir sınıf oluşturulur. Sınıfı, tablodaki tüm Take satırları almak
yerine, sunucudaki verileri filtrelemek için ve deyimlerini kullanır Skip . PaginatedList Aşağıdaki çizimde
sayfalama düğmeleri gösterilmektedir.

Proje klasöründe aşağıdaki kodla oluşturun PaginatedList.cs :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)


{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);

this.AddRange(items);
}

public bool HasPreviousPage


{
get
{
return (PageIndex > 1);
}
}

public bool HasNextPage


{
get
{
return (PageIndex < TotalPages);
}
}

public static async Task<PaginatedList<T>> CreateAsync(


IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip(
(pageIndex - 1) * pageSize)
.Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}

Yukarıdaki koddaki Skip Take IQueryable yöntemi sayfa boyutunu ve sayfa numarasını alır ve ' a uygun ve
deyimlerini uygular. CreateAsync ToListAsync Üzerindeçağrıldığında,yalnızcaistenensayfayı IQueryable içeren bir
liste döndürür. Özellikler HasPreviousPage ve HasNextPage önceki ve sonraki sayfalama düğmelerini
etkinleştirmek veya devre dışı bırakmak için kullanılır.
Yöntemi oluşturmak için kullanılır. PaginatedList<T> CreateAsync Bir Oluşturucu PaginatedList<T> nesneyi
oluşturamaz, oluşturucular zaman uyumsuz kod çalıştıramıyorum.

Dizin yöntemine sayfalama işlevselliği ekleme


Öğrenciler/Index. cshtml. csdosyasında, türünü Student ile PaginatedList<Student> arasında IList<Student>
güncelleştirin:
public PaginatedList<Student> Student { get; set; }

Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)
{
CurrentSort = sortOrder;
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

CurrentFilter = searchString;

IQueryable<Student> studentIQ = from s in _context.Student


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentIQ = studentIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

int pageSize = 3;
Student = await PaginatedList<Student>.CreateAsync(
studentIQ.AsNoTracking(), pageIndex ?? 1, pageSize);
}

Yukarıdaki kod, sayfa dizinini, geçerli sortOrder currentFilter ve öğesini Yöntem imzasına ekler.

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)

Şu durumlarda tüm parametreler null:


Sayfa öğrenciler bağlantısından çağrılır.
Kullanıcı bir sayfalama veya sıralama bağlantısına tıklamadı.
Bir sayfalama bağlantısına tıklandığında, sayfa dizin değişkeni görüntülenecek sayfa numarasını içerir.
CurrentSort geçerli sıralama düzeninde Razor sayfası sağlar. Disk belleği sırasında sıralama düzenini korumak için
geçerli sıralama düzeni, sayfalama bağlantılarına eklenmelidir.
CurrentFilter geçerli filtre dizesiyle Razor sayfasını sağlar. CurrentFilter Değer:
Disk belleği sırasında filtre ayarlarını korumak için disk belleği bağlantılarına eklenmelidir.
Sayfa yeniden görüntülendiğinde metin kutusuna geri yüklenmelidir.
Sayfalama sırasında arama dizesi değiştirilirse sayfa 1 ' e sıfırlanır. Yeni filtre farklı verilerin görüntülenmesini
sağladığından sayfanın 1 olarak sıfırlanması. Bir arama değeri girildiğinde ve Gönder seçildiğinde:
Arama dizesi değiştirildi.
searchString Parametre null değil.

if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

Yöntemi PaginatedList.CreateAsync , öğrenci sorgusunu, sayfalama destekleyen bir koleksiyon türündeki tek bir
öğrenci sayfasına dönüştürür. Bu tek öğrenci sayfası Razor sayfasına geçirilir.

Student = await PaginatedList<Student>.CreateAsync(


studentIQ.AsNoTracking(), pageIndex ?? 1, pageSize);

İçindeki PaginatedList.CreateAsync iki soru işareti, null birleşim işlecinitemsil eder. Null birleşim işleci, null
yapılabilir bir tür için varsayılan değeri tanımlar. İfade (pageIndex ?? 1) , bir değer pageIndex içeriyorsa değerini
döndürür anlamına gelir. pageIndex Değer yoksa 1 döndürün.

Öğrenci Razor sayfasına sayfalama bağlantıları ekleme


Öğrenciler/Index. cshtml'de biçimlendirmeyi güncelleştirin. Değişiklikler vurgulanır:

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name: <input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Student)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@{
var prevDisabled = !Model.Student.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.Student.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @nextDisabled">
Next
</a>

Sütun üst bilgisi bağlantıları, kullanıcının filtre sonuçları içinde sıralama yapabilmesi için geçerli arama dizesini
OnGetAsync yöntemine geçirmek üzere sorgu dizesini kullanır:
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>

Sayfalama düğmeleri etiket yardımcıları tarafından görüntülenir:

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @nextDisabled">
Next
</a>

Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.


Sayfalama 'nin çalıştığından emin olmak için, farklı sıralama emirlerindeki disk belleği bağlantılarına tıklayın.
Disk belleğinin sıralama ve filtreleme ile düzgün çalıştığını doğrulamak için bir arama dizesi girin ve sayfalama
yapmayı deneyin.

Kodu daha iyi anlamak için:


Öğrenciler/Index. cshtml. csdosyasında, üzerinde switch (sortOrder) bir kesme noktası ayarlayın.
, NameSort , Ve DateSort CurrentSort için birizlemeekleyin. Model.Student.PageIndex
Öğrenciler/Index. cshtml'de, üzerinde @Html.DisplayNameFor(model => model.Student[0].LastName) bir kesme
noktası ayarlayın.
Hata ayıklayıcıda adım adım.

Öğrenci istatistiklerini göstermek için hakkında sayfasını güncelleştirin


Bu adımda, Sayfalar/about. cshtml , her bir kayıt tarihi için kaç öğrenciye kaydolduğunu görüntüleyecek şekilde
güncelleştirilir. Güncelleştirme gruplamayı kullanır ve aşağıdaki adımları içerir:
Hakkında sayfasında kullanılan veriler için bir görünüm modeli oluşturun.
Görünüm modelini kullanmak için hakkında sayfasını güncelleştirin.
Görünüm modeli oluşturma
Modeller klasöründe bir SchoolViewModels klasörü oluşturun.
SchoolViewModels klasöründe aşağıdaki kodla bir EnrollmentDateGroup.cs ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; }

public int StudentCount { get; set; }


}
}

Hakkında sayfa modelini Güncelleştir


ASP.NET Core 2,2 ' deki Web şablonları hakkında sayfasını içermez. ASP.NET Core 2,2 kullanıyorsanız, Razor
hakkında sayfasını oluşturun.
Pages/about. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ContosoUniversity.Models;

namespace ContosoUniversity.Pages
{
public class AboutModel : PageModel
{
private readonly SchoolContext _context;

public AboutModel(SchoolContext context)


{
_context = context;
}

public IList<EnrollmentDateGroup> Student { get; set; }

public async Task OnGetAsync()


{
IQueryable<EnrollmentDateGroup> data =
from student in _context.Student
group student by student.EnrollmentDate into dateGroup
select new EnrollmentDateGroup()
{
EnrollmentDate = dateGroup.Key,
StudentCount = dateGroup.Count()
};

Student = await data.AsNoTracking().ToListAsync();


}
}
}

LINQ beyanı, öğrenci varlıklarını kayıt tarihine göre gruplandırır, her bir gruptaki varlıkların sayısını hesaplar ve
sonuçları bir EnrollmentDateGroup görünüm modeli nesneleri koleksiyonunda depolar.
Razor hakkında sayfasında değişiklik yapma
Pages/about. cshtml dosyasındaki kodu aşağıdaki kodla değiştirin:
@page
@model ContosoUniversity.Pages.AboutModel

@{
ViewData["Title"] = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
<tr>
<th>
Enrollment Date
</th>
<th>
Students
</th>
</tr>

@foreach (var item in Model.Student)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

Uygulamayı çalıştırın ve hakkında sayfasına gidin. Her kayıt tarihi için öğrenci sayısı bir tabloda görüntülenir.
Çözemediğiniz sorunlarla karşılaşırsanız, Bu aşama için tamamlanmış uygulamayıindirin.

Ek kaynaklar
2. x kaynağı ASP.NET Core hata ayıklaması
Bu öğreticinin YouTube sürümü
Sonraki öğreticide, uygulama, veri modelini güncelleştirmek için geçişleri kullanır.
ÖN CEKI İleri A S P. N E T C O R E G E Ç IŞ L E R I IL E E F C O R E R A Z O R P A G E S -
4/8
ASP.NET Core geçişleri ile EF Core Razor Pages-4/8
23.11.2019 • 18 minutes to read • Edit Online

, Tom Dykstra, Jon P Smithve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, veri modeli değişikliklerini yönetmek için EF Core geçişleri özelliği tanıtılmıştır.
Yeni bir uygulama geliştirildiğinde, veri modeli sıklıkla değişir. Modelin her değiştirilişinde, model veritabanıyla
eşitlenmemiş olur. Bu öğretici serisi, mevcut değilse veritabanını oluşturmak için Entity Framework yapılandırılarak
başlatılır. Veri modelinin her değiştirilişinde veritabanını bırakmalısınız. Uygulamanın bir sonraki çalıştırılışında,
EnsureCreated çağrısı yeni veri modeliyle eşleşecek şekilde veritabanını yeniden oluşturur. DbInitializer sınıfı,
yeni veritabanını temel alarak çalışır.
Veritabanını veri modeliyle eşitlenmiş halde tutmaya yönelik bu yaklaşım, uygulamayı üretime dağıtana kadar iyi
çalışır. Uygulama üretimde çalıştığında genellikle saklanması gereken verileri depolar. Uygulama her değişiklik
yapıldığında (yeni sütun ekleme gibi) bir test veritabanıyla başlayamaz. EF Core geçişleri özelliği, yeni bir veritabanı
oluşturmak yerine EF Core veritabanı şemasını güncelleştirmesine olanak sağlayarak bu sorunu çözer.
Veri modeli değiştiğinde veritabanını bırakıp yeniden oluşturmak yerine, geçişler şemayı güncelleştirir ve var olan
verileri korur.

NOTE
SQLite sınırlamaları
Bu öğretici, mümkün olduğunda Entity Framework Core geçişleri özelliğini kullanır. Geçişler, veritabanı şemasını veri
modelindeki değişikliklerle eşleşecek şekilde güncelleştirir. Bununla birlikte, geçişler yalnızca veritabanı altyapısının desteklediği
değişiklik türlerini ve SQLite 'un şema değiştirme özellikleri sınırlıdır. Örneğin, bir sütun ekleme desteklenir, ancak bir sütunu
kaldırmak desteklenmez. Bir sütunu kaldırmak için bir geçiş oluşturulduysa, ef migrations add komut başarılı olur
ef database update ancak komut başarısız olur.

SQLite sınırlamalarına yönelik geçici çözüm, tablodaki bir şeyler değiştiğinde tablo yeniden oluşturmak için geçiş kodunu el ile
yazmak için kullanılır. Kod, Up bir geçiş için ve Down yöntemlerine gidip şunları içerir:
Yeni bir tablo oluşturuluyor.
Eski tablodaki veriler yeni tabloya kopyalanıyor.
Eski tablo bırakılıyor.
Yeni tablo yeniden adlandırılıyor.
Bu türün veritabanına özgü kodu yazma, Bu öğreticinin kapsamı dışındadır. Bunun yerine, bu öğretici bir geçiş uygulama
girişimi başarısız olduğunda veritabanını bırakır ve yeniden oluşturur. Daha fazla bilgi için aşağıdaki kaynaklara bakın:
SQLite EF Core veritabanı sağlayıcısı sınırlamaları
Geçiş kodunu özelleştirme
Veri dengeli dağıtımı
SQLite ALTER TABLE ifadesi
Veritabanını bırak
Visual Studio
Visual Studio Code
Veritabanını silmek için SQL Server Nesne Gezgini (ssox) kullanın veya Paket Yöneticisi konsolunda (PMC ) şu
komutu çalıştırın:

Drop-Database

İlk geçiş oluşturma


Visual Studio
Visual Studio Code
PMC 'de şu komutları çalıştırın:

Add-Migration InitialCreate
Update-Database

Yukarı ve aşağı Yöntemler


EF Core migrations add komut, veritabanını oluşturmak için kodu oluşturdu. Bu geçiş kodu geçişleri<zaman
damgasında _InitialCreate. cs dosyasında > . InitialCreate sınıfının Up yöntemi, veri modeli varlık kümelerine
karşılık gelen veritabanı tablolarını oluşturur. Down yöntemi, aşağıdaki örnekte gösterildiği gibi onları siler:

using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace ContosoUniversity.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});

migrationBuilder.CreateTable(
name: "Student",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
LastName = table.Column<string>(nullable: true),
FirstMidName = table.Column<string>(nullable: true),
EnrollmentDate = table.Column<DateTime>(nullable: false)
},
},
constraints: table =>
{
table.PrimaryKey("PK_Student", x => x.ID);
});

migrationBuilder.CreateTable(
name: "Enrollment",
columns: table => new
{
EnrollmentID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
CourseID = table.Column<int>(nullable: false),
StudentID = table.Column<int>(nullable: false),
Grade = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Enrollment", x => x.EnrollmentID);
table.ForeignKey(
name: "FK_Enrollment_Course_CourseID",
column: x => x.CourseID,
principalTable: "Course",
principalColumn: "CourseID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Enrollment_Student_StudentID",
column: x => x.StudentID,
principalTable: "Student",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_Enrollment_CourseID",
table: "Enrollment",
column: "CourseID");

migrationBuilder.CreateIndex(
name: "IX_Enrollment_StudentID",
table: "Enrollment",
column: "StudentID");
}

protected override void Down(MigrationBuilder migrationBuilder)


{
migrationBuilder.DropTable(
name: "Enrollment");

migrationBuilder.DropTable(
name: "Course");

migrationBuilder.DropTable(
name: "Student");
}
}
}

Önceki kod ilk geçişe yöneliktir. Kod:


migrations add InitialCreate komutu tarafından oluşturuldu.
database update komutu tarafından yürütülür.
Veritabanı bağlamı sınıfı tarafından belirtilen veri modeli için bir veritabanı oluşturur.
Dosya adı için geçiş adı parametresi (örnekteki "ınitialcreate") kullanılır. Geçiş adı herhangi bir geçerli dosya adı
olabilir. Geçiş sırasında nelerin yapıldığını özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, bir
departman tablosu ekleyen bir geçişe "AddDepartmentTable" adı verilir.

Geçişler geçmiş tablosu


Veritabanını incelemek için SSOX veya SQLite aracınızı kullanın.
__EFMigrationsHistory tablo ekleme hakkında dikkat edin. __EFMigrationsHistory tablo, hangi geçişlerin
veritabanına uygulandığını izler.
__EFMigrationsHistory tablosundaki verileri görüntüleyin. İlk geçiş için bir satır gösterir.

Veri modeli anlık görüntüsü


Geçişler, geçiş/SchoolContextModelSnapshot. csiçindeki geçerli veri modelinin anlık görüntüsünü oluşturur. Bir
geçiş eklediğinizde, EF geçerli veri modelini Snapshot dosyası ile karşılaştırarak nelerin değiştirildiğini belirler.
Anlık görüntü dosyası veri modelinin durumunu izlediğinden, <timestamp>_<migrationname>.cs dosyasını silerek bir
geçişi silemezsiniz. En son geçişi geri yüklemek için migrations remove komutunu kullanmanız gerekir. Bu komut,
geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar. Daha fazla bilgi için bkz. DotNet EF geçişleri
kaldır.

Yeniden oluşturulmasını kaldır


Bu öğretici serisi EnsureCreated kullanılarak başlatıldı. EnsureCreated geçişler geçmişi tablosu oluşturmaz ve
geçişle birlikte kullanılamaz. Bu, veritabanının düşürülme ve sıklıkla yeniden oluşturulduğu test veya hızlı prototip
oluşturma için tasarlanmıştır.
Bu noktadan sonra öğreticiler, geçişleri kullanacaktır.
Data/Dbınınitializer. csdosyasında aşağıdaki satırı açıklama olarak inceleyin:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve veritabanının çalıştığını doğrulayın.

Üretimde geçişleri uygulama


Uygulama başlangıcında, üretim uygulamalarının Database. Migrate olarak çağırmalarını öneririz. sunucu
grubuna dağıtılan bir uygulamadan Migrate çağrılmamalıdır. Uygulama birden çok sunucu örneğine
ölçekleniyorsa, veritabanı şeması güncelleştirmelerinin birden çok sunucudan oluşmaması veya okuma/yazma
erişimiyle çakışmamasını sağlamak zordur.
Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş
yaklaşımları şunları içerir:
SQL betikleri oluşturmak ve dağıtımda SQL betikleri kullanmak için geçişleri kullanma.
Denetlenen bir ortamdan dotnet ef database update çalıştırılıyor.

Sorun giderme
Uygulama SQL Server LocalDB kullanıyorsa ve aşağıdaki özel durumu görüntülüyorsa:

SqlException: Cannot open database "ContosoUniversity" requested by the login.


The login failed.
Login failed for user 'user name'.
Çözüm, bir komut isteminde dotnet ef database update çalıştırmak olabilir.
Ek kaynaklar
Clı EF Core.
Paket Yöneticisi Konsolu (Visual Studio)

Sonraki adımlar
Sonraki öğreticide, veri modeli, varlık özellikleri ve yeni varlıklar eklenerek oluşturulur.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide, veri modeli değişikliklerini yönetmek için EF Core geçişleri özelliği kullanılır.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.
Yeni bir uygulama geliştirildiğinde, veri modeli sıklıkla değişir. Modelin her değiştirilişinde, model veritabanıyla
eşitlenmemiş olur. Bu öğretici, mevcut değilse veritabanını oluşturmak için Entity Framework yapılandırılarak
başlatılır. Veri modelinin her değiştirilişinde:
DB bırakılır.
EF, modelle eşleşen yeni bir tane oluşturur.
Uygulama, DB 'yi test verileriyle birlikte oluşturur.
Bu yaklaşım, VERITABANıNı veri modeliyle eşitlenmiş halde tutmak, uygulamayı üretime dağıtana kadar iyi çalışır.
Uygulama üretimde çalıştığında genellikle saklanması gereken verileri depolar. Uygulama her değişiklik
yapıldığında (yeni sütun ekleme gibi) bir test DB ile başlayamaz. EF Core geçişleri özelliği, yeni bir VERITABANı
oluşturmak yerine EF Core DB şemasını güncelleştirmesine olanak sağlayarak bu sorunu çözer.
Veri modeli değiştiğinde VERITABANıNı bırakıp yeniden oluşturmak yerine, geçişler şemayı güncelleştirir ve
mevcut verileri korur.

Veritabanını bırak
SQL Server Nesne Gezgini (ssox) veya database drop komutunu kullanın:
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Drop-Database

Yardım bilgileri almak için PMC 'ten Get-Help about_EntityFrameworkCore çalıştırın.

İlk geçiş oluşturma ve VERITABANıNı güncelleştirme


Projeyi derleyin ve ilk geçişi oluşturun.
Visual Studio
Visual Studio Code
Add-Migration InitialCreate
Update-Database

Yukarı ve aşağı yöntemlerini inceleyin


EF Core migrations add komutu VERITABANıNı oluşturmak için kodu oluşturdu. Bu geçiş kodu geçişleri<zaman
damgasında _InitialCreate. cs dosyasında > . InitialCreate sınıfının Up yöntemi, veri modeli varlık kümelerine
karşılık gelen VERITABANı tablolarını oluşturur. Down yöntemi, aşağıdaki örnekte gösterildiği gibi onları siler:

public partial class InitialCreate : Migration


{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});

migrationBuilder.CreateTable(
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");

migrationBuilder.DropTable(
name: "Course");

migrationBuilder.DropTable(
name: "Student");
}
}

Geçişler, bir geçiş için veri modeli değişikliklerini uygulamak üzere Up yöntemini çağırır. Güncelleştirmeyi geri
almak için bir komut girdiğinizde, geçişler Down yöntemini çağırır.
Önceki kod ilk geçişe yöneliktir. Bu kod, migrations add InitialCreate komutu çalıştırıldığında oluşturulmuştur.
Dosya adı için geçiş adı parametresi (örnekteki "ınitialcreate") kullanılır. Geçiş adı herhangi bir geçerli dosya adı
olabilir. Geçiş sırasında nelerin yapıldığını özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, bir
departman tablosu ekleyen bir geçişe "AddDepartmentTable" adı verilir.
İlk geçiş oluşturulur ve VERITABANı varsa:
DB oluşturma kodu oluşturulur.
DB, veri modeliyle zaten eşleştiğinden, DB oluşturma kodunun çalıştırılması gerekmiyor. DB oluşturma kodu
çalıştırılsa, VERITABANı veri modeliyle zaten eşleştiğinden hiçbir değişiklik yapmaz.
Uygulama yeni bir ortama dağıtıldığında, DB oluşturmak için DB oluşturma kodunun çalıştırılması gerekir.
Daha önce VERITABANı bırakılmıştı ve mevcut olmadığından geçişler yeni DB 'yi oluşturur.
Veri modeli anlık görüntüsü
Geçişler geçişlerde/SchoolContextModelSnapshot. cs' de geçerli veritabanı şemasının anlık görüntüsünü oluşturur.
Bir geçiş eklediğinizde EF, veri modeli Snapshot dosyası ile karşılaştırılarak nelerin değiştirildiğini belirler.
Bir geçişi silmek için aşağıdaki komutu kullanın:
Visual Studio
Visual Studio Code
Geçişi Kaldır
Geçişleri Kaldır komutu geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar.
Uygulamayı kaldırın ve uygulamayı test edin
Erken geliştirme için EnsureCreated kullanıldı. Bu öğreticide geçişler kullanılır. EnsureCreated aşağıdaki
sınırlamalara sahiptir:
Geçişleri atlar ve DB ve şema oluşturur.
Geçişler tablosu oluşturmaz.
Geçişlerle kullanılamaz.
, DB 'nin bıraktığı ve sıklıkla yeniden oluşturulduğu test veya hızlı prototipleme için tasarlanmıştır.
EnsureCreated kaldır:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve DB 'nin çalıştığını doğrulayın.


Veritabanını inceleyin
DB 'yi denetlemek için SQL Server Nesne Gezgini kullanın. __EFMigrationsHistory tablo ekleme hakkında dikkat
edin. __EFMigrationsHistory tablo, hangi geçişlerin VERITABANıNA uygulandığını izler. __EFMigrationsHistory
tablosundaki verileri görüntüleyin, ilk geçiş için bir satır gösterir. Önceki CLı çıkış örneğinde yer alan son oturum, bu
satırı oluşturan INSERT ifadesini gösterir.
Uygulamayı çalıştırın ve her şeyin çalıştığını doğrulayın.

Üretimde geçişleri uygulama


Uygulama başlangıcında, üretim uygulamalarının Database. Migrate çağrısını yapmanızı öneririz. sunucu
grubundaki bir uygulamadan Migrate çağrılmamalıdır. Örneğin, uygulama bulutu genişleme ile dağıtılmışsa
(uygulamanın birden çok örneği çalışır).
Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş
yaklaşımları şunları içerir:
SQL betikleri oluşturmak ve dağıtımda SQL betikleri kullanmak için geçişleri kullanma.
Denetlenen bir ortamdan dotnet ef database update çalıştırılıyor.

EF Core, herhangi bir geçişin çalıştırılması gerektiğini görmek için __MigrationsHistory tablosunu kullanır. DB
güncel değilse, hiçbir geçiş çalıştırılmaz.

Sorun giderme
Tamamlanmış uygulamayıindirin.
Uygulama aşağıdaki özel durumu oluşturur:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.

Çözüm: dotnet ef database update Çalıştır


Ek kaynaklar
Bu öğreticinin YouTube sürümü
.NET Core CLI.
Paket Yöneticisi Konsolu (Visual Studio)

ÖN CEKI İL E R I
ASP.NET Core veri modelinde EF Core ile Razor
Pages-5/8
23.11.2019 • 86 minutes to read • Edit Online

Tarafından Tom Dykstra ve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Önceki öğreticiler, üç varlıktan oluşan temel bir veri modeliyle çalışmıştır.Bu öğreticide:
Daha fazla varlık ve ilişki eklenmiştir.
Veri modeli biçimlendirme, doğrulama ve veritabanı eşleme kuralları belirtilerek özelleştirilir.
Tamamlanan veri modeli aşağıdaki çizimde gösterilmiştir:
Öğrenci varlık

Modeller/öğrenci. cs dosyasındaki kodu aşağıdaki kodla değiştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki kod, bir FullName özelliği ekler ve var olan özelliklere aşağıdaki öznitelikleri ekler:
[DataType]
[DisplayFormat]
[StringLength]
[Column]
[Required]
[Display]

FullName hesaplanmış özelliği


FullName , diğer iki özelliği birleştirerek oluşturulmuş bir değer döndüren hesaplanmış bir özelliktir. FullName
ayarlanamaz, bu nedenle yalnızca bir get erişimcisi vardır. Veritabanında FullName sütunu oluşturulmaz.
DataType özniteliği

[DataType(DataType.Date)]

Öğrenci kayıt tarihleri için, tüm sayfalar şu anda tarihle birlikte tarih ile görüntülenir, ancak yalnızca tarihin ilgili
olması gerekir. Veri ek açıklaması özniteliklerini kullanarak, verileri gösteren her sayfada görüntü biçimini giderecek
bir kod değişikliği yapabilirsiniz.
DataType özniteliği, veritabanı iç türünden daha belirgin bir veri türünü belirtir. Bu durumda, tarih ve saat değil
yalnızca tarih görüntülenmelidir. Veri türü numaralandırması , tarih, saat, PhoneNumber, para birimi, emaadresi vb.
gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin:
mailto: bağlantısı DataType.EmailAddress için otomatik olarak oluşturulur.
Tarih Seçici çoğu tarayıcıda DataType.Date için sağlanır.

DataType özniteliği HTML 5 data- (bir veri Dash) öznitelikleri yayar. DataType öznitelikleri doğrulama sağlamaz.
DisplayFormat özniteliği

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, Tarih alanı sunucunun
CultureInfoöğesine göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır. ApplyFormatInEditMode ayarı,
biçimlendirmenin düzenleme kullanıcı arabirimine de uygulanacağını belirtir. Bazı alanlar ApplyFormatInEditMode
kullanmamalıdır. Örneğin, para birimi simgesi genellikle bir düzenleme metin kutusunda gösterilmemelidir.
DisplayFormat özniteliği kendisi tarafından kullanılabilir. DataType özniteliğini DisplayFormat özniteliğiyle
kullanmak genellikle iyi bir fikirdir. DataType özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini tersine
alır. DataType özniteliği, DisplayFormat kullanılamayan aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir. Örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını ve istemci tarafı giriş doğrulamasını gösterin.
Varsayılan olarak tarayıcı, verileri yerel ayara göre doğru biçimi kullanarak işler.
Daha fazla bilgi için bkz. giriş > etiketi Yardımcısı belgeleri<.
StringLength özniteliği

[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]

Veri doğrulama kuralları ve doğrulama hatası iletileri özniteliklerle belirtilebilir. StringLength özniteliği, bir veri
alanında izin verilen en düşük ve en fazla karakter uzunluğunu belirtir. Gösterilen kod, adları 50 karakterden fazla
olmayacak şekilde sınırlar. En küçük dize uzunluğunu ayarlayan bir örnek daha sonragösterilmiştir.
StringLength özniteliği de istemci tarafı ve sunucu tarafı doğrulaması sağlar. En küçük değerin veritabanı şeması
üzerinde hiçbir etkisi yoktur.
StringLength özniteliği, kullanıcının bir ad için boşluk girmesini engellemez. Cevap içerisinde RegularExpression
özniteliği, girişe kısıtlamalar uygulamak için kullanılabilir. Örneğin, aşağıdaki kod ilk karakterin büyük küçük harf
olmasını ve geri kalan karakterlerin alfabetik olmasını gerektirir:
[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]

Visual Studio
Visual Studio Code
SQL Server Nesne Gezgini (ssox) içinde öğrenci tablosuna çift tıklayarak öğrenci tablosu tasarımcısını açın.

Önceki görüntüde Student tablo şeması gösterilmektedir. Ad alanlarında tür nvarchar(MAX) vardır. Bu öğreticide
daha sonra bir geçiş oluşturulup uygulandığında, ad alanları dize uzunluğu özniteliklerinin bir sonucu olarak
nvarchar(50) olur.

Column özniteliği

[Column("FirstName")]
public string FirstMidName { get; set; }

Öznitelikler sınıfların ve özelliklerin veritabanına nasıl eşlenildiğini denetleyebilir. Student modelinde, Column
özniteliği, FirstMidName özelliğinin adını veritabanında "FirstName" olarak eşlemek için kullanılır.
Veritabanı oluşturulduğunda, model üzerindeki özellik adları sütun adları için kullanılır ( Column özniteliği
kullanıldığı durumlar dışında). Student modeli ilk ad alanı için FirstMidName kullanır, çünkü alan de bir orta ad
içerebilir.
[Column] özniteliğiyle, veri modelindeki Student.FirstMidName Student tablonun FirstName sütunuyla eşlenir.
Column özniteliğinin eklenmesi modeli SchoolContext yedekleyen şekilde değiştirir. SchoolContext yedekleyen
model artık veritabanıyla eşleşmez. Bu tutarsızlık, daha sonra bu öğreticide bir geçiş eklenerek çözümlenir.
Gerekli öznitelik

[Required]

Required özniteliği, ad özellikleri gereken alanları sağlar. Değer türleri gibi null yapılamayan türler için Required
özniteliği gerekmez (örneğin, DateTime , int ve double ). Null olmayan türler otomatik olarak gerekli alanlar olarak
değerlendirilir.
MinimumLength zorlanmak için Required özniteliği MinimumLength ile birlikte kullanılmalıdır.
[Display(Name = "Last Name")]
[Required]
[StringLength(50, MinimumLength=2)]
public string LastName { get; set; }

MinimumLength ve Required , doğrulamanın doğrulanmasını yerine getirmek için boşluk kullanılmasına izin verir.
Dize üzerinde tam denetim için RegularExpression özniteliğini kullanın.
Display özniteliği

[Display(Name = "Last Name")]

Display özniteliği, metin kutularının açıklamalı alt yazısının "ad", "soyadı", "tam ad" ve "kayıt tarihi" olması
gerektiğini belirtir. Varsayılan açıklamalı alt yazıların sözcükleri bölen bir boşluk yoktu, örneğin "LastName".
Geçiş oluşturma
Uygulamayı çalıştırın ve öğrenciler sayfasına gidin. Bir özel durum oluşturulur. [Column] özniteliği, EF 'in
FirstName adlı bir sütun bulmasını beklemesine neden olur, ancak veritabanındaki sütun adı hala FirstMidName .

Visual Studio
Visual Studio Code
Hata iletisi aşağıdaki örneğe benzer:

SqlException: Invalid column name 'FirstName'.

PMC 'de yeni bir geçiş oluşturmak ve veritabanını güncelleştirmek için aşağıdaki komutları girin:

Add-Migration ColumnFirstName
Update-Database

Bu komutlardan ilki aşağıdaki uyarı iletisini oluşturur:

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.

Ad alanları artık 50 karakterle sınırlı olduğundan uyarı oluşturulur. Veritabanındaki bir ad 50 karakterden
fazlasına sahipse, son karakter 51 ' i kaybedersiniz.
Öğrenci tablosunu SSOX içinde açın:
Geçiş uygulanmadan önce ad sütunları nvarchar (max)türünde idi. Ad sütunları artık nvarchar(50) . Sütun
adı, FirstMidName FirstName olarak değiştirildi.
Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.
Saatin giriş veya tarih ile birlikte görüntülenmediğine dikkat edin.
Yeni oluştur' u seçin ve 50 karakterden daha uzun bir ad girmeyi deneyin.

NOTE
Aşağıdaki bölümlerde, uygulamanın bazı aşamalardan oluşturulması derleyici hataları oluşturur. Yönergeler uygulamanın ne
zaman derbir olduğunu belirtir.

Eğitmen varlığı

Aşağıdaki kodla modeller/eğitmen. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor
{
public int ID { get; set; }

[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }

[Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get { return LastName + ", " + FirstMidName; }
}

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Birden çok öznitelik tek bir satırda olabilir. HireDate öznitelikleri aşağıdaki gibi yazılabilir:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",


ApplyFormatInEditMode = true)]

Gezinti özellikleri
CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.
Bir eğitmen herhangi bir sayıda kurs öğretebilir, bu nedenle CourseAssignments bir koleksiyon olarak tanımlanır.

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Bir eğitmenin en fazla bir ofisi olabilir, bu nedenle OfficeAssignment özelliği tek bir OfficeAssignment varlık içerir.
Office atanmamışsa OfficeAssignment null olur.

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığı
Aşağıdaki kodla modeller/OfficeAssignment. cs oluşturun:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }

public Instructor Instructor { get; set; }


}
}

Anahtar özniteliği
Özellik adı Classnameıd veya ID dışında bir şey olduğunda, bir özelliği birincil anahtar (PK) olarak tanımlamak için
[Key] özniteliği kullanılır.

Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya arasında bir ilişki vardır. Office ataması, atandığı
eğitmenle ilişkili olarak yalnızca vardır. OfficeAssignment PK Ayrıca, Instructor varlığa ait yabancı anahtarıdır (FK).
EF Core, InstructorID ID veya Classnameıd adlandırma kuralını izlemediği için, InstructorID OfficeAssignment
PK olarak otomatik olarak tanıyamaz. Bu nedenle, Key özniteliği, InstructorID PK olarak tanımlamak için
kullanılır:

[Key]
public int InstructorID { get; set; }

Varsayılan olarak, EF Core, sütun tanımlayıcı bir ilişki için olduğundan, anahtarı veritabanı olmayan bir şekilde
değerlendirir.
Eğitmen gezintisi özelliği
Instructor.OfficeAssignment gezinti özelliği null olabilir çünkü belirli bir eğitmen için bir OfficeAssignment satırı
olmayabilir. Bir eğitmenin Office ataması olmayabilir.
OfficeAssignment.Instructor gezinti özelliği her zaman bir eğitmen varlığına sahip olur çünkü yabancı anahtar
InstructorID türü int , null olamayan bir değer türüdür. Bir Office ataması, bir eğitmen olmadan bulunamaz.
Instructor bir varlık ilişkili bir OfficeAssignment varlığına sahip olduğunda, her varlığın gezinti özelliğinde diğer
birine bir başvurusu vardır.

Kurs varlığı
Modelleri/kursu. cs aşağıdaki kodla güncelleştirin:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Title { get; set; }

[Range(0, 5)]
public int Credits { get; set; }

public int DepartmentID { get; set; }

public Department Department { get; set; }


public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}

Course varlığın bir yabancı anahtar (FK) özelliği DepartmentID vardır. DepartmentID ilgili Department varlığına
işaret eder. Course varlığın bir Department gezinti özelliği vardır.
EF Core, modelin ilgili bir varlık için gezinti özelliği olduğunda bir veri modeli için yabancı anahtar özelliği
gerektirmez. EF Core, gerektiği yerde otomatik olarak veritabanında FKs 'ler oluşturur. EF Core otomatik olarak
oluşturulan FKs 'ler için gölge Özellikler oluşturur. Ancak, doğrudan veri modelinde FK dahil edilmesi,
güncelleştirmelerin daha basit ve daha verimli olmasını sağlayabilir. Örneğin, FK özelliğinin DepartmentID dahil
olmadığı bir model düşünün. Bir kurs varlığı düzenlemek üzere getirilirken:
Department özelliği açıkça yüklenmediyse null olur.
Kurs varlığını güncelleştirmek için öncelikle Department varlığın getirilmesi gerekir.

FK özelliği DepartmentID veri modeline dahil edildiğinde, güncelleştirmeden önce Department varlığını getirmeye
gerek yoktur.
DatabaseGenerated özniteliği
[DatabaseGenerated(DatabaseGeneratedOption.None)] özniteliği, PK 'nin veritabanı tarafından oluşturulması yerine
uygulama tarafından sağlandığını belirtir.
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, EF Core PK değerlerinin veritabanı tarafından oluşturulduğunu varsayar. Veritabanı tarafından
oluşturulan genellikle en iyi yaklaşım vardır. Course varlıklar için Kullanıcı PK 'yi belirtir. Örneğin, matematik
departmanı için 1000 serisi, Ingilizce departmanı için 2000 serisi gibi bir kurs numarası.
DatabaseGenerated özniteliği varsayılan değerler oluşturmak için de kullanılabilir. Örneğin, veritabanı bir satırın
oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için otomatik olarak bir tarih alanı oluşturabilir. Daha fazla
bilgi için bkz. üretilen Özellikler.
Yabancı anahtar ve gezinti özellikleri
Course varlığındaki yabancı anahtar ( FK ) özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:

Bir kurs bir departmana atanır, bu nedenle bir DepartmentID FK ve Department gezinti özelliği vardır.

public int DepartmentID { get; set; }


public Department Department { get; set; }

Bir kurs, kayıtlı sayıda öğrenciye sahip olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

public ICollection<Enrollment> Enrollments { get; set; }

Bir kurs birden fazla eğitmen tarafından tada olabilir, bu nedenle CourseAssignments gezinti özelliği bir
koleksiyondur:

public ICollection<CourseAssignment> CourseAssignments { get; set; }

CourseAssignment daha sonraaçıklanmaktadır.

Departman varlığı

Aşağıdaki kodla modeller/departman. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Column özniteliği
Daha önce Column özniteliği sütun adı eşlemesini değiştirmek için kullanılmıştır. Department varlığın kodunda, SQL
veri türü eşlemesini değiştirmek için Column özniteliği kullanılır. Budget sütunu, veritabanında SQL Server para
türü kullanılarak tanımlanır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Sütun eşlemesi genellikle gerekli değildir. EF Core, özelliğin CLR türüne göre uygun SQL Server veri türünü seçer.
CLR decimal türü bir SQL Server decimal türüne eşlenir. Budget para birimi için ve para veri türü para birimi için
daha uygundur.
Yabancı anahtar ve gezinti özellikleri
FK ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir departman yönetici olabilir veya olmayabilir.
Yönetici her zaman bir eğitmendir. Bu nedenle InstructorID özelliği, Instructor varlığa FK olarak eklenir.

Gezinti özelliği Administrator olarak adlandırılır ancak bir Instructor varlığı tutar:

public int? InstructorID { get; set; }


public Instructor Administrator { get; set; }

Önceki koddaki soru işareti (?) özelliği null yapılabilir olduğunu belirtiyor.
Bir departmanın birçok kursu olabilir, bu nedenle bir kurs gezintisi özelliği vardır:
public ICollection<Course> Courses { get; set; }

Kural gereği EF Core, null yapılamayan ve çok-çok ilişkiler için basamaklı silme imkanı sağlar. Bu varsayılan
davranış, dairesel basamaklı silme kurallarına neden olabilir. Bir geçiş eklendiğinde dairesel basamaklı silme
kuralları bir özel duruma neden olur.
Örneğin, Department.InstructorID özelliği null yapılamayan olarak tanımlanmışsa EF Core bir basamaklı silme
kuralı yapılandırır. Bu durumda, yönetici olarak atanan eğitmen silindiğinde departman silinir. Bu senaryoda
kısıtlama kuralı daha anlamlı hale getirir. Aşağıdaki Fluent API bir kısıtlama kuralı ayarlar ve art arda silmeyi devre
dışı bırakır.

modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)

Kayıt varlık
Kayıt kaydı, tek bir öğrenci tarafından gerçekleştirilen bir kurs içindir.

Modelleri/kaydı. cs 'yi aşağıdaki kodla güncelleştirin:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

Yabancı anahtar ve gezinti özellikleri


FK özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Kayıt kaydı tek bir kursa yöneliktir, bu nedenle bir CourseID FK özelliği ve Course gezinti özelliği vardır:

public int CourseID { get; set; }


public Course Course { get; set; }

Kayıt kaydı bir öğrenci içindir, bu nedenle bir StudentID FK özelliği ve Student gezinti özelliği vardır:

public int StudentID { get; set; }


public Student Student { get; set; }

Çoktan çoğa Ilişkiler


Student ve Course varlıkları arasında çok-çok ilişkisi vardır. Enrollment varlık, veritabanında Yük ile çoktan çoğa
bir JOIN tablosu olarak çalışır. "Yükle", Enrollment tablosunun birleştirilmiş tablolar (Bu durumda, PK ve Grade )
gibi ek verileri içerdiği anlamına gelir.
Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğünü gösterilmektedir. (Bu diyagram EF 6. x
için EF güç araçları kullanılarak oluşturulmuştur. Diyagram oluşturmak öğreticinin bir parçası değildir.)

Her ilişki ucu ve bir yıldız işareti (*) 1 diğer sırasında bir-çok ilişkisi belirten bulunur.
Enrollment tablo, sınıf bilgilerini içermiyorsa, yalnızca iki FKs ( CourseID ve StudentID ) içermesi gerekir. Yük
olmadan çoktan çoğa bir JOIN tablosu bazen saf JOIN tablosu (PJT) olarak adlandırılır.
Instructor ve Course varlıkların, saf bir JOIN tablosu kullanılarak çoktan çoğa bir ilişkisi vardır.
Note: EF 6. x, çoktan çoğa ilişkiler için örtük birleştirmeyi destekler, ancak EF Core değildir. Daha fazla bilgi için EF
Core 2,0 ' de çoktan çoğa ilişkilerbölümüne bakın.

Courseatama varlığı
Aşağıdaki kodla modeller/Courseatama. cs oluşturun:

namespace ContosoUniversity.Models
{
public class CourseAssignment
{
public int InstructorID { get; set; }
public int CourseID { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
}
}

Eğitmenden çok-çok ilişkisi için bir JOIN tablosu gerekir ve bu ekleme tablosu için varlık kurs atamasıdır.

EntityName1EntityName2bir JOIN varlığı adı yaygın olarak vardır. Örneğin, bu model kullanılarak eğitmen-kurslar
JOIN tablosu CourseInstructor . Ancak, ilişkiyi açıklayan bir ad kullanmanızı öneririz.
Veri modelleri basit ve büyümeye başlar. Yük (PJTs) olmayan ekleme tabloları genellikle yükü içerecek şekilde
gelişmektedir. Açıklayıcı bir varlık adıyla başlayarak, ekleme tablosu değiştiğinde adın değiştirilmesi gerekmez. İdeal
olarak, JOIN varlığının iş etki alanında kendi doğal (muhtemelen tek bir kelime) adına sahip olması gerekir.
Örneğin, kitaplar ve müşteriler, derecelendirmeler adlı bir JOIN varlığıyla bağlantı kurulabilir.Eğitmenin kursa çok-
çok ilişkisi için CourseInstructor``CourseAssignment tercih edilir.
Bileşik anahtar
CourseAssignment ( InstructorID ve CourseID ) içindeki iki FKs, CourseAssignment tablosunun her satırını benzersiz
olarak tanımlar. CourseAssignment adanmış bir PK gerektirmez. InstructorID ve CourseID özellikleri bileşik bir PK
olarak çalışır. EF Core bileşik PKs 'leri belirtmenin tek yolu Fluent API' dir. Sonraki bölümde, bileşik PK 'nin nasıl
yapılandırılacağı gösterilmektedir.
Bileşik anahtar şunları sağlar:
Tek bir kurs için birden çok satıra izin verilir.
Birden çok satıra bir eğitmen için izin verilir.
Aynı eğitmen ve kurs için birden çok satıra izin verilmez.
Enrollment JOIN varlığı kendi PK 'yi tanımlar, bu nedenle bu sıralamanın yinelemeleri mümkündür.Bu tür
yinelemeleri engellemek için:
FK alanlara benzersiz bir dizin ekleyin veya
CourseAssignment benzer bir birincil bileşik anahtarla Enrollment yapılandırın. Daha fazla bilgi için bkz. dizinler.

Veritabanı bağlamını güncelleştirme


Data/SchoolContext. cs öğesini şu kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<CourseAssignment> CourseAssignments { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Department>().ToTable("Department");
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");

modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
}
}
}

Yukarıdaki kod, yeni varlıkları ekler ve CourseAssignment varlığın bileşik PK öğesini yapılandırır.

Tutarlı API 'nin özniteliklere alternatif


Önceki koddaki OnModelCreating yöntemi EF Core davranışını yapılandırmak için Fluent API kullanır. Genellikle tek
bir bildirimde bir dizi yöntem çağrısı olan dize olarak kullanıldığından, API "akıcı" olarak adlandırılır. Aşağıdaki kod
Fluent API bir örneğidir:

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}

Bu öğreticide, Fluent API yalnızca özniteliklerle yapılamadığını veritabanı eşlemesi için kullanılır. Ancak Fluent API,
özniteliklerle yapılabilecek biçimlendirme, doğrulama ve eşleme kurallarının çoğunu belirtebilir.
gibi bazı öznitelikler Fluent API uygulanamaz.
MinimumLength MinimumLength şemayı değiştirmez, yalnızca bir
minimum uzunluk doğrulama kuralı uygular.
Bazı geliştiriciler, varlık sınıflarının "temiz" olmasını sağlamak için Fluent API özel olarak kullanmayı tercih eder.
Öznitelikler ve Fluent API karışık olabilir. Yalnızca Fluent API (bileşik bir PK belirterek) yapılabilecek bazı
konfigürasyonlar vardır. Yalnızca özniteliklerle ( MinimumLength ) yapılabilecek bazı konfigürasyonlar vardır. Fluent
API veya özniteliklerini kullanmak için önerilen uygulama:
Bu iki yaklaşımdan birini seçin.
Seçilen yaklaşımı mümkün olduğunca düzenli olarak kullanın.
Bu öğreticide kullanılan özniteliklerin bazıları için kullanılır:
Yalnızca doğrulama (örneğin, MinimumLength ).
Yalnızca yapılandırma EF Core (örneğin, HasKey ).
Doğrulama ve EF Core yapılandırma (örneğin, [StringLength(50)] ).
Öznitelikler ile Fluent API hakkında daha fazla bilgi için bkz. yapılandırma yöntemleri.

Varlık diyagramı
Aşağıdaki çizimde, tamamlanmış okul modeli için EF Power Tools 'un oluştura diyagramı gösterilmektedir.
Önceki diyagramda şunları gösterir:
Birkaç bire çok ilişki satırı (*1).
Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya-bir ilişki çizgisi (1 ila 0.. 1 ).
Instructor ve Department varlıkları arasında sıfır veya-bire çok ilişki çizgisi (0.. 1 -* ).

Veritabanının çekirdeğini oluşturma


Data/Dbınizer. csdosyasındaki kodu güncelleştirin:

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
//context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2016-09-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Arturo", LastName = "Anand",
EnrollmentDate = DateTime.Parse("2019-09-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Yan", LastName = "Li",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Peggy", LastName = "Justice",
EnrollmentDate = DateTime.Parse("2017-09-01") },
new Student { FirstMidName = "Laura", LastName = "Norman",
EnrollmentDate = DateTime.Parse("2019-09-01") },
new Student { FirstMidName = "Nino", LastName = "Olivetto",
EnrollmentDate = DateTime.Parse("2011-09-01") }
};

foreach (Student s in students)


{
context.Students.Add(s);
}
context.SaveChanges();

var instructors = new Instructor[]


{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie",
HireDate = DateTime.Parse("1995-03-11") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri",
HireDate = DateTime.Parse("2002-07-06") },
new Instructor { FirstMidName = "Roger", LastName = "Harui",
HireDate = DateTime.Parse("1998-07-01") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
HireDate = DateTime.Parse("2001-01-15") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng",
HireDate = DateTime.Parse("2004-02-12") }
};

foreach (Instructor i in instructors)


{
context.Instructors.Add(i);
}
context.SaveChanges();

var departments = new Department[]


{
new Department { Name = "English", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").ID },
new Department { Name = "Mathematics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID },
new Department { Name = "Engineering", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").ID },
new Department { Name = "Economics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID }
};

foreach (Department d in departments)


foreach (Department d in departments)
{
context.Departments.Add(d);
}
context.SaveChanges();

var courses = new Course[]


{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID
},
new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 1045, Title = "Calculus", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 2021, Title = "Composition", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
new Course {CourseID = 2042, Title = "Literature", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
};

foreach (Course c in courses)


{
context.Courses.Add(c);
}
context.SaveChanges();

var officeAssignments = new OfficeAssignment[]


{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
Location = "Thompson 304" },
};

foreach (OfficeAssignment o in officeAssignments)


{
context.OfficeAssignments.Add(o);
}
context.SaveChanges();

var courseInstructors = new CourseAssignment[]


{
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Kapoor").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Fakhouri").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Literature" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
};

foreach (CourseAssignment ci in courseInstructors)


{
context.CourseAssignments.Add(ci);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").ID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").ID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
};

foreach (Enrollment e in enrollments)


{
var enrollmentInDataBase = context.Enrollments.Where(
s =>
s.Student.ID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollments.Add(e);
}
}
context.SaveChanges();
}
}
}

Yukarıdaki kod, yeni varlıklar için tohum verileri sağlar. Bu kodun çoğu yeni varlık nesneleri oluşturur ve örnek
verileri yükler. Örnek veriler test için kullanılır. Çoktan çoğa ekleme tablolarının nasıl çalıştırılabilir olduğunu
gösteren örnekler için Enrollments ve CourseAssignments bakın.

Geçiş Ekle
Projeyi oluşturun.
Visual Studio
Visual Studio Code
PMC 'de aşağıdaki komutu çalıştırın.

Add-Migration ComplexDataModel

Yukarıdaki komut, olası veri kaybı hakkında bir uyarı görüntüler.

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.
To undo this action, use 'ef migrations remove'

database update komutu çalıştırıldıysanız aşağıdaki hata oluşturulur:

The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Course_dbo.Department_DepartmentID". The conflict occurred in
database "ContosoUniversity", table "dbo.Department", column 'DepartmentID'.
Sonraki bölümde, bu hatayla ilgili ne yapılacağını görürsünüz.

Geçişi uygulayın veya bırakıp yeniden oluşturun


Artık var olan bir veritabanınız olduğuna göre, değişikliklere nasıl uygulanacağını düşünmeniz gerekir. Bu öğreticide
iki alternatif gösterilmektedir:
Veritabanını bırakıp yeniden oluşturun. SQLite kullanıyorsanız bu bölümü seçin.
Geçişi mevcut veritabanına uygulayın. Bu bölümdeki yönergeler yalnızca SQL Server için geçerlidir, SQLite için
değildir.
Her iki seçenek de SQL Server için geçerlidir. Apply-Migration yöntemi daha karmaşıktır ve zaman alabilir. Bu,
gerçek dünyada üretim ortamları için tercih edilen yaklaşımdır.

Veritabanını bırakıp yeniden oluşturun


SQL Server kullanıyorsanız ve aşağıdaki bölümde uygulanacak geçiş yaklaşımını yapmak istiyorsanız Bu bölümü
atlayın .
Yeni bir veritabanı oluşturmak için EF Core zorlamak için veritabanını bırakıp güncelleştirin:
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Drop-Database

Geçişler klasörünü silin, ardından aşağıdaki komutu çalıştırın:

Add-Migration InitialCreate
Update-Database

Uygulamayı çalıştırın. Uygulamayı çalıştırmak DbInitializer.Initialize yöntemini çalıştırır.


DbInitializer.Initialize yeni veritabanını doldurur.

Visual Studio
Visual Studio Code
Veritabanını SSOX içinde açın:
Daha önce SSOX açıldıysa Yenile düğmesine tıklayın.
Genişletin tabloları düğümü. Oluşturulan tablolar görüntülenir.
Courseatama tablosunu inceleyin:
Courseatama tablosuna sağ tıklayın ve verileri görüntüle' yi seçin.
Courseatama tablosunun veri içerdiğini doğrulayın.

Geçişi Uygula
Bu bölüm isteğe bağlıdır. Bu adımlar yalnızca SQL Server LocalDB için çalışır ve yalnızca önceki bırakma ve
veritabanını yeniden oluştur bölümünü atladıktan sonra.
Geçişler mevcut verilerle çalıştırıldığında, mevcut verilerin karşılanmadığı FK kısıtlamalar olabilir. Üretim verileriyle,
mevcut verilerin geçirilmesi için adımların alınması gerekir. Bu bölüm, FK kısıtlama ihlallerinin düzeltilmesiyle bir
örnek sağlar. Bu kod değişikliklerini yedekleme olmadan yapmayın. Önceki bırakmayı tamamlayıp veritabanını
yeniden oluşturduktan sonra Bu kod değişikliklerini yapmayın.
{Timestamp } _ComplexDataModel. cs dosyası aşağıdaki kodu içerir:

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
type: "int",
nullable: false,
defaultValue: 0);

Yukarıdaki kod Course tabloya null atanamaz DepartmentID FK ekler. Önceki öğreticideki veritabanı Course
satırları içerir, böylece tablo geçişler tarafından güncelleştirilemez.
ComplexDataModel geçişinin mevcut verilerle çalışmasını sağlamak için:
Yeni sütuna ( DepartmentID ) varsayılan değer vermek için kodu değiştirin.
Varsayılan departman olarak davranacak "Temp" adlı sahte bir departman oluşturun.
Yabancı anahtar kısıtlamalarını çözme
ComplexDataModel geçiş sınıfında Up yöntemini güncelleştirin:
{Timestamp } _ComplexDataModel. cs dosyasını açın.
DepartmentID sütununu Course tablosuna ekleyen kod satırını açıklama satırı yapın.

migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldNullable: true);

//migrationBuilder.AddColumn<int>(
// name: "DepartmentID",
// table: "Course",
// nullable: false,
// defaultValue: 0);

Aşağıdaki vurgulanmış kodu ekleyin. Yeni kod .CreateTable( name: "Department" bloğundan sonra geçer:

migrationBuilder.CreateTable(
name: "Department",
columns: table => new
{
DepartmentID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Budget = table.Column<decimal>(type: "money", nullable: false),
InstructorID = table.Column<int>(type: "int", nullable: true),
Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
StartDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Department", x => x.DepartmentID);
table.ForeignKey(
name: "FK_Department_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});

migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1);

Önceki değişikliklerle, ComplexDataModel.Up yöntemi çalıştıktan sonra mevcut Course satırları "Temp" departmanı
ile ilişkilendirilir.
Burada gösterilen durumu işlemenin yolu, bu öğretici için basitleştirilmiştir. Bir üretim uygulaması şöyle olacaktır:
Yeni Department satırlarına Department satırları ve ilgili Course satırlarını eklemek için kod veya komut
dosyaları ekleyin.
"Geçici" Departmanı veya Course.DepartmentID için varsayılan değeri kullanmayın.
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Update-Database

DbInitializer.Initialize yöntemi yalnızca boş bir veritabanıyla çalışacak şekilde tasarlandığından, öğrenci ve kurs
tablolarındaki tüm satırları silmek için SSOX kullanın. (Cascade silme, kayıt tablosundan işlem gerçekleştirir.)
Uygulamayı çalıştırın. Uygulamayı çalıştırmak DbInitializer.Initialize yöntemini çalıştırır.
DbInitializer.Initialize yeni veritabanını doldurur.

Sonraki adımlar
Sonraki iki öğretici ilgili verilerin nasıl okunacağını ve güncelleştirilmesini gösterir.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Önceki öğreticiler, üç varlıktan oluşan temel bir veri modeliyle çalışmıştır.Bu öğreticide:
Daha fazla varlık ve ilişki eklenmiştir.
Veri modeli biçimlendirme, doğrulama ve veritabanı eşleme kuralları belirtilerek özelleştirilir.
Tamamlanan veri modeli için varlık sınıfları aşağıdaki çizimde gösterilmiştir:
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.

Veri modelini özniteliklerle özelleştirme


Bu bölümde, veri modeli öznitelikler kullanılarak özelleştirilir.
DataType özniteliği
Öğrenci sayfaları Şu anda kayıt tarihinin saatini görüntüler. Genellikle, tarih alanları saati değil yalnızca tarihi
gösterir.
Modelleri/öğrenci. cs 'yi aşağıdaki vurgulanmış kodla güncelleştirin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

DataType özniteliği, veritabanı iç türünden daha belirgin bir veri türünü belirtir. Bu durumda, tarih ve saat değil
yalnızca tarih görüntülenmelidir. Veri türü numaralandırması , tarih, saat, PhoneNumber, para birimi, emaadresi vb.
gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin:
mailto: bağlantısı DataType.EmailAddress için otomatik olarak oluşturulur.
Tarih Seçici çoğu tarayıcıda DataType.Date için sağlanır.
DataType özniteliği HTML 5 tarayıcıların kullandığı HTML 5 data- (bir veri Dash) özniteliklerini yayar. DataType
öznitelikleri doğrulama sağlamaz.
DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, Tarih alanı sunucunun
CultureInfoöğesine göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

ApplyFormatInEditMode ayarı, biçimlendirmenin düzenleme kullanıcı arabirimine de uygulanacağını belirtir. Bazı


alanlar ApplyFormatInEditMode kullanmamalıdır. Örneğin, para birimi simgesi genellikle bir düzenleme metin
kutusunda gösterilmemelidir.
DisplayFormat özniteliği kendisi tarafından kullanılabilir. DataType özniteliğini DisplayFormat özniteliğiyle
kullanmak genellikle iyi bir fikirdir. DataType özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini tersine
alır. DataType özniteliği, DisplayFormat kullanılamayan aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir. Örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını, istemci tarafı giriş doğrulamasını vb. göster
Varsayılan olarak tarayıcı, verileri yerel ayara göre doğru biçimi kullanarak işler.
Daha fazla bilgi için bkz. giriş > etiketi Yardımcısı belgeleri<.
Uygulamayı çalıştırın. Öğrenciler dizin sayfasına gidin. Süreler artık görüntülenmiyor. Student modelini kullanan
her görünüm, tarihi zaman içinde görüntüler.
StringLength özniteliği
Veri doğrulama kuralları ve doğrulama hatası iletileri özniteliklerle belirtilebilir. StringLength özniteliği, bir veri
alanında izin verilen en düşük ve en fazla karakter uzunluğunu belirtir. StringLength özniteliği de istemci tarafı ve
sunucu tarafı doğrulaması sağlar. En küçük değerin veritabanı şeması üzerinde hiçbir etkisi yoktur.
Student modelini aşağıdaki kodla güncelleştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki kod, adları 50 karakterden fazla olmayacak şekilde sınırlandırır. StringLength özniteliği, kullanıcının bir
ad için boşluk girmesini engellemez. Cevap içerisinde RegularExpression özniteliği, girişe kısıtlamalar uygulamak
için kullanılır. Örneğin, aşağıdaki kod ilk karakterin büyük küçük harf olmasını ve geri kalan karakterlerin alfabetik
olmasını gerektirir:

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
Uygulamayı çalıştırın:
Öğrenciler sayfasına gidin.
Yeni oluştur' u seçin ve 50 karakterden daha uzun bir ad girin.
Oluştur' u seçin, istemci tarafı doğrulama bir hata iletisi gösterir.

SQL Server Nesne Gezgini (ssox) içinde öğrenci tablosuna çift tıklayarak öğrenci tablosu tasarımcısını açın.

Önceki görüntüde Student tablo şeması gösterilmektedir. VERITABANı üzerinde geçişler çalıştırılmadığından, ad
alanlarının türü nvarchar(MAX) vardır. Bu öğreticide daha sonra geçişler çalıştırıldığında, ad alanları nvarchar(50)
olur.
Column özniteliği
Öznitelikler sınıfların ve özelliklerin veritabanına nasıl eşlenildiğini denetleyebilir. Bu bölümde, Column özniteliği,
FirstMidName özelliğinin adını VERITABANıNDA "FirstName" olarak eşlemek için kullanılır.

DB oluşturulduğunda, model üzerindeki özellik adları sütun adları için kullanılır ( Column özniteliği kullanıldığı
durumlar dışında).
Student modeli ilk ad alanı için FirstMidName kullanır, çünkü alan de bir orta ad içerebilir.
Student.cs dosyasını aşağıdaki vurgulanmış kodla güncelleştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki değişiklik ile uygulamadaki Student.FirstMidName , Student tablosunun FirstName sütunuyla eşlenir.
Column özniteliğinin eklenmesi modeli SchoolContext yedekleyen şekilde değiştirir. SchoolContext yedekleyen
model artık veritabanıyla eşleşmez. Geçiş uygulamadan önce uygulama çalışıyorsa aşağıdaki özel durum
oluşturulur:

SqlException: Invalid column name 'FirstName'.

DB 'yi güncelleştirmek için:


Projeyi oluşturun.
Proje klasöründe bir komut penceresi açın. Yeni bir geçiş oluşturmak ve DB 'yi güncelleştirmek için aşağıdaki
komutları girin:
Visual Studio
Visual Studio Code

Add-Migration ColumnFirstName
Update-Database

migrations add ColumnFirstName komutu aşağıdaki uyarı iletisini üretir:

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.
Ad alanları artık 50 karakterle sınırlı olduğundan uyarı oluşturulur. VERITABANıNDAKI bir ad 50 karakterden
fazlasına sahipse, son karakter 51 ' i kaybedersiniz.
Uygulamayı test edin.
Öğrenci tablosunu SSOX içinde açın:

Geçiş uygulanmadan önce ad sütunları nvarchar (max)türünde idi. Ad sütunları artık nvarchar(50) . Sütun adı,
FirstMidName FirstName olarak değiştirildi.

NOTE
Aşağıdaki bölümde, uygulamanın bazı aşamalardan oluşturulması derleyici hataları oluşturur. Yönergeler uygulamanın ne
zaman derbir olduğunu belirtir.

Öğrenci varlık güncelleştirmesi

Modelleri/öğrenci. cs 'yi aşağıdaki kodla güncelleştirin:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Gerekli öznitelik
Required özniteliği, ad özellikleri gereken alanları sağlar. Değer türleri ( DateTime , int , double , vb.) gibi null
yapılamayan türler için Required özniteliği gerekli değildir. Null olmayan türler otomatik olarak gerekli alanlar
olarak değerlendirilir.
Required özniteliği StringLength özniteliğinde minimum length parametresiyle değiştirilebilir:

[Display(Name = "Last Name")]


[StringLength(50, MinimumLength=1)]
public string LastName { get; set; }

Display özniteliği
Display özniteliği, metin kutularının açıklamalı alt yazısının "ad", "soyadı", "tam ad" ve "kayıt tarihi" olması
gerektiğini belirtir. Varsayılan açıklamalı alt yazıların sözcükleri bölen bir boşluk yoktu, örneğin "LastName".
FullName hesaplanmış özelliği
FullName , diğer iki özelliği birleştirerek oluşturulmuş bir değer döndüren hesaplanmış bir özelliktir. FullName
ayarlanamaz, yalnızca bir get erişimcisi vardır. Veritabanında FullName sütunu oluşturulmaz.

Eğitmen varlığı oluşturma


Aşağıdaki kodla modeller/eğitmen. cs oluşturun:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor
{
public int ID { get; set; }

[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }

[Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get { return LastName + ", " + FirstMidName; }
}

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Birden çok öznitelik tek bir satırda olabilir. HireDate öznitelikleri aşağıdaki gibi yazılabilir:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",


ApplyFormatInEditMode = true)]

Courseatamalar ve OfficeAssignment gezinti özellikleri


CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.

Bir eğitmen herhangi bir sayıda kurs öğretebilir, bu nedenle CourseAssignments bir koleksiyon olarak tanımlanır.
public ICollection<CourseAssignment> CourseAssignments { get; set; }

Bir gezinti özelliği birden çok varlık tutuyorsa:


Girişlerin eklenebileceği, silinebileceği ve güncelleştirilebileceği bir liste türü olmalıdır.
Gezinti özelliği türleri şunları içerir:
ICollection<T>
List<T>
HashSet<T>

ICollection<T> belirtilirse EF Core varsayılan olarak bir HashSet<T> koleksiyonu oluşturur.


CourseAssignment varlığı, çoktan çoğa ilişkilerin bölümünde açıklanmaktadır.
Contoso Üniversitesi iş kuralları, bir eğitmenin en fazla bir ofisiniz olabilir. OfficeAssignment özelliği tek bir
OfficeAssignment varlığı barındırır. Office atanmamışsa OfficeAssignment null olur.

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığını oluşturma

Aşağıdaki kodla modeller/OfficeAssignment. cs oluşturun:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }

public Instructor Instructor { get; set; }


}
}

Anahtar özniteliği
Özellik adı Classnameıd veya ID dışında bir şey olduğunda, bir özelliği birincil anahtar (PK) olarak tanımlamak için
[Key] özniteliği kullanılır.

Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya arasında bir ilişki vardır. Office ataması, atandığı
eğitmenle ilişkili olarak yalnızca vardır. OfficeAssignment PK Ayrıca, Instructor varlığa ait yabancı anahtarıdır (FK).
EF Core, şu nedenle InstructorID otomatik olarak OfficeAssignment PK olarak tanıyamaz:
InstructorID , ID veya Classnameıd adlandırma kuralını takip etmez.
Bu nedenle, Key özniteliği, InstructorID PK olarak tanımlamak için kullanılır:

[Key]
public int InstructorID { get; set; }

Varsayılan olarak, EF Core, sütun tanımlayıcı bir ilişki için olduğundan, anahtarı veritabanı olmayan bir şekilde
değerlendirir.
Eğitmen gezintisi özelliği
Instructor varlık için OfficeAssignment gezinti özelliği null yapılabilir, çünkü:

Başvuru türleri (örneğin, sınıflar Nullable).


Bir eğitmenin Office ataması olmayabilir.
OfficeAssignment varlık null atanamaz Instructor bir gezinti özelliğine sahiptir çünkü:
InstructorID null değer atanamaz.
Bir Office ataması, bir eğitmen olmadan bulunamaz.
Instructor bir varlık ilişkili bir OfficeAssignment varlığına sahip olduğunda, her varlığın gezinti özelliğinde diğer
birine bir başvurusu vardır.
[Required] özniteliği Instructor gezinti özelliğine uygulanabilir:

[Required]
public Instructor Instructor { get; set; }

Yukarıdaki kod, ilgili bir eğitmen olması gerektiğini belirtir. InstructorID yabancı anahtar (aynı zamanda PK) null
değer atanamaz olduğundan, yukarıdaki kod gereksizdir.

Kurs varlığını değiştirme

Modelleri/kursu. cs aşağıdaki kodla güncelleştirin:


using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Title { get; set; }

[Range(0, 5)]
public int Credits { get; set; }

public int DepartmentID { get; set; }

public Department Department { get; set; }


public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}

Course varlığın bir yabancı anahtar (FK) özelliği DepartmentID vardır. DepartmentID ilgili Department varlığına
işaret eder. Course varlığın bir Department gezinti özelliği vardır.
EF Core, modelin ilgili bir varlık için gezinti özelliği olduğunda bir veri modeli için FK özelliği gerektirmez.
EF Core, gerektiği yerde otomatik olarak veritabanında FKs 'ler oluşturur. EF Core otomatik olarak oluşturulan FKs
'ler için gölge Özellikler oluşturur. FK 'in veri modelinde olması, güncelleştirmeleri daha basit ve daha verimli hale
getirir. Örneğin, FK özelliğinin DepartmentID dahil olmadığı bir model düşünün. Bir kurs varlığı düzenlemek üzere
getirilirken:
Department varlığı açık bir şekilde yüklenmediyse null olur.
Kurs varlığını güncelleştirmek için öncelikle Department varlığın getirilmesi gerekir.
FK özelliği DepartmentID veri modeline dahil edildiğinde, güncelleştirmeden önce Department varlığını getirmeye
gerek yoktur.
DatabaseGenerated özniteliği
[DatabaseGenerated(DatabaseGeneratedOption.None)] özniteliği, PK 'nin veritabanı tarafından oluşturulması yerine
uygulama tarafından sağlandığını belirtir.

[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, EF Core PK değerlerinin DB tarafından oluşturulduğunu varsayar. VERITABANı tarafından


oluşturulan PK değerleri genellikle en iyi yaklaşımdır. Course varlıklar için Kullanıcı PK 'yi belirtir. Örneğin,
matematik departmanı için 1000 serisi, Ingilizce departmanı için 2000 serisi gibi bir kurs numarası.
DatabaseGenerated özniteliği varsayılan değerler oluşturmak için de kullanılabilir. Örneğin, VERITABANı bir satırın
oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için otomatik olarak bir tarih alanı oluşturabilir. Daha fazla
bilgi için bkz. üretilen Özellikler.
Yabancı anahtar ve gezinti özellikleri
Course varlığındaki yabancı anahtar (FK) özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir kurs bir departmana atanır, bu nedenle bir DepartmentID FK ve Department gezinti özelliği vardır.

public int DepartmentID { get; set; }


public Department Department { get; set; }

Bir kurs, kayıtlı sayıda öğrenciye sahip olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

public ICollection<Enrollment> Enrollments { get; set; }

Bir kurs birden fazla eğitmen tarafından tada olabilir, bu nedenle CourseAssignments gezinti özelliği bir
koleksiyondur:

public ICollection<CourseAssignment> CourseAssignments { get; set; }

CourseAssignment daha sonraaçıklanmaktadır.

Departman varlığı oluşturma

Aşağıdaki kodla modeller/departman. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Column özniteliği
Daha önce Column özniteliği sütun adı eşlemesini değiştirmek için kullanılmıştır. Department varlığın kodunda, SQL
veri türü eşlemesini değiştirmek için Column özniteliği kullanılır. Budget sütunu, VERITABANıNDA SQL Server
para türü kullanılarak tanımlanır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Sütun eşlemesi genellikle gerekli değildir. EF Core genellikle özelliğin CLR türüne göre uygun SQL Server veri
türünü seçer. CLR decimal türü bir SQL Server decimal türüne eşlenir. Budget para birimi için ve para veri türü
para birimi için daha uygundur.
Yabancı anahtar ve gezinti özellikleri
FK ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir departman yönetici olabilir veya olmayabilir.
Yönetici her zaman bir eğitmendir. Bu nedenle InstructorID özelliği, Instructor varlığa FK olarak eklenir.
Gezinti özelliği Administrator olarak adlandırılır ancak bir Instructor varlığı tutar:

public int? InstructorID { get; set; }


public Instructor Administrator { get; set; }

Önceki koddaki soru işareti (?) özelliği null yapılabilir olduğunu belirtiyor.
Bir departmanın birçok kursu olabilir, bu nedenle bir kurs gezintisi özelliği vardır:
public ICollection<Course> Courses { get; set; }

Note: kurala göre EF Core, null yapılamayan ve çoktan çoğa ilişkiler için art arda silme imkanı sağlar. Basamaklı
silme, dairesel basamaklı silme kurallarına neden olabilir. Döngüsel basamaklı silme kuralları, bir geçiş eklendiğinde
özel duruma neden olur.
Örneğin, Department.InstructorID özelliği null yapılamayan olarak tanımlanmışsa:
EF Core, eğitmen silindiğinde departmanı silmek için bir basamakla silme kuralı yapılandırır.
Eğitmen silindiğinde departmanı silmek amaçlanan davranış değildir.
Aşağıdaki Fluent API Cascade yerine bir kısıtlama kuralı ayarlar.

modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)

Yukarıdaki kod, departman-eğitmen ilişkisindeki basamaklı silmeyi devre dışı bırakır.

Kayıt varlığını güncelleştirme


Kayıt kaydı, tek bir öğrenci tarafından gerçekleştirilen bir kurs içindir.

Modelleri/kaydı. cs 'yi aşağıdaki kodla güncelleştirin:


using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

Yabancı anahtar ve gezinti özellikleri


FK özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Kayıt kaydı tek bir kursa yöneliktir, bu nedenle bir CourseID FK özelliği ve Course gezinti özelliği vardır:

public int CourseID { get; set; }


public Course Course { get; set; }

Kayıt kaydı bir öğrenci içindir, bu nedenle bir StudentID FK özelliği ve Student gezinti özelliği vardır:

public int StudentID { get; set; }


public Student Student { get; set; }

Çoktan çoğa Ilişkiler


Student ve Course varlıkları arasında çok-çok ilişkisi vardır. Enrollment varlık, veritabanında Yük ile çoktan çoğa
bir JOIN tablosu olarak çalışır. "Yükle", Enrollment tablosunun birleştirilmiş tablolar (Bu durumda, PK ve Grade )
gibi ek verileri içerdiği anlamına gelir.
Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğünü gösterilmektedir. (Bu diyagram EF 6. x
için EF güç araçları kullanılarak oluşturulmuştur. Diyagram oluşturmak öğreticinin bir parçası değildir.)
Her ilişki ucu ve bir yıldız işareti (*) 1 diğer sırasında bir-çok ilişkisi belirten bulunur.
Enrollment tablo, sınıf bilgilerini içermiyorsa, yalnızca iki FKs ( CourseID ve StudentID ) içermesi gerekir. Yük
olmadan çoktan çoğa bir JOIN tablosu bazen saf JOIN tablosu (PJT) olarak adlandırılır.
Instructor ve Course varlıkların, saf bir JOIN tablosu kullanılarak çoktan çoğa bir ilişkisi vardır.
Note: EF 6. x, çoktan çoğa ilişkiler için örtük birleştirmeyi destekler, ancak EF Core değildir. Daha fazla bilgi için EF
Core 2,0 ' de çoktan çoğa ilişkilerbölümüne bakın.

Courseatama varlığı

Aşağıdaki kodla modeller/Courseatama. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class CourseAssignment
{
public int InstructorID { get; set; }
public int CourseID { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
}
}

Eğitmenden kurslar

Eğitmenin kurslardan çok-çok ilişkisi:


Bir varlık kümesiyle temsil etmelidir bir JOIN tablosu gerektirir.
, Saf bir JOIN tablosu (yük içermeyen tablo).
EntityName1EntityName2bir JOIN varlığı adı yaygın olarak vardır. Örneğin, bu model kullanılarak eğitmen-kurslar
JOIN tablosu CourseInstructor . Ancak, ilişkiyi açıklayan bir ad kullanmanızı öneririz.
Veri modelleri basit ve büyümeye başlar. Yük yükü dahil olmak üzere genellikle yük-yük birleştirmeleri (PJTs)
gelişmektedir. Açıklayıcı bir varlık adıyla başlayarak, ekleme tablosu değiştiğinde adın değiştirilmesi gerekmez. İdeal
olarak, JOIN varlığının iş etki alanında kendi doğal (muhtemelen tek bir kelime) adına sahip olması gerekir.
Örneğin, kitaplar ve müşteriler, derecelendirmeler adlı bir JOIN varlığıyla bağlantı kurulabilir.Eğitmenin kursa çok-
çok ilişkisi için CourseInstructor``CourseAssignment tercih edilir.
Bileşik anahtar
FKs null değer atanamaz. CourseAssignment ( InstructorID ve CourseID ) içindeki iki FKs, CourseAssignment
tablosunun her satırını benzersiz olarak tanımlar. CourseAssignment adanmış bir PK gerektirmez. InstructorID ve
CourseID özellikleri bileşik bir PK olarak çalışır. EF Core bileşik PKs 'leri belirtmenin tek yolu Fluent API' dir.
Sonraki bölümde, bileşik PK 'nin nasıl yapılandırılacağı gösterilmektedir.
Bileşik anahtar şunları sağlar:
Tek bir kurs için birden çok satıra izin verilir.
Birden çok satıra bir eğitmen için izin verilir.
Aynı eğitmen ve kurs için birden çok satıra izin verilmez.
Enrollment JOIN varlığı kendi PK 'yi tanımlar, bu nedenle bu sıralamanın yinelemeleri mümkündür.Bu tür
yinelemeleri engellemek için:
FK alanlara benzersiz bir dizin ekleyin veya
CourseAssignment benzer bir birincil bileşik anahtarla Enrollment yapılandırın. Daha fazla bilgi için bkz. dizinler.

DB bağlamını güncelleştirme
Data/SchoolContext. cs' ye aşağıdaki vurgulanmış kodu ekleyin:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Models
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollment { get; set; }
public DbSet<Student> Student { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<CourseAssignment> CourseAssignments { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Department>().ToTable("Department");
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");

modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
}
}
}

Yukarıdaki kod, yeni varlıkları ekler ve CourseAssignment varlığın bileşik PK öğesini yapılandırır.

Tutarlı API 'nin özniteliklere alternatif


Önceki koddaki OnModelCreating yöntemi EF Core davranışını yapılandırmak için Fluent API kullanır. Genellikle tek
bir bildirimde bir dizi yöntem çağrısı olan dize olarak kullanıldığından, API "akıcı" olarak adlandırılır. Aşağıdaki kod
Fluent API bir örneğidir:

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}

Bu öğreticide, Fluent API yalnızca özniteliklerle yapılamadığını DB eşlemesi için kullanılır. Ancak Fluent API,
özniteliklerle yapılabilecek biçimlendirme, doğrulama ve eşleme kurallarının çoğunu belirtebilir.
gibi bazı öznitelikler Fluent API uygulanamaz.
MinimumLength MinimumLength şemayı değiştirmez, yalnızca bir
minimum uzunluk doğrulama kuralı uygular.
Bazı geliştiriciler, varlık sınıflarının "temiz" olmasını sağlamak için Fluent API özel olarak kullanmayı tercih eder.
Öznitelikler ve Fluent API karışık olabilir. Yalnızca Fluent API (bileşik bir PK belirterek) yapılabilecek bazı
konfigürasyonlar vardır. Yalnızca özniteliklerle ( MinimumLength ) yapılabilecek bazı konfigürasyonlar vardır. Fluent
API veya özniteliklerini kullanmak için önerilen uygulama:
Bu iki yaklaşımdan birini seçin.
Seçilen yaklaşımı mümkün olduğunca düzenli olarak kullanın.
Bu öğreticide kullanılan özniteliklerin bazıları için kullanılır:
Yalnızca doğrulama (örneğin, MinimumLength ).
Yalnızca yapılandırma EF Core (örneğin, HasKey ).
Doğrulama ve EF Core yapılandırma (örneğin, [StringLength(50)] ).
Öznitelikler ile Fluent API hakkında daha fazla bilgi için bkz. yapılandırma yöntemleri.

Ilişkileri gösteren varlık diyagramı


Aşağıdaki çizimde, tamamlanmış okul modeli için EF Power Tools 'un oluştura diyagramı gösterilmektedir.
Önceki diyagramda şunları gösterir:
Birkaç bire çok ilişki satırı (*1).
Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya-bir ilişki çizgisi (1 ila 0.. 1 ).
Instructor ve Department varlıkları arasında sıfır veya-bire çok ilişki çizgisi (0.. 1 -* ).

VERITABANıNı test verileriyle çekirdek olarak


Data/Dbınizer. csdosyasındaki kodu güncelleştirin:

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
//context.Database.EnsureCreated();
// Look for any students.
if (context.Student.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2010-09-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Arturo", LastName = "Anand",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Yan", LastName = "Li",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Peggy", LastName = "Justice",
EnrollmentDate = DateTime.Parse("2011-09-01") },
new Student { FirstMidName = "Laura", LastName = "Norman",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Nino", LastName = "Olivetto",
EnrollmentDate = DateTime.Parse("2005-09-01") }
};

foreach (Student s in students)


{
context.Student.Add(s);
}
context.SaveChanges();

var instructors = new Instructor[]


{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie",
HireDate = DateTime.Parse("1995-03-11") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri",
HireDate = DateTime.Parse("2002-07-06") },
new Instructor { FirstMidName = "Roger", LastName = "Harui",
HireDate = DateTime.Parse("1998-07-01") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
HireDate = DateTime.Parse("2001-01-15") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng",
HireDate = DateTime.Parse("2004-02-12") }
};

foreach (Instructor i in instructors)


{
context.Instructors.Add(i);
}
context.SaveChanges();

var departments = new Department[]


{
new Department { Name = "English", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").ID },
new Department { Name = "Mathematics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID },
new Department { Name = "Engineering", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").ID },
new Department { Name = "Economics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID }
};

foreach (Department d in departments)


foreach (Department d in departments)
{
context.Departments.Add(d);
}
context.SaveChanges();

var courses = new Course[]


{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID
},
new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 1045, Title = "Calculus", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 2021, Title = "Composition", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
new Course {CourseID = 2042, Title = "Literature", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
};

foreach (Course c in courses)


{
context.Courses.Add(c);
}
context.SaveChanges();

var officeAssignments = new OfficeAssignment[]


{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
Location = "Thompson 304" },
};

foreach (OfficeAssignment o in officeAssignments)


{
context.OfficeAssignments.Add(o);
}
context.SaveChanges();

var courseInstructors = new CourseAssignment[]


{
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Kapoor").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Fakhouri").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Literature" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
};

foreach (CourseAssignment ci in courseInstructors)


{
context.CourseAssignments.Add(ci);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").ID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").ID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
};

foreach (Enrollment e in enrollments)


{
var enrollmentInDataBase = context.Enrollment.Where(
s =>
s.Student.ID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollment.Add(e);
}
}
context.SaveChanges();
}
}
}

Yukarıdaki kod, yeni varlıklar için tohum verileri sağlar. Bu kodun çoğu yeni varlık nesneleri oluşturur ve örnek
verileri yükler. Örnek veriler test için kullanılır. Çoktan çoğa ekleme tablolarının nasıl çalıştırılabilir olduğunu
gösteren örnekler için Enrollments ve CourseAssignments bakın.

Geçiş Ekle
Projeyi oluşturun.
Visual Studio
Visual Studio Code

Add-Migration ComplexDataModel

Yukarıdaki komut, olası veri kaybı hakkında bir uyarı görüntüler.

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.
Done. To undo this action, use 'ef migrations remove'

database update komutu çalıştırıldıysanız aşağıdaki hata oluşturulur:

The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Course_dbo.Department_DepartmentID". The conflict occurred in
database "ContosoUniversity", table "dbo.Department", column 'DepartmentID'.
Geçişi Uygula
Artık var olan bir veritabanınız olduğuna göre, bundan sonraki değişikliklere nasıl uygulanacağını düşünmeniz
gerekir. Bu öğreticide iki yaklaşım gösterilmektedir:
Veritabanını bırakıp yeniden oluşturun
Geçişi mevcut veritabanına uygulayın. Bu yöntem daha karmaşıktır ve zaman alabilir. Bu, gerçek dünyada üretim
ortamları için tercih edilen yaklaşımdır. Note: Bu, öğreticinin isteğe bağlı bir bölümüdür. Bırakma ve yeniden
oluşturma adımlarını gerçekleştirebilir ve bu bölümü atlayabilirsiniz. Bu bölümdeki adımları izlemek isterseniz,
bırakma ve yeniden oluşturma adımlarını yapmayın.
Veritabanını bırakıp yeniden oluşturun
Güncelleştirilmiş DbInitializer kod, yeni varlıklar için tohum verileri ekler. Yeni bir VERITABANı oluşturmak için
EF Core zorlamak için DB 'yi bırakıp güncelleştirin:
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Drop-Database
Update-Database

Yardım bilgileri almak için PMC 'ten Get-Help about_EntityFrameworkCore çalıştırın.


Uygulamayı çalıştırın. Uygulamayı çalıştırmak DbInitializer.Initialize yöntemini çalıştırır.
DbInitializer.Initialize yeni DB 'yi doldurur.

VERITABANıNı SSOX içinde açın:


Daha önce SSOX açıldıysa Yenile düğmesine tıklayın.
Genişletin tabloları düğümü. Oluşturulan tablolar görüntülenir.

Courseatama tablosunu inceleyin:


Courseatama tablosuna sağ tıklayın ve verileri görüntüle' yi seçin.
Courseatama tablosunun veri içerdiğini doğrulayın.
Geçişi mevcut veritabanına Uygula
Bu bölüm isteğe bağlıdır. Bu adımlar yalnızca önceki bırakma ve veritabanını yeniden oluşturma bölümünü
atladıysanız çalışır.
Geçişler mevcut verilerle çalıştırıldığında, mevcut verilerin karşılanmadığı FK kısıtlamalar olabilir. Üretim verileriyle,
mevcut verilerin geçirilmesi için adımların alınması gerekir. Bu bölüm, FK kısıtlama ihlallerinin düzeltilmesiyle bir
örnek sağlar. Bu kod değişikliklerini yedekleme olmadan yapmayın. Önceki bölümü tamamlayıp veritabanını
güncelleştirdiyseniz, bu kod değişikliklerini yapmayın.
{Timestamp } _ComplexDataModel. cs dosyası aşağıdaki kodu içerir:

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
type: "int",
nullable: false,
defaultValue: 0);

Yukarıdaki kod Course tabloya null atanamaz DepartmentID FK ekler. Önceki öğreticideki VERITABANı Course
satırları içerir, böylece tablo geçişler tarafından güncelleştirilemez.
ComplexDataModel geçişinin mevcut verilerle çalışmasını sağlamak için:
Yeni sütuna ( DepartmentID ) varsayılan değer vermek için kodu değiştirin.
Varsayılan departman olarak davranacak "Temp" adlı sahte bir departman oluşturun.
Yabancı anahtar kısıtlamalarını çözme
ComplexDataModel sınıfları Up yöntemini güncelleştirin:
{Timestamp } _ComplexDataModel. cs dosyasını açın.
DepartmentID sütununu Course tablosuna ekleyen kod satırını açıklama satırı yapın.
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldNullable: true);

//migrationBuilder.AddColumn<int>(
// name: "DepartmentID",
// table: "Course",
// nullable: false,
// defaultValue: 0);

Aşağıdaki vurgulanmış kodu ekleyin. Yeni kod .CreateTable( name: "Department" bloğundan sonra geçer:

migrationBuilder.CreateTable(
name: "Department",
columns: table => new
{
DepartmentID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Budget = table.Column<decimal>(type: "money", nullable: false),
InstructorID = table.Column<int>(type: "int", nullable: true),
Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
StartDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Department", x => x.DepartmentID);
table.ForeignKey(
name: "FK_Department_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});

migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1);

Önceki değişikliklerle, ComplexDataModel Up yöntemi çalıştıktan sonra mevcut Course satırları "geçici"
departmanıyla ilişkilendirilir.
Bir üretim uygulaması şöyle olacaktır:
Yeni Department satırlarına Department satırları ve ilgili Course satırlarını eklemek için kod veya komut
dosyaları ekleyin.
"Geçici" Departmanı veya Course.DepartmentID için varsayılan değeri kullanmayın.

Sonraki öğreticide ilgili veriler ele alınmaktadır.

Ek kaynaklar
Bu öğreticinin YouTube sürümü (Bölüm 1)
Bu öğreticinin YouTube sürümü (Bölüm 2)

ÖN CEKI İL E R I
ASP.NET Core EF Core ile Razor Pages-Ilgili verileri
oku-6/8
23.11.2019 • 42 minutes to read • Edit Online

, Tom Dykstra, Jon P Smithve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, ilgili verilerin nasıl okunacağı ve görüntüleneceği gösterilmektedir. İlgili veriler, EF Core gezinti
özelliklerine yüklediği veri.
Aşağıdaki çizimler, Bu öğreticinin tamamlanan sayfalarını göstermektedir:
Eager, açık ve yavaş yükleme
EF Core bir varlığın gezinti özelliklerine ilgili verileri yükleyebilmenin birkaç yolu vardır:
Eager yükleniyor. Ekip yükleme, bir varlık türü için bir sorgu aynı zamanda ilgili varlıkları de yüklediğinde
oluşur. Bir varlık okunmadığınızda ilgili veriler alınır. Bu, genellikle gereken tüm verileri alan tek bir JOIN
sorgusuna neden olur. EF Core, bazı Eager yükleme türleri için birden çok sorgu yayımlayacak. Birden çok
sorgu verme, çok büyük paketlerini tek sorgusundan daha verimli olabilir. Include ve ThenInclude
yöntemleriyle Eager yüklemesi belirtildi.

Bir koleksiyon gezintisi eklendiğinde Eager yüklemesi birden çok sorgu gönderir:
Ana sorgu için bir sorgu
Yükleme ağacındaki her koleksiyon "Edge" için bir sorgu.
Sorguları Load ile ayırın: veriler ayrı sorgularda alınabilir ve EF Core "düzeltmeler" ' i "düzeltir".
"Düzeltmeler", EF Core gezinti özelliklerini otomatik olarak dolduran anlamına gelir. Load ile ayrı sorgular,
ek yükleme Eager 'dan daha da benzer.

Note: EF Core, daha önce bağlam örneğine yüklenmiş olan diğer varlıklar için gezinti özelliklerini otomatik
olarak düzeltir. Bir gezinti özelliği için veriler açıkça dahil edilmese bile, ilgili varlıkların bazıları veya tümü
daha önce yüklenmişse Özellik yine de doldurulabilir.
Açık yükleme. Varlık ilk kez okunmadıysa ilgili veriler alınmadı. Gerektiğinde ilgili verileri almak için kodun
yazılması gerekir. Ayrı sorgularla açık yükleme, veritabanına birden çok sorgu gönderilmesine neden olur.
Açık yükleme ile kod, yüklenecek gezinti özelliklerini belirtir. Açık yükleme yapmak için Load yöntemini
kullanın. Örneğin:

Yavaş yükleme. Sürüm 2,1 ' de EF Core geç yükleme eklendi. Varlık ilk kez okunmadıysa ilgili veriler
alınmadı. Gezinti özelliğine ilk kez erişildiğinde, bu gezinti özelliği için gereken veriler otomatik olarak alınır.
Bir gezinti özelliğine ilk kez erişildiğinde bir sorgu veritabanına gönderilir.

Kurs sayfaları oluşturma


Course varlığı, ilgili Department varlığını içeren bir gezinti özelliği içerir.
Bir kurs için atanan departmanın adını göstermek için:
İlgili Department varlığını Course.Department gezinti özelliğine yükleyin.
Department varlığın Name özelliğinden adı alın.
Yapı iskelesi kurs sayfaları
Visual Studio
Visual Studio Code
Aşağıdaki özel durumlarla birlikte Yapı Fkatlama öğrenci sayfalarındaki yönergeleri izleyin:
Bir Sayfalar/kurslar klasörü oluşturun.
Model sınıfı için Course kullanın.
Yeni bir tane oluşturmak yerine var olan bağlam sınıfını kullanın.
Pages/kurslar/Index. cshtml. cs dosyasını açın ve OnGetAsync metodunu inceleyin. Yapı iskelesi altyapısı,
Department gezinti özelliği için bir yükleme belirtti. Include yöntemi Eager yüklemeyi belirtir.

Uygulamayı çalıştırın ve Kurslar bağlantısını seçin. Departman sütunu, yararlı olmayan DepartmentID
görüntüler.
Departmanın adını görüntüleme
Pages/kurslar/Index. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class IndexModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public IndexModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public IList<Course> Courses { get; set; }

public async Task OnGetAsync()


{
Courses = await _context.Courses
.Include(c => c.Department)
.AsNoTracking()
.ToListAsync();
}
}
}

Yukarıdaki kod Course özelliğini Courses olarak değiştirir ve AsNoTracking ekler. AsNoTracking , döndürülen
varlıklar izlenmediğinden performansı geliştirir. Varlıkların geçerli bağlamda güncelleştirilmediği için izlenmesi
gerekmez.
Pages/kurslar/Index. cshtml 'yi aşağıdaki kodla güncelleştirin.
@page
@model ContosoUniversity.Pages.Courses.IndexModel

@{
ViewData["Title"] = "Courses";
}

<h1>Courses</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Courses[0].CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Courses[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Courses[0].Credits)
</th>
<th>
@Html.DisplayNameFor(model => model.Courses[0].Department)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Courses)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.CourseID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.CourseID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.CourseID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yapı iskelesi kodunda aşağıdaki değişiklikler yapılmıştır:


Course Özellik adı Courses olarak değiştirildi.
CourseID özellik değerini gösteren bir sayı sütunu eklendi. Birincil anahtarlar, genellikle son kullanıcılara
anlamlı olduklarından, varsayılan olarak yapı iskelesi göstermemektedir. Ancak, bu durumda birincil anahtar
anlamlı olur.
Departman adını göstermek için Departman sütunu değiştirildi. Kod, Department gezinti özelliğine
yüklenen Department varlığının Name özelliğini görüntüler:

@Html.DisplayFor(modelItem => item.Department.Name)

Uygulamayı çalıştırın ve bölüm adlarıyla listeyi görmek için Kurslar sekmesini seçin.

Select ile ilgili verileri yükleme


OnGetAsync yöntemi, Include yöntemiyle ilgili verileri yükler. Select yöntemi, yalnızca gerekli ilgili verileri
yükleyen bir alternatiftir. Tek öğeler için, Department.Name gibi bir SQL Iç BIRLEŞIMI kullanır. Koleksiyonlar için,
başka bir veritabanı erişimi kullanır, ancak koleksiyonlar üzerinde Include işleci olur.
Aşağıdaki kod Select yöntemiyle ilgili verileri yükler:

public IList<CourseViewModel> CourseVM { get; set; }

public async Task OnGetAsync()


{
CourseVM = await _context.Courses
.Select(p => new CourseViewModel
{
CourseID = p.CourseID,
Title = p.Title,
Credits = p.Credits,
DepartmentName = p.Department.Name
}).ToListAsync();
}

CourseViewModel :

public class CourseViewModel


{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public string DepartmentName { get; set; }
}

Tüm örnek için bkz. ındexselect. cshtml ve IndexSelect.cshtml.cs .

Eğitmen sayfaları oluşturma


Bu bölüm, eğitmen sayfalarını derler ve ilgili Kurslar ve kayıtları eğitmenler dizin sayfasına ekler.

Bu sayfa aşağıdaki yollarla ilgili verileri okur ve görüntüler:


Eğitmenler listesi OfficeAssignment varlığındaki ilgili verileri (önceki görüntüde Office) görüntüler. Instructor
ve OfficeAssignment varlıkları bire sıfır veya-bir ilişkidir. OfficeAssignment varlıkları için Eager yüklemesi
kullanılır. Eager yüklemesi, ilgili verilerin görüntülenmesi gerektiğinde genellikle daha etkilidir. Bu durumda,
Eğitmenler için Office atamaları görüntülenir.
Kullanıcı bir eğitmen seçtiğinde ilgili Course varlıkları görüntülenir. Instructor ve Course varlıkları çoktan
çoğa bir ilişkidir. Eager yüklemesi, Course varlıkları ve ilgili Department varlıkları için kullanılır. Bu durumda,
yalnızca seçili eğitmen için kurslar gerektiğinden ayrı sorgular daha verimli olabilir. Bu örnek, gezinti
özelliklerinde olan varlıklarda gezinti özellikleri için Eager yükleme 'nin nasıl kullanılacağını gösterir.
Kullanıcı bir kurs seçtiğinde Enrollments varlığındaki ilgili veriler görüntülenir. Önceki görüntüde öğrenci adı ve
sınıf görüntülenir. Course ve Enrollment varlıkları bire çok ilişkidir.
Görünüm modeli oluşturma
Eğitmenler sayfasında, üç farklı tablodan alınan veriler gösterilir. Üç tabloyu temsil eden üç özellik içeren bir
görünüm modeli gerekir.
Aşağıdaki kodla SchoolViewModels/ıncpctorındexdata. cs oluşturun:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
}

Yapı iskelesi eğitmeni sayfaları


Visual Studio
Visual Studio Code
Öğrenci sayfalarını aşağıdaki özel durumlarla birlikte Scaffold içindeki yönergeleri izleyin:
Bir sayfa/eğitmenler klasörü oluşturun.
Model sınıfı için Instructor kullanın.
Yeni bir tane oluşturmak yerine var olan bağlam sınıfını kullanın.
Yapı iskelesi sayfasının güncelleştirmeden önce nasıl göründüğünü görmek için, uygulamayı çalıştırın ve eğitmenler
sayfasına gidin.
Pages/eğitmenler/Index. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels; // Add VM
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class IndexModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public IndexModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public InstructorIndexData InstructorData { get; set; }


public int InstructorID { get; set; }
public int CourseID { get; set; }

public async Task OnGetAsync(int? id, int? courseID)


{
InstructorData = new InstructorIndexData();
InstructorData.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = InstructorData.Instructors
.Where(i => i.ID == id.Value).Single();
InstructorData.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
var selectedCourse = InstructorData.Courses
.Where(x => x.CourseID == courseID).Single();
InstructorData.Enrollments = selectedCourse.Enrollments;
}
}
}
}

OnGetAsync yöntemi, seçilen eğitmenin KIMLIĞI için isteğe bağlı rota verilerini kabul eder.
Pages/eğitmenler/Index. cshtml. cs dosyasındaki sorguyu inceleyin:
InstructorData.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Kod, aşağıdaki gezinti özellikleri için Eager yüklemeyi belirtir:


Instructor.OfficeAssignment
Instructor.CourseAssignments
CourseAssignments.Course
Course.Department
Course.Enrollments
Enrollment.Student

CourseAssignments ve Course için Include ve ThenInclude yöntemlerinin yinelendiğine dikkat edin. Bu yineleme,
Course varlığının iki gezinti özelliği için Eager yüklemesi belirtmek için gereklidir.
Aşağıdaki kod, bir eğitmen seçildiğinde ( id != null ) yürütülür.

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = InstructorData.Instructors
.Where(i => i.ID == id.Value).Single();
InstructorData.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

Seçilen eğitmen, görünüm modelindeki eğitmenler listesinden alınır. Görünüm modelinin Courses özelliği, bu
eğitmenin CourseAssignments gezinti özelliğinden Course varlıklarla birlikte yüklenir.
Where yöntemi bir koleksiyon döndürür. Ancak bu durumda filtre tek bir varlık seçer. Bu nedenle, koleksiyonu tek
bir Instructor varlığına dönüştürmek için Single yöntemi çağırılır. Instructor varlığı CourseAssignments
özelliğine erişim sağlar. CourseAssignments ilgili Course varlıklarına erişim sağlar.
Koleksiyonda yalnızca bir öğe olduğunda Single yöntemi bir koleksiyonda kullanılır. Koleksiyon boşsa veya birden
fazla öğe varsa Single yöntemi bir özel durum oluşturur. Bir alternatif, koleksiyon boşsa varsayılan bir değer (Bu
durumda null) döndüren SingleOrDefault .
Aşağıdaki kod, bir kurs seçildiğinde görünüm modelinin Enrollments özelliğini doldurur:

if (courseID != null)
{
CourseID = courseID.Value;
var selectedCourse = InstructorData.Courses
.Where(x => x.CourseID == courseID).Single();
InstructorData.Enrollments = selectedCourse.Enrollments;
}

Eğitmenler Dizin sayfasını Güncelleştir


Pages/eğitmenler/Index. cshtml dosyasını aşağıdaki kodla güncelleştirin.

@page "{id:int?}"
@model ContosoUniversity.Pages.Instructors.IndexModel

@{
ViewData["Title"] = "Instructors";
}

<h2>Instructors</h2>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th>Courses</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.InstructorData.Instructors)
{
string selectedRow = "";
if (item.ID == Model.InstructorID)
{
selectedRow = "table-success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@if (item.OfficeAssignment != null)
{
@item.OfficeAssignment.Location
}
</td>
<td>
@{
foreach (var course in item.CourseAssignments)
{
@course.Course.CourseID @: @course.Course.Title <br />
}
}
</td>
<td>
<a asp-page="./Index" asp-route-id="@item.ID">Select</a> |
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@if (Model.InstructorData.Courses != null)


{
<h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th></th>
<th>Number</th>
<th>Title</th>
<th>Department</th>
</tr>

@foreach (var item in Model.InstructorData.Courses)


{
string selectedRow = "";
if (item.CourseID == Model.CourseID)
{
selectedRow = "table-success";
}
<tr class="@selectedRow">
<td>
<td>
<a asp-page="./Index" asp-route-courseID="@item.CourseID">Select</a>
</td>
<td>
@item.CourseID
</td>
<td>
@item.Title
</td>
<td>
@item.Department.Name
</td>
</tr>
}

</table>
}

@if (Model.InstructorData.Enrollments != null)


{
<h3>
Students Enrolled in Selected Course
</h3>
<table class="table">
<tr>
<th>Name</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.InstructorData.Enrollments)
{
<tr>
<td>
@item.Student.FullName
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
}

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


Güncelleştirmeleri page gelen yönerge @page için @page "{id:int?}" . "{id:int?}" bir rota şablonudur. Yol
şablonu, verileri yönlendirmek için URL 'deki tamsayı Sorgu dizelerini değiştirir. Örneğin, yalnızca @page
yönergesine sahip bir eğitmenin Select bağlantısına tıkladığınızda aşağıdakiler gıbı bir URL üretilir:
https://localhost:5001/Instructors?id=2

Sayfa yönergesi @page "{id:int?}" olduğunda URL şu şekilde olur:


https://localhost:5001/Instructors/2

Yalnızca item.OfficeAssignment null olmaması durumunda item.OfficeAssignment.Location görüntüleyen bir


Office sütunu ekler. Bu bire sıfır veya-bir ilişki olduğundan ilgili bir OfficeAssignment varlığı bulunmayabilir.

@if (item.OfficeAssignment != null)


{
@item.OfficeAssignment.Location
}

Her bir eğitmen tarafından taders kurslarını görüntüleyen bir Kurslar sütunu ekler. Bu Razor sözdizimi
hakkında daha fazla bilgi için bkz. açık hat geçişi .
Seçilen eğitmenin ve kursun tr öğesine dinamik olarak class="success" ekleyen kodu ekler. Bu, bir
önyükleme sınıfı kullanarak seçili satır için bir arka plan rengi ayarlar.

string selectedRow = "";


if (item.CourseID == Model.CourseID)
{
selectedRow = "success";
}
<tr class="@selectedRow">

Selectetiketli yeni bir köprü ekler. Bu bağlantı, seçilen eğitmenin KIMLIĞINI Index yöntemine gönderir ve
bir arka plan rengi ayarlar.

<a asp-action="Index" asp-route-id="@item.ID">Select</a> |

Seçili eğitmen için bir kurs tablosu ekler.


Seçili kurs için bir öğrenci kayıtları tablosu ekler.
Uygulamayı çalıştırın ve eğitmenler sekmesini seçin. Sayfada ilgili OfficeAssignment varlığındaki Location
(Office) görüntülenir. OfficeAssignment null ise boş bir tablo hücresi görüntülenir.
Bir eğitmenin Seç bağlantısına tıklayın. Bu eğitmenin atandığı satır stili değişiklikleri ve kurslar görüntülenir.
Kayıtlı öğrenciler ve bunların onların listesini görmek için bir kurs seçin.
Tek kullanımı
Single yöntemi, Where yöntemini ayrı çağırmak yerine Where koşulunu geçirebilir:
public async Task OnGetAsync(int? id, int? courseID)
{
InstructorData = new InstructorIndexData();

InstructorData.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = InstructorData.Instructors.Single(
i => i.ID == id.Value);
InstructorData.Courses = instructor.CourseAssignments.Select(
s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
InstructorData.Enrollments = InstructorData.Courses.Single(
x => x.CourseID == courseID).Enrollments;
}
}

Where koşulunun kişisel tercihle ilgili olduğu Single kullanımı. Where yöntemi kullanılarak herhangi bir avantaj
sağlamaz.

Açık yükleme
Geçerli kod Enrollments ve Students için Eager yüklemeyi belirtir:

InstructorData.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Kullanıcıların bir kursa kayıtları nadiren görmek istediğini varsayalım. Bu durumda, bir iyileştirme yalnızca
isteniyorsa kayıt verilerini yüklemek olacaktır. Bu bölümde OnGetAsync , Enrollments ve Students açık yüklemesini
kullanacak şekilde güncelleştirilir.
Pages/eğitmenler/Index. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin.
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels; // Add VM
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class IndexModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public IndexModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public InstructorIndexData InstructorData { get; set; }


public int InstructorID { get; set; }
public int CourseID { get; set; }

public async Task OnGetAsync(int? id, int? courseID)


{
InstructorData = new InstructorIndexData();
InstructorData.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
//.Include(i => i.CourseAssignments)
// .ThenInclude(i => i.Course)
// .ThenInclude(i => i.Enrollments)
// .ThenInclude(i => i.Student)
//.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = InstructorData.Instructors
.Where(i => i.ID == id.Value).Single();
InstructorData.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
var selectedCourse = InstructorData.Courses
.Where(x => x.CourseID == courseID).Single();
await _context.Entry(selectedCourse).Collection(x => x.Enrollments).LoadAsync();
foreach (Enrollment enrollment in selectedCourse.Enrollments)
{
await _context.Entry(enrollment).Reference(x => x.Student).LoadAsync();
}
InstructorData.Enrollments = selectedCourse.Enrollments;
}
}
}
}

Yukarıdaki kod, kayıt ve öğrenci verileri için Thenınclude Yöntem çağrılarını bırakır. Bir kurs seçilirse, açık yükleme
kodu alır:
Seçili kurs için Enrollment varlıkları.
Her bir Enrollment için Student varlıkları.
Yukarıdaki kod yorumlarının .AsNoTracking() dikkat edin. Gezinti özellikleri yalnızca izlenen varlıklar için açık bir
şekilde yüklenebilir.
Uygulamayı test edin. Bir kullanıcının perspektifinden, uygulama önceki sürümle aynı şekilde davranır.

Sonraki adımlar
Sonraki öğreticide ilgili verileri güncelleştirme gösterilmektedir.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide ilgili veriler okundu ve görüntülenir. İlgili veriler, EF Core gezinti özelliklerine yüklediği veri.
Olamaz çözmenize, sorunlarla karşılaşırsanız, indirin veya tamamlanmış uygulamayı görüntüleyin. Yükleme
yönergeleri.
Aşağıdaki çizimler, Bu öğreticinin tamamlanan sayfalarını göstermektedir:
İlgili verilerin Eager, açık ve geç yüklemesi
EF Core bir varlığın gezinti özelliklerine ilgili verileri yükleyebilmenin birkaç yolu vardır:
Eager yükleniyor. Ekip yükleme, bir varlık türü için bir sorgu aynı zamanda ilgili varlıkları de yüklediğinde
oluşur. Varlık okunmadığınızda ilgili veriler alınır. Bu, genellikle gereken tüm verileri alan tek bir JOIN
sorgusuna neden olur. EF Core, bazı Eager yükleme türleri için birden çok sorgu yayımlayacak. Birden çok
sorgu verilmesi, EF6 içindeki bazı sorgular için tek bir sorgunun bulunduğu durumda daha verimli olabilir.
Include ve ThenInclude yöntemleriyle Eager yüklemesi belirtildi.

Bir koleksiyon gezintisi eklendiğinde Eager yüklemesi birden çok sorgu gönderir:
Ana sorgu için bir sorgu
Yükleme ağacındaki her koleksiyon "Edge" için bir sorgu.
Sorguları Load ile ayırın: veriler ayrı sorgularda alınabilir ve EF Core "düzeltmeler" ' i "düzeltir".
"düzeltmeler", EF Core gezinti özelliklerini otomatik olarak dolduran anlamına gelir. Load ile ayrı sorgular, ek
yükleme Eager 'dan daha da benzer.

Note: EF Core, daha önce bağlam örneğine yüklenmiş olan diğer varlıklar için gezinti özelliklerini otomatik
olarak düzeltir. Bir gezinti özelliği için veriler açıkça dahil edilmese bile, ilgili varlıkların bazıları veya tümü
daha önce yüklenmişse Özellik yine de doldurulabilir.
Açık yükleme. Varlık ilk kez okunmadıysa ilgili veriler alınmadı. Gerektiğinde ilgili verileri almak için kodun
yazılması gerekir. Ayrı sorgularla açık yükleme, VERITABANıNA birden çok sorgu gönderilmesine neden
olur. Açık yükleme ile kod, yüklenecek gezinti özelliklerini belirtir. Açık yükleme yapmak için Load yöntemini
kullanın. Örneğin:

Yavaş yükleme. Sürüm 2,1 ' de EF Core geç yükleme eklendi. Varlık ilk kez okunmadıysa ilgili veriler
alınmadı. Gezinti özelliğine ilk kez erişildiğinde, bu gezinti özelliği için gereken veriler otomatik olarak alınır.
Bir gezinti özelliğine ilk kez erişildiğinde bir sorgu VERITABANıNA gönderilir.
Select işleci yalnızca gerekli ilgili verileri yükler.

Bölüm adını görüntüleyen bir kurs sayfası oluşturma


Kurs varlığı, Department varlığını içeren bir gezinti özelliği içerir. Department varlığı, kursun atandığı departmanı
içerir.
Bir kurs listesinde atanan departmanın adını göstermek için:
Department varlığındaki Name özelliğini alın.
Department varlık Course.Department gezinti özelliğinden gelir.
Kurs modelini temklesi
Visual Studio
Visual Studio Code
Bölümündeki yönergeleri Öğrenci modeli iskelesini ve Course model sınıfı için.
Önceki komut iskelesini kurar Course modeli. Projeyi Visual Studio'da açın.
Pages/kurslar/Index. cshtml. cs dosyasını açın ve OnGetAsync metodunu inceleyin. Yapı iskelesi altyapısı,
Department gezinti özelliği için bir yükleme belirtti. Include yöntemi Eager yüklemeyi belirtir.

Uygulamayı çalıştırın ve Kurslar bağlantısını seçin. Departman sütunu, yararlı olmayan DepartmentID görüntüler.
OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
Course = await _context.Courses
.Include(c => c.Department)
.AsNoTracking()
.ToListAsync();
}

Yukarıdaki kod AsNoTracking ekler. AsNoTracking , döndürülen varlıklar izlenmediğinden performansı geliştirir.
Geçerli bağlamda güncelleştirilmemiş oldukları için varlıklar izlenmiyor.
Pages/kurslar/Index. cshtml 'yi aşağıdaki vurgulanmış işaretlerle güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.IndexModel
@{
ViewData["Title"] = "Courses";
}

<h2>Courses</h2>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Course[0].CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Course[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Course[0].Credits)
</th>
<th>
@Html.DisplayNameFor(model => model.Course[0].Department)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Course)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.CourseID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.CourseID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.CourseID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yapı iskelesi kodunda aşağıdaki değişiklikler yapılmıştır:


Başlık dizinden kurslar olarak değiştirildi.
CourseID özellik değerini gösteren bir sayı sütunu eklendi. Birincil anahtarlar, genellikle son kullanıcılara
anlamlı olduklarından, varsayılan olarak yapı iskelesi göstermemektedir. Ancak, bu durumda birincil anahtar
anlamlı olur.
Departman adını göstermek için Departman sütunu değiştirildi. Kod, Department gezinti özelliğine
yüklenen Department varlığının Name özelliğini görüntüler:
@Html.DisplayFor(modelItem => item.Department.Name)

Uygulamayı çalıştırın ve bölüm adlarıyla listeyi görmek için Kurslar sekmesini seçin.

Select ile ilgili verileri yükleme


OnGetAsync yöntemi Include yöntemiyle ilgili verileri yükler:

public async Task OnGetAsync()


{
Course = await _context.Courses
.Include(c => c.Department)
.AsNoTracking()
.ToListAsync();
}

Select işleci yalnızca gerekli ilgili verileri yükler. Tek öğeler için, Department.Name gibi bir SQL Iç BIRLEŞIMI
kullanır. Koleksiyonlar için, başka bir veritabanı erişimi kullanır, ancak koleksiyonlar üzerinde Include işleci olur.
Aşağıdaki kod Select yöntemiyle ilgili verileri yükler:

public IList<CourseViewModel> CourseVM { get; set; }

public async Task OnGetAsync()


{
CourseVM = await _context.Courses
.Select(p => new CourseViewModel
{
CourseID = p.CourseID,
Title = p.Title,
Credits = p.Credits,
DepartmentName = p.Department.Name
}).ToListAsync();
}

CourseViewModel :
public class CourseViewModel
{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public string DepartmentName { get; set; }
}

Tüm örnek için bkz. ındexselect. cshtml ve IndexSelect.cshtml.cs .

Kurslar ve kayıtları gösteren bir eğitmenler sayfası oluşturun


Bu bölümde, Eğitmenler sayfası oluşturulur.
Bu sayfa aşağıdaki yollarla ilgili verileri okur ve görüntüler:
Eğitmenler listesi OfficeAssignment varlığındaki ilgili verileri (önceki görüntüde Office) görüntüler. Instructor
ve OfficeAssignment varlıkları bire sıfır veya-bir ilişkidir. OfficeAssignment varlıkları için Eager yüklemesi
kullanılır. Eager yüklemesi, ilgili verilerin görüntülenmesi gerektiğinde genellikle daha etkilidir. Bu durumda,
Eğitmenler için Office atamaları görüntülenir.
Kullanıcı bir eğitmen (önceki görüntüde Haruı) seçtiğinde ilgili Course varlıkları görüntülenir. Instructor ve
Course varlıkları çoktan çoğa bir ilişkidir. Eager yüklemesi, Course varlıkları ve ilgili Department varlıkları için
kullanılır. Bu durumda, yalnızca seçili eğitmen için kurslar gerektiğinden ayrı sorgular daha verimli olabilir. Bu
örnek, gezinti özelliklerinde olan varlıklarda gezinti özellikleri için Eager yükleme 'nin nasıl kullanılacağını
gösterir.
Kullanıcı bir kurs seçtiğinde (önceki görüntüde kimsiz deneme), Enrollments varlığındaki ilgili veriler
görüntülenir. Önceki görüntüde öğrenci adı ve sınıf görüntülenir. Course ve Enrollment varlıkları bire çok
ilişkidir.
Eğitmen dizini görünümü için bir görünüm modeli oluşturun
Eğitmenler sayfasında, üç farklı tablodan alınan veriler gösterilir. Üç tabloyu temsil eden üç varlığı içeren bir
görünüm modeli oluşturulur.
SchoolViewModels klasöründe, aşağıdaki kodla InstructorIndexData.cs oluşturun:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
}

Eğitmen modelini scafkatlama


Visual Studio
Visual Studio Code
Bölümündeki yönergeleri Öğrenci modeli iskelesini ve Instructor model sınıfı için.
Önceki komut iskelesini kurar Instructor modeli. Uygulamayı çalıştırın ve eğitmenler sayfasına gidin.
Pages/eğitmenler/Index. cshtml. cs öğesini şu kodla değiştirin:
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels; // Add VM
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class IndexModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public IndexModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public InstructorIndexData Instructor { get; set; }


public int InstructorID { get; set; }

public async Task OnGetAsync(int? id)


{
Instructor = new InstructorIndexData();
Instructor.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
}
}
}
}

OnGetAsync yöntemi, seçilen eğitmenin KIMLIĞI için isteğe bağlı rota verilerini kabul eder.
Pages/eğitmenler/Index. cshtml. cs dosyasındaki sorguyu inceleyin:

Instructor.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Sorgunun iki içerme vardır:


OfficeAssignment : eğitmenler görünümündegörüntülenir.
CourseAssignments : kurslar taöğretme.

Eğitmenler Dizin sayfasını Güncelleştir


Sayfaları/eğitmenler/Index. cshtml 'yi şu biçimlendirmeyle güncelleştirin:
@page "{id:int?}"
@model ContosoUniversity.Pages.Instructors.IndexModel

@{
ViewData["Title"] = "Instructors";
}

<h2>Instructors</h2>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th>Courses</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Instructor.Instructors)
{
string selectedRow = "";
if (item.ID == Model.InstructorID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@if (item.OfficeAssignment != null)
{
@item.OfficeAssignment.Location
}
</td>
<td>
@{
foreach (var course in item.CourseAssignments)
{
@course.Course.CourseID @: @course.Course.Title <br />
}
}
</td>
<td>
<a asp-page="./Index" asp-route-id="@item.ID">Select</a> |
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Önceki biçimlendirme, aşağıdaki değişiklikleri yapar:
Güncelleştirmeleri page gelen yönerge @page için @page "{id:int?}" . "{id:int?}" bir rota şablonudur. Yol
şablonu, verileri yönlendirmek için URL 'deki tamsayı Sorgu dizelerini değiştirir. Örneğin, yalnızca @page
yönergesine sahip bir eğitmenin Select bağlantısına tıkladığınızda aşağıdakiler gıbı bir URL üretilir:
http://localhost:1234/Instructors?id=2

Sayfa yönergesi @page "{id:int?}" olduğunda, önceki URL şu şekilde olur:


http://localhost:1234/Instructors/2

Sayfa başlığı eğitmenler' dir.


Yalnızca item.OfficeAssignment null olmaması durumunda item.OfficeAssignment.Location görüntüleyen bir
Office sütunu eklendi. Bu bire sıfır veya-bir ilişki olduğundan ilgili bir OfficeAssignment varlığı
bulunmayabilir.

@if (item.OfficeAssignment != null)


{
@item.OfficeAssignment.Location
}

Her bir eğitmen tarafından taders kurslarını görüntüleyen bir Kurslar sütunu eklendi. Bu Razor sözdizimi
hakkında daha fazla bilgi için bkz. açık hat geçişi .
Seçilen eğitmenin tr öğesine dinamik olarak class="success" ekleyen kod eklendi. Bu, bir önyükleme sınıfı
kullanarak seçili satır için bir arka plan rengi ayarlar.

string selectedRow = "";


if (item.CourseID == Model.CourseID)
{
selectedRow = "success";
}
<tr class="@selectedRow">

Selectetiketli yeni bir köprü eklendi. Bu bağlantı, seçilen eğitmenin KIMLIĞINI Index yöntemine gönderir
ve bir arka plan rengi ayarlar.

<a asp-action="Index" asp-route-id="@item.ID">Select</a> |

Uygulamayı çalıştırın ve eğitmenler sekmesini seçin. Sayfada ilgili OfficeAssignment varlığındaki Location
(Office) görüntülenir. Eğer OfficeAssignment ' null ise boş bir tablo hücresi görüntülenir.
Seç bağlantısına tıklayın. Satır stili değişir.
Seçili eğitmen 'e göre kurslar ekleyin
Pages/eğitmenler/Index. cshtml. cs dosyasındaki OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:
public async Task OnGetAsync(int? id, int? courseID)
{
Instructor = new InstructorIndexData();
Instructor.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = Instructor.Instructors.Where(
i => i.ID == id.Value).Single();
Instructor.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
Instructor.Enrollments = Instructor.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
}

public int CourseID { get; set; } Ekle


public class IndexModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public IndexModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public InstructorIndexData Instructor { get; set; }


public int InstructorID { get; set; }
public int CourseID { get; set; }

public async Task OnGetAsync(int? id, int? courseID)


{
Instructor = new InstructorIndexData();
Instructor.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = Instructor.Instructors.Where(
i => i.ID == id.Value).Single();
Instructor.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
Instructor.Enrollments = Instructor.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
}

Güncelleştirilmiş sorguyu inceleyin:

Instructor.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Yukarıdaki sorgu Department varlıklarını ekler.


Aşağıdaki kod, bir eğitmen seçildiğinde ( id != null ) yürütülür. Seçilen eğitmen, görünüm modelindeki eğitmenler
listesinden alınır. Görünüm modelinin Courses özelliği, bu eğitmenin CourseAssignments gezinti özelliğinden
Course varlıklarla birlikte yüklenir.
if (id != null)
{
InstructorID = id.Value;
Instructor instructor = Instructor.Instructors.Where(
i => i.ID == id.Value).Single();
Instructor.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

Where yöntemi bir koleksiyon döndürür. Önceki Where yönteminde yalnızca tek bir Instructor varlığı döndürülür.
Single yöntemi, koleksiyonu tek bir Instructor varlığına dönüştürür. Instructor varlığı CourseAssignments
özelliğine erişim sağlar. CourseAssignments ilgili Course varlıklarına erişim sağlar.

Koleksiyonda yalnızca bir öğe olduğunda Single yöntemi bir koleksiyonda kullanılır. Koleksiyon boşsa veya birden
fazla öğe varsa Single yöntemi bir özel durum oluşturur. Bir alternatif, koleksiyon boşsa varsayılan bir değer (Bu
durumda null) döndüren SingleOrDefault . Boş bir koleksiyonda SingleOrDefault kullanma:
Bir özel durumla sonuçlanır (null başvuru üzerinde Courses özelliği bulmaya çalışırken).
Özel durum iletisi sorunun nedenini daha az gösterir.
Aşağıdaki kod, bir kurs seçildiğinde görünüm modelinin Enrollments özelliğini doldurur:

if (courseID != null)
{
CourseID = courseID.Value;
Instructor.Enrollments = Instructor.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}

Pages/eğitmenler/Index. cshtml Razor sayfasının sonuna aşağıdaki biçimlendirmeyi ekleyin:


<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@if (Model.Instructor.Courses != null)


{
<h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th></th>
<th>Number</th>
<th>Title</th>
<th>Department</th>
</tr>

@foreach (var item in Model.Instructor.Courses)


{
string selectedRow = "";
if (item.CourseID == Model.CourseID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
<a asp-page="./Index" asp-route-courseID="@item.CourseID">Select</a>
</td>
<td>
@item.CourseID
</td>
<td>
@item.Title
</td>
<td>
@item.Department.Name
</td>
</tr>
}

</table>
}

Yukarıdaki biçimlendirme, bir eğitmen seçildiğinde bir eğitmenin ilgili kursların bir listesini görüntüler.
Uygulamayı test edin. Eğitmenler sayfasında bir seçme bağlantısına tıklayın.
Öğrenci verilerini göster
Bu bölümde, uygulama seçili bir kurs için öğrenci verilerini gösterecek şekilde güncelleştirilir.
Pages/eğitmenler/Index. cshtml. cs içindeki OnGetAsync yönteminde bulunan sorguyu aşağıdaki kodla
güncelleştirin:
Instructor.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Güncelleştirme sayfaları/eğitmenler/Index. cshtml. Aşağıdaki biçimlendirmeyi dosyanın sonuna ekleyin:

@if (Model.Instructor.Enrollments != null)


{
<h3>
Students Enrolled in Selected Course
</h3>
<table class="table">
<tr>
<th>Name</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Instructor.Enrollments)
{
<tr>
<td>
@item.Student.FullName
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
}

Yukarıdaki biçimlendirme, seçili kursa kayıtlı öğrencilerin bir listesini görüntüler.


Sayfayı yenileyin ve bir eğitmen seçin. Kayıtlı öğrenciler ve bunların onların listesini görmek için bir kurs seçin.
Tek kullanımı
Single yöntemi, Where yöntemini ayrı çağırmak yerine Where koşulunu geçirebilir:
public async Task OnGetAsync(int? id, int? courseID)
{
Instructor = new InstructorIndexData();

Instructor.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = Instructor.Instructors.Single(
i => i.ID == id.Value);
Instructor.Courses = instructor.CourseAssignments.Select(
s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
Instructor.Enrollments = Instructor.Courses.Single(
x => x.CourseID == courseID).Enrollments;
}
}

Yukarıdaki Single yaklaşım, Where kullanmaktan faydalanır. Bazı geliştiriciler Single yaklaşım stilini tercih eder.

Açık yükleme
Geçerli kod Enrollments ve Students için Eager yüklemeyi belirtir:

Instructor.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Kullanıcıların bir kursa kayıtları nadiren görmek istediğini varsayalım. Bu durumda, bir iyileştirme yalnızca
isteniyorsa kayıt verilerini yüklemek olacaktır. Bu bölümde OnGetAsync , Enrollments ve Students açık yüklemesini
kullanacak şekilde güncelleştirilir.
OnGetAsync aşağıdaki kodla güncelleştirin:
public async Task OnGetAsync(int? id, int? courseID)
{
Instructor = new InstructorIndexData();
Instructor.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
//.Include(i => i.CourseAssignments)
// .ThenInclude(i => i.Course)
// .ThenInclude(i => i.Enrollments)
// .ThenInclude(i => i.Student)
// .AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
InstructorID = id.Value;
Instructor instructor = Instructor.Instructors.Where(
i => i.ID == id.Value).Single();
Instructor.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
CourseID = courseID.Value;
var selectedCourse = Instructor.Courses.Where(x => x.CourseID == courseID).Single();
await _context.Entry(selectedCourse).Collection(x => x.Enrollments).LoadAsync();
foreach (Enrollment enrollment in selectedCourse.Enrollments)
{
await _context.Entry(enrollment).Reference(x => x.Student).LoadAsync();
}
Instructor.Enrollments = selectedCourse.Enrollments;
}
}

Yukarıdaki kod, kayıt ve öğrenci verileri için Thenınclude Yöntem çağrılarını bırakır. Bir kurs seçilirse vurgulanan kod
şunu alır:
Seçili kurs için Enrollment varlıkları.
Her bir Enrollment için Student varlıkları.
Yukarıdaki kod açıklamalarının .AsNoTracking() dikkat edin. Gezinti özellikleri yalnızca izlenen varlıklar için açık bir
şekilde yüklenebilir.
Uygulamayı test edin. Bir kullanıcının perspektifinden, uygulama önceki sürümle aynı şekilde davranır.
Sonraki öğreticide ilgili verileri güncelleştirme gösterilmektedir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü (part1)
Bu öğreticinin YouTube sürümü (part2)

ÖN CEKI İL E R I
ASP.NET Core ile EF Core Razor Pages-Ilgili verileri
güncelleştirme-7/8
20.08.2019 • 43 minutes to read • Edit Online

, Tom Dykstrave Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide ilgili verileri güncelleştirme gösterilmektedir. Aşağıdaki çizimler tamamlanan sayfalardan bazılarını
göstermektedir.
Kurs oluşturma ve düzenleme sayfalarını güncelleştirme
Kurs oluşturma ve düzenleme sayfaları için yapı iskelesi kodu, departman KIMLIĞI (tamsayı) gösteren bir
departman açılan listesi içerir. Açılan listede bölüm adı gösterilmeli, bu nedenle her iki sayfanın da bir departman
adları listesi olması gerekir. Bu listeyi sağlamak için, oluşturma ve düzenleme sayfaları için bir temel sınıf kullanın.
Kurs oluşturma ve düzenleme için bir temel sınıf oluşturun
Aşağıdaki kodla bir Pages/kurslar/DepartmentNamePageModel. cs dosyası oluşturun:
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;

namespace ContosoUniversity.Pages.Courses
{
public class DepartmentNamePageModel : PageModel
{
public SelectList DepartmentNameSL { get; set; }

public void PopulateDepartmentsDropDownList(SchoolContext _context,


object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name // Sort by name.
select d;

DepartmentNameSL = new SelectList(departmentsQuery.AsNoTracking(),


"DepartmentID", "Name", selectedDepartment);
}
}
}

Yukarıdaki kod, bölüm adlarının listesini içeren bir SelectList oluşturur. Belirtilmişse, bu departman SelectList
öğesinde seçilir. selectedDepartment
Oluşturma ve düzenleme sayfa modeli sınıfları öğesinden DepartmentNamePageModel türetilir.
Kursu güncelleştirme sayfa modeli oluşturma
Bir kurs bir departmana atanır. Oluşturma ve düzenleme sayfaları için temel sınıf, departmanı seçmek için
SelectList bir sağlar. Yabancı anahtar ( FK ) özelliğini kullanan SelectList açılan liste. Course.DepartmentID EF
Core, Course.DepartmentID Department gezinti özelliğini yüklemek için FK kullanır.
Sayfaları/kursları/oluşturma. cshtml. cs dosyasını şu kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class CreateModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public CreateModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public IActionResult OnGet()


{
PopulateDepartmentsDropDownList(_context);
return Page();
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnPostAsync()


{
var emptyCourse = new Course();

if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

// Select DepartmentID if TryUpdateModelAsync fails.


PopulateDepartmentsDropDownList(_context, emptyCourse.DepartmentID);
return Page();
}
}
}

Yukarıdaki kod:
Türetiliyor DepartmentNamePageModel .
TryUpdateModelAsync Aşırı nakletmeyiengellemek için kullanır.
Kaldırır ViewData["DepartmentID"] . DepartmentNameSL temel sınıftan türü kesin belirlenmiş bir modeldir ve Razor
sayfası tarafından kullanılır. Kesin olarak belirlenmiş modeller, kesin olarak yazılan zayıf bir şekilde tercih edilir.
Daha fazla bilgi için bkz. zayıf yazılmış veriler (ViewData ve ViewBag).
Kursu güncelleştirme Razor oluşturma sayfası
Sayfaları/kursları/Create. cshtml 'yi aşağıdaki kodla güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.CreateModel
@{
ViewData["Title"] = "Create Course";
}
<h2>Create</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<input asp-for="Course.CourseID" class="form-control" />
<span asp-validation-for="Course.CourseID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


DepartmentID etiketini departmanadönüştürür.
"ViewBag.DepartmentID" İle DepartmentNameSL değiştirir (taban sınıfından).
"Departmanı Seç" seçeneğini ekler. Bu değişiklik, ilk departman yerine henüz bir departman seçilmedikçe açılan
kutuda "departmanı Seç" i işler.
Departman seçili olmadığında bir doğrulama iletisi ekler.
Razor sayfası seçme etiketi yardımcısınıkullanır:
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>

Oluştur sayfasını test edin. Oluştur sayfası departman KIMLIĞI yerine departman adını görüntüler.
Kurs düzenleme sayfası modelini güncelleştirme
Pages/kurslar/Edit. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class EditModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.Include(c => c.Department).FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}

// Select current DepartmentID.


PopulateDepartmentsDropDownList(_context, Course.DepartmentID);
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

var courseToUpdate = await _context.Courses.FindAsync(id);

if (courseToUpdate == null)
{
return NotFound();
}
}

if (await TryUpdateModelAsync<Course>(
courseToUpdate,
"course", // Prefix for form value.
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

// Select DepartmentID if TryUpdateModelAsync fails.


PopulateDepartmentsDropDownList(_context, courseToUpdate.DepartmentID);
return Page();
}
}
}

Değişiklikler, oluşturma sayfası modelinde yapılanlarla benzerdir. Yukarıdaki kodda,


PopulateDepartmentsDropDownList bu departmanı açılan listede seçen departman kimliği ' nde geçirilir.

Kurs düzenleme Razor sayfasını güncelleştirme


Pages/kurslar/Edit. cshtml dosyasını aşağıdaki kodla güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.EditModel

@{
ViewData["Title"] = "Edit";
}

<h2>Edit</h2>

<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Course.CourseID" />
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.Course.CourseID)</div>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL"></select>
<span asp-validation-for="Course.DepartmentID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


Kurs KIMLIĞINI görüntüler. Genellikle bir varlığın birincil anahtarı (PK) gösterilmez. PKs 'ler genellikle
kullanıcılara daha az anlamlı olur. Bu durumda, PK kurs numarasıdır.
Bölüm açılan başlığını DepartmentID ' dan departmanadönüştürür.
"ViewBag.DepartmentID" İle DepartmentNameSL değiştirir (taban sınıfından).

Sayfa, kurs numarası için gizli bir <input type="hidden"> alan () içerir. <label> Etiket asp-for="Course.CourseID"
Yardımcısı ekleme, gizli alan gereksinimini ortadan kaldırmaz. <input type="hidden"> Kullanıcı Kaydet' e
tıkladığında, gönderilen veriler için kurs numarasının dahil olması gerekir.

Kurs ayrıntılarını güncelleştirme ve sayfaları silme


Anotracking , izleme gerekli olmadığında performansı iyileştirebilir.
Kurs sayfası modellerini güncelleştirme
Sayfa/kurslar/delete. cshtml. cs öğesini aşağıdaki kodla AsNoTracking güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses.FindAsync(id);

if (Course != null)
{
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
}

return RedirectToPage("./Index");
}
}
}

Sayfalar/kurslar/details. cshtml. cs dosyasında aynı değişikliği yapın:


using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class DetailsModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DetailsModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public Course Course { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}
return Page();
}
}
}

Kurs Razor sayfalarını güncelleştirme


Pages/kurslar/delete. cshtml dosyasını aşağıdaki kodla güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>

Ayrıntılar sayfasında aynı değişiklikleri yapın.


@page
@model ContosoUniversity.Pages.Courses.DetailsModel

@{
ViewData["Title"] = "Details";
}

<h2>Details</h2>

<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Course.CourseID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>

Kurs sayfalarını test etme


Oluşturma, düzenleme, ayrıntıları ve silme sayfalarını test edin.

Eğitmen oluşturma ve düzenleme sayfalarını güncelleştirme


Eğitmenler, istediğiniz sayıda kurs öğretebilir. Aşağıdaki görüntüde, bir dizi kurs onay kutusu ile eğitmen düzenleme
sayfası gösterilmektedir.
Onay kutuları, bir eğitmenin atandığı kurslara değişiklikler sağlar. Veritabanındaki her kurs için bir onay kutusu
görüntülenir. Eğitmenin atandığı kurslar seçilidir. Kullanıcı kurs atamalarını değiştirmek için onay kutularını seçebilir
veya temizleyebilir. Kurs sayısı çok büyükse, farklı bir kullanıcı arabirimi daha iyi çalışabilir. Ancak burada gösterilen
çoktan çoğa ilişkiyi yönetme yöntemi değişmez. İlişki oluşturmak veya silmek için bir JOIN varlığını işlersiniz.
Atanan kurslar verileri için bir sınıf oluşturma
Aşağıdaki kodla SchoolViewModels/AssignedCourseData. cs oluşturun:

namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}

Sınıfı AssignedCourseData , bir eğitmene atanan kurslar için onay kutularını oluşturmak üzere verileri içerir.
Bir eğitmen sayfa modeli temel sınıfı oluşturma
Pages/eğitmenler/Komutctorcoursespagemodel. cs temel sınıfını oluşturun:

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
namespace ContosoUniversity.Pages.Instructors
{
public class InstructorCoursesPageModel : PageModel
{

public List<AssignedCourseData> AssignedCourseDataList;

public void PopulateAssignedCourseData(SchoolContext context,


Instructor instructor)
{
var allCourses = context.Courses;
var instructorCourses = new HashSet<int>(
instructor.CourseAssignments.Select(c => c.CourseID));
AssignedCourseDataList = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
AssignedCourseDataList.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
}

public void UpdateInstructorCourses(SchoolContext context,


string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}
}
}
}
}
, Düzenleme ve oluşturma sayfa modelleri için kullanacağınız temel sınıftır.
InstructorCoursesPageModel
PopulateAssignedCourseData``Course doldurmak AssignedCourseDataList için tüm varlıkları okur. Her kurs için kod,
başlığı ve eğitmenin CourseID kursa atanıp atanmadığını belirler. Bir diyez kümesi etkili aramalar için kullanılır.
Razor sayfasında bir kurs varlıkları koleksiyonu olmadığından, model Bağlayıcısı CourseAssignments gezinti
özelliğini otomatik olarak güncelleştiremez. CourseAssignments Gezinti özelliğini güncelleştirmek için model cildi
kullanmak yerine, bunu yeni UpdateInstructorCourses yöntemde yapmanız gerekir. Bu nedenle, CourseAssignments
özelliği model bağlamadan hariç bırakmanız gerekir. Bu, beyaz liste aşırı yüklemesini kullandığınız ve
TryUpdateModel CourseAssignments içerme listesinde olmadığı için çağıran kodda herhangi bir değişiklik
yapılmasını gerektirmez.
Hiçbir onay kutusu seçili değilse, içindeki UpdateInstructorCourses kod CourseAssignments gezinti özelliğini boş bir
koleksiyonla başlatır ve döndürür:

if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

Kod daha sonra, veritabanındaki tüm kurslardan geçer ve bu her kursu, sayfada seçili olanlar ile ilgili olarak,
eğitmene atanmış olanlara karşı denetler. Etkili aramaları kolaylaştırmak için, ikinci iki koleksiyon HashSet
nesnelerde depolanır.
Kurs onay kutusu seçilmişse ancak kurs, Instructor.CourseAssignments gezinti özelliğinde değilse kurs, Gezinti
özelliğindeki koleksiyona eklenir.

if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}

Kurs onay kutusu seçili değilse, ancak kurs Instructor.CourseAssignments gezinti özelliği ise, kurs, gezinti
özelliğinden kaldırılır.

else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}

Office konumunu işle


Düzenleme sayfasının işlemesi gereken başka bir ilişki ise, eğitmen varlığının OfficeAssignment varlığa sahip
olduğu bire sıfır veya-bir ilişkidir. Eğitmen düzenleme kodu aşağıdaki senaryoları işlemelidir:
Kullanıcı Office atamasını temizlediğinde OfficeAssignment varlığı silin.
Kullanıcı bir Office ataması girerse ve boşsa, yeni OfficeAssignment bir varlık oluşturun.
Kullanıcı Office atamasını değiştirirse OfficeAssignment varlığı güncelleştirin.
Eğitmen düzenleme sayfası modelini güncelleştirme
Pages/eğitmenler/Edit. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class EditModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(_context, Instructor);
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id, string[] selectedCourses)


{
if (id == null)
{
return NotFound();
}

var instructorToUpdate = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(s => s.ID == id);

if (instructorToUpdate == null)
{
return NotFound();
}

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(_context, instructorToUpdate);
return Page();
}
}
}

Yukarıdaki kod:
OfficeAssignment , Instructor ,Ve CourseAssignment.Course gezinme özellikleri için Eager yükleme kullanarak
geçerli varlığı veritabanından alır. CourseAssignment
Alınan Instructor varlığı model Ciltçideki değerlerle güncelleştirir. TryUpdateModel fazla nakletmeyiönler.
Office konumu boşsa, null olarak ayarlar Instructor.OfficeAssignment . Null Instructor.OfficeAssignment
olduğunda, OfficeAssignment tablodaki ilgili satır silinir.
Görüntüleme modeli OnGetAsync sınıfını kullanarak onay kutuları PopulateAssignedCourseData için bilgi
sağlamak üzere ' de çağırır. AssignedCourseData
Onay UpdateInstructorCourses kutularından OnPostAsync düzenlenmekte olan eğitmen varlığına bilgi
uygulamak için ' de çağırır.
Başarısız olursa UpdateInstructorCourses , OnPostAsync ve ' de PopulateAssignedCourseData çağırır.
TryUpdateModel Bu yöntem çağrıları, bir hata iletisiyle yeniden görüntülendiğinde sayfaya girilen atanan kurs
verilerini geri yükler.
Eğitmen düzenleme Razor sayfasını güncelleştirme
Pages/eğitmenler/Edit. cshtml dosyasını aşağıdaki kodla güncelleştirin:

@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;

foreach (var course in Model.AssignedCourseDataList)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Yukarıdaki kod, üç sütun içeren bir HTML tablosu oluşturur. Her sütunda, kurs numarasını ve başlığını içeren bir
CheckBox ve bir açıklamalı alt yazı vardır. Onay kutularının hepsi aynı ada ("Selectedkurslar") sahiptir. Aynı adı
kullanmak model cildi bir grup olarak kabul etmek üzere bilgilendirir. Her onay kutusunun değer özniteliği olarak
CourseID ayarlanır. Sayfa gönderildiğinde, model Ciltçi yalnızca seçili onay kutularının CourseID değerlerinden
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmen 'e atanan kurslar seçilir.
Not: Eğitim kursu verilerini düzenlemek için buradaki yaklaşım, sınırlı sayıda kurs olduğunda iyi bir şekilde
gerçekleştirilir. Çok daha büyük olan koleksiyonlar için, farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme
yöntemi daha erişilebilir ve verimli olacaktır.
Uygulamayı çalıştırın ve güncelleştirilmiş eğitmenler düzenleme sayfasını test edin. Bazı kurs atamalarını değiştirin.
Değişiklikler Dizin sayfasında yansıtılır.
Eğitmen oluştur sayfasını güncelleştirme
, Düzenleme sayfasına benzer kodla, bir sayfa modeli ve Razor sayfası oluşturma adlı eğitmeni güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class CreateModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public CreateModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public IActionResult OnGet()


{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();

// Provides an empty collection for the foreach loop


// foreach (var course in Model.AssignedCourseDataList)
// in the Create Razor page.
PopulateAssignedCourseData(_context, instructor);
return Page();
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnPostAsync(string[] selectedCourses)


{
var newInstructor = new Instructor();
if (selectedCourses != null)
{
newInstructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment
{
CourseID = int.Parse(course)
};
newInstructor.CourseAssignments.Add(courseToAdd);
}
}

if (await TryUpdateModelAsync<Instructor>(
newInstructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
_context.Instructors.Add(newInstructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
PopulateAssignedCourseData(_context, newInstructor);
return Page();
}
}
}

@page
@model ContosoUniversity.Pages.Instructors.CreateModel
@{
ViewData["Title"] = "Create";
}

<h2>Create</h2>

<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;

foreach (var course in Model.AssignedCourseDataList)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Eğitmen oluşturma sayfasını test edin.

Eğitmen silme sayfasını Güncelleştir


Sayfaları/eğitmenler/delete. cshtml. cs dosyasını şu kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor = await _context.Instructors.FirstOrDefaultAsync(m => m.ID == id);

if (Instructor == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor instructor = await _context.Instructors


.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);

if (instructor == null)
{
return RedirectToPage("./Index");
}

var departments = await _context.Departments


.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);

_context.Instructors.Remove(instructor);

await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
CourseAssignments Gezinti özelliği için Eager yüklemesi kullanır. CourseAssignments eğitmen silindiğinde,
dahil edilmiş veya silinmemelidir. Bunları okumaktan kaçınmak için, veritabanında basamaklı silme 'yı
yapılandırın.
Silinecek eğitmen herhangi bir departmanların Yöneticisi olarak atanırsa, bu departmanlardan eğitmen
atamasını kaldırır.
Uygulamayı çalıştırın ve silme sayfasını test edin.

Sonraki adımlar

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide ilgili verilerin güncelleştirilmesi gösterilmektedir. Olamaz çözmenize, sorunlarla karşılaşırsanız, indirin
veya tamamlanmış uygulamayı görüntüleyin. Yükleme yönergeleri.
Aşağıdaki çizimler tamamlanan sayfalardan bazılarını göstermektedir.
Kurs oluşturma ve düzenleme sayfalarını inceleyin ve test edin. Yeni bir kurs oluşturun. Departman, adı değil,
birincil anahtarı (bir tamsayı) tarafından seçilir. Yeni kursu düzenleyin. Sınamayı bitirdiğinizde yeni kursu silin.

Ortak kod paylaşmak için bir temel sınıf oluşturun


Kurslar/oluştur ve kurslar/Düzenle sayfaları, her birinin departman adları listesine ihtiyacı vardır. Oluşturma ve
düzenleme sayfaları için Pages/kurslar/DepartmentNamePageModel. cshtml. cs temel sınıfını oluşturun:
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;

namespace ContosoUniversity.Pages.Courses
{
public class DepartmentNamePageModel : PageModel
{
public SelectList DepartmentNameSL { get; set; }

public void PopulateDepartmentsDropDownList(SchoolContext _context,


object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name // Sort by name.
select d;

DepartmentNameSL = new SelectList(departmentsQuery.AsNoTracking(),


"DepartmentID", "Name", selectedDepartment);
}
}
}

Yukarıdaki kod, bölüm adlarının listesini içeren bir SelectList oluşturur. Belirtilmişse, bu departman SelectList
öğesinde seçilir. selectedDepartment
Oluşturma ve düzenleme sayfa modeli sınıfları öğesinden DepartmentNamePageModel türetilir.

Kurslar sayfalarını özelleştirme


Yeni bir kurs varlığı oluşturulduğunda, mevcut bir departmanla bir ilişkisi olmalıdır. Bir kurs oluştururken bir
departman eklemek için, oluşturma ve düzenleme için temel sınıf, departmanı seçmeye yönelik bir açılan liste içerir.
Açılan liste, Course.DepartmentID yabancı anahtar (FK) özelliğini ayarlar. EF Core, Course.DepartmentID Department
gezinti özelliğini yüklemek için FK kullanır.
Oluşturma sayfası modelini aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class CreateModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public CreateModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public IActionResult OnGet()


{
PopulateDepartmentsDropDownList(_context);
return Page();
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var emptyCourse = new Course();

if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

// Select DepartmentID if TryUpdateModelAsync fails.


PopulateDepartmentsDropDownList(_context, emptyCourse.DepartmentID);
return Page();
}
}
}

Yukarıdaki kod:
Türetiliyor .
DepartmentNamePageModel
TryUpdateModelAsync Aşırı nakletmeyiengellemek için kullanır.
ViewData["DepartmentID"] İle DepartmentNameSL değiştirir (taban sınıfından).

ViewData["DepartmentID"] , türü kesin belirlenmiş DepartmentNameSL olan ile değiştirilmiştir. Kesin olarak belirlenmiş
modeller, kesin olarak yazılan zayıf bir şekilde tercih edilir. Daha fazla bilgi için bkz. zayıf yazılmış veriler (ViewData
ve ViewBag).
Kurslar oluşturma sayfasını güncelleştirme
Sayfaları/kursları/Create. cshtml 'yi aşağıdaki kodla güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.CreateModel
@{
ViewData["Title"] = "Create Course";
}
<h2>Create</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<input asp-for="Course.CourseID" class="form-control" />
<span asp-validation-for="Course.CourseID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Önceki biçimlendirme, aşağıdaki değişiklikleri yapar:


DepartmentID etiketini departmanadönüştürür.
"ViewBag.DepartmentID" İle DepartmentNameSL değiştirir (taban sınıfından).
"Departmanı Seç" seçeneğini ekler. Bu değişiklik, ilk departman yerine "departmanı Seç" i işler.
Departman seçili olmadığında bir doğrulama iletisi ekler.
Razor sayfası seçme etiketi yardımcısınıkullanır:
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>

Oluştur sayfasını test edin. Oluştur sayfası departman KIMLIĞI yerine departman adını görüntüler.
Kurslar düzenleme sayfasını güncelleştirin.
Pages/kurslar/Edit. cshtml. cs dosyasındaki kodu aşağıdaki kodla değiştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Courses
{
public class EditModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.Include(c => c.Department).FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}

// Select current DepartmentID.


PopulateDepartmentsDropDownList(_context,Course.DepartmentID);
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (!ModelState.IsValid)
{
return Page();
}

var courseToUpdate = await _context.Courses.FindAsync(id);

if (await TryUpdateModelAsync<Course>(
courseToUpdate,
"course", // Prefix for form value.
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

// Select DepartmentID if TryUpdateModelAsync fails.


PopulateDepartmentsDropDownList(_context, courseToUpdate.DepartmentID);
return Page();
}
}
}

Değişiklikler, oluşturma sayfası modelinde yapılanlarla benzerdir. Yukarıdaki kodda


PopulateDepartmentsDropDownList , açılan listede belirtilen departmanı belirleyen departman kimliği ' nde geçirilir.
Pages/kurslar/Edit. cshtml 'yi şu biçimlendirmeyle güncelleştirin:

@page
@model ContosoUniversity.Pages.Courses.EditModel

@{
ViewData["Title"] = "Edit";
}

<h2>Edit</h2>

<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Course.CourseID" />
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.Course.CourseID)</div>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL"></select>
<span asp-validation-for="Course.DepartmentID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Önceki biçimlendirme, aşağıdaki değişiklikleri yapar:


Kurs KIMLIĞINI görüntüler. Genellikle bir varlığın birincil anahtarı (PK) gösterilmez. PKs 'ler genellikle
kullanıcılara daha az anlamlı olur. Bu durumda, PK kurs numarasıdır.
DepartmentID etiketini departmanadönüştürür.
"ViewBag.DepartmentID" İle DepartmentNameSL değiştirir (taban sınıfından).

Sayfa, kurs numarası için gizli bir <input type="hidden"> alan () içerir. <label> Etiket asp-for="Course.CourseID"
Yardımcısı ekleme, gizli alan gereksinimini ortadan kaldırmaz. <input type="hidden"> Kullanıcı Kaydet' e
tıkladığında, gönderilen veriler için kurs numarasının dahil olması gerekir.
Güncelleştirilmiş kodu test edin. Kurs oluşturun, düzenleyin ve silin.

Ayrıntılara AsNoTracking ekleme ve sayfa modellerini silme


Anotracking , izleme gerekli olmadığında performansı iyileştirebilir. Sil AsNoTracking ve Ayrıntılar sayfa modeline
ekleyin. Aşağıdaki kod, güncelleştirilmiş silme sayfası modelini göstermektedir:

public class DeleteModel : PageModel


{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Course Course { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);

if (Course != null)
{
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
}

return RedirectToPage("./Index");
}
}

Pages/kurslar/details. cshtml. cs dosyasındaki yöntemigüncelleştirin: OnGetAsync


public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}

Course = await _context.Courses


.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);

if (Course == null)
{
return NotFound();
}
return Page();
}

Silme ve Ayrıntılar sayfalarını değiştirme


Razor Sil sayfasını aşağıdaki biçimlendirmeyle güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Course</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Department.DepartmentID)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>

Ayrıntılar sayfasında aynı değişiklikleri yapın.


Kurs sayfalarını test etme
Test oluşturma, düzenleme, Ayrıntılar ve silme.

Eğitmen sayfalarını güncelleştirme


Aşağıdaki bölümlerde, eğitmen sayfaları günceldir.
Office konumu Ekle
Bir eğitmen kaydını düzenlediğinizde, eğitmenin Office atamasını güncelleştirmek isteyebilirsiniz. Instructor
Varlığın OfficeAssignment varlıkla bire sıfır veya-bir ilişkisi vardır. Eğitmen kodu şu şekilde olmalıdır:
Kullanıcı Office atamasını temizlediğinde OfficeAssignment varlığı silin.
Kullanıcı bir Office ataması girerse ve boşsa, yeni OfficeAssignment bir varlık oluşturun.
Kullanıcı Office atamasını değiştirirse OfficeAssignment varlığı güncelleştirin.
Eğitmenler düzenleme sayfası modelini aşağıdaki kodla güncelleştirin:

public class EditModel : PageModel


{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor = await _context.Instructors


.Include(i => i.OfficeAssignment)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Instructor == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (!ModelState.IsValid)
{
return Page();
}

var instructorToUpdate = await _context.Instructors


.Include(i => i.OfficeAssignment)
.FirstOrDefaultAsync(s => s.ID == id);

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");

}
}

Yukarıdaki kod:
Gezinti OfficeAssignment özelliği için Instructor Eager yüklemesini kullanarak geçerli varlığı veritabanından
alır.
Alınan Instructor varlığı model Ciltçideki değerlerle güncelleştirir. TryUpdateModel fazla nakletmeyiönler.
Office konumu boşsa, null olarak ayarlar Instructor.OfficeAssignment . Null Instructor.OfficeAssignment
olduğunda, OfficeAssignment tablodaki ilgili satır silinir.
Eğitmen düzenleme sayfasını güncelleştirme
Sayfaları/eğitmenler/Edit. cshtml dosyasını Office konumuyla güncelleştirin:

@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Bir eğitmenler ofis konumunu değiştirebildiğinizi doğrulayın.

Eğitmen düzenleme sayfasına kurs atamaları ekleme


Eğitmenler, istediğiniz sayıda kurs öğretebilir. Bu bölümde kurs atamalarını değiştirme olanağını eklersiniz.
Aşağıdaki görüntüde güncelleştirilmiş eğitmen düzenleme sayfası gösterilmektedir:
Course ve Instructor çoktan çoğa ilişkisine sahiptir. İlişki eklemek ve kaldırmak için, CourseAssignments JOIN
varlık kümesinden varlık ekleyin ve kaldırın.
Onay kutuları, bir eğitmenin atandığı kurslara değişiklikler sağlar. Veritabanındaki her kurs için bir onay kutusu
görüntülenir. Eğitmenin atandığı kurslar denetlenir. Kullanıcı kurs atamalarını değiştirmek için onay kutularını
seçebilir veya temizleyebilir. Kurs sayısı çok fazlaysa:
Kursları göstermek için büyük olasılıkla farklı bir kullanıcı arabirimi kullanıyorsunuz.
İlişki oluşturmak veya silmek için bir JOIN varlığını düzenleme yöntemi değişmez.
Eğitmen sayfaları oluşturma ve düzenleme desteğini desteklemek için sınıflar ekleme
Aşağıdaki kodla SchoolViewModels/AssignedCourseData. cs oluşturun:

namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}

Sınıfı AssignedCourseData , bir eğitmen tarafından atanan kurslar için onay kutularını oluşturacak verileri içerir.
Pages/eğitmenler/Komutctorcoursespagemodel. cshtml. cs temel sınıfını oluşturun:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;

namespace ContosoUniversity.Pages.Instructors
{
public class InstructorCoursesPageModel : PageModel
{

public List<AssignedCourseData> AssignedCourseDataList;

public void PopulateAssignedCourseData(SchoolContext context,


Instructor instructor)
{
var allCourses = context.Courses;
var instructorCourses = new HashSet<int>(
instructor.CourseAssignments.Select(c => c.CourseID));
AssignedCourseDataList = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
AssignedCourseDataList.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
}

public void UpdateInstructorCourses(SchoolContext context,


string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}
}
}
}
}

, Düzenleme ve oluşturma sayfa modelleri için kullanacağınız temel sınıftır.


InstructorCoursesPageModel
PopulateAssignedCourseData``Course doldurmak AssignedCourseDataList için tüm varlıkları okur. Her kurs için kod,
başlığı ve eğitmenin CourseID kursa atanıp atanmadığını belirler. Bir diyez kümesi , verimli aramalar oluşturmak için
kullanılır.
Eğitmenler sayfa modelini Düzenle
Eğitmen düzenleme sayfası modelini aşağıdaki kodla güncelleştirin:
public class EditModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(_context, Instructor);
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id, string[] selectedCourses)


{
if (!ModelState.IsValid)
{
return Page();
}

var instructorToUpdate = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(s => s.ID == id);

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(_context, instructorToUpdate);
return Page();
}
}
Yukarıdaki kod, Office atama değişikliklerini işler.
Eğitmen Razor görünümünü güncelleştirin:

@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;

foreach (var course in Model.AssignedCourseDataList)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
</div>

<div>
<a asp-page="./Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

NOTE
Kodu Visual Studio 'Ya yapıştırdığınızda, satır sonları kodu kesen bir şekilde değiştirilir. Otomatik biçimlendirmeyi geri almak
için CTRL + Z bir kez tuşuna basın. CTRL + Z, burada gördüğünüz gibi görünmeleri için satır sonlarını düzeltir. Girintide
kusursuz @:</tr><tr> olması gerekmez, ancak @:<td> @:</td> ,, ve @:</tr> çizgilerinin her biri gösterildiği gibi tek bir
satırda olması gerekir. Yeni kod bloğu seçiliyken, yeni kodu mevcut kodla hizalamak için üç kez Tab tuşuna basın. Bu bağlantı
ilebu hatanın durumunu oylayın veya gözden geçirin.

Yukarıdaki kod, üç sütun içeren bir HTML tablosu oluşturur. Her sütunda bir onay kutusu ve kurs numarasını ve
başlığını içeren bir açıklamalı alt yazı vardır. Onay kutularının hepsi aynı ada ("Selectedkurslar") sahiptir. Aynı adı
kullanmak model cildi bir grup olarak kabul etmek üzere bilgilendirir. Her onay kutusunun değer özniteliği olarak
CourseID ayarlanır. Sayfa gönderildiğinde, model Ciltçi yalnızca seçili onay kutularının CourseID değerlerinden
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmenin atandığı kursların denetlenen öznitelikleri vardır.
Uygulamayı çalıştırın ve güncelleştirilmiş eğitmenler düzenleme sayfasını test edin. Bazı kurs atamalarını değiştirin.
Değişiklikler Dizin sayfasında yansıtılır.
Not: Eğitim kursu verilerini düzenlemek için buradaki yaklaşım, sınırlı sayıda kurs olduğunda iyi bir şekilde
gerçekleştirilir. Çok daha büyük olan koleksiyonlar için, farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme
yöntemi daha erişilebilir ve verimli olacaktır.
Eğitmenler oluştur sayfasını güncelleştirme
Aşağıdaki kodla, eğitmen sayfa modeli oluştur sayfasını güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class CreateModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public CreateModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

public IActionResult OnGet()


{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();

// Provides an empty collection for the foreach loop


// foreach (var course in Model.AssignedCourseDataList)
// in the Create Razor page.
PopulateAssignedCourseData(_context, instructor);
PopulateAssignedCourseData(_context, instructor);
return Page();
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnPostAsync(string[] selectedCourses)


{
if (!ModelState.IsValid)
{
return Page();
}

var newInstructor = new Instructor();


if (selectedCourses != null)
{
newInstructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment
{
CourseID = int.Parse(course)
};
newInstructor.CourseAssignments.Add(courseToAdd);
}
}

if (await TryUpdateModelAsync<Instructor>(
newInstructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
_context.Instructors.Add(newInstructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
PopulateAssignedCourseData(_context, newInstructor);
return Page();
}
}
}

Yukarıdaki kod, Pages/eğitmenler/Edit. cshtml. cs koduna benzerdir.


Eğitmen oluşturma Razor sayfasını aşağıdaki biçimlendirmeyle güncelleştirin:

@page
@model ContosoUniversity.Pages.Instructors.CreateModel

@{
ViewData["Title"] = "Create";
}

<h2>Create</h2>

<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>

<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;

foreach (var course in Model.AssignedCourseDataList)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Eğitmen oluşturma sayfasını test edin.

Silme sayfası
Delete sayfa modeli aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Instructors
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Instructor Instructor { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Instructor = await _context.Instructors.SingleAsync(m => m.ID == id);

if (Instructor == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
Instructor instructor = await _context.Instructors
.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);

var departments = await _context.Departments


.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);

_context.Instructors.Remove(instructor);

await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


CourseAssignments Gezinti özelliği için Eager yüklemesi kullanır. CourseAssignments eğitmen silindiğinde,
dahil edilmiş veya silinmemelidir. Bunları okumaktan kaçınmak için, veritabanında basamaklı silme 'yı
yapılandırın.
Silinecek eğitmen herhangi bir departmanların Yöneticisi olarak atanırsa, bu departmanlardan eğitmen
atamasını kaldırır.
Ek kaynaklar
Bu öğreticinin YouTube sürümü (Bölüm 1)
Bu öğreticinin YouTube sürümü (Bölüm 2)

ÖN CEKI İleri A S P. N E T C O R E ' D A - E Ş Z A M A N L IL IK - 8 8 E F Ç E K IR D E K L I R A Z O R


SA Y FA L A RI
ASP.NET core'da - eşzamanlılık - 8 8 EF çekirdekli
Razor sayfaları
23.11.2019 • 51 minutes to read • Edit Online

Tarafından Rick Anderson, Tom Dykstra, ve Jon P Smith


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, birden çok kullanıcı aynı anda (aynı anda) bir varlık güncelleştirdiğinizde çakışmalarına
gösterilmektedir.

Eşzamanlılık çakışmaları
Bir eşzamanlılık çakışması ortaya olduğunda:
Bir kullanıcı bir varlığın düzenleme sayfasına götürür.
İlk kullanıcının değişikliği veritabanına yazılmadan önce, başka bir kullanıcı aynı varlığı güncelleştirir.
Eşzamanlılık algılama etkinleştirilmemişse, veritabanını güncelleştirme son olarak diğer kullanıcının değişikliklerinin
üzerine yazılır. Bu risk kabul edilebilir ise, eşzamanlılık için programlama maliyeti avantaja aykırı bir ücret verebilir.
Kötümser eşzamanlılık (kilitleme )
Eşzamanlılık çakışmalarını önlemenin bir yolu veritabanı kilitlerini kullanmaktır. Bu, Kötümser eşzamanlılık olarak
adlandırılır. Uygulama, güncelleştirmeyi amaçladığı bir veritabanı satırını okumadan önce bir kilit ister. Bir satır,
güncelleştirme erişimi için kilitlendiğinde, ilk kilit yayımlanıncaya kadar başka hiçbir kullanıcının satırı kilitlemesine
izin verilmez.
Kilitleri yönetmek dezavantajlara sahiptir. Program, karmaşık olabilir ve Kullanıcı sayısı arttıkça performans
sorunlarına neden olabilir. Entity Framework Core, BT için yerleşik destek sağlamaz ve bu öğretici Bu öğreticinin
nasıl uygulanacağını göstermez.
İyimser eşzamanlılık
İyimser eşzamanlılık eşzamanlılık çakışmalarını olmasını sağlar ve tepki verdiğini uygun olduğunda bunlar yapın.
Örneğin, Jane departmanı Düzen sayfasını ziyaret ve İngilizce departmanı için bütçe 350,000.00 $0,00 değiştirir.
Jane tıkladığında önce Kaydet, John aynı sayfayı ziyaret eder ve alanın başlangıç tarihi 1/9/2013 1/9/2007'deki
değiştirir.
Gamze önce Kaydet ' i tıklatır ve değişiklik etkin duruma geçer çünkü tarayıcı Dizin sayfasını bütçe miktarı olarak
sıfır ile görüntülüyor.
John tıkladığında Kaydet yine de bir bütçe $350,000.00 birini gösteren bir Düzenle sayfasında. Sonraki durum
eşzamanlılık çakışmalarını nasıl işleydiğinize göre belirlenir:
Bir kullanıcının hangi özelliği değiştirdiği ve yalnızca ilgili sütunları veritabanında güncelleştirdiğinden
haberdar olabilirsiniz.
Bu senaryoda, veri kaybolacak. Farklı özellikler iki kullanıcı tarafından güncelleştirildi. Biri İngilizce,
departman gözatar sonraki açışınızda Gamze'nin hem Can'ın değişiklikleri görürler. Bu güncelleştirme
yöntemini, veri kaybına neden olabilecek çakışmaları sayısını azaltabilirsiniz. Bu yaklaşım bazı dezavantajlara
sahiptir:
Aynı özelliğe rakip bir değişiklik yaptıysanız, veri kaybını önlemek olamaz.
Genellikle bir web uygulaması pratik değildir. Tüm getirilen ve yeni değerleri izlemek için önemli durum
koruma gerektiriyor. Büyük miktarlarda durumu bakımını yapma, uygulama performansını etkileyebilir.
Bir varlıkta eşzamanlılık algılama ile karşılaştırıldığında app karmaşıklığı artırabilirsiniz.
Gamze'nin değişikliğinin üzerine Can'ın değişiklik sağlayabilirsiniz.
Sonraki biri İngilizce departmanı gözatar, 1/9/2013 görürler ve getirilen $350,000.00 değeri. Bu yaklaşım
olarak adlandırılan bir istemci WINS veya WINS'te son senaryo. (İstemciden gelen tüm değerler veri
deposunda yer alacak şekilde önceliklidir.) Eşzamanlılık işleme için herhangi bir kodlama yapmazsanız,
Istemci WINS otomatik olarak gerçekleşir.
John 'un değişikliğini veritabanında güncelleştirilmesini engelleyebilirsiniz. Genellikle, bir uygulamayı
atadığınız:
Bir hata iletisi görüntüler.
Verilerin geçerli durumunu gösterir.
Değişiklikleri uygulamak verin.
Bu adlı bir Store WINS senaryo. (Veri deposu değerleri, istemci tarafından gönderilen değerlere göre
önceliklidir.) Bu öğreticide mağaza WINS senaryosunu uygulamanız gerekir. Bu yöntem, hiçbir değişiklik
uyarı bir kullanıcı kılınmamasını sağlar.

EF Core çakışma algılama


EF Core, çakışmalar algıladığında DbConcurrencyException özel durum oluşturur. Çakışma algılamayı etkinleştirmek
için veri modeli yapılandırılmalıdır. Çakışma algılamayı etkinleştirme seçenekleri şunlardır:
EF Core, Update ve DELETE komutlarının WHERE yan tümcesinde eşzamanlılık belirteçleri olarak
yapılandırılan sütunların özgün değerlerini içerecek şekilde yapılandırın.
SaveChanges çağrıldığında WHERE yan tümcesi ConcurrencyCheck özniteliğiyle açıklama eklenmiş herhangi
bir özelliğin özgün değerlerini arar. Update deyimleri, satır ilk okunduğundan bu yana eşzamanlılık belirteci
özelliklerinden herhangi biri değiştiyse güncelleştirilecek bir satır bulmayacaktır. EF Core eşzamanlılık
çakışması olarak yorumlar. Birçok sütunu olan veritabanı tablolarında bu yaklaşım çok büyük WHERE yan
tümceleriyle sonuçlanabilir ve büyük miktarlarda durum gerektirebilir. Bu nedenle bu yaklaşım genellikle
önerilmez ve bu öğreticide kullanılan yöntem değildir.
Veritabanı tablosunda, bir satırın ne zaman değiştirildiğini belirlemede kullanılabilecek bir izleme sütunu
ekleyin.
SQL Server veritabanında, izleme sütununun veri türü rowversion . rowversion değeri, satır her
güncelleştirildiği zaman artılan sıralı bir sayıdır. Bir Update veya delete komutunda WHERE yan tümcesi,
izleme sütununun (orijinal satır sürüm numarası) orijinal değerini içerir. Güncelleştirilmekte olan satır başka
bir kullanıcı tarafından değiştirilmişse, rowversion sütunundaki değer özgün değerden farklıdır. Bu durumda,
Update veya DELETE deyimi WHERE yan tümcesi nedeniyle güncelleştirilecek satırı bulamıyor. Bir Update
veya delete komutundan hiçbir satır etkilenmeden EF Core eşzamanlılık özel durumu oluşturur.

İzleme özelliği Ekle


İçinde Models/Department.cs, RowVersion adlı izleme özelliği ekleyin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Timestamp özniteliği sütunu eşzamanlılık izleme sütunu olarak tanımlar. Fluent API, izleme özelliğini belirtmenin
alternatif bir yoludur:

modelBuilder.Entity<Department>()
.Property<byte[]>("RowVersion")
.IsRowVersion();

Visual Studio
Visual Studio Code
Bir SQL Server veritabanı için, bayt dizisi olarak tanımlanan bir varlık özelliğindeki [Timestamp] özniteliği:
Sütunun WHERE yan tümceleri DELETE ve UPDATE 'e dahil edilmesini sağlar.
Veritabanındaki sütun türünü rowversionolarak ayarlar.
Veritabanı, satır her güncelleştirildiği zaman artılan sıralı bir satır sürüm numarası oluşturur. Bir Update veya
Delete komutunda, Where yan tümcesi getirilen satır sürümü değerini içerir. Güncelleştirilmekte olan satır
getirilmesinden sonra değiştiyse:
Geçerli satır sürümü değeri getirilen değerle eşleşmiyor.
Whereyan tümcesi getirilen satır sürümü değerini aradığı için Update veya Delete komutları bir satır bulamaz.
A DbUpdateConcurrencyException oluşturulur.

Aşağıdaki kod, T-SQL bölüm adını güncelleştirildiğinde EF Core tarafından oluşturulan bir bölümü
gösterilmektedir:

SET NOCOUNT ON;


UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;

Önceki kodun gösterdiği vurgulanmış WHERE yan tümcesi içeren RowVersion . Veritabanı RowVersion RowVersion
parametresine eşit değilse ( @p2 ), hiçbir satır güncellenmez.
Aşağıdaki vurgulanmış kodu tam olarak bir satır güncellenmedi doğrular T-SQL gösterir:

SET NOCOUNT ON;


UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;

@@ROWCOUNT son deyiminden etkilenen satır sayısını döndürür. Hiçbir satır güncellenmemişse, EF Core bir
DbUpdateConcurrencyException oluşturur.

Veritabanını güncelleştirme
RowVersion özelliği eklendiğinde geçiş gerektiren veri modeli değişir.

Projeyi oluşturun.
Visual Studio
Visual Studio Code
PMC 'de şu komutu çalıştırın:

Add-Migration RowVersion

Bu komut:
Geçişleri/{zaman damgası} _RowVersion. cs geçiş dosyasını oluşturur.
Güncelleştirmeleri Migrations/SchoolContextModelSnapshot.cs dosya. Bu güncelleştirme aşağıdaki
vurgulanmış kodu ekler BuildModel yöntemi:
modelBuilder.Entity("ContosoUniversity.Models.Department", b =>
{
b.Property<int>("DepartmentID")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn);

b.Property<decimal>("Budget")
.HasColumnType("money");

b.Property<int?>("InstructorID");

b.Property<string>("Name")
.HasMaxLength(50);

b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate();

b.Property<DateTime>("StartDate");

b.HasKey("DepartmentID");

b.HasIndex("InstructorID");

b.ToTable("Department");
});

Visual Studio
Visual Studio Code
PMC 'de şu komutu çalıştırın:

Update-Database

Yapı iskelesi departmanı sayfaları


Visual Studio
Visual Studio Code
Aşağıdaki özel durumlarla birlikte Yapı Fkatlama öğrenci sayfalarındaki yönergeleri izleyin:
Sayfalar/departmanlar klasörü oluşturun.
Model sınıfı için Department kullanın.
Yeni bir tane oluşturmak yerine var olan bağlam sınıfını kullanın.
Projeyi oluşturun.

Dizin sayfasını Güncelleştir


Scafkatlama aracı Dizin sayfası için bir RowVersion sütunu oluşturdu, ancak bu alan bir üretim uygulamasında
gösterilmemelidir. Bu öğreticide, eşzamanlılık işlemenin nasıl çalıştığını göstermeye yardımcı olmak için RowVersion
son baytı görüntülenir. Son baytın kendi kendine benzersiz olması garanti edilmez.
Pages\Departments\Index.cshtml sayfasını güncelleştir:
Dizin bölümlerine değiştirin.
Yalnızca bayt dizisinin son baytını göstermek için RowVersion içeren kodu değiştirin.
FirstMidName tam adı ile değiştirin.
Aşağıdaki kod, güncelleştirilmiş sayfayı gösterir:

@page
@model ContosoUniversity.Pages.Departments.IndexModel

@{
ViewData["Title"] = "Departments";
}

<h2>Departments</h2>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Department[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].Budget)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].StartDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].Administrator)
</th>
<th>
RowVersion
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Department)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Budget)
</td>
<td>
@Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Administrator.FullName)
</td>
<td>
@item.RowVersion[7]
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.DepartmentID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.DepartmentID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.DepartmentID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Düzenleme sayfa modeli güncelleştirme
Aşağıdaki kodla Pages\Departments\Edit.cshtml.cs güncelleştirin:

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Departments
{
public class EditModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Department Department { get; set; }
// Replace ViewData["InstructorID"]
public SelectList InstructorNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(int id)


{
Department = await _context.Departments
.Include(d => d.Administrator) // eager loading
.AsNoTracking() // tracking not required
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (Department == null)
{
return NotFound();
}

// Use strongly typed data rather than ViewData.


InstructorNameSL = new SelectList(_context.Instructors,
"ID", "FirstMidName");

return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
if (!ModelState.IsValid)
{
return Page();
}

var departmentToUpdate = await _context.Departments


.Include(i => i.Administrator)
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (departmentToUpdate == null)
{
return HandleDeletedDepartment();
}

_context.Entry(departmentToUpdate)
.Property("RowVersion").OriginalValue = Department.RowVersion;

if (await TryUpdateModelAsync<Department>(
if (await TryUpdateModelAsync<Department>(
departmentToUpdate,
"Department",
s => s.Name, s => s.StartDate, s => s.Budget, s => s.InstructorID))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}
}

InstructorNameSL = new SelectList(_context.Instructors,


"ID", "FullName", departmentToUpdate.InstructorID);

return Page();
}

private IActionResult HandleDeletedDepartment()


{
var deletedDepartment = new Department();
// ModelState contains the posted data because of the deletion error
// and will overide the Department instance values when displaying Page().
ModelState.AddModelError(string.Empty,
"Unable to save. The department was deleted by another user.");
InstructorNameSL = new SelectList(_context.Instructors, "ID", "FullName", Department.InstructorID);
return Page();
}

private async Task setDbErrorMessage(Department dbValues,


Department clientValues, SchoolContext context)
{

if (dbValues.Name != clientValues.Name)
{
ModelState.AddModelError("Department.Name",
$"Current value: {dbValues.Name}");
}
if (dbValues.Budget != clientValues.Budget)
{
ModelState.AddModelError("Department.Budget",
$"Current value: {dbValues.Budget:c}");
}
if (dbValues.StartDate != clientValues.StartDate)
{
ModelState.AddModelError("Department.StartDate",
$"Current value: {dbValues.StartDate:d}");
}
if (dbValues.InstructorID != clientValues.InstructorID)
if (dbValues.InstructorID != clientValues.InstructorID)
{
Instructor dbInstructor = await _context.Instructors
.FindAsync(dbValues.InstructorID);
ModelState.AddModelError("Department.InstructorID",
$"Current value: {dbInstructor?.FullName}");
}

ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}
}
}

OriginalValue , OnGet yönteminde alındığı sırada varlıktaki rowVersion değeriyle güncelleştirilir. EF Core özgün
içeren bir WHERE yan tümcesi ile SQL güncelleştirme komut oluşturur RowVersion değeri. Hiçbir satır
güncelleştirme komutu tarafından etkileniyorsanız (hiçbir satır özgün sahip RowVersion değer),
DbUpdateConcurrencyException özel durumu oluşturulur.

public async Task<IActionResult> OnPostAsync(int id)


{
if (!ModelState.IsValid)
{
return Page();
}

var departmentToUpdate = await _context.Departments


.Include(i => i.Administrator)
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (departmentToUpdate == null)
{
return HandleDeletedDepartment();
}

_context.Entry(departmentToUpdate)
.Property("RowVersion").OriginalValue = Department.RowVersion;

Vurgulanan kodda:
Department.RowVersion değeri, ilk olarak düzenleme sayfasına yönelik GET isteğine getirilen varlıkta yer alır.
Değer, düzenlenecek varlığı görüntüleyen Razor sayfasındaki gizli bir alan tarafından OnPost yöntemine
sağlanır. Gizli alan değeri model cildi tarafından Department.RowVersion ' a kopyalanır.
OriginalValue WHERE yan tümcesinde kullanılacak EF Core. Vurgulanan kod satırı çalıştırılmadan önce,
FirstOrDefaultAsync Bu yöntemde çağrıldığında, düzenleme sayfasında görüntülendiklerden farklı olabilen
OriginalValue veritabanında bulunan değeri vardır.
Vurgulanan kod, EF Core SQL UPDATE ifadesinin WHERE yan tümcesindeki görüntülenen Department
varlığındaki özgün RowVersion değerini kullandığından emin olur.

Bir eşzamanlılık hatası oluştuğunda, aşağıdaki vurgulanmış kod istemci değerlerini (Bu yönteme gönderilen
değerler) ve veritabanı değerlerini alır.
if (await TryUpdateModelAsync<Department>(
departmentToUpdate,
"Department",
s => s.Name, s => s.StartDate, s => s.Budget, s => s.InstructorID))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}

Aşağıdaki kod, OnPostAsync gönderilen değerden farklı veritabanı değerleri olan her bir sütun için özel bir hata
iletisi ekler:
private async Task setDbErrorMessage(Department dbValues,
Department clientValues, SchoolContext context)
{

if (dbValues.Name != clientValues.Name)
{
ModelState.AddModelError("Department.Name",
$"Current value: {dbValues.Name}");
}
if (dbValues.Budget != clientValues.Budget)
{
ModelState.AddModelError("Department.Budget",
$"Current value: {dbValues.Budget:c}");
}
if (dbValues.StartDate != clientValues.StartDate)
{
ModelState.AddModelError("Department.StartDate",
$"Current value: {dbValues.StartDate:d}");
}
if (dbValues.InstructorID != clientValues.InstructorID)
{
Instructor dbInstructor = await _context.Instructors
.FindAsync(dbValues.InstructorID);
ModelState.AddModelError("Department.InstructorID",
$"Current value: {dbInstructor?.FullName}");
}

ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}

Aşağıdaki vurgulanan kod, RowVersion değerini veritabanından alınan yeni değer olarak ayarlar. Kullanıcının bir
sonraki tıklayışında Kaydet, düzenleme sayfası son görüntülenmesini yakalandı beri gerçekleşen eşzamanlılık
hataları.
if (await TryUpdateModelAsync<Department>(
departmentToUpdate,
"Department",
s => s.Name, s => s.StartDate, s => s.Budget, s => s.InstructorID))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}

ModelState.Remove Deyimi, çünkü gereklidir ModelState eski olan RowVersion değeri. Razor Sayfası'nda
ModelState değerinin ikisi de mevcut olduğunda alan üzerinde model özellik değerlerini öncelik kazanır.
Razor sayfasını güncelleştirme
Sayfaları/departmanları/Düzenle. cshtml 'yi aşağıdaki kodla güncelleştirin:
@page "{id:int}"
@model ContosoUniversity.Pages.Departments.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Department</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Department.DepartmentID" />
<input type="hidden" asp-for="Department.RowVersion" />
<div class="form-group">
<label>RowVersion</label>
@Model.Department.RowVersion[7]
</div>
<div class="form-group">
<label asp-for="Department.Name" class="control-label"></label>
<input asp-for="Department.Name" class="form-control" />
<span asp-validation-for="Department.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Department.Budget" class="control-label"></label>
<input asp-for="Department.Budget" class="form-control" />
<span asp-validation-for="Department.Budget" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Department.StartDate" class="control-label"></label>
<input asp-for="Department.StartDate" class="form-control" />
<span asp-validation-for="Department.StartDate" class="text-danger">
</span>
</div>
<div class="form-group">
<label class="control-label">Instructor</label>
<select asp-for="Department.InstructorID" class="form-control"
asp-items="@Model.InstructorNameSL"></select>
<span asp-validation-for="Department.InstructorID" class="text-danger">
</span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Yukarıdaki kod:
Güncelleştirmeleri page gelen yönerge @page için @page "{id:int}" .
Gizli satır sürümü ekler. RowVersion POST geri değere bağlar, böylece eklenmesi gerekir.
Son baytı görüntüler RowVersion hata ayıklama amacıyla.
Değiştirir ViewData türü kesin belirlenmiş ile InstructorNameSL .
Eşzamanlılık çakışmalarını düzenleme sayfası ile test
İki tarayıcılar örneklerinde düzenleme İngilizce departmanı açın:
Uygulamayı çalıştırın ve bölümleri seçin.
Sağ Düzenle seçin ve İngilizce departmanı için köprü yeni sekmede aç.
Birinci sekmede tıklayın Düzenle İngilizce departmanı için köprü.
Aynı bilgilerin iki tarayıcı sekmeleri görüntüleyin.
' A tıklayın ve ilk tarayıcı sekmesine adını değiştirmek Kaydet.

Tarayıcı değiştirilen değer ve güncelleştirilmiş rowVersion göstergesi ile dizin sayfası gösterilir. Güncelleştirilmiş
rowVersion göstergesi, Not, ikinci geri göndermenin diğer sekmesinde görüntülenir.
İkinci bir tarayıcı sekmesinde farklı bir alana değiştirin.
Kaydet’e tıklayın. Veritabanı değerleriyle eşleşmeyen tüm alanlar için hata iletileri görürsünüz:
Ad alanı değiştirmek bu tarayıcı penceresini düşünmediğiniz. Kopyalama ve geçerli değerin (dil) adı alanına
yapıştırın. Sekme genişletme. İstemci tarafı doğrulaması hata iletisini kaldırır.
Tıklayın Kaydet yeniden. İkinci tarayıcı sekmesinde girdiğiniz değer kaydedilir. Dizin sayfasında kaydedilen değerler
görürsünüz.

Silme sayfası
Sayfaları/departmanları/delete. cshtml. cs öğesini aşağıdaki kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Departments
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Department Department { get; set; }
public string ConcurrencyErrorMessage { get; set; }

public async Task<IActionResult> OnGetAsync(int id, bool? concurrencyError)


{
Department = await _context.Departments
.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (Department == null)
{
return NotFound();
}

if (concurrencyError.GetValueOrDefault())
{
ConcurrencyErrorMessage = "The record you attempted to delete "
+ "was modified by another user after you selected delete. "
+ "The delete operation was canceled and the current values in the "
+ "database have been displayed. If you still want to delete this "
+ "record, click the Delete button again.";
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
try
{
if (await _context.Departments.AnyAsync(
m => m.DepartmentID == id))
{
// Department.rowVersion value is from when the entity
// was fetched. If it doesn't match the DB, a
// DbUpdateConcurrencyException exception is thrown.
_context.Departments.Remove(Department);
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToPage("./Delete",
new { concurrencyError = true, id = id });
}
}
}
}

Varlık getirildi sonra değiştiğinde silme sayfası eşzamanlılık çakışmalarını algılar. Department.RowVersion Varlık
getirildi satır sürümü andır. EF Core SQL DELETE komutu oluşturduğunda, WHERE yan tümcesi ile içerdiği
RowVersion . Sıfır satır SQL DELETE komutu sonuçları etkileniyorsa:

SQL DELETE komutundaki RowVersion veritabanındaki RowVersion eşleşmiyor.


DbUpdateConcurrencyException özel durum oluşturulur.
OnGetAsync çağrılır concurrencyError .

Razor Sil sayfasını Güncelleştir


Güncelleştirme Pages/Departments/Delete.cshtml aşağıdaki kod ile:
@page "{id:int}"
@model ContosoUniversity.Pages.Departments.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<p class="text-danger">@Model.ConcurrencyErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Department</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Department.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.Budget)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Budget)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.StartDate)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.StartDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.RowVersion)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.RowVersion[7])
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.Administrator)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Administrator.FullName)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Department.DepartmentID" />
<input type="hidden" asp-for="Department.RowVersion" />
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</div>
</form>
</div>

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


Güncelleştirmeleri page gelen yönerge @page için @page "{id:int}" .
Bir hata iletisi ekler.
FullName FirstMidName değiştirir yönetici alan.
Değişiklikleri RowVersion son bayt görüntülenecek.
Gizli satır sürümü ekler. RowVersion eklenmesi gerekir, çünkü postgit ekleme geri eklemesi değeri bağlar.
Eşzamanlılık çakışmalarını test et
Test bölümü oluşturun.
İki tarayıcılar örneklerinde DELETE test departmanı açın:
Uygulamayı çalıştırın ve bölümleri seçin.
Sağ Sil seçin ve test departmanı için köprü yeni sekmede aç.
Tıklayın Düzenle köprü test bölümü için.
Aynı bilgilerin iki tarayıcı sekmeleri görüntüleyin.
İlk tarayıcı sekmesine bütçede değiştirip'ı Kaydet.
Tarayıcı değiştirilen değer ve güncelleştirilmiş rowVersion göstergesi ile dizin sayfası gösterilir. Güncelleştirilmiş
rowVersion göstergesi, Not, ikinci geri göndermenin diğer sekmesinde görüntülenir.
İkinci sekmeden test departmanını silin. Veritabanında geçerli değerlerle birlikte bir eşzamanlılık hatası
görüntülenir. Tıklayarak Sil sürece varlığını siler RowVersion updated.department silinmiş olmuştur.

Ek kaynaklar
EF Core eşzamanlılık belirteçleri
EF Core eşzamanlılık işleme
2. x kaynağı ASP.NET Core hata ayıklaması

Sonraki adımlar
Bu, serideki son öğreticidir. Bu öğretici serisinin MVC sürümündeek konular ele alınmıştır.

ÖN CEKI
Ö Ğ R E T IC I

Bu öğreticide, birden çok kullanıcı aynı anda (aynı anda) bir varlık güncelleştirdiğinizde çakışmalarına
gösterilmektedir. Olamaz çözmenize, sorunlarla karşılaşırsanız, indirin veya tamamlanmış uygulamayı görüntüleyin.
Yükleme yönergeleri.

Eşzamanlılık çakışmaları
Bir eşzamanlılık çakışması ortaya olduğunda:
Bir kullanıcı bir varlığın düzenleme sayfasına götürür.
İlk kullanıcının değişiklik DB'ye yazılmadan önce başka bir kullanıcı aynı varlık güncelleştirir.
Eşzamanlılık algılama etkin değil, eş zamanlı güncelleştirmeler olduğunda:
Son güncelleştirme WINS. Diğer bir deyişle, son güncelleştirme değerleri Veritabanına kaydedilir.
Geçerli güncelleştirme ilk kaybolur.
İyimser eşzamanlılık
İyimser eşzamanlılık eşzamanlılık çakışmalarını olmasını sağlar ve tepki verdiğini uygun olduğunda bunlar yapın.
Örneğin, Jane departmanı Düzen sayfasını ziyaret ve İngilizce departmanı için bütçe 350,000.00 $0,00 değiştirir.
Jane tıkladığında önce Kaydet, John aynı sayfayı ziyaret eder ve alanın başlangıç tarihi 1/9/2013 1/9/2007'deki
değiştirir.
Jane tıkladığında Kaydet ilk ve her tarayıcı dizin sayfası görüntülendiğinde değiştirme görür.

John tıkladığında Kaydet yine de bir bütçe $350,000.00 birini gösteren bir Düzenle sayfasında. Sonraki işlemin ne
eşzamanlılık çakışmalarını nasıl ele tarafından belirlenir.
İyimser eşzamanlılık aşağıdaki seçenekleri içerir:
Bir kullanıcı değiştirmiş hangi özelliğinin kaydını ve yalnızca ilgili sütunları DB'de güncelleştirin.
Bu senaryoda, veri kaybolacak. Farklı özellikler iki kullanıcı tarafından güncelleştirildi. Biri İngilizce,
departman gözatar sonraki açışınızda Gamze'nin hem Can'ın değişiklikleri görürler. Bu güncelleştirme
yöntemini, veri kaybına neden olabilecek çakışmaları sayısını azaltabilirsiniz. Bu yaklaşım:
Aynı özelliğe rakip bir değişiklik yaptıysanız, veri kaybını önlemek olamaz.
Genellikle bir web uygulaması pratik değildir. Tüm getirilen ve yeni değerleri izlemek için önemli durum
koruma gerektiriyor. Büyük miktarlarda durumu bakımını yapma, uygulama performansını etkileyebilir.
Bir varlıkta eşzamanlılık algılama ile karşılaştırıldığında app karmaşıklığı artırabilirsiniz.
Gamze'nin değişikliğinin üzerine Can'ın değişiklik sağlayabilirsiniz.
Sonraki biri İngilizce departmanı gözatar, 1/9/2013 görürler ve getirilen $350,000.00 değeri. Bu yaklaşım
olarak adlandırılan bir istemci WINS veya WINS'te son senaryo. (İstemciden gelen tüm değerler veri
deposunda yer alacak şekilde önceliklidir.) Eşzamanlılık işleme için herhangi bir kodlama yapmazsanız,
Istemci WINS otomatik olarak gerçekleşir.
Can'ın değişiklik DB'de güncelleştirilmesini engelleyebilir. Genellikle, bir uygulamayı atadığınız:
Bir hata iletisi görüntüler.
Verilerin geçerli durumunu gösterir.
Değişiklikleri uygulamak verin.
Bu adlı bir Store WINS senaryo. (Veri deposu değerleri, istemci tarafından gönderilen değerlere göre
önceliklidir.) Bu öğreticide mağaza WINS senaryosunu uygulamanız gerekir. Bu yöntem, hiçbir değişiklik
uyarı bir kullanıcı kılınmamasını sağlar.

Eşzamanlılığı işleme
Ne zaman bir özellik olarak yapılandırıldığında bir eşzamanlılık belirteci:
EF Core getirildi sonra'nın özellik değiştirilmedi doğrular. Onay gerçekleşir, SaveChanges veya
SaveChangesAsync çağrılır.
Özelliği, getirildikten sonra değiştirilmişse, bir DbUpdateConcurrencyException oluşturulur.
DB ve veri modeli oluşturma destekleyecek şekilde yapılandırılması gerekir DbUpdateConcurrencyException .
Bir özellik eşzamanlılık çakışmaları algılama
Eşzamanlılık çakışmaları ile özellik düzeyinde algılanamıyor ConcurrencyCheck özniteliği. Öznitelik, birden çok
modelin özellikleri için uygulanabilir. Daha fazla bilgi için veri ek açıklamaları-ConcurrencyCheck.
[ConcurrencyCheck] Özniteliği, bu öğreticide kullanılmaz.
Bir satırda eşzamanlılık çakışmaları algılama
Eşzamanlılık çakışmalarını algılamak için bir rowversion sütun izleme modele eklenir. rowversion :
SQL Server özeldir. Diğer veritabanlarının benzer bir özellik sağlamayabilir.
Veritabanından getirildikten sonra'nın bir varlık değiştirilmediğinden belirlemek için kullanılır.
Bir sıralı bir veritabanı oluşturur rowversion her zaman satır artan sayısı güncelleştirilir. İçinde bir Update veya
Delete komutu Where yan tümcesi içeren getirilen değeri rowversion . Güncelleştirilen satır değiştiyse:

rowversiongetirilen değeri ile eşleşmiyor.


Update Veya Delete olduğundan, komut satır Bul yok Where yan tümcesi içeren getirilen rowversion .
A DbUpdateConcurrencyException oluşturulur.
EF Core tarafından hiçbir satır güncelleştirildiğinde içinde bir Update veya Delete komutu, bir eşzamanlılık özel
durumu oluşturulur.
Departman varlığa izleme özelliği ekleme
İçinde Models/Department.cs, RowVersion adlı izleme özelliği ekleyin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Zaman damgası özniteliği, bu sütunda yer belirtir Where yan tümcesi Update ve Delete komutları. Adlandırılan
öznitelik Timestamp bir SQL SQL Server'ın önceki sürümlerinde kullanılan çünkü timestamp veri türü SQL önce
rowversion türü değiştirildi.

Fluent API'si izleme özelliği de belirtebilirsiniz:

modelBuilder.Entity<Department>()
.Property<byte[]>("RowVersion")
.IsRowVersion();

Aşağıdaki kod, T-SQL bölüm adını güncelleştirildiğinde EF Core tarafından oluşturulan bir bölümü
gösterilmektedir:

SET NOCOUNT ON;


UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;

Önceki kodun gösterdiği vurgulanmış WHERE yan tümcesi içeren RowVersion . Varsa DB RowVersion eşit değildir
RowVersion parametre ( @p2 ), satır güncelleştirilir.

Aşağıdaki vurgulanmış kodu tam olarak bir satır güncellenmedi doğrular T-SQL gösterir:
SET NOCOUNT ON;
UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;

@@ROWCOUNT son deyiminden etkilenen satır sayısını döndürür. Hayır, satır güncelleştirilir, EF Core oluşturur
bir DbUpdateConcurrencyException .
T-SQL EF Core oluşturur Visual Studio çıktı penceresinde görebilirsiniz.
DB update
Ekleme RowVersion geçiş gerektiren DB modeli özelliğini değiştirir.
Projeyi oluşturun. Bir komut penceresinde aşağıdakileri girin:

dotnet ef migrations add RowVersion


dotnet ef database update

Yukarıdaki komutlar:
Ekler geçişleri / {zaman stamp }_RowVersion.cs geçiş dosyası.
Güncelleştirmeleri Migrations/SchoolContextModelSnapshot.cs dosya. Bu güncelleştirme aşağıdaki
vurgulanmış kodu ekler BuildModel yöntemi:

DB güncelleştirilemedi geçişlerini çalıştırır.

İskele Departmanlar modeli


Visual Studio
Visual Studio Code
Bölümündeki yönergeleri Öğrenci modeli iskelesini ve Department model sınıfı için.
Önceki komut iskelesini kurar Department modeli. Projeyi Visual Studio'da açın.
Projeyi oluşturun.
Departmanlar dizin sayfası
Oluşturulan yapı iskelesi altyapısı bir RowVersion sütunu için dizin sayfasını, ancak bu alanı olmamalıdır
görüntülenecek. Bu öğreticide, son baytı RowVersion eşzamanlılık anlamanıza yardımcı olması için görüntülenir.
Son bayta kalan benzersiz olması garanti yoktur. Gerçek bir uygulamada görüntüleyemiyordu RowVersion veya son
baytı RowVersion .
Dizin Sayfası güncelleştirin:
Dizin bölümlerine değiştirin.
Biçimlendirme içeren değiştirin RowVersion son baytı ile RowVersion .
FirstMidName tam adı ile değiştirin.
Güncelleştirilen sayfaya aşağıdaki işaretlemeyi gösterir:
@page
@model ContosoUniversity.Pages.Departments.IndexModel

@{
ViewData["Title"] = "Departments";
}

<h2>Departments</h2>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Department[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].Budget)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].StartDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Department[0].Administrator)
</th>
<th>
RowVersion
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Department) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Budget)
</td>
<td>
@Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Administrator.FullName)
</td>
<td>
@item.RowVersion[7]
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.DepartmentID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.DepartmentID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.DepartmentID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Düzenleme sayfa modeli güncelleştirme


Aşağıdaki kodla Pages\Departments\Edit.cshtml.cs güncelleştirin:

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Departments
{
public class EditModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public EditModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Department Department { get; set; }
// Replace ViewData["InstructorID"]
public SelectList InstructorNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(int id)


{
Department = await _context.Departments
.Include(d => d.Administrator) // eager loading
.AsNoTracking() // tracking not required
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (Department == null)
{
return NotFound();
}

// Use strongly typed data rather than ViewData.


InstructorNameSL = new SelectList(_context.Instructors,
"ID", "FirstMidName");

return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
if (!ModelState.IsValid)
{
return Page();
}

var departmentToUpdate = await _context.Departments


.Include(i => i.Administrator)
.FirstOrDefaultAsync(m => m.DepartmentID == id);

// null means Department was deleted by another user.


if (departmentToUpdate == null)
{
return HandleDeletedDepartment();
}

// Update the RowVersion to the value when this entity was


// fetched. If the entity has been updated after it was
// fetched, RowVersion won't match the DB RowVersion and
// a DbUpdateConcurrencyException is thrown.
// A second postback will make them match, unless a new
// concurrency issue happens.
_context.Entry(departmentToUpdate)
.Property("RowVersion").OriginalValue = Department.RowVersion;

if (await TryUpdateModelAsync<Department>(
if (await TryUpdateModelAsync<Department>(
departmentToUpdate,
"Department",
s => s.Name, s => s.StartDate, s => s.Budget, s => s.InstructorID))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Must clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}
}

InstructorNameSL = new SelectList(_context.Instructors,


"ID", "FullName", departmentToUpdate.InstructorID);

return Page();
}

private IActionResult HandleDeletedDepartment()


{
var deletedDepartment = new Department();
// ModelState contains the posted data because of the deletion error and will overide the
Department instance values when displaying Page().
ModelState.AddModelError(string.Empty,
"Unable to save. The department was deleted by another user.");
InstructorNameSL = new SelectList(_context.Instructors, "ID", "FullName", Department.InstructorID);
return Page();
}

private async Task setDbErrorMessage(Department dbValues,


Department clientValues, SchoolContext context)
{

if (dbValues.Name != clientValues.Name)
{
ModelState.AddModelError("Department.Name",
$"Current value: {dbValues.Name}");
}
if (dbValues.Budget != clientValues.Budget)
{
ModelState.AddModelError("Department.Budget",
$"Current value: {dbValues.Budget:c}");
}
if (dbValues.StartDate != clientValues.StartDate)
{
ModelState.AddModelError("Department.StartDate",
$"Current value: {dbValues.StartDate:d}");
}
if (dbValues.InstructorID != clientValues.InstructorID)
{
Instructor dbInstructor = await _context.Instructors
.FindAsync(dbValues.InstructorID);
ModelState.AddModelError("Department.InstructorID",
$"Current value: {dbInstructor?.FullName}");
}

ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}
}
}

Bir eşzamanlılık algılanması OriginalValue güncelleştirilmesi rowVersion alınan varlık değeri. EF Core özgün içeren
bir WHERE yan tümcesi ile SQL güncelleştirme komut oluşturur RowVersion değeri. Hiçbir satır güncelleştirme
komutu tarafından etkileniyorsanız (hiçbir satır özgün sahip RowVersion değer), DbUpdateConcurrencyException özel
durumu oluşturulur.

public async Task<IActionResult> OnPostAsync(int id)


{
if (!ModelState.IsValid)
{
return Page();
}

var departmentToUpdate = await _context.Departments


.Include(i => i.Administrator)
.FirstOrDefaultAsync(m => m.DepartmentID == id);

// null means Department was deleted by another user.


if (departmentToUpdate == null)
{
return HandleDeletedDepartment();
}

// Update the RowVersion to the value when this entity was


// fetched. If the entity has been updated after it was
// fetched, RowVersion won't match the DB RowVersion and
// a DbUpdateConcurrencyException is thrown.
// A second postback will make them match, unless a new
// concurrency issue happens.
_context.Entry(departmentToUpdate)
.Property("RowVersion").OriginalValue = Department.RowVersion;

Önceki kodda, Department.RowVersion varlık getirildi değeri olur. OriginalValue DB değer olduğunda
FirstOrDefaultAsync bu yöntemi çağrıldı.
Aşağıdaki kod, istemci değerler (Bu yönteme gönderilen değerler) ve DB değerleri alır:
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Must clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}

Aşağıdaki kod, OnPostAsync gönderilen değerden farklı olan DB değerleri olan her bir sütun için özel bir hata iletisi
ekler:

private async Task setDbErrorMessage(Department dbValues,


Department clientValues, SchoolContext context)
{

if (dbValues.Name != clientValues.Name)
{
ModelState.AddModelError("Department.Name",
$"Current value: {dbValues.Name}");
}
if (dbValues.Budget != clientValues.Budget)
{
ModelState.AddModelError("Department.Budget",
$"Current value: {dbValues.Budget:c}");
}
if (dbValues.StartDate != clientValues.StartDate)
{
ModelState.AddModelError("Department.StartDate",
$"Current value: {dbValues.StartDate:d}");
}
if (dbValues.InstructorID != clientValues.InstructorID)
{
Instructor dbInstructor = await _context.Instructors
.FindAsync(dbValues.InstructorID);
ModelState.AddModelError("Department.InstructorID",
$"Current value: {dbInstructor?.FullName}");
}

ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}
Aşağıdaki vurgulanmış kodu kümeleri RowVersion değerden yeni değere Veritabanından alınır. Kullanıcının bir
sonraki tıklayışında Kaydet, düzenleme sayfası son görüntülenmesini yakalandı beri gerçekleşen eşzamanlılık
hataları.

try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The department was deleted by another user.");
return Page();
}

var dbValues = (Department)databaseEntry.ToObject();


await setDbErrorMessage(dbValues, clientValues, _context);

// Save the current RowVersion so next postback


// matches unless an new concurrency issue happens.
Department.RowVersion = (byte[])dbValues.RowVersion;
// Must clear the model error for the next postback.
ModelState.Remove("Department.RowVersion");
}

ModelState.Remove Deyimi, çünkü gereklidir ModelState eski olan RowVersion değeri. Razor Sayfası'nda
ModelState değerinin ikisi de mevcut olduğunda alan üzerinde model özellik değerlerini öncelik kazanır.

Güncelleştirme düzenleme sayfası


Güncelleştirme Pages/Departments/Edit.cshtml aşağıdaki işaretlemeyle:
@page "{id:int}"
@model ContosoUniversity.Pages.Departments.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Department</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Department.DepartmentID" />
<input type="hidden" asp-for="Department.RowVersion" />
<div class="form-group">
<label>RowVersion</label>
@Model.Department.RowVersion[7]
</div>
<div class="form-group">
<label asp-for="Department.Name" class="control-label"></label>
<input asp-for="Department.Name" class="form-control" />
<span asp-validation-for="Department.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Department.Budget" class="control-label"></label>
<input asp-for="Department.Budget" class="form-control" />
<span asp-validation-for="Department.Budget" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Department.StartDate" class="control-label"></label>
<input asp-for="Department.StartDate" class="form-control" />
<span asp-validation-for="Department.StartDate" class="text-danger">
</span>
</div>
<div class="form-group">
<label class="control-label">Instructor</label>
<select asp-for="Department.InstructorID" class="form-control"
asp-items="@Model.InstructorNameSL"></select>
<span asp-validation-for="Department.InstructorID" class="text-danger">
</span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Önceki işaretlemesi:
Güncelleştirmeleri page gelen yönerge @page için @page "{id:int}" .
Gizli satır sürümü ekler. RowVersion POST geri değere bağlar, böylece eklenmesi gerekir.
Son baytı görüntüler RowVersion hata ayıklama amacıyla.
Değiştirir ViewData türü kesin belirlenmiş ile InstructorNameSL .

Eşzamanlılık çakışmalarını düzenleme sayfası ile test


İki tarayıcılar örneklerinde düzenleme İngilizce departmanı açın:
Uygulamayı çalıştırın ve bölümleri seçin.
Sağ Düzenle seçin ve İngilizce departmanı için köprü yeni sekmede aç.
Birinci sekmede tıklayın Düzenle İngilizce departmanı için köprü.
Aynı bilgilerin iki tarayıcı sekmeleri görüntüleyin.
' A tıklayın ve ilk tarayıcı sekmesine adını değiştirmek Kaydet.

Tarayıcı değiştirilen değer ve güncelleştirilmiş rowVersion göstergesi ile dizin sayfası gösterilir. Güncelleştirilmiş
rowVersion göstergesi, Not, ikinci geri göndermenin diğer sekmesinde görüntülenir.
İkinci bir tarayıcı sekmesinde farklı bir alana değiştirin.
Kaydet’e tıklayın. DB değerleri eşleşmeyen tüm alanlar için hata iletileri görürsünüz:
Ad alanı değiştirmek bu tarayıcı penceresini düşünmediğiniz. Kopyalama ve geçerli değerin (dil) adı alanına
yapıştırın. Sekme genişletme. İstemci tarafı doğrulaması hata iletisini kaldırır.
Tıklayın Kaydet yeniden. İkinci tarayıcı sekmesinde girdiğiniz değer kaydedilir. Dizin sayfasında kaydedilen değerler
görürsünüz.

Silme sayfası
Delete sayfa modeli aşağıdaki kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Departments
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}

[BindProperty]
public Department Department { get; set; }
public string ConcurrencyErrorMessage { get; set; }

public async Task<IActionResult> OnGetAsync(int id, bool? concurrencyError)


{
Department = await _context.Departments
.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.DepartmentID == id);

if (Department == null)
{
return NotFound();
}

if (concurrencyError.GetValueOrDefault())
{
ConcurrencyErrorMessage = "The record you attempted to delete "
+ "was modified by another user after you selected delete. "
+ "The delete operation was canceled and the current values in the "
+ "database have been displayed. If you still want to delete this "
+ "record, click the Delete button again.";
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
try
{
if (await _context.Departments.AnyAsync(
m => m.DepartmentID == id))
{
// Department.rowVersion value is from when the entity
// was fetched. If it doesn't match the DB, a
// DbUpdateConcurrencyException exception is thrown.
_context.Departments.Remove(Department);
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToPage("./Delete",
new { concurrencyError = true, id = id });
}
}
}
}

Varlık getirildi sonra değiştiğinde silme sayfası eşzamanlılık çakışmalarını algılar. Department.RowVersion Varlık
getirildi satır sürümü andır. EF Core SQL DELETE komutu oluşturduğunda, WHERE yan tümcesi ile içerdiği
RowVersion . Sıfır satır SQL DELETE komutu sonuçları etkileniyorsa:

RowVersionSQL DELETE komutu eşleşmiyor RowVersion DB'de.


DbUpdateConcurrencyException özel durum oluşturulur.
OnGetAsync çağrılır concurrencyError .

Silme sayfası
Güncelleştirme Pages/Departments/Delete.cshtml aşağıdaki kod ile:

@page "{id:int}"
@model ContosoUniversity.Pages.Departments.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<p class="text-danger">@Model.ConcurrencyErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Department</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Department.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.Budget)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Budget)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.StartDate)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.StartDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.RowVersion)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.RowVersion[7])
</dd>
<dt>
@Html.DisplayNameFor(model => model.Department.Administrator)
</dt>
<dd>
@Html.DisplayFor(model => model.Department.Administrator.FullName)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Department.DepartmentID" />
<input type="hidden" asp-for="Department.RowVersion" />
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-page="./Index">Back to List</a>
</div>
</form>
</div>

Yukarıdaki kod aşağıdaki değişiklikleri yapar:


Güncelleştirmeleri page gelen yönerge @page için @page "{id:int}" .
Bir hata iletisi ekler.
FullName FirstMidName değiştirir yönetici alan.
Değişiklikleri RowVersion son bayt görüntülenecek.
Gizli satır sürümü ekler. RowVersion POST geri değere bağlar, böylece eklenmesi gerekir.
Eşzamanlılık çakışmalarını silme sayfası ile test
Test bölümü oluşturun.
İki tarayıcılar örneklerinde DELETE test departmanı açın:
Uygulamayı çalıştırın ve bölümleri seçin.
Sağ Sil seçin ve test departmanı için köprü yeni sekmede aç.
Tıklayın Düzenle köprü test bölümü için.
Aynı bilgilerin iki tarayıcı sekmeleri görüntüleyin.
İlk tarayıcı sekmesine bütçede değiştirip'ı Kaydet.
Tarayıcı değiştirilen değer ve güncelleştirilmiş rowVersion göstergesi ile dizin sayfası gösterilir. Güncelleştirilmiş
rowVersion göstergesi, Not, ikinci geri göndermenin diğer sekmesinde görüntülenir.
İkinci sekmeden test departmanını silin. Bir eşzamanlılık hatası, VERITABANıNDAKI geçerli değerlerle birlikte
görüntülenir. Tıklayarak Sil sürece varlığını siler RowVersion updated.department silinmiş olmuştur.
Bkz: devralma nasıl bir veri modeli devralır.
Ek kaynaklar
EF Core eşzamanlılık belirteçleri
EF Core eşzamanlılık işleme
Bu öğreticinin YouTube sürümü (eşzamanlılık çakışmalarını Işleme)
Bu öğreticinin YouTube sürümü (Bölüm 2)
Bu öğreticinin YouTube sürümü (Bölüm 3)

ÖN CEKI
EF Core öğreticisi serisi ile MVC ASP.NET Core
13.11.2019 • 2 minutes to read • Edit Online

Bu öğretici 3,0 ASP.NET Core güncelleştirilmedi. Razor Pages sürümü güncelleştirildi. Bunun ne zaman
güncelleştirilemeyebilir hakkında bilgi edinmek için Bu GitHub sorununabakın.
Bu öğretici, ASP.NET Core MVC ve denetleyiciler ve görünümlerle Entity Framework Core öğretir. Razor Pages ,
ASP.NET Core 2,0 ' de tanıtılan alternatif bir programlama modelidir. Yeni geliştirme için, denetleyiciler ve
görünümlerle MVC üzerinde Razor Pages önerilir. Bu öğreticinin Razor Pages bir sürümü bulunmaktadır. Her
öğreticide diğer malzemeler ele alınmaktadır:
Bu MVC öğreticisine bazı şeyler Razor Pages öğreticiye sahip değildir:
Veri modelinde devralma uygulama
Ham SQL sorguları gerçekleştirme
Kodu basitleştirmek için dinamik LINQ kullanma
Razor Pages öğreticide şunları gerçekleştirmeyen şeyler:
İlgili verileri yüklemek için Select metodunu kullanın
ASP.NET Core 3,0 için kullanılabilen bir sürüm
1. Kullanmaya başlama
2. İşlem Oluşturma, Okuma, Güncelleştirme ve Silme
3. Sıralama, filtreleme, disk belleği ve gruplandırma
4. Geçişler
5. Karmaşık veri modeli oluşturma
6. İlgili verileri okuma
7. İlgili verileri güncelleştirme
8. Eşzamanlılık çakışmalarını işleme
9. Devralma
10. Gelişmiş konular
Öğretici: bir ASP.NET MVC web uygulamasında EF
Core kullanmaya başlama
23.11.2019 • 34 minutes to read • Edit Online

Bu öğretici 3,0 ASP.NET Core güncelleştirilmedi. Razor Pages sürümü güncelleştirildi. Bunun ne zaman
güncelleştirilemeyebilir hakkında bilgi edinmek için Bu GitHub sorununabakın.
Bu öğretici, ASP.NET Core MVC ve denetleyiciler ve görünümlerle Entity Framework Core öğretir. Razor Pages ,
ASP.NET Core 2,0 ' de tanıtılan alternatif bir programlama modelidir. Yeni geliştirme için, denetleyiciler ve
görünümlerle MVC üzerinde Razor Pages önerilir. Bu öğreticinin Razor Pages bir sürümü bulunmaktadır. Her
öğreticide diğer malzemeler ele alınmaktadır:
Bu MVC öğreticisine bazı şeyler Razor Pages öğreticiye sahip değildir:
Veri modelinde devralma uygulama
Ham SQL sorguları gerçekleştirme
Kodu basitleştirmek için dinamik LINQ kullanma
Razor Pages öğreticide şunları gerçekleştirmeyen şeyler:
İlgili verileri yüklemek için Select metodunu kullanın
ASP.NET Core 3,0 için kullanılabilen bir sürüm
Contoso Üniversitesi örnek Web uygulaması, Entity Framework (EF ) Core 2,2 ve Visual Studio 2017 veya 2019
kullanarak ASP.NET Core 2,2 MVC web uygulamalarının nasıl oluşturulacağını gösterir.
Örnek uygulama, kurgusal bir Contoso Üniversitesi için bir Web sitesidir. Öğrenci giriş, kurs oluşturma ve Eğitmen
atamaları gibi işlevleri içerir. Bu, Contoso Üniversitesi örnek uygulamasının sıfırdan nasıl oluşturulacağını açıklayan
bir öğretici serisinin ilkisidir.
Bu öğreticide şunları yaptınız:
ASP.NET Core MVC web uygulaması oluşturma
Site stili Ayarla
EF Core NuGet paketleri hakkında bilgi edinin
Veri modeli oluşturma
Veritabanı bağlamını oluşturma
Bağımlılık ekleme için bağlamı kaydetme
Test verileriyle veritabanını başlatma
Denetleyici ve görünüm oluşturma
Veritabanını görüntüleme

Önkoşullar
.NET Core SDK 2,2
Aşağıdaki iş yükleriyle Visual Studio 2019 :
ASP.net ve Web geliştirme iş yükü
.NET Core platformlar arası geliştirme iş yükü
Sorun giderme
Bir sorunla karşılaşırsanız, çözümleyemiyor çalıştırırsanız, genel olarak çözüm kodunuzda karşılaştırarak
bulabilirsiniz projeyi. Yaygın hataların bir listesi ve bunların nasıl çözüleceği için, serideki son öğreticinin sorun
giderme bölümünebakın. İhtiyacınız olanları bulamazsanız, ASP.NET Core veya EF Coreiçin bir soru
gönderebilirsiniz.

TIP
Bu, her biri daha önceki öğreticilerde gerçekleştirilen bir dizi 10 öğreticisidir. Her başarılı öğreticinin tamamlanmasından sonra
projenin bir kopyasını kaydetmeyi göz önünde bulundurun. Daha sonra sorunlarla karşılaşırsanız, tüm serinin başlangıcına
dönmek yerine önceki öğreticiden baştan başlayabilirsiniz.

Contoso Üniversitesi web uygulaması


Bu öğreticilerde oluşturacağınız uygulama basit bir üniversite web sitesidir.
Kullanıcılar görüntüleyebilir ve Öğrenci, kurs ve Eğitmen bilgileri güncelleştirin. Oluşturacağınız ekranların bazıları
aşağıda verilmiştir.
Web uygulaması oluşturma
Visual Studio'yu açın.
Dosya menüsünden Yeni > proje' yi seçin.
Sol bölmeden, Visual C# > Web > yüklü' i seçin.
ASP.NET Core Web uygulaması proje şablonunu seçin.
Ad olarak Contosouniversity yazın ve Tamam' a tıklayın.

Yeni ASP.NET Core Web uygulaması iletişim kutusunun görünmesini bekleyin.


.NET Core, ASP.NET Core 2,2 ve Web uygulaması (Model-View-Controller) şablonu ' nu seçin.
Kimlik doğrulamanın kimlik doğrulaması yokolarak ayarlandığından emin olun.
Tamam 'ı seçin

Site stili Ayarla


Birkaç basit değişiklik, site menüsünü, düzeni ve giriş sayfasını ayarlar.
Görünümler/paylaşılan/_Layout. cshtml dosyasını açın ve aşağıdaki değişiklikleri yapın:
"Contoso Üniversitesi" için "ContosoUniversity" her örneğini değiştirin. Üç örnekleri vardır.
Hakkında, öğrenciler, Kurslar, eğitmenlerve Departmanlariçin menü girişleri ekleyin ve Gizlilik menü
girişini silin.
Değişiklikler vurgulanır.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Contoso University</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.1.3/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute"
crossorigin="anonymous"
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
</environment>
<link rel="stylesheet" href="~/css/site.css" />
</head>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow
mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Contoso
University</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="About">About</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Students" asp-
action="Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Courses" asp-
action="Index">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Instructors" asp-
action="Index">Instructors</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Departments" asp-
action="Index">Departments</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<partial name="_CookieConsentPartial" />
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Contoso University - <a asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</div>
</footer>

<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
</script>
</environment>
<script src="~/js/site.js" asp-append-version="true"></script>

@RenderSection("Scripts", required: false)


</body>
</html>

Görünümler/Home/Index. cshtml'de, ASP.net ve MVC hakkındaki metni bu uygulamayla ilgili metinle değiştirmek
için dosyanın içeriğini aşağıdaki kodla değiştirin:

@{
ViewData["Title"] = "Home Page";
}

<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core MVC web application.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the
tutorial &raquo;</a></p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p><a class="btn btn-default"
href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final">See
project source code &raquo;</a></p>
</div>
</div>

Projeyi çalıştırmak için CTRL + F5 tuşlarına basın veya menüden hata ayıklama > Başlat ' ı seçin. Bu öğreticilerde
oluşturacağınız sayfaların sekmelerini içeren giriş sayfasını görürsünüz.
NuGet paketleri EF Core hakkında
Bir projeye EF Core destek eklemek için hedeflemek istediğiniz veritabanı sağlayıcısını yükleyebilirsiniz. Bu öğretici
SQL Server kullanır ve sağlayıcı paketi Microsoft. EntityFrameworkCore. SqlServer' dır. Bu paket Microsoft.
AspNetCore. app metapackageiçinde bulunur, bu nedenle pakete başvurmanız gerekmez.
EF SQL Server paketi ve bağımlılıkları ( Microsoft.EntityFrameworkCore ve
Microsoft.EntityFrameworkCore.Relational ) EF için çalışma zamanı desteği sağlar. Geçiş öğreticisinde daha sonra bir
araç paketi ekleyeceksiniz.
Entity Framework Core için kullanılabilen diğer veritabanı sağlayıcıları hakkında daha fazla bilgi için bkz. veritabanı
sağlayıcıları.

Veri modeli oluşturma


Daha sonra Contoso Üniversitesi uygulaması için varlık sınıfları oluşturacaksınız. Aşağıdaki üç varlıkla
başlayacaksınız.
Student ve Enrollment varlıkları arasında bire çok ilişki vardır ve Course ile Enrollment varlıkları arasında bire
çok bir ilişki vardır. Diğer bir deyişle, bir öğrenci herhangi bir sayıda kursa kaydedilebilir ve bir kurs, kayıtlı sayıda
öğrenciye sahip olabilir.
Aşağıdaki bölümlerde, bu varlıkların her biri için bir sınıf oluşturacaksınız.
Öğrenci varlık

Modeller klasöründe, Student.cs adlı bir sınıf dosyası oluşturun ve şablon kodunu aşağıdaki kodla değiştirin.

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

ID özelliği, bu sınıfa karşılık gelen veritabanı tablosunun birincil anahtar sütunu olacak. Varsayılan olarak, Entity
Framework ID veya classnameID adında bir özelliği birincil anahtar olarak yorumlar.
Enrollments Özelliği bir gezinti özelliği. Gezinti özellikleri, bu varlıkla ilgili diğer varlıkları tutar. Bu durumda, bir
Student entity Enrollments özelliği, bu Student varlıkla ilgili Enrollment varlıkların tümünü tutacaktır. Diğer bir
deyişle, veritabanında verilen bir öğrenci satırı, iki ilişkili kayıt satırına (bu öğrencinin birincil anahtar değerini kendi
StudentID yabancı anahtar sütununda içeren satırlar) sahipse, Student varlığın Enrollments gezinti özelliği bu iki
Enrollment varlığını içerir.

Bir gezinti özelliği birden çok varlığı tutabileceiyorsa (çok-çok veya bire çok ilişkilerde olduğu gibi), türü
ICollection<T> gibi girişlerin eklenebileceği, silinebileceği ve güncelleştirilemeyebilir bir liste olmalıdır.
ICollection<T> veya List<T> veya HashSet<T> gibi bir tür belirtebilirsiniz. ICollection<T> belirtirseniz, EF
varsayılan olarak bir HashSet<T> koleksiyonu oluşturur.
Kayıt varlık

Modeller klasöründe enrollment.cs oluşturun ve mevcut kodu şu kodla değiştirin:

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

EnrollmentID özelliği birincil anahtar olacaktır; Bu varlık, Student varlığında gördüğünüz gibi kendisini ID yerine
classnameID modelini kullanır. Normalde tek bir model seçip veri modeliniz genelinde kullanabilirsiniz. Burada,
değişim, her iki stili de kullanabileceğinizi gösterir. Daha sonraki bir öğreticide, ID 'yi ClassName olmadan
kullanarak, veri modelinde devralma uygulamayı daha kolay hale getirir.
Grade Özelliği bir enum . Sonra soru işareti Grade türü bildirimi gösterir Grade özelliği boş değer atanabilir. Boş
bir sınıf bir sıfır sınıf farklı--null anlamına gelir bir sınıf bilinen değil veya henüz atanmamış.
StudentID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Student . Enrollment bir varlık
bir Student varlığıyla ilişkilendirilir, bu nedenle özellik yalnızca tek bir Student varlığı tutabilir (daha önce
gördüğünüz Student.Enrollments gezinti özelliğinden farklı olarak, birden çok Enrollment varlığı tutabilir).
CourseID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Course . Bir Enrollment varlıktır
biriyle ilişkili Course varlık.
Entity Framework, <navigation property name><primary key property name> adında bir özelliği yabancı anahtar
özelliği olarak Yorumlar (örneğin, Student varlığının birincil anahtarı ID olduğundan Student gezinti özelliği için
StudentID ). Yabancı anahtar özelliklerine de yalnızca <primary key property name> (örneğin CourseID , Course
varlığının birincil anahtarı CourseID olduğundan) adlandırılmış olabilir.
Kurs varlık
Modeller klasöründe Course.cs oluşturun ve mevcut kodu şu kodla değiştirin:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Enrollments Özelliktir bir gezinme özelliği. A Course varlık dilediğiniz sayıda ilgili olabileceğini Enrollment
varlıklar.
Bu serinin sonraki bir öğreticide DatabaseGenerated özniteliği hakkında daha fazla bilgi edineceksiniz. Temel olarak
bu öznitelik, veritabanının oluşturması yerine kursa ait birincil anahtarı girmenize olanak sağlar.

Veritabanı bağlamını oluşturma


Belirli bir veri modeli için Entity Framework işlevselliğini koordine eden ana sınıf veritabanı bağlamı sınıfıdır. Bu
sınıfı, Microsoft.EntityFrameworkCore.DbContext sınıfından türeterek oluşturursunuz. Kodunuzda, veri modeline
hangi varlıkların ekleneceğini belirtirsiniz. Ayrıca, belirli Entity Framework davranışlarını özelleştirebilirsiniz. Bu
projede adlı sınıfı SchoolContext .
Proje klasöründe, veriadlı bir klasör oluşturun.
Veri klasöründe, SchoolContext.csadlı yeni bir sınıf dosyası oluşturun ve şablon kodunu şu kodla değiştirin:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
}
}
Bu kod, her varlık kümesi için bir DbSet özelliği oluşturur. Entity Framework terimlerinde, genellikle bir varlık
kümesi bir veritabanı tablosuna karşılık gelir ve bir varlık tablodaki bir satıra karşılık gelir.
DbSet<Enrollment> ve DbSet<Course>deyimlerini atlamış olabilirsiniz ve aynı şekilde çalışır. Entity Framework,
Student varlık Enrollment varlığına başvurduğundan ve Enrollment varlığı Course varlığına başvurduğundan
bunları örtülü olarak içerebilir.
Veritabanı oluşturulduğunda EF, DbSet Özellik adlarıyla aynı adlara sahip tablolar oluşturur. Koleksiyonlar için
özellik adları genellikle plural (öğrenci yerine öğrenciler), ancak geliştiriciler tablo adlarının plurulululmasını kabul
etmez. Bu öğreticiler için DbContext içinde tekil tablo adları belirterek varsayılan davranışı geçersiz kılarsınız. Bunu
yapmak için, son DbSet özelliğinden sonra aşağıdaki vurgulanmış kodu ekleyin.

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}

SchoolContext kaydetme
ASP.NET Core, varsayılan olarak bağımlılık ekleme işlemini uygular. Hizmetler (EF veritabanı bağlamı gibi)
uygulama başlatma sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetleri gerektiren bileşenler (MVC
denetleyicileri gibi) bu hizmetleri Oluşturucu parametreleri aracılığıyla sağlamaktadır. Bu öğreticide daha sonra bir
bağlam örneği alan denetleyici Oluşturucu kodunu görürsünüz.
SchoolContext bir hizmet olarak kaydetmek için Startup.csaçın ve vurgulanan satırları ConfigureServices
yöntemine ekleyin.

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddMvc();
}
Bağlantı dizesinin adı, DbContextOptionsBuilder nesnesi üzerinde bir yöntem çağırarak bağlama geçirilir. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
ContosoUniversity.Data ve Microsoft.EntityFrameworkCore ad alanları için using deyimleri ekleyin ve ardından
projeyi derleyin.

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;

AppSettings. JSON dosyasını açın ve aşağıdaki örnekte gösterildiği gibi bir bağlantı dizesi ekleyin.

{
"ConnectionStrings": {
"DefaultConnection": "Server=
(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}

SQL Server Express LocalDB


Bağlantı dizesi bir SQL Server LocalDB veritabanı belirtir. LocalDB, SQL Server Express veritabanı altyapısının hafif
bir sürümüdür ve üretim kullanımı için değil uygulama geliştirmeye yöneliktir. LocalDB, isteğe bağlı olarak başlar ve
karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak, LocalDB C:/Users/<user>
dizininde . mdf veritabanı dosyaları oluşturur.

Test verileriyle VERITABANıNı başlatma


Entity Framework, sizin için boş bir veritabanı oluşturacaktır. Bu bölümde, test verileriyle doldurmak için veritabanı
oluşturulduktan sonra çağrılan bir yöntem yazarsınız.
Burada, veritabanını otomatik olarak oluşturmak için EnsureCreated yöntemini kullanacaksınız. Sonraki bir
öğreticide , veritabanını bırakıp yeniden oluşturmak yerine veritabanı şemasını değiştirmek için Code First
Migrations kullanarak model değişikliklerini nasıl işleyeceğinizi göreceksiniz.
Veri klasöründe, DbInitializer.cs adlı yeni bir sınıf dosyası oluşturun ve şablon kodunu, gerektiğinde bir
veritabanının oluşturulmasına neden olan aşağıdaki kodla değiştirin ve test verilerini yeni veritabanına yükler.

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();

// Look for any students.


if (context.Students.Any())
{
return; // DB has been seeded
}
}

var students = new Student[]


{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-
01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();

var courses = new Course[]


{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}

Kod, veritabanında herhangi bir öğrenci olup olmadığını denetler ve yoksa, veritabanının yeni olduğunu ve test
verileriyle hazırlanması gerektiğini varsayar. Diziye test verileri yükler yerine List<T> performansını iyileştirmek
için koleksiyonları.
Program.cs' de, uygulama başlangıcında aşağıdakini yapmak için Main yöntemini değiştirin:
Bağımlılık ekleme kapsayıcısından bir veritabanı bağlamı örneği alın.
Temel yöntemi çağırın ve bu yönteme geçerek bağlamı geçer.
Çekirdek yöntemi tamamlandığında bağlamı atın.

public static void Main(string[] args)


{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<SchoolContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}

host.Run();
}

using deyimleri ekle:

using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Data;

Daha eski öğreticilerde, Startup.csiçinde Configure yönteminde benzer bir kod görebilirsiniz. Yalnızca istek ardışık
düzenini ayarlamak için Configure yöntemini kullanmanızı öneririz. Uygulama başlangıç kodu Main yöntemine
aittir.
Uygulamayı ilk kez çalıştırdığınızda veritabanı oluşturulur ve test verileriyle birlikte gösterilir. Veri modelinizi her
değiştirdiğinizde, veritabanını silebilir, çekirdek yönteminizi güncelleştirebilir ve yeni bir veritabanıyla aynı şekilde
bir baştan başlatabilirsiniz. Sonraki öğreticilerde, veri modeli değiştiğinde ve yeniden oluşturmadan veritabanını
nasıl değiştireceğiniz hakkında bilgi edineceksiniz.

Denetleyici ve görünüm oluşturma


Daha sonra, verileri sorgulamak ve kaydetmek için EF 'i kullanacak bir MVC denetleyicisi ve görünümleri eklemek
üzere Visual Studio 'da scafkatlama altyapısını kullanacaksınız.
CRUD eylem yöntemlerinin ve görünümlerinin otomatik olarak oluşturulması, yapı iskelesi olarak bilinir. Yapı
iskelesi, yapı oluşturma işleminden farklı olarak, kendi gereksinimlerinize uyacak şekilde değiştirebileceğiniz bir
başlangıç noktası ve genellikle oluşturulan kodu değiştirmezsiniz. Oluşturulan kodu özelleştirmeniz gerektiğinde,
kısmi sınıfları kullanırsınız veya işlemler değiştiğinde kodu yeniden oluşturmanız gerekir.
Çözüm Gezgini ' de denetleyiciler klasörüne sağ tıklayın ve > yeni iskele öğe Ekle' yi seçin.
Yapı Iskelesi Ekle iletişim kutusunda:
Entity Framework kullanarak, görünümlerle MVC denetleyicisi ' niseçin.
Ekle'ye tıklayın. Görünümler Ile MVC denetleyicisi ekleme, Entity Framework kullanma
iletişim kutusu görüntülenir.
Model sınıfı ' nda öğrenci' yi seçin.
Veri bağlamı sınıfında SchoolContextöğesini seçin.
Varsayılan Studentscontroller adını olarak kabul edin.
Ekle'ye tıklayın.
Ekle' ye tıkladığınızda, Visual Studio yapı iskelesi altyapısı, denetleyicisiyle birlikte çalışan bir
StudentsController.cs dosyası ve bir dizi görünüm ( . cshtml dosyası) oluşturur.
(Yapı iskelesi altyapısı, daha önce Bu öğreticide yaptığınız gibi, daha önce el ile oluşturmazsanız, sizin için veritabanı
bağlamını de oluşturabilir. Veri bağlam sınıfınınsağ tarafındaki artı Işaretine tıklayarak Denetleyici Ekle
kutusunda yeni bir bağlam sınıfı belirtebilirsiniz. Daha sonra Visual Studio, DbContext sınıfınızın yanı sıra
denetleyiciyi ve görünümleri de oluşturacaktır.)
Denetleyicinin bir SchoolContext Oluşturucu parametresi olarak aldığını fark edeceksiniz.

namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;

public StudentsController(SchoolContext context)


{
_context = context;
}

ASP.NET Core bağımlılığı ekleme, denetleyiciye SchoolContext bir örneği geçirmekten yararlanır. Bunu Startup.cs
dosyasında daha önce yapılandırdınız.
Denetleyici, veritabanındaki tüm öğrencileri görüntüleyen bir Index Action yöntemi içerir. Yöntemi, veritabanı
bağlamı örneğinin Students özelliğini okuyarak öğrenciler varlık kümesinden öğrencilerin bir listesini alır:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}

Öğreticide daha sonra bu kodda zaman uyumsuz programlama öğeleri hakkında bilgi edineceksiniz.
Views/öğrenciler/Index. cshtml görünümü bu listeyi bir tabloda görüntüler:

@model IEnumerable<ContosoUniversity.Models.Student>

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
@Html.DisplayNameFor(model => model.EnrollmentDate)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Projeyi çalıştırmak için CTRL + F5 tuşlarına basın veya menüden hata ayıklama > Başlat ' ı seçin.
DbInitializer.Initialize yönteminin eklendiği test verilerini görmek için öğrenciler sekmesine tıklayın. Tarayıcı
pencerenizin ne kadar dar olduğuna bağlı olarak, sayfanın üst kısmında Students Tab bağlantısını görürsünüz veya
bağlantıyı görmek için sağ üst köşedeki gezinti simgesine tıklamanız gerekir.
Veritabanını görüntüleme
Uygulamayı başlattığınızda, DbInitializer.Initialize yöntemi EnsureCreated çağırır. EF, bir veritabanı olmadığını
ve bu nedenle bir tane oluşturduğunu gördük, Initialize yöntemi kodunun geri kalanı veritabanını verilerle
doldurmuş. Visual Studio 'da veritabanını görüntülemek için SQL Server Nesne Gezgini (ssox) kullanabilirsiniz.
Tarayıcıyı kapatın.
SSOX penceresi henüz açık değilse, Visual Studio 'daki Görünüm menüsünden bunu seçin.
SSOX 'te (LocalDB ) \MSSQLLocalDB > veritabanları' na tıklayın ve ardından appSettings. JSON dosyanızdaki
bağlantı dizesinde bulunan veritabanı adı için girişe tıklayın.
Veritabanınızdaki tabloları görmek için Tablolar düğümünü genişletin.
Oluşturulan sütunları ve tabloya eklenmiş satırları görmek için öğrenci tablosuna sağ tıklayın ve verileri
görüntüle ' ye tıklayın.

. Mdf ve . ldf veritabanı dosyaları, C:\Users\<YourUserName > klasöründedir.


Uygulama başlatma sırasında çalışan Başlatıcı yönteminde EnsureCreated çağırırken, artık Student sınıfında bir
değişiklik yapabilir, veritabanını silebilir, uygulamayı yeniden çalıştırabilirsiniz ve veritabanı, değişikliklerinizi
eşleştirmek için otomatik olarak yeniden oluşturulur. Örneğin, Student sınıfına bir EmailAddress özelliği eklerseniz,
yeniden oluşturulan tabloda yeni bir EmailAddress sütunu görürsünüz.

Kurallar
Entity Framework, kuralların kullanımı veya Entity Framework varsayımlarıyla ilgili olarak en az bir veritabanı
oluşturabilmesini sağlamak için yazmanız gereken kod miktarı.
DbSet özelliklerinin adları tablo adı olarak kullanılır. DbSet özelliği tarafından başvurulmayan varlıklar için,
varlık sınıfı adları tablo adı olarak kullanılır.
Varlık özelliği adları, sütun adları için kullanılır.
ID veya Classnameıd olarak adlandırılan varlık özellikleri, birincil anahtar özellikleri olarak tanınır.
Bir özellik, bir yabancı anahtar özelliği olarak yorumlanır <gezinti özelliği adı ><birincil anahtar özellik adı >
(örneğin, StudentID , birincil anahtarı Student olduğundan Student gezinti özelliği için ID ). Yabancı
anahtar özellikleri, <birincil anahtar özellik adı > olarak da adlandırılabilir (örneğin, Enrollment varlığının
birincil anahtarı EnrollmentID olduğundan EnrollmentID ).
Geleneksel davranış geçersiz kılınabilir. Örneğin, bu öğreticide daha önce gördüğünüz gibi tablo adlarını açıkça
belirtebilirsiniz. Ayrıca, bu serinin sonraki bir öğreticide göreceğiniz gibi, sütun adlarını ayarlayabilir ve herhangi bir
özelliği birincil anahtar veya yabancı anahtar olarak ayarlayabilirsiniz.

Zaman uyumsuz kod


Zaman uyumsuz programlama, ASP.NET Core ve EF Core için varsayılan moddur.
Sınırlı sayıda iş parçacığı kullanılabilir bir web sunucusuna sahip ve yüksek yük durumlarda tüm kullanılabilir iş
parçacıklarının kullanımda olabilir. Bu durum oluştuğunda, sunucunun iş parçacıklarının serbest bırakılana kadar
yeni istekleri işleyemiyor. G/ç tamamlanması bekleniyor çünkü bunlar herhangi bir iş gerçekten yapmamanız
sırasında eş zamanlı kod ile birçok iş parçacığı bağlanması. İşlemi tamamlamak, g/ç için beklerken zaman uyumsuz
kod ile diğer istekleri işlemek için kullanılacak sunucuyu için kendi iş parçacığı serbest bırakılır. Sonuç olarak,
sunucu kaynaklarının daha etkin kullanılması zaman uyumsuz kod sağlar ve sunucu gecikmeler olmadan daha fazla
trafik işlemek için etkinleştirilir.
Zaman uyumsuz kod, çalışma zamanında az miktarda yük getirir, ancak düşük trafik durumlarında performans artışı
göz ardı edilebilir, ancak yüksek trafik durumları için olası performans iyileştirmesi oldukça önemlidir.
Aşağıdaki kodda async anahtar sözcüğü, Task<T> dönüş değeri, await anahtar sözcüğü ve ToListAsync metodu
kodu zaman uyumsuz olarak yürütür.

public async Task<IActionResult> Index()


{
return View(await _context.Students.ToListAsync());
}

asyncanahtar sözcüğü, derleyiciye Yöntem gövdesinin parçaları için geri çağrılar oluşturmasını ve
döndürülen Task<IActionResult> nesnesini otomatik olarak oluşturmasını söyler.
Task<IActionResult> dönüş türü, IActionResult türünde bir sonuçla devam eden işi temsil eder.
await Anahtar sözcüğü, derleyicinin yöntemin iki parçalara bölmek neden olur. İlk bölüm ile zaman
uyumsuz olarak başlatıldığında işlemi sonlandırır. İkinci bölümü, işlemi tamamlandıktan sonra çağrılan bir
geri çağırma yöntemi yerleştirilir.
ToListAsync zaman uyumsuz sürümüdür ToList genişletme yöntemi.

Entity Framework kullanan zaman uyumsuz kod yazarken dikkat edilmesi gereken bazı şeyler:
Yalnızca sorguları veya komutlarının veritabanına gönderilmesine neden olan deyimler zaman uyumsuz
olarak yürütülür. Bu, örneğin, ToListAsync , SingleOrDefaultAsync ve SaveChangesAsync içerir. Örneğin,
var students = context.Students.Where(s => s.LastName == "Davolio") gibi yalnızca bir IQueryable değiştiren
deyimler dahil değildir.
EF bağlamı iş parçacığı açısından güvenli değildir: paralel olarak birden çok işlem yapmayı denemeyin.
Herhangi bir zaman uyumsuz EF yöntemini çağırdığınızda her zaman await anahtar sözcüğünü kullanın.
Zaman uyumsuz kodun performans avantajlarından yararlanmak isterseniz, kullanmakta olduğunuz tüm
kitaplık paketlerinin (örneğin, sayfalama için), sorguların veritabanına gönderilmesine neden olan herhangi
bir Entity Framework yöntemini çağırıyorsa, zaman uyumsuz olarak da kullanılmasını sağlayın.
.NET ' te zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. Async Overview.

Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
ASP.NET Core MVC web uygulaması oluşturuldu
Site stili Ayarla
EF Core NuGet paketleri hakkında bilgi edinildi
Veri modeli oluşturuldu
Veritabanı bağlamı oluşturuldu
SchoolContext kaydedildi
Test verileriyle VERITABANı başlatıldı
Denetleyici ve görünümler oluşturuldu
Veritabanı görüntüleniyor
Aşağıdaki öğreticide, temel CRUD (oluşturma, okuma, güncelleştirme, silme) işlemlerini nasıl gerçekleştireceğinizi
öğreneceksiniz.
Temel CRUD (oluşturma, okuma, güncelleştirme, silme) işlemlerini nasıl gerçekleştireceğinizi öğrenmek için sonraki
öğreticiye ilerleyin.
Temel CRUD işlevlerini uygulama
Öğretici: EF Core ile CRUD Işlevselliği uygulama-
ASP.NET MVC
11.10.2019 • 32 minutes to read • Edit Online

Önceki öğreticide, Entity Framework ve LocalDB SQL Server kullanarak verileri depolayan ve görüntüleyen bir
MVC uygulaması oluşturdunuz. Bu öğreticide, bu CRUD (oluşturma, okuma, güncelleştirme, silme) kodunu
inceleyerek, MVC yapı iskelesi denetleyiciler ve görünümlerde sizin için otomatik olarak oluşturulur.

NOTE
Denetleyiciniz ve veri erişim katmanı arasında bir soyutlama katmanı oluşturmak için depo deseninin uygulanması yaygın bir
uygulamadır. Bu öğreticileri basit tutmak ve Entity Framework kendisini nasıl kullanacağınızı öğretmeniz için, depoları
kullanmaz. EF olan depolar hakkında daha fazla bilgi için Bu serideki son öğreticiyebakın.

Bu öğreticide şunları yaptınız:


Ayrıntılar sayfasını özelleştirme
Oluştur sayfasını Güncelleştir
Düzenleme sayfasını Güncelleştir
Silme sayfasını Güncelleştir
Veritabanı bağlantılarını kapat

Önkoşullar
EF Core ve ASP.NET Core MVC ile çalışmaya başlama

Ayrıntılar sayfasını özelleştirme


Bu özellik bir koleksiyon içerdiğinden, öğrenciler dizin sayfasına yönelik scafkatlanmış kod Enrollments özelliğini
bıraktı. Ayrıntılar sayfasında, koleksiyonun IÇERIĞINI bir HTML tablosunda görüntüleyeceksiniz.
Controllers/StudentsController. csdosyasında, Ayrıntılar görünümü için eylem yöntemi tek bir Student varlığı
almak için SingleOrDefaultAsync yöntemini kullanır. @No__t-0 çağıran kodu ekleyin. Aşağıdaki Vurgulanan kodda
gösterildiği gibi, ThenInclude ve AsNoTracking yöntemleri.
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var student = await _context.Students


.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (student == null)
{
return NotFound();
}

return View(student);
}

@No__t-0 ve ThenInclude yöntemleri, bağlamın Student.Enrollments gezinti özelliğini yüklemesine ve her kayıt
için Enrollment.Course gezinti özelliğine neden olur. İlgili verileri oku öğreticisinde bu yöntemler hakkında daha
fazla bilgi edineceksiniz.
@No__t-0 yöntemi, döndürülen varlıkların geçerli bağlamın ömrü içinde güncellenmeyeceği senaryolarda
performansı geliştirir. Bu öğreticinin sonunda AsNoTracking hakkında daha fazla bilgi edineceksiniz.
Veri yönlendirme
@No__t-0 yöntemine geçirilen anahtar değeri Rota verilerindengelir. Rota verileri, model cildin URL 'nin bir
kesiminde bulduğu veriler olur. Örneğin, varsayılan yol denetleyiciyi, eylemi ve kimlik segmentlerini belirtir:

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Aşağıdaki URL 'de, varsayılan yol eğitmeni denetleyici olarak eşler, eylem olarak dizin ve kimlik olarak 1; Bunlar
rota veri değerleridir.

http://localhost:1230/Instructor/Index/1?courseID=2021

URL 'nin son bölümü ("? CourseID = 2021") bir sorgu dizesi değeridir. Model Ciltçi Ayrıca KIMLIK değerini bir
sorgu dizesi değeri olarak geçirdiğinizde Index yöntemine id parametresine geçicektir:

http://localhost:1230/Instructor/Index?id=1&CourseID=2021

Dizin sayfasında, bağ URL 'Leri Razor görünümündeki Tag Helper deyimleri tarafından oluşturulur. Aşağıdaki
Razor kodunda, id parametresi varsayılan yol ile eşleşir, bu nedenle yol verilerine id eklenir.

<a asp-action="Edit" asp-route-id="@item.ID">Edit</a>

Bu, item.ID 6 olduğunda aşağıdaki HTML 'yi oluşturur:


<a href="/Students/Edit/6">Edit</a>

Aşağıdaki Razor kodunda, studentID varsayılan rotadaki bir parametreyle eşleşmez, bu nedenle bir sorgu dizesi
olarak eklenir.

<a asp-action="Edit" asp-route-studentID="@item.ID">Edit</a>

Bu, item.ID 6 olduğunda aşağıdaki HTML 'yi oluşturur:

<a href="/Students/Edit?studentID=6">Edit</a>

Etiket Yardımcıları hakkında daha fazla bilgi için bkz. ASP.NET Core etiket yardımcıları.
Ayrıntılar görünümüne kayıtları ekleyin
Görünümleri/öğrencileri/details. cshtmldosyasını açın. Her alan, aşağıdaki örnekte gösterildiği gibi DisplayNameFor
ve DisplayFor yardımcıları kullanılarak görüntülenir:

<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.LastName)
</dd>

Son alandan sonra ve kapanış </dl> etiketinden hemen önce, kayıt listesini göstermek için aşağıdaki kodu ekleyin:

<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Enrollments)
</dt>
<dd class="col-sm-10">
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>

Kodu yapıştırdıktan sonra kod girintileme yanlış ise, düzeltmek için CTRL -K-D tuşlarına basın.
Bu kod Enrollments Gezinti özelliğindeki varlıklar aracılığıyla döngü başlatır. Her kayıt için kurs başlığını ve sınıfı
görüntüler. Kurs başlığı, kayıt varlığının Course gezinti özelliğinde depolanan kurs varlığından alınır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir öğrenci için Ayrıntılar bağlantısına tıklayın. Seçili öğrenci
için Kurslar ve notlar listesini görürsünüz:
Oluştur sayfasını Güncelleştir
StudentsController.cs' de, bir try-catch bloğu ekleyerek ve Bind özniteliğinden kimliği kaldırarak httppost Create
yöntemini değiştirin.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("EnrollmentDate,FirstMidName,LastName")] Student student)
{
try
{
if (ModelState.IsValid)
{
_context.Add(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists " +
"see your system administrator.");
}
return View(student);
}

Bu kod, ASP.NET Core MVC model Ciltçi tarafından oluşturulan öğrenci varlığını öğrenciler varlık kümesine ekler
ve değişiklikleri veritabanına kaydeder. (Model Ciltçi, bir form tarafından gönderilen verilerle çalışmanıza daha
kolay hale getiren ASP.NET Core MVC işlevselliğine başvurur; bir model Bağlayıcısı, postalanan form değerlerini
CLR türlerine dönüştürür ve parametreleri parametreler ' de eylem yöntemine geçirir. Bu durumda model Ciltçi,
form koleksiyonundaki özellik değerlerini kullanarak sizin için bir öğrenci varlığı oluşturur.)
"Satır eklendiğinde SQL Server otomatik olarak ayarlanacak birincil anahtar değeri olduğundan, Bind
özniteliğinden ID ' yı kaldırmış olursunuz. Kullanıcı girişi, KIMLIK değerini ayarladı.
@No__t-0 özniteliği dışında, try-catch bloğu, scafkatlanmış kodda yapmış olduğunuz tek değişikdir. Değişiklikler
kaydedilirken DbUpdateException ' dan türetilen bir özel durum yakalanmışsa, genel bir hata iletisi görüntülenir.
DbUpdateException özel durumlar bazen bir programlama hatası yerine uygulamanın harici bir şeydir. bu nedenle,
kullanıcının yeniden denemek tavsiye edilir. Bu örnekte uygulanmamış olsa da, bir üretim kalitesi uygulaması özel
durumu günlüğe kaydeder. Daha fazla bilgi için bkz. Izleme ve telemetri bölümünde Öngörüler Için günlük
(Azure Ile gerçek bulut uygulamaları oluşturma).
@No__t-0 özniteliği, siteler arası istek sahteciliği (CSRF ) saldırılarını önlemeye yardımcı olur. Belirteç,
Formtaghelper tarafından otomatik olarak görünüme eklenir ve form kullanıcı tarafından gönderildiğinde dahil
edilir. Belirteç ValidateAntiForgeryToken özniteliği tarafından onaylanır. CSRF hakkında daha fazla bilgi için bkz.
Istek önleyicigüvenlik.
Fazla nakil hakkında güvenlik notunda
İskele eklenen kodun Create yöntemine dahil olduğu Bind özniteliği, oluşturma senaryolarında çok fazla
gönderim için bir yoldur. Örneğin, öğrenci varlığının bu Web sayfasının ayarlamak istemediğiniz bir Secret özelliği
içerdiğini varsayalım.

public class Student


{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}

Web sayfasında Secret alanı olmasa bile, bir korsan Fiddler gibi bir araç kullanabilir veya bir Secret form değeri
göndermek için bazı JavaScript 'ler yazabilir. @No__t-0 özniteliği olmadan model cildin bir öğrenci örneği
oluşturduğunda kullandığı alanları sınırlayarak model Ciltçi, bu Secret form değerini seçer ve öğrenci varlık
örneğini oluşturmak için onu kullanır. Daha sonra, Secret form alanı için belirtilen korsanın hangi değeri
veritabanınızda güncelleştirilemeyebilir. Aşağıdaki görüntüde, Secret alanı ("OverPost" değeri ile), postalanan form
değerlerine eklenirken Fiddler aracı gösterilmektedir.

Daha sonra "OverPost" değeri, eklenen satırın Secret özelliğine başarıyla eklenir, ancak hiçbir şekilde Web
sayfasının bu özelliği ayarlayabilmesini amaçlayamazsınız.
Önce veritabanından varlığı okuyup daha sonra açıkça izin verilen bir Özellikler listesine geçirerek TryUpdateModel '
ı çağırarak düzenleme senaryolarında fazla nakletmeyi engelleyebilirsiniz. Bu, bu öğreticilerde kullanılan yöntemidir.
Birçok geliştirici tarafından tercih edilen aşırı nakletmeyi önlemenin alternatif bir yolu, model bağlamasıyla varlık
sınıfları yerine görüntüleme modellerini kullanmaktır. Yalnızca görünüm modelinde güncelleştirmek istediğiniz
özellikleri ekleyin. MVC model Bağlayıcısı tamamlandıktan sonra, görünüm modeli özelliklerini, isteğe bağlı olarak,
Automaber gibi bir araç kullanarak varlık örneğine kopyalayın. Varlık örneğindeki _context.Entry ' ı kullanarak
durumunu Unchanged olarak ayarlayın ve ardından Görünüm modelinde bulunan her bir varlık özelliğinde
Property("PropertyName").IsModified ' yi true olarak ayarlayın. Bu yöntem hem düzenleme hem de oluşturma
senaryolarında çalışmaktadır.
Oluştur sayfasını test etme
Views/öğrenciler/Create. cshtml içindeki kod, her alan için label , input ve span (doğrulama iletileri için) etiket
yardımcıları kullanır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve Yeni oluştur' a tıklayın.
Ad ve tarih girin. Tarayıcınız bunu yapmanızı sağlar, geçersiz bir tarih girmeyi deneyin. (Bazı tarayıcılar bir tarih
seçici kullanmanıza zorlar.) Hata iletisini görmek için Oluştur ' a tıklayın.

Bu, varsayılan olarak aldığınız sunucu tarafı doğrulamadır; sonraki bir öğreticide, istemci tarafı doğrulama için kod
oluşturacak özniteliklerin nasıl ekleneceğini görürsünüz. Aşağıdaki Vurgulanan kodda, Create yönteminde model
doğrulama denetimi gösterilmektedir.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("EnrollmentDate,FirstMidName,LastName")] Student student)
{
try
{
if (ModelState.IsValid)
{
_context.Add(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists " +
"see your system administrator.");
}
return View(student);
}

Tarihi geçerli bir değer olarak değiştirin ve yeni öğrencinin Dizin sayfasında göründüğünü görmek için Oluştur ' a
tıklayın.

Düzenleme sayfasını Güncelleştir


StudentController.cs' de, httpget Edit yöntemi ( HttpPost özniteliği olmayan), Details yönteminde gördüğünüz
gibi seçili öğrenci varlığını almak için SingleOrDefaultAsync yöntemini kullanır. Bu yöntemi değiştirmeniz gerekmez.
Önerilen HttpPost düzenleme kodu: okuma ve güncelleştirme
HttpPost düzenleme eylemi yöntemini aşağıdaki kodla değiştirin.
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}
var studentToUpdate = await _context.Students.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
try
{
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
}
return View(studentToUpdate);
}

Bu değişiklikler, aşırı nakletmeyi engellemek için en iyi güvenlik uygulamasını uygular.Desteği bir Bind özniteliği
üretti ve model Ciltçi tarafından oluşturulan varlığı bir Modified bayrağıyla ekledi. Bu kod pek çok senaryo için
önerilmez çünkü Bind özniteliği Include parametresinde listelenmeyen alanlarda önceden var olan verileri
temizler.
Yeni kod, mevcut varlığı okur ve alınan varlıktaki alanları, postalanan form verilerinde Kullanıcı girişine
göregüncelleştirmek için TryUpdateModel çağırır. Entity Framework otomatik değişiklik izleme, form girişi tarafından
değiştirilen alanlarda Modified bayrağını ayarlar. @No__t-0 yöntemi çağrıldığında, Entity Framework veritabanı
satırını güncelleştirmek için SQL deyimleri oluşturur. Eşzamanlılık çakışmaları yok sayılır ve yalnızca Kullanıcı
tarafından güncellenen tablo sütunları veritabanında güncelleştirilir. (Sonraki bir öğretici eşzamanlılık
çakışmalarının nasıl işleneceğini gösterir.)
Fazla nakletmeyi önleyen en iyi yöntem olarak, düzenleme sayfası tarafından güncelleştirilemek istediğiniz alanlar
TryUpdateModel parametrelerinde beyaz listeye alınır. ( Parametre listesindeki alanlar listesinden önceki boş dize,
form alanları adlarıyla kullanılacak bir ön ek içindir.) Şu anda koruduğunuz ek alan yok, ancak model cildin
bağlamasını istediğiniz alanları listelemek, gelecekte veri modeline alanlar eklerseniz, bunları buraya açıkça
eklemeene kadar otomatik olarak korunur.
Bu değişikliklerin sonucu olarak, HttpPost Edit yönteminin yöntem imzası, HttpGet Edit yöntemiyle aynıdır; Bu
nedenle, EditPost metodunu yeniden adlandırdınız.
Alternatif HttpPost düzenleme kodu: oluşturma ve iliştirme
Önerilen HttpPost düzenleme kodu yalnızca değiştirilen sütunların güncelleştirilmesini sağlar ve model bağlama
dahil etmek istemediğiniz özelliklerde verileri korur. Ancak, ilk okuma yaklaşımı, fazladan bir veritabanı okuması
gerektirir ve eşzamanlılık çakışmalarını işlemek için daha karmaşık kod oluşmasına neden olabilir. Diğer bir seçenek
de model cildi tarafından oluşturulan bir varlığı EF bağlamına eklemektir ve değiştirildi olarak işaretler. (Projenizi bu
kodla güncelleştirmeyin, yalnızca isteğe bağlı bir yaklaşımı göstermek için gösterilir.)
public async Task<IActionResult> Edit(int id, [Bind("ID,EnrollmentDate,FirstMidName,LastName")] Student
student)
{
if (id != student.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
}
return View(student);
}

Web sayfası kullanıcı arabirimi varlıktaki tüm alanları içerdiğinde ve bunlardan herhangi birini güncelleştirebilmeniz
durumunda bu yaklaşımı kullanabilirsiniz.
Scafkatlanmış kod, oluşturma ve iliştirme yaklaşımını kullanır, ancak yalnızca DbUpdateConcurrencyException özel
durumlarını yakalar ve 404 hata kodları döndürür. Gösterilen örnek herhangi bir veritabanı güncelleştirme özel
durumunu yakalar ve bir hata iletisi görüntüler.
Varlık durumları
Veritabanı bağlamı, bellekteki varlıkların veritabanında karşılık gelen satırlarıyla eşitlenmiş olup olmadığını izler ve
bu bilgiler SaveChanges yöntemini çağırdığınızda ne olacağını belirler. Örneğin, Add yöntemine yeni bir varlık
geçirdiğinizde, bu varlığın durumu Added olarak ayarlanır. Sonra, SaveChanges yöntemini çağırdığınızda veritabanı
bağlamı bir SQL INSERT komutu yayınlar.
Bir varlık aşağıdaki durumlardan birinde olabilir:
Added . Varlık veritabanında henüz yok. @No__t-0 yöntemi bir INSERT ifadesini yayınlar.
. @No__t-0 yöntemiyle bu varlıkla hiçbir şeyin yapılması gerekmez. Veritabanından bir varlık
Unchanged
okuduğunuzda, varlık bu durumla başlar.
Modified . Varlığın özellik değerlerinin bazıları veya tümü değiştirildi. @No__t-0 yöntemi bir UPDATE
ifadesini yayınlar.
Deleted . Varlık silinmek üzere işaretlendi. @No__t-0 yöntemi bir DELETE ifadesini yayınlar.
Detached . Varlık, veritabanı bağlamı tarafından izlenmiyor.
Bir masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlığı okur ve bazı özellik
değerlerinde değişiklik yaparsınız. Bu, varlık durumunun otomatik olarak Modified olarak değiştirilmesine neden
olur. @No__t-0 ' ı çağırdığınızda, Entity Framework yalnızca değiştirdiğiniz gerçek özellikleri güncelleştiren bir SQL
UPDATE bildirisi oluşturur.
Bir Web uygulamasında, ilk olarak bir varlığı okuyan DbContext ve bir sayfa işlendikten sonra düzenlenecek
verilerini görüntüler. HttpPost Edit eylem yöntemi çağrıldığında yeni bir Web isteği yapılır ve DbContext ' in yeni
bir örneğine sahip olursunuz. Varlığı bu yeni bağlamda yeniden okuduğunuzda masaüstü işleme benzetimi yapılır.
Ancak, fazladan okuma işlemi yapmak istemiyorsanız, model Ciltçi tarafından oluşturulan varlık nesnesini
kullanmanız gerekir. Bunu yapmanın en kolay yolu, daha önce gösterilen diğer HttpPost düzenleme kodunda
yapıldığı gibi varlık durumunun değiştirilme olarak ayarlanmanız olur. Sonra, SaveChanges ' ı çağırdığınızda, bağlam
hangi özelliklerden hangilerinin değiştirildiğini bilen bir yolu olmadığından, Entity Framework veritabanı satırının
tüm sütunlarını günceller.
İlk okuma yaklaşımına engel olmak istiyorsanız, ancak SQL UPDATE bildiriminin yalnızca kullanıcının gerçekten
değiştirdiği alanları güncelleştirmesini istiyorsanız, kod daha karmaşıktır. HttpPost Edit yöntemi çağrıldığında
kullanılabilir olmaları için özgün değerleri bir şekilde (örneğin, gizli alanları kullanarak) kaydetmeniz gerekir.
Ardından özgün değerleri kullanarak bir öğrenci varlığı oluşturabilir, Attach yöntemini varlığın orijinal sürümüyle
çağırabilir, varlığın değerlerini yeni değerlerle güncelleştirebilir ve ardından SaveChanges ' i çağırabilirsiniz.
Düzenleme sayfasını test etme
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve köprü Düzenle ' ye tıklayın.

Bazı verileri değiştirin ve Kaydet' e tıklayın. Dizin sayfası açılır ve değiştirilen verileri görürsünüz.

Silme sayfasını Güncelleştir


StudentController.cs' de, httpget Delete yöntemi için şablon kodu, Ayrıntılar ve düzenleme yöntemlerinde
gördüğünüz gibi seçili öğrenci varlığını almak için SingleOrDefaultAsync yöntemini kullanır. Ancak, SaveChanges ' a
yapılan çağrı başarısız olduğunda özel bir hata iletisi uygulamak için, bu yönteme ve buna karşılık gelen görünüme
bazı işlevler eklersiniz.
Güncelleştirme ve oluşturma işlemleri için gördüğünüz gibi silme işlemleri için iki eylem yöntemi gerekir. GET
isteğine yanıt olarak çağrılan yöntem, kullanıcıya silme işlemini onaylama veya iptal etme şansı veren bir görünüm
görüntüler. Kullanıcı onu onayladığında, bir POST isteği oluşturulur. Bu durumda, HttpPost Delete yöntemi çağrılır
ve bu yöntem aslında silme işlemini gerçekleştirir.
Veritabanı güncelleştirilirken oluşabilecek hataları işlemek için HttpPost Delete yöntemine bir try-catch bloğu
ekleyeceksiniz. Bir hata oluşursa, HttpPost Delete yöntemi bir hata oluştuğunu gösteren bir parametre geçirerek
HttpGet Delete yöntemini çağırır. HttpGet Delete yöntemi daha sonra hata iletisiyle birlikte onay sayfasını yeniden
görüntüler ve kullanıcıya iptal etmek veya yeniden denemek için bir fırsat verir.
HttpGet Delete eylem yöntemini aşağıdaki kodla değiştirin, bu hata raporlamayı yönetir.

public async Task<IActionResult> Delete(int? id, bool? saveChangesError = false)


{
if (id == null)
{
return NotFound();
}

var student = await _context.Students


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (student == null)
{
return NotFound();
}

if (saveChangesError.GetValueOrDefault())
{
ViewData["ErrorMessage"] =
"Delete failed. Try again, and if the problem persists " +
"see your system administrator.";
}

return View(student);
}

Bu kod, bir yöntemin değişiklikleri kaydetme hatasından sonra döndürülüp çağrılmadığını belirten isteğe bağlı bir
parametresini kabul eder. HttpGet Delete yöntemi önceki bir hata olmadan çağrıldığında bu parametre false 'tur.
Bir veritabanı güncelleştirme hatasına yanıt olarak HttpPost Delete yöntemi tarafından çağrıldığında, parametresi
true olur ve görünüme bir hata mesajı geçirilir.
HttpPost silme için ilk okuma yaklaşımı
HttpPost Delete eylem yöntemini ( DeleteConfirmed adlı), gerçek silme işlemini gerçekleştiren ve tüm veritabanı
güncelleştirme hatalarını yakalayan aşağıdaki kodla değiştirin.

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var student = await _context.Students.FindAsync(id);
if (student == null)
{
return RedirectToAction(nameof(Index));
}

try
{
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
}
}
Bu kod seçili varlığı alır, ardından varlığın durumunu Deleted olarak ayarlamak için Remove yöntemini çağırır.
@No__t-0 çağrıldığında, bir SQL DELETE komutu oluşturulur.
HttpPost silme için Oluştur ve Ekle yaklaşımı
Yüksek hacimli bir uygulamadaki performansı artırmak bir önceliktir, yalnızca birincil anahtar değerini kullanarak
bir öğrenci varlığı oluşturarak ve ardından varlık durumunu Deleted olarak ayarlayarak gereksiz bir SQL
sorgusundan kaçınabilirsiniz. Bu, Entity Framework varlığı silmek için ihtiyaç duymaktadır. (Bu kodu projenize
yerleştirmeyin; bir alternatif göstermek de yeterlidir.)

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
try
{
Student studentToDelete = new Student() { ID = id };
_context.Entry(studentToDelete).State = EntityState.Deleted;
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
}
}

Varlığın de silinmesi gereken ilgili veriler varsa, veritabanında Cascade silmenin yapılandırıldığından emin olun.
Varlık silme yaklaşımıyla EF, silinecek ilgili varlıkların olduğunu fark etmeyebilir.
Silme görünümünü Güncelleştir
Görünümler/öğrenci/delete. cshtml' de, aşağıdaki örnekte gösterildiği gibi, H2 başlığı ve H3 başlığı arasına bir hata
iletisi ekleyin:

<h2>Delete</h2>
<p class="text-danger">@ViewData["ErrorMessage"]</p>
<h3>Are you sure you want to delete this?</h3>

Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir Delete köprüsüne tıklayın:


Sil'e tıklayın. Dizin sayfası, silinen öğrenci olmadan görüntülenir. (Eşzamanlılık öğreticisinde işlem içinde kodu
işleme hatası hakkında bir örnek görürsünüz.)

Veritabanı bağlantılarını kapat


Bir veritabanı bağlantısının tuttuğu kaynakları boşaltmak için bağlam örneği, bununla işiniz bittiğinde en kısa
sürede atılmalıdır. ASP.NET Core yerleşik bağımlılık ekleme , sizin için bu görevi gerçekleştirir.
Startup.cs, DbContext SıNıFıNı ASP.NET Core dı kapsayıcısında sağlamak Için adddbcontext genişletme yöntemini
çağırın. Bu yöntem, hizmet ömrünü varsayılan olarak Scoped olarak ayarlar. Scoped , Web isteği yaşam süresi ile
saatle çakışan bağlam nesnesi ömrünü gösterir ve Web isteğinin sonunda Dispose yöntemi otomatik olarak
çağrılır.

İşlemleri işle
Entity Framework, varsayılan olarak işlemleri örtülü olarak uygular. Birden çok satır veya tabloda değişiklik
yaptığınız ve sonra SaveChanges ' ı çağıran senaryolarda, Entity Framework otomatik olarak tüm değişikliklerinizin
başarılı olduğundan veya tümünün başarısız olduğundan emin olur. Önce bazı değişiklikler yapıldıktan sonra bir
hata oluşursa, bu değişiklikler otomatik olarak geri alınır. Daha fazla denetime ihtiyacınız olan senaryolar için--
örneğin, işlem içinde Entity Framework dışında yapılan işlemleri eklemek istiyorsanız, bkz. işlemler.

İzleme sorguları yok


Bir veritabanı bağlamı tablo satırları aldığında ve bunları temsil eden varlık nesneleri oluşturduğunda, varsayılan
olarak, bellekteki varlıkların veritabanında bulunan verilerle eşitlenmiş olup olmadığını izler. Bellekteki veriler
önbellek olarak davranır ve bir varlığı güncelleştirdiğinizde kullanılır. Bağlam örnekleri genellikle kısa süreli
olduğundan (her istek için yeni bir tane oluşturulup bırakıldığı) ve bir varlığı okuyan bağlam genellikle bu varlık
yeniden kullanılmadan önce atıldığından, bu önbelleğe alma işlemi bir Web uygulamasında genellikle gereksizdir.
@No__t-0 yöntemini çağırarak bellekte varlık nesnelerinin izlenmesini devre dışı bırakabilirsiniz. Bunu yapmak
isteyebileceğiniz tipik senaryolar şunlardır:
Bağlam ömrü boyunca herhangi bir varlığı güncelleştirmeniz gerekmez ve ayrı sorgular tarafından alınan
varlıklarla birlikte gezinti özelliklerini otomatik olarak yüklemekiçin EF 'e ihtiyacınız yoktur. Bu koşullar
genellikle denetleyicinin HttpGet eylem yöntemlerinde karşılanır.
Büyük miktarda veri alan bir sorgu çalıştırıyorsunuz ve döndürülen verilerin yalnızca küçük bir kısmı
güncelleştiriliyor. Büyük sorgu için izlemeyi devre dışı bırakmak ve daha sonra güncellenmesi gereken birkaç
varlık için bir sorgu çalıştırmak daha verimli olabilir.
Bir varlığı güncelleştirmek için eklemek istiyorsunuz, ancak daha önce farklı bir amaç için aynı varlığı elde
edersiniz. Varlık veritabanı bağlamı tarafından zaten izlenmekte olduğundan, değiştirmek istediğiniz varlığı
iliştiremiyoruz. Bu durumu işlemenin bir yolu, önceki sorgudaki AsNoTracking öğesini çağırmanız olur.

Daha fazla bilgi için bkz. izleme vs.

Kodu edinin
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Ayrıntılar sayfası özelleştirildi
Oluşturma sayfası güncelleştirildi
Düzenleme sayfası güncelleştirildi
Silme sayfası güncelleştirildi
Kapalı veritabanı bağlantıları
Sıralama, filtreleme ve sayfalama ekleyerek Dizin sayfasının işlevselliğini genişletmeyi öğrenmek için sonraki
öğreticiye ilerleyin.
Sonraki: sıralama, filtreleme ve sayfalama
Öğretici: EF Core sıralama, filtreleme ve sayfalama-
ASP.NET MVC ekleme
23.11.2019 • 21 minutes to read • Edit Online

Önceki öğreticide, öğrenci varlıkları için temel CRUD işlemleri için bir dizi Web sayfası uyguladık. Bu öğreticide,
öğrenciler dizin sayfasına sıralama, filtreleme ve sayfalama işlevselliği ekleyeceksiniz. Ayrıca basit gruplandırma
yapan bir sayfa oluşturacaksınız.
Aşağıdaki çizimde, işiniz bittiğinde sayfanın nasıl görüneceği gösterilmektedir. Sütun başlıkları, kullanıcının sütuna
göre sıralamak için tıkladığı bağlantılardır. Sütun başlığına tıklanması artan ve azalan sıralama düzeni arasında
sürekli olarak geçiş yapar.

Bu öğreticide şunları yaptınız:


Sütun sıralama bağlantıları Ekle
Arama kutusu ekleme
Öğrenciler dizinine sayfalama ekleme
Dizin yöntemine sayfalama ekleme
Sayfalama bağlantıları Ekle
Hakkında bir sayfa oluşturun

Önkoşullar
CRUD Işlevlerini uygulama

Sütun sıralama bağlantıları Ekle


Öğrenci dizini sayfasına sıralama eklemek için, öğrenciler denetleyicisinin Index yöntemini değiştirecek ve öğrenci
dizini görünümüne kod ekleyeceksiniz.
Dizin yöntemine sıralama Işlevi ekleme
StudentsController.cs' de Index yöntemini aşağıdaki kodla değiştirin:

public async Task<IActionResult> Index(string sortOrder)


{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
var students = from s in _context.Students
select s;
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
return View(await students.AsNoTracking().ToListAsync());
}

Bu kod, URL 'deki sorgu dizesinden bir sortOrder parametresi alır. Sorgu dizesi değeri, ASP.NET Core MVC
tarafından eylem yöntemine bir parametre olarak sağlanır. Parametresi, "Name" veya "Date" adlı bir dize, isteğe
bağlı olarak bir alt çizgi ve azalan sıralama belirtmek için "desc" dizesi olacaktır. Varsayılan sıralama düzeni artan.
Dizin sayfası ilk kez istendiğinde sorgu dizesi yoktur. Öğrenciler, son ada göre artan sırada görüntülenir, bu, switch
deyimindeki karşı bir durum tarafından kurulduğu varsayılan değer olan addır. Kullanıcı bir sütun başlığı köprüsüne
tıkladığında, sorgu dizesinde uygun sortOrder değeri sağlanır.
İki ViewData öğesi (Namesortpara ve Datesortpard), sütun başlığı köprülerini uygun sorgu dizesi değerleriyle
yapılandırmak için görünüm tarafından kullanılır.
public async Task<IActionResult> Index(string sortOrder)
{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
var students = from s in _context.Students
select s;
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
return View(await students.AsNoTracking().ToListAsync());
}

Bunlar Üçlü ifadelerdir. İlki sortOrder parametresi null veya boş ise, Namesortparı 'nin "name_desc" olarak
ayarlanması gerektiğini belirtir; Aksi takdirde, boş bir dizeye ayarlanmalıdır. Bu iki deyim, görünümün sütun başlığı
köprülerini şu şekilde ayarlamaya olanak tanır:

GEÇERLI SIRALAMA DÜZENI SON AD KÖPRÜSÜ TARIH KÖPRÜSÜ

Artan son ad descending ascending

Azalan son ad ascending ascending

Artan Tarih ascending descending

Azalan Tarih ascending ascending

Yöntemi, sıralama yapılacak sütunu belirtmek için LINQ to Entities kullanır. Kod, Switch ifadesinden önce bir
IQueryable değişkeni oluşturur, Switch ifadesinde değiştirir ve switch deyimden sonra ToListAsync yöntemini
çağırır. IQueryable değişkenleri oluşturup değiştirirken veritabanına hiçbir sorgu gönderilmez. Sorgu, ToListAsync
gibi bir yöntemi çağırarak IQueryable nesnesini bir koleksiyona dönüştürene kadar yürütülmez. Bu nedenle, bu
kod return View ifadeye kadar Yürütülmeyen tek bir sorgu ile sonuçlanır.
Bu kod çok sayıda sütunla ayrıntı alabilir. Bu serideki son öğretici , bir dize değişkeninde OrderBy sütununun adını
geçirmenize olanak sağlayan kodun nasıl yazılacağını gösterir.
Öğrenci dizini görünümüne sütun başlığı köprüleri ekleme
Görünümler/öğrenciler/Index. cshtmliçindeki kodu, sütun başlığı köprüleri eklemek için aşağıdaki kodla değiştirin.
Değiştirilen çizgiler vurgulanır.
@model IEnumerable<ContosoUniversity.Models.Student>

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
<a asp-action="Index" asp-route-
sortOrder="@ViewData["NameSortParm"]">@Html.DisplayNameFor(model => model.LastName)</a>
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
<a asp-action="Index" asp-route-
sortOrder="@ViewData["DateSortParm"]">@Html.DisplayNameFor(model => model.EnrollmentDate)</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Bu kod, uygun sorgu dizesi değerleriyle köprüler ayarlamak için ViewData özelliklerindeki bilgileri kullanır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve sıralamanın çalıştığını doğrulamak Için son ad ve kayıt tarihi
sütun başlıklarına tıklayın.
Arama kutusu ekleme
Öğrenciler dizin sayfasına filtre eklemek için, görünüme bir metin kutusu ve Gönder düğmesi ekleyeceksiniz ve
Index yönteminde ilgili değişiklikleri yapmanız gerekir. Metin kutusu, ilk adı ve soyadı alanlarını aramak için bir
dize girmenizi sağlar.
Dizin yöntemine filtreleme işlevi ekleme
StudentsController.cs' de Index yöntemini aşağıdaki kodla değiştirin (değişiklikler vurgulanır).

public async Task<IActionResult> Index(string sortOrder, string searchString)


{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
ViewData["CurrentFilter"] = searchString;

var students = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
return View(await students.AsNoTracking().ToListAsync());
}
Index yöntemine bir searchString parametresi eklediniz. Arama dizesi değeri, dizin görünümüne ekleyeceğiniz bir
metin kutusundan alınır. Ayrıca, yalnızca adı veya soyadı arama dizesini içeren öğrencileri seçen bir where yan
tümcesine LINQ deyimi de eklediniz. WHERE yan tümcesini ekleyen deyimi, yalnızca aranacak bir değer varsa
yürütülür.

NOTE
Burada Where yöntemi bir IQueryable nesnesi üzerinde arıyorsanız ve filtrenin sunucuda işlenmesi gerekir. Bazı
senaryolarda, bellek içi bir koleksiyonda Where yöntemini genişletme yöntemi olarak çağırma olabilirsiniz. (Örneğin,
_context.Students başvurusunu, bir DbSet EF yerine bir IEnumerable koleksiyonu döndüren bir depo yöntemine
başvurduğu gibi) değiştirdiğinizi varsayın.) Sonuç normalde aynı olur, ancak bazı durumlarda farklı olabilir.
Örneğin, Contains yönteminin .NET Framework uygulanması, varsayılan olarak büyük/küçük harfe duyarlı bir karşılaştırma
gerçekleştirir, ancak SQL Server ' de SQL Server örneğinin harmanlama ayarı tarafından belirlenir. Bu ayar varsayılan olarak
büyük/küçük harfe duyarsız olur. Testi açıkça büyük/küçük harfe duyarsız hale getirmek için ToUpper yöntemini
çağırabilirsiniz: burada (s = > s. LastName. ToUpper (). Contains (searchString. ToUpper ()) . Bu, kodu daha sonra bir
IQueryable nesnesi yerine IEnumerable koleksiyonu döndüren bir depoyu kullanacak şekilde değiştirirseniz sonuçların aynı
kalmasını sağlar. (Bir IEnumerable koleksiyonunda Contains yöntemini çağırdığınızda .NET Framework uygulamasını
alırsınız; bunu bir IQueryable nesnesi üzerinde çağırdığınızda, veritabanı sağlayıcısı uygulamasını alırsınız.) Ancak, bu çözüm
için bir performans cezası vardır. ToUpper kodu, TSQL SELECT ifadesinin WHERE yan tümcesine bir işlev koyar. Bu,
iyileştiricinin bir dizin kullanmasını engelleyecek. SQL 'in çoğu büyük küçük harfe duyarsız olarak yüklendiği için, büyük/küçük
harfe duyarlı bir veri deposuna geçiş yapılıncaya kadar ToUpper koddan kaçınmak en iyisidir.

Öğrenci dizini görünümüne arama kutusu ekleme


Görünümler/öğrenci/Index. cshtml'de, bir başlık, metin kutusu ve bir arama düğmesi oluşturmak için, açılan tablo
etiketinden hemen önce vurgulanan kodu ekleyin.

<p>
<a asp-action="Create">Create New</a>
</p>

<form asp-action="Index" method="get">


<div class="form-actions no-color">
<p>
Find by name: <input type="text" name="SearchString" value="@ViewData["currentFilter"]" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-action="Index">Back to Full List</a>
</p>
</div>
</form>

<table class="table">

Bu kod, arama metin kutusu ve düğmesini eklemek için <form> Tag yardımcısını kullanır. Varsayılan olarak, <form>
etiketi Yardımcısı, form verilerini bir GÖNDERIYLE gönderir, yani Parametreler, URL 'de sorgu dizeleri olarak değil,
HTTP ileti gövdesinde geçirilir. HTTP GET belirttiğinizde, form verileri URL 'ye sorgu dizeleri olarak geçirilir ve bu
da kullanıcıların URL 'ye yer işareti eklemesini sağlar. W3C yönergeleri, eylem bir güncelleştirme ile sonuçlanmazsa
Al ' ın kullanılması önerilir.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin, bir arama dizesi girin ve filtreleme 'nin çalıştığını doğrulamak
için ara ' ya tıklayın.
URL 'nin arama dizesini içerdiğine dikkat edin.

http://localhost:5813/Students?SearchString=an

Bu sayfaya yer işareti eklerseniz, yer işaretini kullandığınızda filtrelenmiş listeyi alırsınız. form etiketine
method="get" eklemek, sorgu dizesinin oluşturulmasına neden olur.

Bu aşamada, bir sütun başlığı sıralama bağlantısını tıklatırsanız, arama kutusuna girdiğiniz filtre değerini
kaybedersiniz. Sonraki bölümde bunu çözeceksiniz.

Öğrenciler dizinine sayfalama ekleme


Öğrenciler dizin sayfasına sayfalama eklemek için, Skip ve Take deyimlerini kullanan bir PaginatedList sınıfını,
tablodaki verileri her zaman almak yerine, sunucuda filtrelemek için oluşturacaksınız. Daha sonra Index
yönteminde ek değişiklikler yapar ve Index görünümüne sayfalama düğmeleri eklersiniz. Aşağıdaki çizimde
sayfalama düğmeleri gösterilmektedir.
Proje klasöründe PaginatedList.cs oluşturun ve ardından şablon kodunu aşağıdaki kodla değiştirin.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)


{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);

this.AddRange(items);
}

public bool HasPreviousPage


{
get
{
return (PageIndex > 1);
}
}

public bool HasNextPage


{
get
{
return (PageIndex < TotalPages);
}
}

public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int


pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}

Bu koddaki yöntemi sayfa boyutunu ve sayfa numarasını alır ve uygun Skip ve Take deyimlerini
CreateAsync
IQueryable uygular. IQueryable``ToListAsync çağrıldığında, yalnızca istenen sayfayı içeren bir liste döndürür.
HasPreviousPage ve HasNextPage özellikleri, önceki ve sonraki sayfalama düğmelerini etkinleştirmek veya devre
dışı bırakmak için kullanılabilir.
Oluşturucular zaman uyumsuz kod çalıştıramadığından PaginatedList<T> nesnesini oluşturmak için bir Oluşturucu
yerine bir CreateAsync yöntemi kullanılır.

Dizin yöntemine sayfalama ekleme


StudentsController.cs' de Index yöntemini aşağıdaki kodla değiştirin.
public async Task<IActionResult> Index(
string sortOrder,
string currentFilter,
string searchString,
int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";

if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}

ViewData["CurrentFilter"] = searchString;

var students = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}

int pageSize = 3;
return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(), pageNumber ?? 1, pageSize));
}

Bu kod, bir sayfa numarası parametresi, geçerli bir sıralama düzeni parametresi ve Yöntem imzasına geçerli bir filtre
parametresi ekler.

public async Task<IActionResult> Index(


string sortOrder,
string currentFilter,
string searchString,
int? pageNumber)

Sayfa ilk kez görüntülenirken veya Kullanıcı bir sayfalama veya sıralama bağlantısına tıklamamışsa, tüm
parametreler null olur. Bir sayfalama bağlantısına tıklandıysanız, sayfa değişkeni görüntülenecek sayfa numarasını
içerir.
CurrentSort adlı ViewData öğesi, sayfalama bağlantılarına dahil edilmesi gerektiğinden, bu sıralama düzeni geçerli
sıralama düzeni ile birlikte sağlar.
CurrentFilter adlı ViewData öğesi, geçerli filtre dizesiyle görünüm sağlar. Bu değer, disk belleği sırasında filtre
ayarlarını korumak için disk belleği bağlantılarına dahil olmalıdır ve sayfa yeniden görüntülenirken metin kutusuna
geri yüklenmesi gerekir.
Arama dizesi sayfalama sırasında değiştirilmişse, yeni filtre farklı verilerin görüntülenmesini sağladığından sayfanın
1 olarak sıfırlanması gerekir. Metin kutusuna bir değer girildiğinde ve Gönder düğmesine basıldığında arama dizesi
değişir. Bu durumda searchString parametresi null değildir.

if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}

Index yönteminin sonunda, PaginatedList.CreateAsync yöntemi öğrenci sorgusunu, sayfalama destekleyen bir
koleksiyon türünde tek bir öğrenciye dönüştürür. Bu tek bir öğrenci sayfası daha sonra görünüme geçirilir.

return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(), pageNumber ?? 1, pageSize));

PaginatedList.CreateAsync yöntemi bir sayfa numarası alır. İki soru işareti, null birleşim işlecini temsil eder. Null
birleşim işleci, Nullable bir tür için varsayılan değeri tanımlar; (pageNumber ?? 1) ifadesi bir değere sahipse
pageNumber değerini döndürür veya pageNumber null ise 1 döndürür.

Sayfalama bağlantıları Ekle


Görünümler/öğrenciler/Index. cshtml'de, mevcut kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

@model PaginatedList<ContosoUniversity.Models.Student>

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-action="Create">Create New</a>
</p>

<form asp-action="Index" method="get">


<div class="form-actions no-color">
<p>
Find by name: <input type="text" name="SearchString" value="@ViewData["CurrentFilter"]" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-action="Index">Back to Full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<tr>
<th>
<a asp-action="Index" asp-route-sortOrder="@ViewData["NameSortParm"]" asp-route-
currentFilter="@ViewData["CurrentFilter"]">Last Name</a>
</th>
<th>
First Name
First Name
</th>
<th>
<a asp-action="Index" asp-route-sortOrder="@ViewData["DateSortParm"]" asp-route-
currentFilter="@ViewData["CurrentFilter"]">Enrollment Date</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : "";
}

<a asp-action="Index"
asp-route-sortOrder="@ViewData["CurrentSort"]"
asp-route-pageNumber="@(Model.PageIndex - 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @prevDisabled">
Previous
</a>
<a asp-action="Index"
asp-route-sortOrder="@ViewData["CurrentSort"]"
asp-route-pageNumber="@(Model.PageIndex + 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @nextDisabled">
Next
</a>

Sayfanın üst kısmındaki @model ifade, görünümün artık List<T> nesnesi yerine PaginatedList<T> bir nesne
aldığından emin olarak belirtir.
Sütun üst bilgisi bağlantıları, kullanıcının filtre sonuçları içinde sıralama yapabilmesi için geçerli arama dizesini
denetleyiciye geçirmek için sorgu dizesini kullanır:

<a asp-action="Index" asp-route-sortOrder="@ViewData["DateSortParm"]" asp-route-currentFilter


="@ViewData["CurrentFilter"]">Enrollment Date</a>

Sayfalama düğmeleri etiket yardımcıları tarafından görüntülenir:


<a asp-action="Index"
asp-route-sortOrder="@ViewData["CurrentSort"]"
asp-route-pageNumber="@(Model.PageIndex - 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @prevDisabled">
Previous
</a>

Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.

Disk belleğinin çalıştığından emin olmak için farklı sıralama emirlerindeki disk belleği bağlantılarına tıklayın. Daha
sonra bir arama dizesi girin ve sayfalama ve filtreleme ile doğru şekilde çalıştığını doğrulamak için sayfalama işlemi
yeniden deneyin.

Hakkında bir sayfa oluşturun


Contoso Üniversitesi web sitesinin hakkında sayfasında, her bir kayıt tarihi için kaç öğrenciye kaydolduğunu
görüntüleyeceksiniz. Bu, gruplar üzerinde gruplandırma ve basit hesaplamalar gerektirir. Bunu gerçekleştirmek için
aşağıdakileri yapmanız gerekir:
Görünüme geçirmeniz gereken veriler için bir görünüm modeli sınıfı oluşturun.
Giriş denetleyicisinde hakkında yöntemini oluşturun.
Hakkında görünümünü oluşturun.
Görünüm modeli oluşturma
Modeller klasöründe bir SchoolViewModels klasörü oluşturun.
Yeni klasörde, EnrollmentDateGroup.cs bir sınıf dosyası ekleyin ve şablon kodunu şu kodla değiştirin:
using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; }

public int StudentCount { get; set; }


}
}

Ana denetleyiciyi değiştirme


HomeController.cs' de, aşağıdaki using deyimlerini dosyanın en üstüne ekleyin:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Data;
using ContosoUniversity.Models.SchoolViewModels;

Sınıf için açma küme ayracından hemen sonra veritabanı bağlamı için bir sınıf değişkeni ekleyin ve ASP.NET Core
DI 'den bağlamın bir örneğini alın:

public class HomeController : Controller


{
private readonly SchoolContext _context;

public HomeController(SchoolContext context)


{
_context = context;
}

Aşağıdaki kodla bir About yöntemi ekleyin:

public async Task<ActionResult> About()


{
IQueryable<EnrollmentDateGroup> data =
from student in _context.Students
group student by student.EnrollmentDate into dateGroup
select new EnrollmentDateGroup()
{
EnrollmentDate = dateGroup.Key,
StudentCount = dateGroup.Count()
};
return View(await data.AsNoTracking().ToListAsync());
}

LINQ deyimleri, öğrenci varlıklarını kayıt tarihine göre gruplandırır, her bir gruptaki varlıkların sayısını hesaplar ve
sonuçları bir EnrollmentDateGroup View model nesneleri koleksiyonunda depolar.
Hakkında görünüm oluştur
Aşağıdaki kodla bir Görünümler/Home/about. cshtml dosyası ekleyin:
@model IEnumerable<ContosoUniversity.Models.SchoolViewModels.EnrollmentDateGroup>

@{
ViewData["Title"] = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
<tr>
<th>
Enrollment Date
</th>
<th>
Students
</th>
</tr>

@foreach (var item in Model)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

Uygulamayı çalıştırın ve hakkında sayfasına gidin. Her kayıt tarihi için öğrenci sayısı bir tabloda görüntülenir.

Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Sütun sıralama bağlantıları eklendi
Arama kutusu eklendi
Öğrenciler dizinine sayfalama eklendi
Dizin oluşturma yöntemine sayfalama eklendi
Sayfalama bağlantıları eklendi
Hakkında bir sayfa oluşturuldu
Geçiş kullanarak veri modeli değişikliklerini nasıl işleyebileceğinizi öğrenmek için sonraki öğreticiye ilerleyin.
Sonraki: veri modeli değişikliklerini Işle
Öğretici: EF Core ile geçiş özelliğini kullanma-ASP.NET
MVC
23.11.2019 • 11 minutes to read • Edit Online

Bu öğreticide, veri modeli değişikliklerini yönetmek için EF Core geçişleri özelliğini kullanmaya başlayabilirsiniz.
Sonraki öğreticilerde, veri modelini değiştirirken daha fazla geçiş ekleyeceksiniz.
Bu öğreticide şunları yaptınız:
Geçişler hakkında bilgi edinin
Bağlantı dizesini değiştirme
İlk geçiş oluşturma
Yukarı ve aşağı yöntemleri inceleyin
Veri modeli anlık görüntüsü hakkında bilgi edinin
Geçişi Uygula

Önkoşullar
Sıralama, filtreleme ve sayfalama

Geçişler hakkında
Yeni bir uygulama geliştirirken, veri modeliniz sıklıkla değişir ve model her değiştiğinde veritabanıyla eşitlenmemiş
olur. Mevcut değilse veritabanını oluşturmak için Entity Framework yapılandırarak bu öğreticileri başlatmış
olursunuz. Veri modelini her değiştirdiğinizde (varlık sınıfları ekleyin, kaldırın veya değiştirin ya da DbContext
sınıfınızı değiştirin); veritabanını silebilir ve EF, modelle eşleşen yeni bir tane oluşturur ve test verileriyle birlikte olur.
Veritabanını veri modeliyle eşitlenmiş halde tutma yöntemi, uygulamayı üretime dağıtana kadar iyi çalışır.
Uygulama üretimde çalışırken, genellikle tutmak istediğiniz verileri saklar ve yeni sütun ekleme gibi her değişiklik
yaptığınızda her şeyi kaybetmek istemezsiniz. EF Core geçişleri özelliği, yeni bir veritabanı oluşturmak yerine EF 'in
veritabanı şemasını güncelleştirmesine olanak sağlayarak bu sorunu çözer.
Geçişlerle çalışmak için Paket Yöneticisi konsolu 'nu (PMC ) veya komut satırı ARABIRIMINI (CLI)
kullanabilirsiniz. Bu öğreticiler CLı komutlarının nasıl kullanılacağını göstermektedir. PMC hakkındaki bilgiler Bu
öğreticinin sonunda.

Bağlantı dizesini değiştirme


AppSettings. JSON dosyasında, bağlantı dizesindeki veritabanının adını ContosoUniversity2 veya kullandığınız
bilgisayarda kullanmadığınız başka bir ad olarak değiştirin.

{
"ConnectionStrings": {
"DefaultConnection": "Server=
(localdb)\\mssqllocaldb;Database=ContosoUniversity2;Trusted_Connection=True;MultipleActiveResultSets=true"
},

Bu değişiklik projeyi ilk geçişin yeni bir veritabanı oluşturacak şekilde ayarlar. Bu, geçişleri kullanmaya başlamak için
gerekli değildir, ancak daha sonra iyi bir fikir olduğunu göreceksiniz.
NOTE
Veritabanı adını değiştirmeye alternatif olarak, veritabanını silebilirsiniz. SQL Server Nesne Gezgini (ssox) veya
database drop CLI komutunu kullanın:

dotnet ef database drop

Aşağıdaki bölümde CLı komutlarının nasıl çalıştırılacağı açıklanmaktadır.

İlk geçiş oluşturma


Değişikliklerinizi kaydedin ve projeyi derleyin. Sonra bir komut penceresi açın ve proje klasörüne gidin. Bunu
yapmanın hızlı bir yolu aşağıda verilmiştir:
Çözüm Gezgini' de projeye sağ tıklayın ve bağlam menüsünden klasörü dosya Gezgini 'nde aç ' ı seçin.

Adres çubuğuna "cmd" yazın ve ENTER tuşuna basın.

Komut penceresine aşağıdaki komutu girin:

dotnet ef migrations add InitialCreate

Komut penceresinde aşağıdakine benzer bir çıktı görürsünüz:


info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 2.2.0-rtm-35687 initialized 'SchoolContext' using provider
'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Done. To undo this action, use 'ef migrations remove'

NOTE
"DotNet-EF" komutuyla eşleşen yürütülebilir dosya bulunamadıhata iletisi görürseniz, sorun giderme konusunda yardım için
Bu blog gönderisine bakın.

Bir hata iletisi görürseniz "dosyaya erişilemiyor... ContosoUniversity. dll başka bir işlem tarafından kullanıldığı için. ",
Windows sistem tepsisinde IIS Express simgesini bulun ve sağ tıklayın, sonra da contosouniversity > siteyi
durdur' a tıklayın.

Yukarı ve aşağı yöntemleri inceleyin


migrations add komutunu çalıştırdığınızda EF, veritabanını sıfırdan oluşturacak kodu oluşturdu. Bu kod,
_InitialCreate. cs ><zaman damgasıadlı dosyada geçişler klasöründedir. InitialCreate sınıfının Up yöntemi, veri
modeli varlık kümelerine karşılık gelen veritabanı tablolarını oluşturur ve aşağıdaki örnekte gösterildiği gibi Down
yöntemi onları siler.

public partial class InitialCreate : Migration


{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Credits = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});

// Additional code not shown


}

protected override void Down(MigrationBuilder migrationBuilder)


{
migrationBuilder.DropTable(
name: "Enrollment");
// Additional code not shown
}
}

Geçişler, bir geçiş için veri modeli değişikliklerini uygulamak üzere Up yöntemini çağırır. Güncelleştirmeyi geri
almak için bir komut girdiğinizde, geçişler Down yöntemini çağırır.
Bu kod, migrations add InitialCreate komutunu girdiğinizde oluşturulan ilk geçişe yöneliktir. Geçiş adı
parametresi (örnekteki "ınitialcreate") dosya adı için kullanılır ve istediğiniz her şey olabilir. Geçiş sırasında nelerin
yapıldığını özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, "AddDepartmentTable" adlı bir geçişe
daha sonra ad yazabilirsiniz.
Veritabanı zaten mevcut olduğunda ilk geçişi oluşturduysanız veritabanı oluşturma kodu oluşturulur, ancak
veritabanı veri modeliyle zaten eşleştiğinden çalıştırması gerekmez. Uygulamayı, veritabanının mevcut olmadığı
başka bir ortama dağıttığınızda, bu kod veritabanınızı oluşturmak için çalışır, bu nedenle ilk önce test etmek iyi bir
fikirdir. Bu nedenle, bağlantı dizesinde veritabanının adını daha önce değiştirmiş olursunuz. böylece geçişler sıfırdan
yeni bir tane oluşturabilir.

Veri modeli anlık görüntüsü


Geçişler, geçiş/SchoolContextModelSnapshot. csiçinde geçerli veritabanı şemasının bir anlık görüntüsünü oluşturur.
Bir geçiş eklediğinizde EF, veri modeli Snapshot dosyası ile karşılaştırılarak nelerin değiştirildiğini belirler.
Bir geçişi silerken DotNet EF geçişleri kaldır komutunu kullanın. dotnet ef migrations remove geçişi siler ve anlık
görüntünün doğru şekilde sıfırlanmasını sağlar.
Anlık görüntü dosyasının nasıl kullanıldığı hakkında daha fazla bilgi için bkz. Takım ortamlarında EF Core geçişleri .

Geçişi Uygula
Komut penceresinde, veritabanı ve tabloları oluşturmak için aşağıdaki komutu girin.

dotnet ef database update

Komutun çıktısı, veritabanının ayarlandığı SQL komutlarının günlüklerini görmeniz dışında migrations add
komutuna benzerdir. Günlüklerin çoğu aşağıdaki örnek çıktıda atlanır. Günlük iletilerinde bu ayrıntı düzeyini
görmemeyi tercih ediyorsanız, appSettings 'de günlük düzeyini değiştirebilirsiniz . Development. JSON dosyası.
Daha fazla bilgi için bkz. .NET Core ve ASP.NET Core oturum açma.

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 2.2.0-rtm-35687 initialized 'SchoolContext' using provider
'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (274ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
CREATE DATABASE [ContosoUniversity2];
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (60ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE [ContosoUniversity2] SET READ_COMMITTED_SNAPSHOT ON;
END;
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (15ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);

<logs omitted for brevity>

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20190327172701_InitialCreate', N'2.2.0-rtm-35687');
Done.

İlk öğreticide yaptığınız gibi veritabanını incelemek için SQL Server Nesne Gezgini kullanın. Hangi geçişlerin
veritabanına uygulandığını izleyen bir __EFMigrationsHistory tablosunun eklenmesini fark edeceksiniz. Bu
tablodaki verileri görüntüleyin ve ilk geçiş için bir satır görürsünüz. (Önceki CLı çıkış örneğinde son oturum, bu
satırı oluşturan INSERT ifadesini gösterir.)
Her şeyin daha önce olduğu gibi çalıştığını doğrulamak için uygulamayı çalıştırın.

CLı ve PMC karşılaştırması


Geçişleri yönetmek için EF araçları, .NET Core CLI komutlardan veya Visual Studio Paket Yöneticisi konsolu
(PMC ) penceresindeki PowerShell cmdlet 'lerinde bulunabilir. Bu öğreticide, CLı 'nın nasıl kullanılacağı
gösterilmektedir, ancak isterseniz PMC 'yi kullanabilirsiniz.
PMC komutlarına yönelik EF komutları Microsoft. EntityFrameworkCore. Tools paketidir. Bu paket Microsoft.
AspNetCore. app metapackageiçinde bulunur, bu nedenle uygulamanızın Microsoft.AspNetCore.App için bir paket
başvurusu varsa bir paket başvurusu eklemeniz gerekmez.
Önemli: Bu, . csproj dosyasını düzenleyerek CLI için yüklediğiniz paket ile aynı değildir. Bu adın adı, Tools.DotNet
biten CLı paketi adından farklı olarak Tools biter.
CLı komutları hakkında daha fazla bilgi için bkz. .NET Core CLI.
PMC komutları hakkında daha fazla bilgi için bkz. Paket Yöneticisi Konsolu (Visual Studio).

Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adım
Bu öğreticide şunları yaptınız:
Geçişler hakkında öğrenildi
NuGet geçiş paketleri hakkında bilgi edinildi
Bağlantı dizesi değiştirildi
İlk geçiş oluşturuldu
Yukarı ve aşağı yöntemleri İnceleme
Veri modeli anlık görüntüsü hakkında bilgi edinildi
Geçiş uygulandı
Veri modelini genişletme hakkında daha gelişmiş konulara bakmak için sonraki öğreticiye ilerleyin. Ek geçişler
oluşturma ve uygulama gibi.
Ek geçişler oluşturma ve uygulama
Öğretici: EF Core ile karmaşık veri modeli oluşturma-
ASP.NET MVC
25.11.2019 • 46 minutes to read • Edit Online

Önceki öğreticilerde, üç varlıktan oluşan basit bir veri modeliyle çalıştık. Bu öğreticide, daha fazla varlık ve ilişki
ekleyeceksiniz ve biçimlendirme, doğrulama ve veritabanı eşleme kurallarını belirterek veri modelini
özelleştireceksiniz.
İşiniz bittiğinde, varlık sınıfları aşağıdaki çizimde gösterilen tamamlanmış veri modelini oluşturacak:

Bu öğreticide şunları yaptınız:


Veri modelini özelleştirme
Öğrenci varlığında değişiklik yap
Eğitmen varlığı oluşturma
OfficeAssignment varlığı oluştur
Kurs varlığını değiştirme
Departman varlığı oluştur
Kayıt varlığını değiştirme
Veritabanı bağlamını güncelleştirme
Test verileriyle çekirdek veritabanı
Geçiş Ekle
Bağlantı dizesini değiştirme
Veritabanını güncelleştirme

Önkoşullar
EF Core geçişleri kullanma

Veri modelini özelleştirme


Bu bölümde, biçimlendirme, doğrulama ve veritabanı eşleme kurallarını belirten öznitelikleri kullanarak veri
modelini nasıl özelleştireceğinizi göreceksiniz. Ardından, aşağıdaki bölümlerde, zaten oluşturduğunuz sınıflara
öznitelikler ekleyerek ve modeldeki kalan varlık türleri için yeni sınıflar oluşturarak tüm okul veri modelini
oluşturacaksınız.
DataType özniteliği
Öğrenci kayıt tarihleri için tüm Web sayfaları Şu anda tarihle birlikte görüntülenir, ancak bu alan için tüm önemli bir
tarih olması gerekir. Veri ek açıklaması özniteliklerini kullanarak, verileri gösteren her görünümde görüntü biçimini
giderecek bir kod değişikliği yapabilirsiniz. Bunun nasıl yapılacağını gösteren bir örnek görmek için, Student
sınıfındaki EnrollmentDate özelliğine bir öznitelik ekleyeceksiniz.
Modeller/öğrenci. cs' de, System.ComponentModel.DataAnnotations ad alanı için using bir ifade ekleyin ve aşağıdaki
örnekte gösterildiği gibi EnrollmentDate özelliğine DataType ve DisplayFormat özniteliklerini ekleyin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

DataType özniteliği, veritabanı iç türünden daha özel bir veri türü belirtmek için kullanılır. Bu durumda, tarihi ve
saati değil yalnızca tarihi izlemek istiyoruz. DataType numaralandırması, tarih, saat, PhoneNumber, para birimi,
Emaadresi ve daha fazlası gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri
otomatik olarak sağlamasını da sağlayabilir. Örneğin, DataType.EmailAddress için mailto: bir bağlantı
oluşturulabilir ve HTML5 'i destekleyen tarayıcılarda DataType.Date için bir tarih seçici sağlaneklenebilir. DataType
özniteliği HTML 5 tarayıcıların anlayabilmesi için HTML 5 data- (bir veri Dash) öznitelikleri yayar. DataType
öznitelikleri herhangi bir doğrulama sağlamaz.
DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, veri alanı sunucunun CultureInfo
öğesine göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

ApplyFormatInEditMode ayarı, bir metin kutusunda değer görüntülenmek üzere görüntülendiğinde


biçimlendirmenin de uygulanacağını belirtir. (Bazı alanlar için bunu istemiyor olabilirsiniz; örneğin, para birimi
değerleri için metin kutusundaki para birimi sembolünü düzenlemenin değiştirilmesini istemeyebilirsiniz.)
DisplayFormat özniteliğini kendisi kullanabilirsiniz, ancak DataType özniteliğini de kullanmak genellikle iyi bir
fikirdir. DataType özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini değil, DisplayFormat ile elde
olmadığınız avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını, bazı istemci tarafı giriş doğrulamasını vb. göstermek için).
Varsayılan olarak tarayıcı, verileri yerel ayarınızı temel alarak doğru biçimi kullanarak işleyebilir.
Daha fazla bilgi için bkz. giriş > etiketi Yardımcısı belgeleri<.
Uygulamayı çalıştırın, öğrenciler dizin sayfasına gidin ve kayıt tarihleri için saatlerin artık gösterilmediğine dikkat
edin. Aynı değer öğrenci modelini kullanan herhangi bir görünüm için de geçerli olacaktır.

StringLength özniteliği
Ayrıca, öznitelikleri kullanarak veri doğrulama kuralları ve doğrulama hata iletileri de belirtebilirsiniz. StringLength
özniteliği, veritabanında en fazla uzunluğu ayarlar ve ASP.NET Core MVC için istemci tarafı ve sunucu tarafı
doğrulaması sağlar. Bu öznitelikte en küçük dize uzunluğunu da belirtebilirsiniz, ancak en küçük değerin veritabanı
şemasında hiçbir etkisi yoktur.
Kullanıcıların bir ad için 50 ' den fazla karakter girmemesini istediğinizi varsayalım. Bu kısıtlamayı eklemek için,
aşağıdaki örnekte gösterildiği gibi, LastName ve FirstMidName özelliklerine StringLength öznitelikleri ekleyin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50)]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

StringLength özniteliği bir kullanıcının ad için boşluk girmesini engellemez. Girişe kısıtlama uygulamak için
RegularExpression özniteliğini kullanabilirsiniz. Örneğin, aşağıdaki kod ilk karakterin büyük küçük harf olmasını ve
geri kalan karakterlerin alfabetik olmasını gerektirir:

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]

MaxLength özniteliği, StringLength özniteliğe benzer ancak istemci tarafı doğrulaması sağlamayan işlevselliği
sağlar.
Veritabanı modeli, veritabanı şemasında değişiklik yapılmasını gerektiren bir şekilde değiştirildi. Uygulama kullanıcı
arabirimini kullanarak, veritabanına eklemiş olduğunuz herhangi bir veriyi kaybetmeden Şemayı güncelleştirmek
için geçişleri kullanacaksınız.
Değişikliklerinizi kaydedin ve projeyi derleyin. Ardından proje klasöründe komut penceresini açın ve aşağıdaki
komutları girin:

dotnet ef migrations add MaxLengthOnNames

dotnet ef database update

migrations add komutu, bu değişiklik, iki sütun için en fazla uzunluğu daha kısa hale yaptığından, veri kaybının
gerçekleşebileceğini uyarır. Geçişler _MaxLengthOnNames. cs ><zaman damgasıadlı bir dosya oluşturur. Bu dosya,
veritabanını geçerli veri modeliyle eşleşecek şekilde güncelleştirecek Up yönteminde kod içerir. database update
komutu bu kodu çalıştırdı.
Geçiş dosyası adının ön eki olan zaman damgası, geçişleri sıralamak için Entity Framework tarafından kullanılır.
Update-database komutunu çalıştırmadan önce birden çok geçiş oluşturabilirsiniz ve sonra tüm geçişler
oluşturuldukları sırada uygulanır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin, Yeni oluştur' a tıklayın ve 50 karakterden daha uzun bir ad
girmeyi deneyin. Uygulamanın bunu yapmasını önleyebilmelidir.
Column özniteliği
Ayrıca, sınıflarınızın ve özelliklerinin veritabanına nasıl eşlenildiğini denetlemek için özniteliklerini de
kullanabilirsiniz. Alan aynı zamanda bir orta ad içerebileceğinden, ilk ad alanı için FirstMidName adı kullandığınızı
varsayalım. Ancak veritabanına karşı geçici sorgular yazmayacak olan kullanıcılar bu ada alışkın olduğundan,
veritabanı sütununun FirstName adlandırılmış olmasını isteyebilirsiniz. Bu eşlemeyi yapmak için, Column
özniteliğini kullanabilirsiniz.
Column özniteliği, veritabanı oluşturulduğunda, FirstMidName özelliğine eşlenen Student tablosunun sütununun
FirstName adlandırılacağını belirtir. Diğer bir deyişle, kodunuz Student.FirstMidName başvurduğunda, veriler
Student tablosunun FirstName sütununda gönderilir veya güncelleştirilir. Sütun adları belirtmezseniz, bunlar
Özellik adı ile aynı ada verilir.
Student.cs dosyasında, System.ComponentModel.DataAnnotations.Schema için using bir ifade ekleyin ve sütun adı
özniteliğini aşağıdaki vurgulanmış kodda gösterildiği gibi FirstMidName özelliğine ekleyin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50)]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Column özniteliği ekleme modeli, SchoolContext yedekleyen, bu nedenle veritabanıyla eşleşmez.


Değişikliklerinizi kaydedin ve projeyi derleyin. Ardından proje klasöründe komut penceresini açın ve başka bir geçiş
oluşturmak için aşağıdaki komutları girin:

dotnet ef migrations add ColumnFirstName

dotnet ef database update

SQL Server Nesne Gezgini , öğrenci tablosuna çift tıklayarak öğrenci tablosu tasarımcısını açın.
İlk iki geçişi uygulamadan önce ad sütunları nvarchar (MAX) türünde. Artık nvarchar (50) ve sütun adı
FirstMidName iken FirstName olarak değiştirilmiştir.

NOTE
Aşağıdaki bölümlerde tüm varlık sınıflarını oluşturmayı bitirmeden önce derlemeyi denerseniz Derleyici hataları alabilirsiniz.

Öğrenci varlığındaki değişiklikler

Modeller/öğrenci. cs' de, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50)]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Gerekli öznitelik
Required özniteliği, ad özellikleri gereken alanları sağlar. Değer türleri ( DateTime, int, Double, float, vb.) gibi null
yapılamayan türler için Required özniteliği gerekli değildir. Null olmayan türler otomatik olarak gerekli alanlar
olarak değerlendirilir.
MinimumLength zorlanmak için Required özniteliği MinimumLength ile birlikte kullanılmalıdır.

[Display(Name = "Last Name")]


[Required]
[StringLength(50, MinimumLength=2)]
public string LastName { get; set; }

Display özniteliği
Display özniteliği, metin kutularının açıklamalı alt yazısının her örnekteki Özellik adı yerine "Ilk ad", "soyadı", "tam
ad" ve "kayıt tarihi" olması gerektiğini belirtir (kelimeleri bir boşluk yoktur).
FullName hesaplanmış özelliği
FullName , diğer iki özelliği birleştirerek oluşturulmuş bir değer döndüren hesaplanmış bir özelliktir. Bu nedenle,
yalnızca bir get erişimcisine sahiptir ve veritabanında FullName sütunu oluşturulmaz.

Eğitmen varlığı oluşturma


Şablon kodunu aşağıdaki kodla değiştirerek modeller/eğitmen. csoluşturun:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor
{
public int ID { get; set; }

[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }

[Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get { return LastName + ", " + FirstMidName; }
}

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Öğrenci ve eğitmen varlıklarında birçok özellik aynı olduğuna dikkat edin. Devralma öğreticisini bu serinin ilerleyen
kısımlarında uyguladığınızda , artıklığı ortadan kaldırmak için bu kodu yeniden düzenlemelisiniz.
Birden çok özniteliği tek bir satıra koyabilirsiniz, bu nedenle HireDate özniteliklerini aşağıdaki gibi yazabilirsiniz:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",


ApplyFormatInEditMode = true)]

Courseatamalar ve OfficeAssignment gezinti özellikleri


CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.
Bir eğitmen herhangi bir sayıda kurs öğretebilir, bu nedenle CourseAssignments bir koleksiyon olarak tanımlanır.

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Bir gezinti özelliği birden çok varlık tukiyorsa, türü girişlerin eklenebileceği, silinebileceği ve güncelleştirilemeyebilir
bir liste olmalıdır. ICollection<T> veya List<T> veya HashSet<T> gibi bir tür belirtebilirsiniz. ICollection<T>
belirtirseniz, EF varsayılan olarak bir HashSet<T> koleksiyonu oluşturur.
Bunların CourseAssignment varlıkların nedenleri, çoktan çoğa ilişkiler hakkında bölümünde aşağıda açıklanmıştır.
Contoso Üniversitesi iş kuralları, bir eğitmenin yalnızca en fazla bir ofise sahip olabileceğini, bu nedenle
OfficeAssignment özelliği tek bir OfficeAssignment varlığı ( Office atanmamışsa null olabilir ) bulundurmasıdır.

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığı oluştur

Aşağıdaki kodla modeller/OfficeAssignment. cs oluşturun:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }

public Instructor Instructor { get; set; }


}
}

Anahtar özniteliği
Eğitmen ve OfficeAssignment varlıkları arasında bire sıfır veya-bir ilişki vardır. Office ataması, atandığı eğitmenle
ilişkili olarak yalnızca kendi birincil anahtarı da eğitmen varlığına ait yabancı anahtarıdır. Ancak Entity Framework,
adı ID veya Classnameıd adlandırma kuralını izlemediği için bu varlığın birincil anahtarı olarak Komutctorıd 'yi
otomatik olarak tanıyamaz. Bu nedenle, Key özniteliği onu anahtar olarak tanımlamak için kullanılır:

[Key]
public int InstructorID { get; set; }

Varlık kendi birincil anahtarına sahip olsa da, özelliği Classnameıd veya ID dışında bir şekilde adlandırmak
istiyorsanız Key özniteliğini de kullanabilirsiniz.
Varsayılan olarak, tam olarak, sütun tanımlayıcı bir ilişki için olduğundan EF, anahtarı veritabanı olmayan bir şekilde
değerlendirir.
Eğitmen gezintisi özelliği
Eğitmen varlığı, null yapılabilir bir OfficeAssignment gezinti özelliğine sahiptir (bir eğitmenin bir Office ataması
olmayabilir) ve OfficeAssignment varlığı null atanamaz Instructor bir gezinti özelliğine sahiptir (bir Office ataması
bir eğitmen olmadan mevcut olamaz-- InstructorID null değer atanamaz). Bir eğitmen varlığı ilgili bir
OfficeAssignment varlığına sahip olduğunda, her varlığın gezinti özelliğinde diğer birine bir başvurusu olur.
İlgili bir eğitmen olması gerektiğini belirtmek için, eğitmen gezinti özelliğine bir [Required] özniteliği koyabilirsiniz,
ancak bunu yapmak zorunda kalmazsınız çünkü bu, InstructorID yabancı anahtar (aynı zamanda bu tablodaki
anahtar) null atanamaz.

Kurs varlığını değiştirme

Modeller/kurs. cs' de, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Title { get; set; }

[Range(0, 5)]
public int Credits { get; set; }

public int DepartmentID { get; set; }

public Department Department { get; set; }


public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}

Kurs varlığının, ilgili departman varlığına işaret eden ve Department bir gezinti özelliği olan DepartmentID yabancı
anahtar özelliği vardır.
Entity Framework, ilgili varlık için bir gezinti özelliği olduğunda, veri modelinize yabancı anahtar özelliği eklemenizi
gerektirmez. EF, gerektiğinde otomatik olarak yabancı anahtarlar oluşturur ve bunlar için gölge Özellikler oluşturur.
Ancak veri modelinde yabancı anahtar olması, güncelleştirmeleri daha basit ve daha verimli hale getirir. Örneğin,
düzenlemek üzere bir kurs varlığı aldığınızda, bunu yüklemezseniz departman varlığı null olur, bu nedenle kurs
varlığını güncelleştirdiğinizde öncelikle departman varlığını almanız gerekir. Yabancı anahtar özelliği DepartmentID
veri modeline dahil edildiğinde, güncelleştirmeden önce bölüm varlığını almanız gerekmez.
DatabaseGenerated özniteliği
CourseID özelliğindeki None parametresine sahip DatabaseGenerated özniteliği, birincil anahtar değerlerinin
veritabanı tarafından oluşturulması yerine Kullanıcı tarafından sağlandığını belirtir.

[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, Entity Framework birincil anahtar değerlerinin veritabanı tarafından oluşturulduğunu varsayar.
Bu, Çoğu senaryoda istediğiniz şeydir. Ancak, kurs varlıkları için bir departman için 1000 serisi, başka bir
departman için 2000 serisi vb. gibi kullanıcı tarafından belirtilen bir kurs numarası kullanırsınız.
DatabaseGenerated özniteliği, bir satırın oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için kullanılan
veritabanı sütunları durumunda olduğu gibi varsayılan değerleri oluşturmak için de kullanılabilir. Daha fazla bilgi
için bkz. üretilen Özellikler.
Yabancı anahtar ve gezinti özellikleri
Kurs varlığındaki yabancı anahtar özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir kurs bir departmana atanır, bu nedenle yukarıda bahsedilen nedenlerle DepartmentID yabancı anahtar ve
Department gezinti özelliği vardır.

public int DepartmentID { get; set; }


public Department Department { get; set; }

Bir kurs, kayıtlı sayıda öğrenciye sahip olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

public ICollection<Enrollment> Enrollments { get; set; }

Bir kurs birden fazla eğitmen tarafından tada olabilir, bu nedenle CourseAssignments gezinti özelliği bir koleksiyon
olur ( CourseAssignment türü daha sonraaçıklanmıştır):

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Departman varlığı oluştur

Aşağıdaki kodla modeller/departman. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Column özniteliği
Daha önce, sütun adı eşlemesini değiştirmek için Column özniteliğini kullandınız. Bölüm varlığının kodunda,
sütunun veritabanındaki SQL Server para türü kullanılarak tanımlanması için SQL veri türü eşlemesini değiştirmek
üzere Column özniteliği kullanılır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Entity Framework, özellik için tanımladığınız CLR türüne göre uygun SQL Server veri türünü seçtiği için sütun
eşlemesi genellikle gerekli değildir. CLR decimal türü bir SQL Server decimal türüne eşlenir. Ancak bu durumda,
sütunun para birimi tutarlarını tutuını ve para veri türü bunun için daha uygun olduğunu bilirsiniz.
Yabancı anahtar ve gezinti özellikleri
Yabancı anahtar ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir departman yönetici olabilir veya olmayabilir ve yönetici her zaman bir eğitmendir. Bu nedenle InstructorID
özelliği, eğitmen varlığına yabancı anahtar olarak dahil edilir ve özelliği null yapılabilir olarak işaretlemek için int
tür atamadan sonra bir soru işareti eklenir. Gezinti özelliği Administrator olarak adlandırılır ancak bir eğitmen
varlığı tutar:

public int? InstructorID { get; set; }


public Instructor Administrator { get; set; }

Bir departmanın birçok kursu olabilir, bu nedenle bir kurs gezintisi özelliği vardır:

public ICollection<Course> Courses { get; set; }


NOTE
Kurala göre Entity Framework, null olamayan yabancı anahtarlar ve çoktan çoğa ilişkiler için art arda silme imkanı sağlar. Bu, bir
geçiş eklemeye çalıştığınızda bir özel duruma neden olacak dairesel basamaklı silme kurallarına neden olabilir. Örneğin,
Department. Komutctorıd özelliğini null yapılabilir olarak tanımlamadıysanız, bu, bir basamak silme kuralını, eğitmeni
sildiğinizde, ne yapmak istediğinize ilişkin olmayan bir şeyi silmek için yapılandırır. İş kurallarınız InstructorID özelliğini null
atanamaz olarak gerektiriyorsa, ilişkide basamaklı silmeyi devre dışı bırakmak için aşağıdaki Fluent API ifadesini kullanmanız
gerekir:

modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)

Kayıt varlığını değiştirme

Modeller/kayıt. cs' de, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

Yabancı anahtar ve gezinti özellikleri


Yabancı anahtar özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Kayıt kaydı tek bir kurs için olduğundan CourseID yabancı anahtar özelliği ve Course gezinti özelliği vardır:
public int CourseID { get; set; }
public Course Course { get; set; }

Kayıt kaydı tek bir öğrenci içindir, bu nedenle StudentID yabancı anahtar özelliği ve Student gezinti özelliği vardır:

public int StudentID { get; set; }


public Student Student { get; set; }

Çoktan çoğa ilişkiler


Öğrenci ve kurs varlıkları arasında çok-çok ilişkisi vardır ve kayıt varlığı, veritabanında Yük içeren çoktan çoğa bir
JOIN tablosu gibi çalışır. "Yük ile", kayıt tablosunun birleştirilmiş tablolar için yabancı anahtarlar (Bu durumda bir
birincil anahtar ve bir sınıf özelliği) yanında ek veriler içerdiği anlamına gelir.
Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğünü gösterilmektedir. (Bu diyagram EF 6. x
için Entity Framework güç araçları kullanılarak oluşturulmuştur; diyagramı oluşturmak öğreticinin bir parçası
değildir, burada yalnızca bir çizim olarak kullanılmaktadır.)

Her ilişki ucu ve bir yıldız işareti (*) 1 diğer sırasında bir-çok ilişkisi belirten bulunur.
Kayıt tablosu, sınıf bilgilerini içermiyorsa, yalnızca iki yabancı anahtar olan CourseID ve Studentitıd 'yi içermelidir.
Bu durumda, veritabanına yük (veya saf bir JOIN tablosu) olmadan çok-çok arasında bir JOIN tablosu olacaktır.
Eğitmen ve kurs varlıklarının bu tür çok-çok ilişkisi vardır ve bir sonraki adımınız, yük olmadan bir JOIN tablosu
olarak çalışacak bir varlık sınıfı oluşturmaktır.
(EF 6. x, çoktan çoğa ilişkiler için örtük birleştirmeyi destekler, ancak EF Core. Daha fazla bilgi için, EF Core GitHub
deposundaki tartışmayabakın.)

Courseatama varlığı
Aşağıdaki kodla modeller/Courseatama. cs oluşturun:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class CourseAssignment
{
public int InstructorID { get; set; }
public int CourseID { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
}
}

Varlık adlarını Birleştir


Eğitim--çok ilişkisi için veritabanında bir JOIN tablosu gereklidir ve bir varlık kümesi tarafından temsil edilir. Bu
örnekte CourseInstructor``EntityName1EntityName2 bir JOIN varlığının adı yaygın olarak kullanılır. Ancak, ilişkiyi
açıklayan bir ad seçmenizi öneririz. Veri modelleri, daha sonra yükleri daha sonra almak için, yük olmayan
birleşimler olmadan basit ve büyümeye başlar. Açıklayıcı bir varlık adıyla başladıysanız, daha sonra adı
değiştirmeniz gerekmez. İdeal olarak, JOIN varlığının iş etki alanında kendi doğal (muhtemelen tek bir kelime)
adına sahip olması gerekir. Örneğin, kitaplar ve müşteriler derecelendirmeler aracılığıyla bağlanabilir. Bu ilişki için
CourseAssignment CourseInstructor daha iyi bir seçenektir.

Bileşik anahtar
Yabancı anahtarlar null değer atanmadığından ve tablodaki her satırı benzersiz bir şekilde tanımladığından, ayrı bir
birincil anahtar gerekmez. Komutctorıd ve CourseID özellikleri bir bileşik birincil anahtar olarak çalışır. EF için
bileşik birincil anahtarları tanımlamanın tek yolu Fluent API kullanmaktır (öznitelikleri kullanılarak
gerçekleştirilemez). Bir sonraki bölümde bileşik birincil anahtarı nasıl yapılandıracağınızı göreceksiniz.
Bileşik anahtar, tek bir kurs için birden çok satır ve bir eğitmen için birden fazla satır, aynı eğitmen ve kurs için
birden çok satıra sahip olmanızı sağlar. Enrollment JOIN varlığı kendi birincil anahtarını tanımlar, bu nedenle bu
sıralamanın yinelemeleri mümkündür. Bu tür yinelemeleri engellemek için yabancı anahtar alanlarına benzersiz bir
dizin ekleyebilir veya CourseAssignment benzer bir birincil bileşik anahtarla Enrollment yapılandırabilirsiniz. Daha
fazla bilgi için bkz. dizinler.

Veritabanı bağlamını güncelleştirme


Data/SchoolContext. cs dosyasına aşağıdaki vurgulanmış kodu ekleyin:
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<CourseAssignment> CourseAssignments { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Department>().ToTable("Department");
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");

modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
}
}
}

Bu kod yeni varlıkları ekler ve Courseatama varlığının bileşik birincil anahtarını yapılandırır.

Fluent API alternatifi hakkında


DbContext sınıfının OnModelCreating yöntemindeki kod, EF davranışını yapılandırmak için Fluent API kullanır. Bu
örnekte, EF Core belgelerindenfarklı olarak, bir dizi yöntemi çağıran tek bir bildirimde dize tarafından
KULLANıLDıĞıNDAN, API "floent" olarak adlandırılır:

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}

Bu öğreticide, yalnızca öznitelikleri ile yapaamıyoruz veritabanı eşlemesi için Fluent API kullanıyorsunuz. Ancak,
özniteliklerini kullanarak yapabileceğiniz biçimlendirme, doğrulama ve eşleme kurallarının çoğunu belirtmek için
Fluent API de kullanabilirsiniz. MinimumLength gibi bazı öznitelikler Fluent API uygulanamaz. Daha önce belirtildiği
gibi, MinimumLength şemayı değiştirmez, yalnızca bir istemci ve sunucu tarafı doğrulama kuralı uygular.
Bazı geliştiriciler, varlık sınıflarının "temiz" olmasını sağlamak için Fluent API özel olarak kullanmayı tercih eder.
İsterseniz öznitelikleri ve Fluent API karıştırabilir ve yalnızca Fluent API kullanılarak gerçekleştirilebilecek bazı
özelleştirmeler de vardır ancak genel olarak önerilen uygulama, bu iki yaklaşımdan birini seçmek ve bunları
mümkün olduğunca tutarlı bir şekilde kullanmaktır. Her ikisini de kullanırsanız, bir çakışma olduğunda, akıcı API
'nin öznitelikleri geçersiz kıldığını unutmayın.
Öznitelikler ile Fluent API hakkında daha fazla bilgi için bkz. yapılandırma yöntemleri.

Ilişkileri gösteren varlık diyagramı


Aşağıdaki çizimde, Entity Framework Power Tools 'un tamamlanmış okul modeli için kullandığı diyagram
gösterilmektedir.

Bire çok ilişki çizgilerinin yanı sıra (1 ' den *), eğitmen ve OfficeAssignment varlıkları arasında (1 ila 0.. 1) ve
eğitmen ve departman varlıkları arasında sıfır veya-bire çok ilişki satırı (0.. 1 ile *) arasında bir tek-sıfır veya-bir ilişki
satırını görebilirsiniz.

Test verileriyle çekirdek veritabanı


Veri/Dbınınitializer. cs dosyasındaki kodu, oluşturduğunuz yeni varlıklar için çekirdek verileri sağlamak üzere
aşağıdaki kodla değiştirin.

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
//context.Database.EnsureCreated();

// Look for any students.


if (context.Students.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2010-09-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Arturo", LastName = "Anand",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Yan", LastName = "Li",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Peggy", LastName = "Justice",
EnrollmentDate = DateTime.Parse("2011-09-01") },
new Student { FirstMidName = "Laura", LastName = "Norman",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Nino", LastName = "Olivetto",
EnrollmentDate = DateTime.Parse("2005-09-01") }
};

foreach (Student s in students)


{
context.Students.Add(s);
}
context.SaveChanges();

var instructors = new Instructor[]


{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie",
HireDate = DateTime.Parse("1995-03-11") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri",
HireDate = DateTime.Parse("2002-07-06") },
new Instructor { FirstMidName = "Roger", LastName = "Harui",
HireDate = DateTime.Parse("1998-07-01") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
HireDate = DateTime.Parse("2001-01-15") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng",
HireDate = DateTime.Parse("2004-02-12") }
};

foreach (Instructor i in instructors)


{
context.Instructors.Add(i);
}
context.SaveChanges();

var departments = new Department[]


{
new Department { Name = "English", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").ID },
new Department { Name = "Mathematics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID },
new Department { Name = "Engineering", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").ID },
new Department { Name = "Economics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID }
};

foreach (Department d in departments)


{
context.Departments.Add(d);
}
context.SaveChanges();

var courses = new Course[]


{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID
},
new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 1045, Title = "Calculus", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 2021, Title = "Composition", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
new Course {CourseID = 2042, Title = "Literature", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
};

foreach (Course c in courses)


{
context.Courses.Add(c);
}
context.SaveChanges();

var officeAssignments = new OfficeAssignment[]


{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
Location = "Thompson 304" },
};

foreach (OfficeAssignment o in officeAssignments)


{
context.OfficeAssignments.Add(o);
}
context.SaveChanges();

var courseInstructors = new CourseAssignment[]


{
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Kapoor").ID
},
new CourseAssignment {
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Fakhouri").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Literature" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
};

foreach (CourseAssignment ci in courseInstructors)


{
context.CourseAssignments.Add(ci);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").ID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").ID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
};

foreach (Enrollment e in enrollments)


{
var enrollmentInDataBase = context.Enrollments.Where(
s =>
s.Student.ID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollments.Add(e);
}
}
context.SaveChanges();
}
}
}

İlk öğreticide gördüğünüz gibi, bu kodun çoğu yalnızca yeni varlık nesneleri oluşturur ve test için gereken şekilde,
örnek verileri özelliklere yükler. Çoktan çoğa ilişkilerin nasıl işlendiği hakkında dikkat edin: kod, Enrollments
varlıklar oluşturup CourseAssignment varlık kümelerine katmak yoluyla ilişkiler oluşturur.

Geçiş Ekle
Değişikliklerinizi kaydedin ve projeyi derleyin. Ardından proje klasöründe komut penceresini açın ve
migrations add komutunu girin (henüz Update-database komutunu yapmayın):

dotnet ef migrations add ComplexDataModel

Olası veri kaybı hakkında bir uyarı alırsınız.

An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
Done. To undo this action, use 'ef migrations remove'

database update komutunu bu noktada çalıştırmayı denediyseniz (henüz yapmayın), şu hatayı alırsınız:

ALTER TABLE ifadesi, "FK_dbo yabancı anahtar kısıtlaması ile çakışıyor. Course_dbo.
Department_DepartmentID ". "ContosoUniversity" veritabanında, "dbo" tablosunda çakışma oluştu. Bölüm ",
sütun ' DepartmentID '.

Bazı durumlarda, mevcut verilerle geçişleri yürüttüğünüzde, yabancı anahtar kısıtlamalarını karşılamak için saplama
verilerini veritabanına eklemeniz gerekir. Up yönteminde oluşturulan kod, kurs tablosuna null yapılamayan bir
DepartmentID yabancı anahtarı ekler. Kurs tablosunda kod çalıştırıldığında zaten satırlar varsa, SQL Server null
olmayan sütuna hangi değerin yerleştirileceğini bilmediği için AddColumn işlemi başarısız olur. Bu öğreticide, geçişi
yeni bir veritabanında çalıştıracaksınız, ancak bir üretim uygulamasında geçiş, mevcut verileri işleyeceğinizden, bu
sayede bunun nasıl yapılacağını gösteren bir örnek gösterilmektedir.
Bu geçişi mevcut verilerle birlikte çalışarak, yeni sütuna varsayılan bir değer vermek için kodu değiştirmeniz ve
varsayılan departman görevi gören "Temp" adlı bir saplama departmanı oluşturmanız gerekir. Sonuç olarak,
mevcut kurs satırları Up yöntemi çalıştıktan sonra "geçici" departmanla ilgili olacaktır.
{Timestamp } _ComplexDataModel. cs dosyasını açın.
DepartmentID sütununu kurs tablosuna ekleyen kod satırını açıklama satırı yapın.

migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldNullable: true);

//migrationBuilder.AddColumn<int>(
// name: "DepartmentID",
// table: "Course",
// nullable: false,
// defaultValue: 0);

Departman tablosunu oluşturan koddan sonra aşağıdaki vurgulanmış kodu ekleyin:


migrationBuilder.CreateTable(
name: "Department",
columns: table => new
{
DepartmentID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Budget = table.Column<decimal>(type: "money", nullable: false),
InstructorID = table.Column<int>(nullable: true),
Name = table.Column<string>(maxLength: 50, nullable: true),
StartDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Department", x => x.DepartmentID);
table.ForeignKey(
name: "FK_Department_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});

migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00,


GETDATE())");
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1);

Bir üretim uygulamasında, departman satırları eklemek ve kurs satırlarını yeni departman satırlarıyla
ilişkilendirmek için kod veya komut dosyaları yazın. Bundan sonra "geçici" Departmanı veya kurs. DepartmentID
sütununda Varsayılan değer gerekmez.
Değişikliklerinizi kaydedin ve projeyi derleyin.

Bağlantı dizesini değiştirme


Artık, yeni varlıkların temel verilerini boş bir veritabanına ekleyen DbInitializer sınıfında yeni kodunuz var. EF 'in
yeni boş bir veritabanı oluşturmasını sağlamak için appSettings. JSON içindeki bağlantı dizesinde veritabanının
adını ContosoUniversity3 veya kullandığınız bilgisayarda kullanmadığınız başka bir adla değiştirin.

{
"ConnectionStrings": {
"DefaultConnection": "Server=
(localdb)\\mssqllocaldb;Database=ContosoUniversity3;Trusted_Connection=True;MultipleActiveResultSets=true"
},

Değişiklerinizi appSettings. JSON' da kaydedin.


NOTE
Veritabanı adını değiştirmeye alternatif olarak, veritabanını silebilirsiniz. SQL Server Nesne Gezgini (ssox) veya
database drop CLI komutunu kullanın:

dotnet ef database drop

Veritabanını güncelleştirme
Veritabanı adını değiştirdikten veya veritabanını sildikten sonra, geçişleri yürütmek için komut penceresinde
database update komutunu çalıştırın.

dotnet ef database update

DbInitializer.Initialize yönteminin çalışmasına ve yeni veritabanını doldurmasına neden olmak için uygulamayı
çalıştırın.
Veritabanını daha önce yaptığınız gibi SSOX içinde açın ve tabloların tümünün oluşturulduğunu görmek için Tables
düğümünü genişletin. (Yine de bir daha önceki zamanda SSOX açıksa Yenile düğmesine tıklayın.)

Veritabanını gösteren Başlatıcı kodunu tetiklemek için uygulamayı çalıştırın.


Courseatama tablosuna sağ tıklayın ve verileri görüntüle ' yi seçerek veri içerdiğinden emin olun.
Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Veri modeli özelleştirildi
Öğrenci varlığında değişiklikler yapıldı
Eğitmen varlığı oluşturuldu
OfficeAssignment varlığı oluşturuldu
Değiştirilen kurs varlığı
Departman varlığı oluşturuldu
Değiştirilen kayıt varlığı
Veritabanı bağlamı güncelleştirildi
Test verileriyle birlikte sağlanan veritabanı
Geçiş eklendi
Bağlantı dizesi değiştirildi
Veritabanı güncelleştirildi
İlgili verilere erişme hakkında daha fazla bilgi edinmek için sonraki öğreticiye ilerleyin.
Sonraki: ilgili verilere erişin
Öğretici: EF Core ile ilgili verileri okuma-ASP.NET
MVC
23.11.2019 • 22 minutes to read • Edit Online

Önceki öğreticide, okul veri modelini tamamladınız. Bu öğreticide ilgili verileri okur ve görüntüleriz. Bu, Entity
Framework, gezinti özelliklerine yüklediği veriler.
Aşağıdaki çizimlerde, birlikte çalışacağımız sayfalar gösterilmektedir.
Bu öğreticide şunları yaptınız:
İlgili verileri yüklemeyi öğrenin
Kurslar sayfası oluşturma
Eğitmenler sayfası oluşturma
Açık yükleme hakkında bilgi edinin

Önkoşullar
Karmaşık veri modeli oluşturma

İlgili verileri yüklemeyi öğrenin


Entity Framework gibi nesne Ilişkisel eşleme (ORM ) yazılımının bir varlığın gezinti özelliklerine ilgili verileri
yükleyebilmesinin birkaç yolu vardır:
Eager yükleniyor. Varlık okurken ilgili veriler onunla birlikte alınır. Bu, genellikle gereken tüm verileri alan tek
bir JOIN sorgusuna neden olur. Include ve ThenInclude yöntemlerini kullanarak Entity Framework Core '
de bir Eager yüklemesi belirlersiniz.

Bazı verileri ayrı sorgularda alabilir ve "düzeltmeler" i "düzeltir" seçeneğini kullanabilirsiniz. Diğer bir deyişle,
EF, daha önce alınan varlıkların gezinti özelliklerine ait oldukları ayrı alınan varlıkları otomatik olarak ekler.
İlgili verileri alan sorgu için, ToList veya Single gibi bir liste veya nesne döndüren bir yöntem yerine Load
yöntemini kullanabilirsiniz.

Açık yükleme. Varlık ilk kez okunmadıysa ilgili veriler alınmadı. Gerekirse ilgili verileri alan kodu yazarsınız.
Ayrı sorgularla yükleme durumunda olduğu gibi, açıkça yükleme, veritabanına gönderilen birden çok sorgu
ile sonuçlanır. Fark, açık yükleme ile kod, yüklenecek gezinti özelliklerini belirtir. Entity Framework Core 1,1 '
de, açık yükleme yapmak için Load yöntemini kullanabilirsiniz. Örneğin:

Yavaş yükleme. Varlık ilk kez okunmadıysa ilgili veriler alınmadı. Ancak, bir gezinti özelliğine ilk kez erişmeye
çalıştığınızda, bu gezinti özelliği için gereken veriler otomatik olarak alınır. Bir gezinti özelliğinden ilk kez veri
almaya çalıştığınızda veritabanına bir sorgu gönderilir. Entity Framework Core 1,0, yavaş yüklemeyi
desteklemez.
Performans değerlendirmeleri
Alınan her varlık için ilgili verilerin gerekli olduğunu biliyorsanız, tek bir sorgu genellikle en iyi performansı sunar,
çünkü veritabanına gönderilen tek bir sorgu genellikle alınan her varlık için ayrı sorgulardan daha etkilidir. Örneğin,
her departmanın on ile ilgili kurs olduğunu varsayalım. Tüm ilgili verilerin bir şekilde yüklenmesi, tek bir (JOIN )
sorgusuna ve veritabanına yönelik tek gidiş dönüş oluşmasına neden olur. Her bölüme yönelik kurslar için ayrı bir
sorgu, veritabanı üzerinde on bir gidiş dönüş oluşmasına neden olur. Gecikme süresi yüksek olduğunda
veritabanına yönelik ek gidiş dönüşler özellikle performansa neden olur.
Öte yandan, bazı senaryolarda ayrı sorgular daha etkilidir. Tek bir sorgudaki ilgili verilerin tümünü yükleme, SQL
Server verimli bir şekilde bir birleştirmenin oluşturulmasına neden olabilir ve bu da etkili bir şekilde işleyemez. Ya
da bir varlığın gezinti özelliklerine yalnızca işlemekte olduğunuz varlıkların kümesinin bir alt kümesi için erişmeniz
gerekiyorsa, her şeyin en baştan yüklenmesi gerekenden fazla veri alacağından ayrı sorgular daha iyi çalışabilir.
Performans önemliyse, en iyi seçimi yapmak için her iki şekilde de performansı test etmek en iyisidir.

Kurslar sayfası oluşturma


Kurs varlığı, kursun atandığı departmanın departman varlığını içeren bir gezinti özelliği içerir. Bir kurs listesinde
atanan departmanın adını göstermek için, Course.Department Gezinti özelliğindeki departman varlığındaki Name
özelliğini almanız gerekir.
Aşağıdaki çizimde gösterildiği gibi, daha önce öğrenciler denetleyicisi için yaptığınız Entity Framework desteği ' ı
kullanarak, MVC denetleyicisi için, görünümler ile aynı seçenekleri kullanarak kurs varlık türü için
coursescontroller adlı bir denetleyici oluşturun:

CoursesController.cs 'i açın ve Index metodunu inceleyin. Otomatik yapı iskelesi, Department gezinti özelliği için
Include yöntemi kullanılarak bir Eager yüklemesi belirtti.

Index yöntemini, kurs varlıklarını döndüren IQueryable için daha uygun bir ad kullanan aşağıdaki kodla değiştirin
( schoolContext yerine courses ):

public async Task<IActionResult> Index()


{
var courses = _context.Courses
.Include(c => c.Department)
.AsNoTracking();
return View(await courses.ToListAsync());
}

Views/kurslar/Index. cshtml dosyasını açın ve şablon kodunu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:
@model IEnumerable<ContosoUniversity.Models.Course>

@{
ViewData["Title"] = "Courses";
}

<h2>Courses</h2>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Credits)
</th>
<th>
@Html.DisplayNameFor(model => model.Department)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.CourseID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.CourseID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.CourseID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yapı iskelesi kodunda aşağıdaki değişiklikleri yaptınız:


Başlık dizinden kurslar olarak değiştirildi.
CourseID özellik değerini gösteren bir sayı sütunu eklendi. Birincil anahtarlar, genellikle son kullanıcılara
anlamlı olduklarından, varsayılan olarak yapı iskelesi göstermemektedir. Ancak, bu durumda birincil anahtar
anlamlı olur ve göstermek istersiniz.
Departman adını göstermek için Departman sütunu değiştirildi. Kod, Department gezinti özelliğine
yüklenen departman varlığının Name özelliğini görüntüler:
@Html.DisplayFor(modelItem => item.Department.Name)

Uygulamayı çalıştırın ve bölüm adlarıyla listeyi görmek için Kurslar sekmesini seçin.

Eğitmenler sayfası oluşturma


Bu bölümde, Eğitmenler sayfasını görüntülemek için eğitmen varlığı için bir denetleyici ve görünüm
oluşturacaksınız:
Bu sayfa aşağıdaki yollarla ilgili verileri okur ve görüntüler:
Eğitmenler listesi, OfficeAssignment varlığındaki ilgili verileri görüntüler. Eğitmen ve OfficeAssignment
varlıkları bire sıfır veya-bir ilişkidir. OfficeAssignment varlıkları için Eager yükleme kullanacaksınız. Daha
önce açıklandığı gibi, birincil tablonun alınan tüm satırları için ilgili verilere ihtiyacınız olduğunda Eager
yüklemesi genellikle daha etkilidir. Bu durumda, tüm görüntülenen Eğitmenler için Office atamalarını
göstermek istersiniz.
Kullanıcı bir eğitmen seçtiğinde ilgili kurs varlıkları görüntülenir. Eğitmen ve kurs varlıkları çoktan çoğa bir
ilişkidir. Kurs varlıkları ve ilgili departman varlıkları için Eager yükleme kullanacaksınız. Bu durumda, yalnızca
seçili eğitmen için kurslar gerektiğinden ayrı sorgular daha verimli olabilir. Ancak, bu örnek, gezinti özellikleri
' nde olan varlıkların içindeki gezinti özellikleri için Eager yükleme 'nin nasıl kullanılacağını gösterir.
Kullanıcı bir kurs seçtiğinde, kayıt varlığı kümesindeki ilgili veriler görüntülenir. Kurs ve kayıt varlıkları bire
çok ilişkisinde. Kayıt varlıkları ve ilgili öğrenci varlıkları için ayrı sorgular kullanacaksınız.
Eğitmen dizini görünümü için bir görünüm modeli oluşturun
Eğitmenler sayfasında, üç farklı tablodan alınan veriler gösterilir. Bu nedenle, her biri tablolardan birine ait verileri
tutan üç özellik içeren bir görünüm modeli oluşturacaksınız.
SchoolViewModels klasöründe InstructorIndexData.cs oluşturun ve mevcut kodu şu kodla değiştirin:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
}

Eğitmen denetleyicisi ve görünümleri oluşturma


Aşağıdaki çizimde gösterildiği gibi EF okuma/yazma eylemleri ile bir eğitmenler denetleyicisi oluşturun:

InstructorsController.cs açın ve ViewModel ad alanı için bir using ifadesini ekleyin:

using ContosoUniversity.Models.SchoolViewModels;

İlişkili verilerin yüklenmesini ve görünüm modeline koymak için Dizin yöntemini aşağıdaki kodla değiştirin.
public async Task<IActionResult> Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}

return View(viewModel);
}

Yöntemi, seçilen eğitmenin ve seçili kursun KIMLIK değerlerini sağlayan isteğe bağlı yol verilerini ( id ) ve bir sorgu
dizesi parametresini ( courseID ) kabul eder. Parametreler, sayfadaki Köprü seçme ile sağlanır.
Kod, görünüm modelinin bir örneğini oluşturarak ve bu örneğe eğitmen listesine yerleştirilerek başlar. Kod,
Instructor.OfficeAssignment ve Instructor.CourseAssignments gezinti özellikleri için Eager yüklemeyi belirtir.
CourseAssignments özelliği içinde, Course özelliği yüklenir ve bunun içinde, Enrollments ve Department özellikleri
yüklenir ve her Enrollment varlığı içinde Student özelliği yüklenir.

viewModel.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Görünüm her zaman OfficeAssignment varlığını gerektirdiğinden, bunu aynı sorguda getirmek daha etkilidir. Web
sayfasında bir eğitmen seçildiğinde kurs varlıkları gereklidir, bu yüzden tek bir sorgu birden çok sorgudan daha
iyidir, bu nedenle yalnızca sayfa, hiçbir zaman tarafından seçilen bir kurs ile daha sık görüntüleniyorsa.
Course iki özelliği gerektiğinden, kod CourseAssignments yinelenir ve Course . ThenInclude çağrılarının ilk dizesi
CourseAssignment.Course , Course.Enrollments ve Enrollment.Student alır.
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Kodun bu noktasında, başka bir ThenInclude , gerekli Student gezinti özellikleri için olacaktır. Ancak Include
çağrılması Instructor özellikleriyle çalışmaya başlar. bu kez, bu kez Course.Enrollments yerine Course.Department
belirterek zinciri yeniden gitmeniz gerekir.

viewModel.Instructors = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();

Aşağıdaki kod, bir eğitmen seçildiğinde yürütülür. Seçilen eğitmen, görünüm modelindeki eğitmenler listesinden
alınır. Görünüm modelinin Courses özelliği daha sonra bu eğitmenin CourseAssignments gezinti özelliğinden kurs
varlıklarıyla yüklenir.

if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

Where yöntemi bir koleksiyon döndürür, ancak bu yönteme geçirilen kriterler yalnızca tek bir eğitmen varlığının
döndürüldüğünden sonuçlanır. Single yöntemi, koleksiyonu tek bir eğitmen varlığına dönüştürür, bu da o varlığın
CourseAssignments özelliğine erişmenizi sağlar. CourseAssignments özelliği, yalnızca ilgili Course varlıklarını
istediğiniz CourseAssignment varlıkları içerir.
Koleksiyonun yalnızca bir öğesi olacağını bildiğiniz durumlarda Single yöntemini bir koleksiyonda kullanırsınız.
Tek yöntem, koleksiyon boş veya birden fazla öğe varsa bir özel durum oluşturur. Bir alternatif, koleksiyon boşsa
varsayılan bir değer (Bu durumda null) döndüren SingleOrDefault . Bununla birlikte, bu durumda yine de bir özel
durumla sonuçlanacaktır (null başvuru üzerinde Courses özelliği bulmaya çalışırken) ve özel durum iletisi sorunun
nedenini daha az gösterir. Single yöntemini çağırdığınızda, ayrıca Where yöntemini ayrı çağırmak yerine WHERE
koşulunu da geçirebilirsiniz:

.Single(i => i.ID == id.Value)

Onun yerine:
.Where(i => i.ID == id.Value).Single()

Ardından, bir kurs seçilmişse, seçilen kurs, görünüm modelindeki kurslar listesinden alınır. Ardından, görünüm
modelinin Enrollments özelliği, bu kursun Enrollments gezinti özelliğinden kayıt varlıklarıyla yüklenir.

if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}

Eğitmen dizini görünümünü değiştirme


Views/eğitmenler/Index. cshtmliçinde, şablon kodunu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.
@model ContosoUniversity.Models.SchoolViewModels.InstructorIndexData

@{
ViewData["Title"] = "Instructors";
}

<h2>Instructors</h2>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th>Courses</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Instructors)
{
string selectedRow = "";
if (item.ID == (int?)ViewData["InstructorID"])
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@if (item.OfficeAssignment != null)
{
@item.OfficeAssignment.Location
}
</td>
<td>
@{
foreach (var course in item.CourseAssignments)
{
@course.Course.CourseID @: @course.Course.Title <br />
}
}
</td>
<td>
<a asp-action="Index" asp-route-id="@item.ID">Select</a> |
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Varolan koda aşağıdaki değişiklikleri yaptınız:


Model sınıfı InstructorIndexData olarak değiştirildi.
Sayfa başlığı dizinden eğitmenlerolarak değiştirildi.
Yalnızca item.OfficeAssignment null olmaması durumunda item.OfficeAssignment.Location görüntüleyen bir
Office sütunu eklendi. (Bu bire sıfır veya-bir ilişki olduğundan ilgili bir OfficeAssignment varlığı
bulunmayabilir.)

@if (item.OfficeAssignment != null)


{
@item.OfficeAssignment.Location
}

Her bir eğitmen tarafından taders kurslarını görüntüleyen bir Kurslar sütunu eklendi. Daha fazla bilgi için
Razor söz dizimi makalesinin Açık çizgi geçişi bölümüne bakın.
Seçilen eğitmenin tr öğesine dinamik olarak class="success" ekleyen kod eklendi. Bu, bir önyükleme sınıfı
kullanarak seçili satır için bir arka plan rengi ayarlar.

string selectedRow = "";


if (item.ID == (int?)ViewData["InstructorID"])
{
selectedRow = "success";
}
<tr class="@selectedRow">

Her satırdaki diğer bağlantılardan hemen önce Seç etiketli yeni bir köprü eklendiğinde, SEÇILEN eğitmenin
kimliğinin Index yöntemine gönderilmesine neden olur.

<a asp-action="Index" asp-route-id="@item.ID">Select</a> |

Uygulamayı çalıştırın ve eğitmenler sekmesini seçin. Sayfa ilgili OfficeAssignment varlıklarının Location özelliğini
ve ilişkili OfficeAssignment varlığı olmadığında boş bir tablo hücresini görüntüler.

Views/eğitmenler/Index. cshtml dosyasında, Kapanış tablosu öğesinden sonra (dosyanın sonunda) aşağıdaki kodu
ekleyin. Bu kod, bir eğitmen seçildiğinde bir eğitmenin ilgili kursların bir listesini görüntüler.
@if (Model.Courses != null)
{
<h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th></th>
<th>Number</th>
<th>Title</th>
<th>Department</th>
</tr>

@foreach (var item in Model.Courses)


{
string selectedRow = "";
if (item.CourseID == (int?)ViewData["CourseID"])
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
</td>
<td>
@item.CourseID
</td>
<td>
@item.Title
</td>
<td>
@item.Department.Name
</td>
</tr>
}

</table>
}

Bu kod, kurs listesini görüntülemek için görünüm modelinin Courses özelliğini okur. Ayrıca, seçilen kursun
KIMLIĞINI Index Action yöntemine gönderen bir seçme Köprüsü de sağlar.
Sayfayı yenileyin ve bir eğitmen seçin. Artık Seçili eğitmenin atandığı kursları görüntüleyen bir kılavuz görürsünüz
ve her kurs için atanan departmanın adını görürsünüz.
Yeni eklediğiniz kod bloğundan sonra aşağıdaki kodu ekleyin. Bu, kurs seçildiğinde bir kursa kaydedilen
öğrencilerin listesini görüntüler.

@if (Model.Enrollments != null)


{
<h3>
Students Enrolled in Selected Course
</h3>
<table class="table">
<tr>
<th>Name</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@item.Student.FullName
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
}

Bu kod, kursa kayıtlı öğrencilerin listesini görüntülemek için görünüm modelinin kayıtları özelliğini okur.
Sayfayı yeniden yenileyip bir eğitmen seçin. Ardından, kayıtlı öğrenciler ve bunların onların listesini görmek için bir
kurs seçin.
Açık yükleme hakkında
InstructorsController.cs' de eğitmenler listesini aldığınızda, CourseAssignments gezinti özelliği için bir Eager
yüklemesi belirttiniz.
Kullanıcılardan yalnızca, seçili bir eğitmenin ve kursla kayıtlarını yalnızca nadiren görmek istediğini varsayalım. Bu
durumda, kayıt verilerini yalnızca istenirse yüklemek isteyebilirsiniz. Açık yüklemenin nasıl yapılacağını gösteren bir
örnek görmek için Index yöntemini aşağıdaki kodla değiştirin, bu da kayıtları için Eager yüklemesini kaldırır ve bu
özelliği açıkça yükler. Kod değişiklikleri vurgulanır.
public async Task<IActionResult> Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.OrderBy(i => i.LastName)
.ToListAsync();

if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}

if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).Single();
await _context.Entry(selectedCourse).Collection(x => x.Enrollments).LoadAsync();
foreach (Enrollment enrollment in selectedCourse.Enrollments)
{
await _context.Entry(enrollment).Reference(x => x.Student).LoadAsync();
}
viewModel.Enrollments = selectedCourse.Enrollments;
}

return View(viewModel);
}

Yeni kod, eğitmen varlıklarını alan koddan kayıt verileri için Thenınclude Yöntem çağrılarını bırakır. Ayrıca
AsNoTracking bırakır. Bir eğitmen ve kurs seçilirse, vurgulanan kod seçili kurs için kayıt varlıklarını ve her kayıt için
öğrenci varlıklarını alır.
Uygulamayı çalıştırın, şimdi eğitmenler dizin sayfasına gidin ve sayfada görüntülendikleriyle ilgili hiçbir fark
görmezsiniz; ancak verilerin nasıl alındığını değiştirmiş olursunuz.

Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
İlgili verileri yükleme hakkında öğrenilen
Bir kurslar sayfası oluşturuldu
Bir eğitmenler sayfası oluşturuldu
Açık yükleme hakkında bilgi edinildi
İlgili verileri güncelleştirme hakkında bilgi edinmek için sonraki öğreticiye ilerleyin.
İlgili verileri güncelleştirme
Öğretici: ilgili verileri güncelleştirme-ASP.NET MVC EF
Core
11.10.2019 • 27 minutes to read • Edit Online

Önceki öğreticide ilgili verileri görüntülediyseniz; Bu öğreticide, yabancı anahtar alanlarını ve gezinti özelliklerini
güncelleştirerek ilgili verileri güncelleştireceksiniz.
Aşağıdaki çizimlerde, üzerinde çalıştığınız sayfaların bazıları gösterilmektedir.
Bu öğreticide şunları yaptınız:
Kurslar sayfalarını özelleştirme
Eğitmenler düzenleme sayfası ekle
Düzenleme sayfasına kurslar ekleyin
Güncelleştirme silme sayfası
Sayfa oluşturmak için Office konumu ve kurslar ekleme

Önkoşullar
İlgili verileri okuma

Kurslar sayfalarını özelleştirme


Yeni bir kurs varlığı oluşturulduğunda, mevcut bir departmanla bir ilişkisi olmalıdır. Bunu kolaylaştırmak için, yapı
iskelesi kodu denetleyici yöntemlerini içerir ve departmanı seçmeye yönelik bir açılan liste içeren görünümler
oluşturup düzenleyebilir. Açılır liste Course.DepartmentID yabancı anahtar özelliğini ayarlar ve ilgili departman
varlığıyla Department gezinti özelliğini yüklemek için tüm Entity Framework ihtiyacı vardır. Scafkatmış kodu
kullanacaksınız, ancak hata işleme eklemek ve açılan listeyi sıralamak için biraz değişiklik yapacaksınız.
CoursesController.cs' de, dört oluşturma ve düzenleme yöntemini silin ve bunları şu kodla değiştirin:
public IActionResult Create()
{
PopulateDepartmentsDropDownList();
return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("CourseID,Credits,DepartmentID,Title")] Course course)
{
if (ModelState.IsValid)
{
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}

public async Task<IActionResult> Edit(int? id)


{
if (id == null)
{
return NotFound();
}

var course = await _context.Courses


.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}

var courseToUpdate = await _context.Courses


.FirstOrDefaultAsync(c => c.CourseID == id);

if (await TryUpdateModelAsync<Course>(courseToUpdate,
"",
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(courseToUpdate.DepartmentID);
return View(courseToUpdate);
}

@No__t-0 HttpPost yönteminden sonra, açılan liste için departman bilgisini yükleyen yeni bir yöntem oluşturun.

private void PopulateDepartmentsDropDownList(object selectedDepartment = null)


{
var departmentsQuery = from d in _context.Departments
orderby d.Name
select d;
ViewBag.DepartmentID = new SelectList(departmentsQuery.AsNoTracking(), "DepartmentID", "Name",
selectedDepartment);
}

@No__t-0 yöntemi, ada göre sıralanmış tüm bölümlerin bir listesini alır, açılan liste için bir SelectList koleksiyonu
oluşturur ve koleksiyonu ViewBag ' deki görünüme geçirir. Yöntemi, çağıran kodun, açılan liste işlendiğinde
seçilecek öğeyi belirtmesini sağlayan isteğe bağlı selectedDepartment parametresini kabul eder. Görünüm,
"DepartmentID" adını <select> etiketi yardımcısından geçireceğini ve yardımcı sonra, "DepartmentID" adlı bir
SelectList için ViewBag nesnesine baktığınızın bilmesini sağlar.

HttpGet Create yöntemi, bölüm henüz kurulmadığı için, yeni bir kurs için seçili öğeyi ayarlamadan
PopulateDepartmentsDropDownList yöntemini çağırır:

public IActionResult Create()


{
PopulateDepartmentsDropDownList();
return View();
}

HttpGet Edit yöntemi, düzenlenen kursa zaten atanmış departmanın KIMLIğINE bağlı olarak seçili öğeyi ayarlar:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var course = await _context.Courses


.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}

Hem Create hem de Edit için HttpPost yöntemleri, bir hatadan sonra sayfayı yeniden görüntülerken seçili öğeyi
ayarlayan kodu da içerir. Bu, sayfa hata iletisini göstermek için yeniden görüntülendiğinde, seçilen departmanın
seçili kalır olduğunu sağlar.
Ekleyemiyorum. Ayrıntı ve silme yöntemlerine AsNoTracking
Kurs ayrıntılarının ve sayfa silmenin performansını iyileştirmek için, Details ve HttpGet Delete yöntemlerine
AsNoTracking çağrıları ekleyin.

public async Task<IActionResult> Details(int? id)


{
if (id == null)
{
return NotFound();
}

var course = await _context.Courses


.Include(c => c.Department)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}

return View(course);
}
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}

var course = await _context.Courses


.Include(c => c.Department)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}

return View(course);
}

Kurs görünümlerini değiştirme


Görünümler/kurslar/oluşturma. cshtml'de, Departman açılan listesine bir "Departman Seç" seçeneği ekleyin,
DepartmentID etiketini bölümolarak değiştirin ve bir doğrulama iletisi ekleyin.

<div class="form-group">
<label asp-for="Department" class="control-label"></label>
<select asp-for="DepartmentID" class="form-control" asp-items="ViewBag.DepartmentID">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="DepartmentID" class="text-danger" />

Görünümler/kurslar/Düzenle. cshtml'de, Create. cshtmliçinde yaptığınız departman alanı için aynı değişikliği yapın.
Ayrıca, Görünümler/kurslar/Düzenle. cshtml'de başlık alanından önce bir kurs numarası alanı ekleyin. Kurs
numarası birincil anahtar olduğundan, görüntülenir, ancak değiştirilemez.

<div class="form-group">
<label asp-for="CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.CourseID)</div>
</div>

Düzenleme görünümündeki kurs numarası için gizli bir alan ( <input type="hidden"> ) zaten var. @No__t-0 etiketi
Yardımcısı eklemek, Kullanıcı düzenleme sayfasında Kaydet ' i tıklattığında, kurs numarasının gönderilen verilere
dahil edilmesini neden olmadığı için gizli alanın gereksinimini ortadan kaldırmaz.
Görünümler/kurslar/delete. cshtml'de, üst kısımdaki bir kurs numarası alanı ekleyin ve bölüm kimliğini bölüm adı
olarak değiştirin.
@model ContosoUniversity.Models.Course

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Department.Name)
</dd>
</dl>

<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a>
</div>
</form>
</div>

Görünümler/kurslar/ayrıntılar. cshtml'de, delete. cshtmliçin yaptığınız aynı değişikliği yapın.


Kurs sayfalarını test etme
Uygulamayı çalıştırın, Kurslar sekmesini seçin, Yeni oluştur' a tıklayın ve yeni bir kurs için veri girin:
Oluştur’a tıklayın. Kurslar Dizin sayfası, listeye eklenen yeni kursla birlikte görüntülenir. Dizin sayfası listesindeki
departman adı, ilişkinin doğru şekilde oluşturulduğunu gösteren gezinti özelliğinden gelir.
Kurslar Dizin sayfasında bir kursa Düzenle ' ye tıklayın.
Sayfadaki verileri değiştirin ve Kaydet' e tıklayın. Kurslar Dizin sayfası, güncelleştirilmiş kurs verileriyle birlikte
görüntülenir.

Eğitmenler düzenleme sayfası ekle


Bir eğitmen kaydını düzenlediğinizde, eğitmenin Office atamasını güncelleştirebilmek istersiniz. Eğitmen varlığı,
OfficeAssignment varlığıyla bire sıfır veya-arasında bir ilişkiye sahiptir; bu, kodunuzun aşağıdaki durumları işlemesi
gerektiği anlamına gelir:
Kullanıcı Office atamasını temizlediğinde ve başlangıçta bir değere sahipse, OfficeAssignment varlığını silin.
Kullanıcı bir Office atama değeri girerse ve başlangıçta boşsa, yeni bir OfficeAssignment varlığı oluşturun.
Kullanıcı bir Office atamasının değerini değiştirirse, var olan bir OfficeAssignment varlığındaki değeri
değiştirin.
Eğitmenler denetleyicisini güncelleştirme
InstructorsController.cs' de, httpget Edit yöntemindeki kodu değiştirerek eğitmen varlığının OfficeAssignment
gezinti özelliğini yükler ve AsNoTracking ' i çağırır:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var instructor = await _context.Instructors


.Include(i => i.OfficeAssignment)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (instructor == null)
{
return NotFound();
}
return View(instructor);
}

Office atama güncelleştirmelerini işlemek için HttpPost Edit yöntemini aşağıdaki kodla değiştirin:

[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}

var instructorToUpdate = await _context.Instructors


.Include(i => i.OfficeAssignment)
.FirstOrDefaultAsync(s => s.ID == id);

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"",
i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
return View(instructorToUpdate);
}

Kod şunları yapar:


İmza artık HttpGet Edit yöntemiyle aynı olduğundan ( ActionName özniteliği /Edit/ URL 'sinin hala
kullanıldığını belirten), yöntem adını EditPost olarak değiştirir.
@No__t-0 gezinti özelliği için Eager yükleme kullanarak geçerli eğitmen varlığını veritabanından alır. Bu,
HttpGet Edit yönteminde yaptığınız şeydir.
Alınan eğitmen varlığını model Ciltçideki değerlerle güncelleştirir. @No__t-0 aşırı yüklemesi, dahil etmek
istediğiniz özellikleri beyaz listelemenize olanak sağlar. Bu, ikinci öğreticideaçıklandığı gibi, daha fazla
nakletmeyi önler.

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"",
i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))

Office konumu boşsa, OfficeAssignment tablosundaki ilgili satırın silinebilmesi için eğitmen.
OfficeAssignment özelliğini null olarak ayarlar.

if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}

Değişiklikleri veritabanına kaydeder.


Eğitmen düzenleme görünümünü güncelleştirme
Görünümler/eğitmenler/Edit. cshtml' de, Kaydet düğmesinin sonundaki Office konumunu düzenlemek için yeni bir
alan ekleyin:

<div class="form-group">
<label asp-for="OfficeAssignment.Location" class="control-label"></label>
<input asp-for="OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="OfficeAssignment.Location" class="text-danger" />
</div>

Uygulamayı çalıştırın, eğitmenler sekmesini seçin ve ardından bir eğitmende Düzenle ' ye tıklayın. Office
konumunu değiştirin ve Kaydet' e tıklayın.
Düzenleme sayfasına kurslar ekleyin
Eğitmenler, istediğiniz sayıda kurs öğretebilir. Artık, aşağıdaki ekran görüntüsünde gösterildiği gibi, bir grup onay
kutusu kullanarak kurs atamalarını değiştirme özelliğini ekleyerek eğitmen düzenleme sayfasını geliştirirsiniz:
Kurs ve eğitmen varlıkları arasındaki ilişki çoktan çoğa olur. İlişki eklemek ve kaldırmak için, kurs ekleme ve kurs,
katılımcı varlık kümesine ekleme ve kaldırma.
Bir eğitmenin hangi kurslara atandığını değiştirmenize olanak sağlayan kullanıcı arabirimi bir grup onay kutusu
olur. Veritabanındaki her kurs için bir onay kutusu görüntülenir ve eğitmenin Şu anda atanmış olduğu yer seçilidir.
Kullanıcı kurs atamalarını değiştirmek için onay kutularını seçebilir veya temizleyebilir. Kurs sayısı çok fazlaysa,
büyük olasılıkla görünümde verileri göstermek için farklı bir yöntem kullanmak isteyeceksiniz, ancak ilişkiler
oluşturmak veya silmek için bir JOIN varlığını işlemek için aynı yöntemi kullanmanız gerekir.
Eğitmenler denetleyicisini güncelleştirme
Onay kutuları listesinin görünümüne veri sağlamak için bir görünüm modeli sınıfı kullanacaksınız.
SchoolViewModels klasöründe AssignedCourseData.cs oluşturun ve mevcut kodu şu kodla değiştirin:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}

InstructorsController.cs' de, httpget Edit yöntemini aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

public async Task<IActionResult> Edit(int? id)


{
if (id == null)
{
return NotFound();
}

var instructor = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(instructor);
return View(instructor);
}

private void PopulateAssignedCourseData(Instructor instructor)


{
var allCourses = _context.Courses;
var instructorCourses = new HashSet<int>(instructor.CourseAssignments.Select(c => c.CourseID));
var viewModel = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
viewModel.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
ViewData["Courses"] = viewModel;
}

Kod, Courses gezinti özelliği için Eager yüklemesi ekler ve AssignedCourseData View model sınıfını kullanarak onay
kutusu dizisine bilgi sağlamak için yeni PopulateAssignedCourseData yöntemini çağırır.
@No__t-0 yöntemindeki kod, görünüm modeli sınıfını kullanarak bir kurs listesi yüklemek için tüm kurs varlıklarını
okur. Kod, her kurs için, kursun Courses gezinti özelliğinde mevcut olup olmadığını denetler. Eğitmenin bir kurs
atanıp atanmadığını denetlerken etkili arama oluşturmak için, eğitmene atanan kurslar HashSet koleksiyonuna
konur. @No__t-0 özelliği, eğitmenin atandığı kurslar için true olarak ayarlanır. Görünüm, hangi onay kutularının
seçili olarak gösterileceğini belirlemede bu özelliği kullanır. Son olarak, liste ViewData ' daki görünüme geçirilir.
Sonra, Kullanıcı Kaydet' i tıklattığında yürütülen kodu ekleyin. @No__t-0 yöntemini aşağıdaki kodla değiştirin ve
eğitmen varlığının Courses gezinti özelliğini güncelleştiren yeni bir yöntem ekleyin.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int? id, string[] selectedCourses)
{
if (id == null)
{
return NotFound();
}

var instructorToUpdate = await _context.Instructors


.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(m => m.ID == id);

if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"",
i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(instructorToUpdate);
return View(instructorToUpdate);
}
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID =
instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{

if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i =>
i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}

Yöntem imzası artık HttpGet Edit yönteminden farklıdır, bu nedenle Yöntem adı EditPost ' den Edit ' ye geri
değişir.
Görünüm bir kurs varlıkları koleksiyonuna sahip olmadığından, model Bağlayıcısı CourseAssignments gezinti
özelliğini otomatik olarak güncelleştiremez. @No__t-0 gezinti özelliğini güncelleştirmek için model cildi kullanmak
yerine, bunu yeni UpdateInstructorCourses yönteminde yapmanız gerekir. Bu nedenle, CourseAssignments özelliğini
model bağlamadan hariç bırakmanız gerekir. Bu, TryUpdateModel ' i çağıran kodda herhangi bir değişiklik
yapılmasını gerektirmez ve bu nedenle, beyaz liste aşırı yüklemesini kullandığınızdan ve CourseAssignments ekleme
listesinde yer almayız.
Hiçbir onay kutusu seçilmediyse, UpdateInstructorCourses ' daki kod, CourseAssignments gezinti özelliğini boş bir
koleksiyonla başlatır ve döndürür:
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID =
instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{

if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i =>
i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}

Kod daha sonra, veritabanındaki tüm kurslardan geçer ve bu her kursu, görünümde seçili olanlar ile ilgili olarak
eğitmenin atandığı her bir kursa karşı denetler. Etkili aramaları kolaylaştırmak için, ikinci iki koleksiyon HashSet
nesnelerinde depolanır.
Kurs onay kutusu seçilmişse ancak kurs Instructor.CourseAssignments gezinti özelliğinde değilse kurs, Gezinti
özelliğindeki koleksiyona eklenir.
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID =
instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{

if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i =>
i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}

Kurs onay kutusu seçilmemişse, ancak kurs Instructor.CourseAssignments gezinti özelliği ise, kurs, gezinti
özelliğinden kaldırılır.
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}

var selectedCoursesHS = new HashSet<string>(selectedCourses);


var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID =
instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{

if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i =>
i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}

Eğitmen görünümlerini güncelleştirme


Görünümler/eğitmenler/Edit. cshtmlIçinde, Office alanı için div öğelerinden hemen sonra ve Kaydet için div
öğesinden önce aşağıdaki kodu ekleyerek bir dizi onay kutusu içeren bir Kurslar alanı ekleyin Bu.

NOTE
Kodu Visual Studio 'Ya yapıştırdığınızda, satır sonları kodu kesen bir şekilde değiştirilebilir. Kod yapıştırdıktan sonra farklı
görünüyorsa, otomatik biçimlendirmeyi geri almak için CTRL + Z bir kez tuşuna basın. Bu işlem satır sonlarını, burada
gördüğünüz gibi görünmeleri için düzeltir. Girintide kusursuz olması gerekmez, ancak @</tr><tr> , @:<td> , @:</td> ve
@:</tr> çizgilerinin her biri gösterildiği gibi tek bir satırda olması gerekir, aksi halde bir çalışma zamanı hatası alırsınız. Yeni
kod bloğu seçiliyken, yeni kodu mevcut kodla hizalamak için üç kez Tab tuşuna basın. Bu sorun Visual Studio 2019 ' de
düzeltilmiştir.
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<ContosoUniversity.Models.SchoolViewModels.AssignedCourseData> courses =
ViewBag.Courses;

foreach (var course in courses)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>

Bu kod, üç sütun içeren bir HTML tablosu oluşturur. Her sütunda, bir onay kutusu ve ardından kurs numarası ve
başlığından oluşan bir açıklamalı alt yazı bulunur. Onay kutularının hepsi aynı ada ("Selectedkurslar") sahiptir, bu da
model cilde bir grup olarak değerlendirilme bildirir. Her onay kutusunun değer özniteliği CourseID değerine
ayarlanır. Sayfa gönderildiğinde, model Ciltçi yalnızca seçili onay kutuları için CourseID değerlerinden oluşan
denetleyiciye bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmenin atandığı kurslara yönelik olanlar, işaretlenmiş özniteliklere
sahiptir ve bunları seçer (denetlenen görüntüler).
Uygulamayı çalıştırın, eğitmenler sekmesini seçin ve ardından düzenleme sayfasını görmek Için bir eğitmende
Düzenle ' ye tıklayın.
Bazı kurs atamalarını değiştirin ve Kaydet ' e tıklayın. Yaptığınız değişiklikler Dizin sayfasında yansıtılır.

NOTE
Eğitim kursu verilerini düzenlemek için buradaki yaklaşım, sınırlı sayıda kurs olduğunda iyi bir şekilde gerçekleştirilir. Çok daha
büyük olan koleksiyonlar için, farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme yöntemi gerekir.

Güncelleştirme silme sayfası


InstructorsController.cs' de DeleteConfirmed yöntemini silin ve yerine aşağıdaki kodu ekleyin.
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
Instructor instructor = await _context.Instructors
.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);

var departments = await _context.Departments


.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);

_context.Instructors.Remove(instructor);

await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}

Bu kod aşağıdaki değişiklikleri yapar:


@No__t-0 gezinti özelliği için Eager yüklemesi yapar. Bunu eklemeniz gerekir, ilgili CourseAssignment
varlıkları hakkında bilgi sahibi olmaz ve onları silmez. Bunları okumaktan kaçınmak için, veritabanında art
arda silme yapılandırabilirsiniz.
Silinecek eğitmen herhangi bir departmanların Yöneticisi olarak atanırsa, bu departmanlardan eğitmen
atamasını kaldırır.

Sayfa oluşturmak için Office konumu ve kurslar ekleme


InstructorsController.cs' de, HttpGet ve httppost Create yöntemlerini silin ve ardından aşağıdaki kodu kendi yerine
ekleyin:
public IActionResult Create()
{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();
PopulateAssignedCourseData(instructor);
return View();
}

// POST: Instructors/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("FirstMidName,HireDate,LastName,OfficeAssignment")] Instructor
instructor, string[] selectedCourses)
{
if (selectedCourses != null)
{
instructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment { InstructorID = instructor.ID, CourseID = int.Parse(course)
};
instructor.CourseAssignments.Add(courseToAdd);
}
}
if (ModelState.IsValid)
{
_context.Add(instructor);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateAssignedCourseData(instructor);
return View(instructor);
}

Bu kod, başlangıçta hiçbir kurs seçilmemiş olması dışında Edit yöntemleri için gördüğünüz gibi benzerdir.
@No__t, ancak görünümde foreach döngüsü için boş bir koleksiyon sağlamak üzere, HttpGet-0 yöntemi
PopulateAssignedCourseData yöntemini çağırır. Aksi takdirde görünüm kodu bir null başvuru özel durumu oluşturur.

HttpPost Create yöntemi, seçili her kursu doğrulama hatalarını kontrol etmeden önce CourseAssignments gezinti
özelliğine ekler ve yeni eğitmeni veritabanına ekler. Model hataları olduğunda (örneğin, Kullanıcı geçersiz bir tarih
anahtarlanır) ve sayfa bir hata iletisiyle yeniden görüntülenirken, yapılan kurs seçimleri otomatik olarak geri
yüklenir.
@No__t-0 gezinti özelliğine kurslar ekleyebilmesinin, özelliği boş bir koleksiyon olarak başlatmak için sahip olmanız
gerektiğini unutmayın:

instructor.CourseAssignments = new List<CourseAssignment>();

Bunu denetleyici kodunda yapmanın bir alternatifi olarak, aşağıdaki örnekte gösterildiği gibi, özellik alıcısının,
koleksiyonu otomatik olarak oluşturmak üzere değiştirerek, bunu eğitmen modelinde yapabilirsiniz:
private ICollection<CourseAssignment> _courseAssignments;
public ICollection<CourseAssignment> CourseAssignments
{
get
{
return _courseAssignments ?? (_courseAssignments = new List<CourseAssignment>());
}
set
{
_courseAssignments = value;
}
}

@No__t-0 özelliğini bu şekilde değiştirirseniz, denetleyicideki açık özellik başlatma kodunu kaldırabilirsiniz.
Görünümler/eğitmen/oluşturma. cshtml'de, gönder düğmesinden önce kurslar için bir Office konum metin kutusu
ve onay kutuları ekleyin. Düzenleme sayfasında olduğu gibi, dosyayı yapıştırdığınızda Visual Studio kodu yeniden
biçimlendirdiğinden biçimlendirmeyi onarın.

<div class="form-group">
<label asp-for="OfficeAssignment.Location" class="control-label"></label>
<input asp-for="OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="OfficeAssignment.Location" class="text-danger" />
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<ContosoUniversity.Models.SchoolViewModels.AssignedCourseData> courses =
ViewBag.Courses;

foreach (var course in courses)


{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>

Uygulamayı çalıştırıp bir eğitmen oluşturarak test edin.

Işlemleri işleme
CRUD öğreticisindeaçıklandığı gibi Entity Framework, işlemleri örtük olarak uygular. Daha fazla denetime
ihtiyacınız olan senaryolar için--örneğin, işlem içinde Entity Framework dışında yapılan işlemleri eklemek
istiyorsanız, bkz. işlemler.
Kodu edinin
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Özelleştirilmiş Kurslar sayfaları
Eklenen eğitmenler düzenleme sayfası
Düzenleme sayfasına kurslar eklendi
Silme sayfası güncelleştirildi
Sayfa oluşturmak için Office konumu ve kurslar eklendi
Eşzamanlılık çakışmalarını nasıl işleyeceğinizi öğrenmek için sonraki öğreticiye ilerleyin.
Eşzamanlılık çakışmalarını işle
Öğretici: EF Core eşzamanlılık-ASP.NET MVC 'yi
Işleme
23.11.2019 • 29 minutes to read • Edit Online

Önceki öğreticilerde, verileri güncelleştirme hakkında daha fazla öğrendiniz. Bu öğreticide, birden çok kullanıcı aynı
anda aynı varlık güncelleştirdiğinizde çakışmalarına gösterilmektedir.
Departman varlığıyla çalışan ve eşzamanlılık hatalarını işleyecek Web sayfaları oluşturacaksınız. Aşağıdaki çizimler,
bir eşzamanlılık çakışması oluşursa görüntülenen bazı iletiler dahil olmak üzere, düzenleme ve silme sayfalarını
gösterir.
Bu öğreticide şunları yaptınız:
Eşzamanlılık çakışmaları hakkında bilgi edinin
İzleme özelliği Ekle
Departmanlar denetleyicisi ve görünümleri oluşturma
Dizin görünümünü Güncelleştir
Düzenleme yöntemlerini Güncelleştir
Güncelleştirme düzenleme görünümü
Eşzamanlılık çakışmalarını test et
Silme sayfası
Güncelleştirme ayrıntıları ve görünüm oluşturma

Önkoşullar
İlgili verileri güncelleştirme

Eşzamanlılık çakışmaları
Bir Kullanıcı bir varlığın verilerini düzenlemek için bir varlık verileri görüntülediğinde bir eşzamanlılık çakışması
oluşur ve sonra, ilk kullanıcının değişikliği veritabanına yazılmadan önce diğer Kullanıcı aynı varlığın verilerini
günceller. Bu tür çakışmaların algılanmasını etkinleştirmezseniz, veritabanını güncelleştirme son olarak diğer
kullanıcının değişikliklerinin üzerine yazar. Birçok uygulamada, bu risk kabul edilebilir: birkaç Kullanıcı veya birkaç
güncelleştirme varsa veya bazı değişikliklerin üzerine yazılırsa gerçekten önemli değilse, eşzamanlılık için
programlama maliyeti avantajdan yararlanabilir. Bu durumda, uygulamayı eşzamanlılık çakışmalarını işleyecek
şekilde yapılandırmanız gerekmez.
Kötümser eşzamanlılık (kilitleme )
Uygulamanızın eşzamanlılık senaryolarında yanlışlıkla veri kaybını önlemesi gerekiyorsa, bunu yapmanın bir yolu
veritabanı kilitlerini kullanmaktır. Bu, Kötümser eşzamanlılık olarak adlandırılır. Örneğin, bir veritabanından bir satırı
okuyabilmeniz için, salt okunurdur veya güncelleştirme erişimi için bir kilit isteyin. Bir satırı güncelleştirme erişimi
için kilitlerseniz, başka hiçbir kullanıcının satırı değiştirme sürecinde olan verilerin bir kopyasını alması için salt
okunurdur veya güncelleştirme erişimi için bu satırı kilitlemesine izin verilmez. Bir satırı salt okuma erişimi için
kilitlerseniz, diğerleri dosyayı salt okuma erişimi için de kilitleyip güncelleştirme için de kilitleyebilirler.
Kilitleri yönetmek dezavantajlara sahiptir. Program, karmaşık olabilir. Önemli veritabanı yönetim kaynakları
gerektirir ve bir uygulamanın kullanıcı sayısı arttıkça performans sorunlarına neden olabilir. Bu nedenlerden dolayı,
tüm veritabanı yönetim sistemleri Kötümser eşzamanlılık 'yi desteklemez. Entity Framework Core, BT için yerleşik
destek sağlamaz ve bu öğretici bunu nasıl uygulayacağınızı göstermez.
İyimser Eşzamanlılık
Kötümser eşzamanlılık yerine iyimser eşzamanlılık yapılır. İyimser eşzamanlılık, eşzamanlılık çakışmalarının
gerçekleşmesine ve sonra uygun şekilde yeniden davranmasını sağlar. Örneğin, Gamze departman düzenleme
sayfasını ziyaret ettiğinde, Ingilizce departmanı $350.000,00 olan bütçe tutarını $0,00 olarak değiştirir.

Jane tıkladığında önce Kaydet, John aynı sayfayı ziyaret eder ve alanın başlangıç tarihi 1/9/2013 1/9/2007'deki
değiştirir.
Gamze önce Kaydet ' i tıklatır ve tarayıcı dizin sayfasına döndüğünde değişikliği görür.

Ardından John, hala $350.000,00 bütçesini gösteren bir düzenleme sayfasında Kaydet ' e tıklamakta. Sonraki
işlemin ne eşzamanlılık çakışmalarını nasıl ele tarafından belirlenir.
Bazı seçenekler şunlardır:
Bir kullanıcının hangi özelliği değiştirdiği ve yalnızca ilgili sütunları veritabanında güncelleştirdiğinden
haberdar olabilirsiniz.
Örnek senaryoda, iki kullanıcı tarafından farklı özellikler güncelleştirildiğinden hiçbir veri kaybolmaz.
Ingilizce bölüme bir dahaki sefer ilk kez gözattığında, hem gamze 'nin hem de John 'un değişikliklerini görür;
başlangıç tarihi 9/1/2013 ve sıfır dolar bir bütçe olur. Bu güncelleştirme yöntemi, veri kaybına neden
olabilecek çakışmaların sayısını azaltabilir, ancak bir varlığın aynı özelliğinde rekabet değişiklikleri yapılırsa
veri kaybını önleyebilir. Entity Framework bu şekilde çalışıp çalışmadığını, güncelleştirme kodunuzu nasıl
uygulayadığınıza bağlıdır. Genellikle bir Web uygulamasında pratik değildir, çünkü bir varlığın tüm özgün
özellik değerlerini ve yeni değerleri izlemek için büyük miktarlarda durum tutmanızı gerektirebilir. Büyük
miktarlarda durum bulundurma, uygulama performansını etkileyebilir çünkü sunucu kaynakları gerektirir ya
da Web sayfasının kendisine (örneğin, gizli alanlarda) veya bir tanımlama bilgisinde yer almalıdır.
Gamze'nin değişikliğinin üzerine Can'ın değişiklik sağlayabilirsiniz.
Ingilizce bölüme bir dahaki sefer gözattığında, 9/1/2013 ve geri yüklenen $350.000,00 değerini görür. Bu,
Istemci WINS veya son WINS senaryosu olarak adlandırılır. (İstemciden gelen tüm değerler veri deposunda
yer alacak şekilde önceliklidir.) Bu bölümün giriş bölümünde belirtildiği gibi, eşzamanlılık işleme için
herhangi bir kodlama yapmazsanız, bu otomatik olarak gerçekleşir.
John 'un değişikliğini veritabanında güncelleştirilmesini engelleyebilirsiniz.
Genellikle bir hata iletisi görüntüler, verilerin geçerli durumunu gösterir ve yine de bunu yapmak istiyorsa,
yaptığı değişiklikleri yeniden uygular. Bu adlı bir Store WINS senaryo. (Veri deposu değerleri, istemci
tarafından gönderilen değerlere göre önceliklidir.) Bu öğreticide mağaza WINS senaryosunu
uygulayacaksınız. Bu yöntem, bir kullanıcının neler olduğunu bildirmeden önce hiçbir değişikliğin üzerine
yazılmamasını sağlar.
Eşzamanlılık çakışmalarını algılama
Entity Framework oluşturduğu DbConcurrencyException özel durumları işleyerek çakışmaları çözebilirsiniz. Bu özel
durumların ne zaman throw hakkında bilgi edinmek için Entity Framework çakışmaları algılayabilmelidir. Bu
nedenle, veritabanını ve veri modelini uygun şekilde yapılandırmanız gerekir. Çakışma algılamayı etkinleştirmeye
yönelik bazı seçenekler şunlardır:
Veritabanı tablosunda, bir satırın ne zaman değiştirildiğini belirlemede kullanılabilecek bir izleme sütunu
ekleyin. Daha sonra Entity Framework SQL Update veya delete komutlarının WHERE yan tümcesinde bu
sütunu içerecek şekilde yapılandırabilirsiniz.
İzleme sütununun veri türü genellikle rowversion . rowversion değeri, satır her güncelleştirildiği zaman
artılan sıralı bir sayıdır. Bir Update veya delete komutunda WHERE yan tümcesi, izleme sütununun (orijinal
satır sürümü) orijinal değerini içerir. Güncelleştirilmekte olan satır başka bir kullanıcı tarafından
değiştirilmişse, rowversion sütunundaki değer özgün değerden farklıdır, bu nedenle Update veya DELETE
deyimi WHERE yan tümcesi nedeniyle güncelleştirilecek satırı bulamaz. Entity Framework, Update veya
delete komutuyla hiçbir satır güncelleştirilmediğini bulduğunda (yani, etkilenen satır sayısı sıfır olduğunda),
bunu bir eşzamanlılık çakışması olarak yorumlar.
Entity Framework, Update ve DELETE komutlarının WHERE yan tümcesindeki tablodaki her sütunun özgün
değerlerini içerecek şekilde yapılandırın.
İlk seçenekte olduğu gibi, satırdaki herhangi bir şey satırın ilk okuduğundan beri değiştiyse WHERE yan
tümcesi güncelleştirilecek bir satır döndürmez, bu da Entity Framework eşzamanlılık çakışması olarak
yorumlar. Birçok sütunu olan veritabanı tablolarında, bu yaklaşım çok büyük WHERE yan tümceleriyle
sonuçlanabilir ve büyük miktarlarda durum bulundurmasını gerektirebilir. Daha önce belirtildiği gibi, büyük
miktarlarda durumu korumak uygulama performansını etkileyebilir. Bu nedenle bu yaklaşım genellikle
önerilmez ve bu öğreticide kullanılan yöntem değildir.
Bu yaklaşımı eşzamanlılık 'e uygulamak istiyorsanız, ConcurrencyCheck özniteliğini bunlara ekleyerek
eşzamanlılık izlemek istediğiniz varlıktaki tüm birincil anahtar olmayan Özellikleri işaretlemeniz gerekir. Bu
değişiklik Entity Framework, tüm sütunları Update ve DELETE deyimlerinin SQL WHERE yan tümcesinde
içermesini sağlar.
Bu öğreticinin geri kalanında, departman varlığına bir rowversion izleme özelliği ekleyecek, bir denetleyici ve
görünümler oluşturacak ve her şeyin doğru şekilde çalıştığını doğrulamak için test edeceksiniz.
İzleme özelliği Ekle
İçinde Models/Department.cs, RowVersion adlı izleme özelliği ekleyin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Timestamp özniteliği, bu sütunun veritabanına gönderilen WHERE yan tümcesine ve DELETE komutlarına dahil
edileceğini belirtir. Önceki SQL Server sürümleri, SQL rowversion değiştirilmeden önce bir SQL timestamp veri
türü kullandığından özniteliğe Timestamp denir. rowversion için .NET türü bir bayt dizisidir.
Fluent API kullanmayı tercih ediyorsanız, aşağıdaki örnekte gösterildiği gibi izleme özelliğini belirtmek için
IsConcurrencyToken yöntemini ( Data/SchoolContext. cs) kullanabilirsiniz:

modelBuilder.Entity<Department>()
.Property(p => p.RowVersion).IsConcurrencyToken();

Bir özellik ekleyerek, veritabanı modelini değiştirdiğiniz için başka bir geçiş yapmanız gerekir.
Değişikliklerinizi kaydedin ve projeyi derleyin ve ardından komut penceresine aşağıdaki komutları girin:

dotnet ef migrations add RowVersion

dotnet ef database update

Departmanlar denetleyicisi ve görünümleri oluşturma


Daha önce öğrenciler, Kurslar ve Eğitmenler için yaptığınız gibi bir departman denetleyicisini ve görünümlerini
derden katlayın.

DepartmentsController.cs dosyasında, "FirstMidName" sözcüğünün dört yinelemesini "FullName" olarak değiştirin,


böylece Departman Yöneticisi açılan listeleri yalnızca soyadı yerine eğitmenin tam adını içerecektir.

ViewData["InstructorID"] = new SelectList(_context.Instructors, "ID", "FullName", department.InstructorID);

Dizin görünümünü Güncelleştir


Yapı iskelesi altyapısı dizin görünümünde bir ROWVERSION sütunu oluşturdu, ancak bu alan gösterilmemelidir.
Views/departmanlar/Index. cshtml içindeki kodu aşağıdaki kodla değiştirin.
@model IEnumerable<ContosoUniversity.Models.Department>

@{
ViewData["Title"] = "Departments";
}

<h2>Departments</h2>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Budget)
</th>
<th>
@Html.DisplayNameFor(model => model.StartDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Administrator)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Budget)
</td>
<td>
@Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Administrator.FullName)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.DepartmentID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.DepartmentID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.DepartmentID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Bu, başlığı "departmanlar" olarak değiştirir, RowVersion sütununu siler ve yöneticinin adı yerine tam adı gösterir.

Düzenleme yöntemlerini Güncelleştir


Hem HttpGet Edit yönteminde hem de Details yönteminde AsNoTracking ekleyin. HttpGet Edit yönteminde,
yönetici için Eager yüklemesi ekleyin.
var department = await _context.Departments
.Include(i => i.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.DepartmentID == id);

HttpPost Edit yöntemi için mevcut kodu şu kodla değiştirin:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int? id, byte[] rowVersion)
{
if (id == null)
{
return NotFound();
}

var departmentToUpdate = await _context.Departments.Include(i => i.Administrator).FirstOrDefaultAsync(m =>


m.DepartmentID == id);

if (departmentToUpdate == null)
{
Department deletedDepartment = new Department();
await TryUpdateModelAsync(deletedDepartment);
ModelState.AddModelError(string.Empty,
"Unable to save changes. The department was deleted by another user.");
ViewData["InstructorID"] = new SelectList(_context.Instructors, "ID", "FullName",
deletedDepartment.InstructorID);
return View(deletedDepartment);
}

_context.Entry(departmentToUpdate).Property("RowVersion").OriginalValue = rowVersion;

if (await TryUpdateModelAsync<Department>(
departmentToUpdate,
"",
s => s.Name, s => s.StartDate, s => s.Budget, s => s.InstructorID))
{
try
{
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Department)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty,
"Unable to save changes. The department was deleted by another user.");
}
else
{
var databaseValues = (Department)databaseEntry.ToObject();

if (databaseValues.Name != clientValues.Name)
{
ModelState.AddModelError("Name", $"Current value: {databaseValues.Name}");
}
if (databaseValues.Budget != clientValues.Budget)
{
ModelState.AddModelError("Budget", $"Current value: {databaseValues.Budget:c}");
}
if (databaseValues.StartDate != clientValues.StartDate)
{
ModelState.AddModelError("StartDate", $"Current value: {databaseValues.StartDate:d}");
}
if (databaseValues.InstructorID != clientValues.InstructorID)
{
Instructor databaseInstructor = await _context.Instructors.FirstOrDefaultAsync(i => i.ID ==
databaseValues.InstructorID);
ModelState.AddModelError("InstructorID", $"Current value: {databaseInstructor?.FullName}");
}

ModelState.AddModelError(string.Empty, "The record you attempted to edit "


+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
departmentToUpdate.RowVersion = (byte[])databaseValues.RowVersion;
ModelState.Remove("RowVersion");
}
}
}
ViewData["InstructorID"] = new SelectList(_context.Instructors, "ID", "FullName",
departmentToUpdate.InstructorID);
return View(departmentToUpdate);
}

Kod, güncellenen departmanı okumaya çalışırken başlar. FirstOrDefaultAsync yöntemi null döndürürse, departman
başka bir kullanıcı tarafından silindi. Bu durumda, kod, düzenleme sayfasının bir hata iletisiyle yeniden
görüntülenebilmesi için bir departman varlığı oluşturmak üzere postalanan form değerlerini kullanır. Alternatif
olarak, departman alanlarını yeniden görüntülemeden yalnızca bir hata iletisi görüntülediğinizde, departman
varlığını yeniden oluşturmanız gerekmez.
Görünüm özgün RowVersion değerini gizli bir alana depolar ve bu yöntem, rowVersion parametresindeki bu değeri
alır. SaveChanges çağırmadan önce, bu özgün RowVersion özellik değerini varlık için OriginalValues koleksiyonuna
koymanız gerekir.

_context.Entry(departmentToUpdate).Property("RowVersion").OriginalValue = rowVersion;

Entity Framework bir SQL UPDATE komutu oluşturduğunda, bu komut özgün RowVersion değerine sahip bir satırı
aramak için bir WHERE yan tümcesi içerecektir. GÜNCELLEŞTIRME komutundan hiçbir satır etkilenmiyorsa
(özgün RowVersion değerine sahip satır yoksa) Entity Framework bir DbUpdateConcurrencyException özel durumu
oluşturur.
Bu özel durum için catch bloğundaki kod, özel durum nesnesindeki Entries özelliğinden güncelleştirilmiş
değerlere sahip etkilenen departman varlığını alır.

var exceptionEntry = ex.Entries.Single();

Entries koleksiyonu yalnızca bir EntityEntry nesnesine sahip olur. Kullanıcı tarafından girilen yeni değerleri ve
geçerli veritabanı değerlerini almak için bu nesneyi kullanabilirsiniz.

var clientValues = (Department)exceptionEntry.Entity;


var databaseEntry = exceptionEntry.GetDatabaseValues();

Kod, kullanıcının düzenleme sayfasına girdikten farklı veritabanı değerleri olan her bir sütun için özel bir hata iletisi
ekler (yalnızca bir alan, kısaltma için burada gösterilir).
var databaseValues = (Department)databaseEntry.ToObject();

if (databaseValues.Name != clientValues.Name)
{
ModelState.AddModelError("Name", $"Current value: {databaseValues.Name}");

Son olarak kod, departmentToUpdate RowVersion değerini veritabanından alınan yeni değere ayarlar. Bu yeni
RowVersion değeri, düzenleme sayfası yeniden görüntülenirken gizli alanda saklanır ve Kullanıcı Kaydet' i
tıkladığında, düzenleme sayfasının yeniden görüntülenmesinden bu yana yalnızca gerçekleşen eşzamanlılık hataları
yakalanacaktır.

departmentToUpdate.RowVersion = (byte[])databaseValues.RowVersion;
ModelState.Remove("RowVersion");

ModelState.Remove Deyimi, çünkü gereklidir ModelState eski olan RowVersion değeri. Görünümde, bir alan için
ModelState değeri, her ikisi de varsa Model özelliği değerlerinin üzerine gelir.

Güncelleştirme düzenleme görünümü


Görünümler/departmanlar/Düzenle. cshtml'de aşağıdaki değişiklikleri yapın:
RowVersion özellik değerini kaydetmek için, DepartmentID özelliğinin gizli alanından hemen sonra bir gizli
alan ekleyin.
Açılan listeye "Yönetici Seç" seçeneği ekleyin.
@model ContosoUniversity.Models.Department

@{
ViewData["Title"] = "Edit";
}

<h2>Edit</h2>

<h4>Department</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="DepartmentID" />
<input type="hidden" asp-for="RowVersion" />
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Budget" class="control-label"></label>
<input asp-for="Budget" class="form-control" />
<span asp-validation-for="Budget" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StartDate" class="control-label"></label>
<input asp-for="StartDate" class="form-control" />
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="InstructorID" class="control-label"></label>
<select asp-for="InstructorID" class="form-control" asp-items="ViewBag.InstructorID">
<option value="">-- Select Administrator --</option>
</select>
<span asp-validation-for="InstructorID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>

<div>
<a asp-action="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Eşzamanlılık çakışmalarını test et


Uygulamayı çalıştırın ve departmanlar dizini sayfasına gidin. Ingilizce departman için düzenleme köprüsüne sağ
tıklayın ve Yeni sekmesinde aç' ı seçin ve ardından İngilizce bölümünün düzenleme Köprüsü ' ne tıklayın. İki
tarayıcı sekmesi artık aynı bilgileri görüntüler.
İlk tarayıcı sekmesinde bir alanı değiştirin ve Kaydet' e tıklayın.
Tarayıcı, değiştirilen değeri olan dizin sayfasını gösterir.
İkinci tarayıcı sekmesinden bir alanı değiştirin.
Kaydet’e tıklayın. Bir hata iletisi görürsünüz:
Tıklayın Kaydet yeniden. İkinci tarayıcı sekmesinde girdiğiniz değer kaydedilir. Dizin sayfası göründüğünde
kaydedilen değerleri görürsünüz.

Silme sayfası
Silme sayfası için Entity Framework, başka birinin departmanı benzer bir şekilde düzenlemesinden kaynaklanan
eşzamanlılık çakışmalarını algılar. HttpGet Delete yöntemi onay görünümünü görüntülediğinde, görünüm, gizli bir
alanda özgün RowVersion değerini içerir. Bu değer daha sonra Kullanıcı silmeyi onayladığında çağrılan HttpPost
Delete yöntemi için kullanılabilir. Entity Framework, SQL DELETE komutunu oluşturduğunda, özgün RowVersion
değerine sahip bir WHERE yan tümcesi içerir. Komut, sıfır satır etkilenirse (satır silme onayı sayfası
görüntülendikten sonra değiştirildiğinde), bir eşzamanlılık özel durumu oluşturulur ve onay sayfasını bir hata
iletisiyle yeniden görüntülemek için HttpGet Delete yöntemi bir hata bayrağı true olarak çağırılır. Satır başka bir
kullanıcı tarafından silindiğinden, bu durumda herhangi bir hata iletisi görüntülenmediğinden sıfır satırların
etkilenmesi de mümkündür.
Departmanlar denetleyicisindeki silme yöntemlerini güncelleştirme
DepartmentsController.cs' de, httpget Delete yöntemini aşağıdaki kodla değiştirin:
public async Task<IActionResult> Delete(int? id, bool? concurrencyError)
{
if (id == null)
{
return NotFound();
}

var department = await _context.Departments


.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.DepartmentID == id);
if (department == null)
{
if (concurrencyError.GetValueOrDefault())
{
return RedirectToAction(nameof(Index));
}
return NotFound();
}

if (concurrencyError.GetValueOrDefault())
{
ViewData["ConcurrencyErrorMessage"] = "The record you attempted to delete "
+ "was modified by another user after you got the original values. "
+ "The delete operation was canceled and the current values in the "
+ "database have been displayed. If you still want to delete this "
+ "record, click the Delete button again. Otherwise "
+ "click the Back to List hyperlink.";
}

return View(department);
}

Yöntemi, sayfanın bir eşzamanlılık hatasından sonra yeniden görüntülenip görüntülenmeyeceğini belirten isteğe
bağlı bir parametresini kabul eder. Bu bayrak true ise ve belirtilen departman artık mevcut değilse, başka bir
kullanıcı tarafından silindi. Bu durumda, kod dizin sayfasına yeniden yönlendirir. Bu bayrak true ise ve departman
varsa, başka bir kullanıcı tarafından değiştirilmiştir. Bu durumda, kod ViewData kullanarak görünüme bir hata mesajı
gönderir.
HttpPost Delete yöntemindeki ( DeleteConfirmed adlı) kodu şu kodla değiştirin:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(Department department)
{
try
{
if (await _context.Departments.AnyAsync(m => m.DepartmentID == department.DepartmentID))
{
_context.Departments.Remove(department);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
catch (DbUpdateConcurrencyException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction(nameof(Delete), new { concurrencyError = true, id = department.DepartmentID });
}
}

Az önce değiştirdiğiniz scafkatlanmış kodda, bu yöntem yalnızca bir kayıt KIMLIĞI kabul etti:
public async Task<IActionResult> DeleteConfirmed(int id)

Bu parametreyi model Ciltçi tarafından oluşturulan bir departman varlığı örneğine değiştirdiniz. Bu, kayıt
anahtarına ek olarak ROWVERSION özellik değerine EF erişimi verir.

public async Task<IActionResult> Delete(Department department)

Ayrıca DeleteConfirmed eylem yöntemi adını Delete olarak değiştirdiniz. Yapı iskelesi kodu, HttpPost yöntemine
benzersiz bir imza vermek için DeleteConfirmed adı kullandı. (CLR aşırı yüklenmiş yöntemlerin farklı yöntem
parametrelerine sahip olmasını gerektirir.) İmzalar benzersiz olduğuna göre, MVC kuralını seçebilir ve HttpPost ve
HttpGet silme yöntemleri için aynı adı kullanabilirsiniz.
Departman zaten silinirse, AnyAsync yöntemi false döndürür ve uygulama yalnızca dizin yöntemine geri döner.
Bir eşzamanlılık hatası yakalanmışsa, kod silme onayı sayfasını yeniden görüntüler ve bir eşzamanlılık hata mesajı
görüntülemesi gerektiğini belirten bir bayrak sağlar.
Silme görünümünü Güncelleştir
Views/departmanlar/delete. cshtmliçinde, scafkatkli kodunu, DepartmentID ve rowversion özellikleri için bir hata
iletisi alanı ve gizli alanları ekleyen aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.
@model ContosoUniversity.Models.Department

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<p class="text-danger">@ViewData["ConcurrencyErrorMessage"]</p>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Department</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Name)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Budget)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Budget)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.StartDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.StartDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Administrator)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Administrator.FullName)
</dd>
</dl>

<form asp-action="Delete">
<input type="hidden" asp-for="DepartmentID" />
<input type="hidden" asp-for="RowVersion" />
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a>
</div>
</form>
</div>

Bu, aşağıdaki değişiklikleri yapar:


h2 ve h3 başlıkları arasında bir hata iletisi ekler.
FullName FirstMidName değiştirir yönetici alan.
RowVersion alanını kaldırır.
RowVersion özelliği için gizli bir alan ekler.

Uygulamayı çalıştırın ve departmanlar dizini sayfasına gidin. Ingilizce departman için Sil köprüsünü sağ tıklayın ve
Yeni sekmede aç' ı seçin ve ardından ilk sekmede İngilizce departman için düzenleme Köprüsü ' ne tıklayın.
İlk pencerede, değerlerden birini değiştirin ve Kaydet' e tıklayın:
İkinci sekmede Sil' e tıklayın. Eşzamanlılık hata iletisini görürsünüz ve departman değerleri şu anda veritabanında
olan ile yenilenir.
Yeniden Sil ' e tıklarsanız, departmanın silindiğini gösteren dizin sayfasına yönlendirilirsiniz.

Güncelleştirme ayrıntıları ve görünüm oluşturma


İsteğe bağlı olarak ayrıntılarda bulunan kodu temizleyebilir ve görünümler oluşturabilirsiniz.
RowVersion sütununu silmek ve yöneticinin tam adını göstermek için views/departmanlar/details. cshtml içindeki
kodu değiştirin.
@model ContosoUniversity.Models.Department

@{
ViewData["Title"] = "Details";
}

<h2>Details</h2>

<div>
<h4>Department</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Name)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Budget)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Budget)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.StartDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.StartDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Administrator)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Administrator.FullName)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.DepartmentID">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Açılan listeye bir SELECT seçeneği eklemek için views/departmanlar/Create. cshtml içindeki kodu değiştirin.
@model ContosoUniversity.Models.Department

@{
ViewData["Title"] = "Create";
}

<h2>Create</h2>

<h4>Department</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Budget" class="control-label"></label>
<input asp-for="Budget" class="form-control" />
<span asp-validation-for="Budget" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StartDate" class="control-label"></label>
<input asp-for="StartDate" class="form-control" />
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="InstructorID" class="control-label"></label>
<select asp-for="InstructorID" class="form-control" asp-items="ViewBag.InstructorID">
<option value="">-- Select Administrator --</option>
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>

<div>
<a asp-action="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Kodu alın
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Ek kaynaklar
EF Core eşzamanlılık işleme hakkında daha fazla bilgi için bkz. eşzamanlılık çakışmaları.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Eşzamanlılık çakışmaları hakkında öğrenildi
İzleme özelliği eklendi
Oluşturulan departmanlar denetleyicisi ve görünümleri
Güncelleştirilmiş dizin görünümü
Güncelleştirilmiş düzenleme yöntemleri
Güncelleştirilmiş düzenleme görünümü
Test edilen eşzamanlılık çakışmaları
Silme sayfası güncelleştirildi
Güncelleştirilmiş Ayrıntılar ve görünüm oluşturma
Eğitmen ve öğrenci varlıkları için tablo başına devralma devralmayı nasıl uygulayacağınızı öğrenmek için sonraki
öğreticiye ilerleyin.
Sonraki: tablo-hiyerarşi devralmayı Uygula
Öğretici: EF Core devralma-ASP.NET MVC uygulama
11.10.2019 • 12 minutes to read • Edit Online

Önceki öğreticide eşzamanlılık özel durumlarını ele alırsınız. Bu öğretici, veri modelinde devralmayı nasıl
uygulayacağınızı gösterir.
Nesne odaklı programlamada, kod yeniden kullanımını kolaylaştırmak için devralmayı kullanabilirsiniz. Bu
öğreticide, Instructor ve Student sınıflarını, hem Eğitmenler hem de öğrenciler için ortak olan LastName gibi
özellikleri içeren Person taban sınıfından türetireceğiz olacak şekilde değiştireceksiniz. Herhangi bir Web sayfası
eklemez veya değiştirmezsiniz, ancak koddan bazılarını değiştireceksiniz ve bu değişiklikler otomatik olarak
veritabanına yansıtılacaktır.
Bu öğreticide şunları yaptınız:
Devralmayı veritabanına eşle
Kişi sınıfını oluşturma
Eğitmeni ve öğrenci 'yi güncelleştirme
Modele kişi ekleme
Geçişleri oluşturma ve güncelleştirme
Uygulamayı test etme

Önkoşullar
Eşzamanlılık işle

Devralmayı veritabanına eşle


Okul veri modelindeki Instructor ve Student sınıflarının özdeş birkaç özelliği vardır:

@No__t-0 ve Student varlıkları tarafından paylaşılan özellikler için gereksiz kodu ortadan kaldırmak istediğinizi
varsayalım. Ya da adın bir eğitmenden veya bir öğrenciye ait olup olmadığına bakılmaksızın adları
biçimlendirmeden bir hizmet yazmak isteyebilirsiniz. Yalnızca bu paylaşılan özellikleri içeren bir Person taban sınıfı
oluşturabilirsiniz, ardından aşağıdaki çizimde gösterildiği gibi, Instructor ve Student sınıflarının bu temel sınıftan
devralmasını sağlayabilirsiniz:
Bu devralma yapısının veritabanında temsil edilebilmesi için birkaç yol vardır. Tek bir tabloda hem öğrenciler hem
de eğitmenler hakkında bilgi içeren bir kişi tablonuz olabilir. Bazı sütunlar yalnızca Eğitmenler (HireDate), bazıları
yalnızca öğrencilerle (kayıttarihi), bazıları ise (soyadı, adı) için geçerlidir. Genellikle, her bir satırın temsil ettiği türü
belirtmek için bir Ayrıştırıcı sütunu vardır. Örneğin, ayrıştırıcı sütununda, Eğitmenler için "eğitmen" ve öğrenciler
için "öğrenci" bulunabilir.

Tek bir veritabanı tablosundan bir varlık devralma yapısı oluşturmanın bu düzeni, hiyerarşi başına tablo (TPH)
devralma olarak adlandırılır.
Alternatif olarak, veritabanının devralma yapısına benzer bir şekilde görünmesini sağlayabilirsiniz. Örneğin, kişi
tablosunda yalnızca ad alanları olabilir ve Tarih alanlarıyla ayrı eğitmen ve öğrenci tabloları vardır.

Her varlık sınıfı için bir veritabanı tablosu yapmanın bu düzeni, tür başına tablo (TPT) devralma olarak adlandırılır.
Başka bir seçenek de Özet olmayan tüm türleri tek tek tablolarla eşlemenize olanak sağlar. Devralınan özellikler de
dahil olmak üzere bir sınıfın tüm özellikleri karşılık gelen tablonun sütunlarına eşlenir. Bu düzene, tablo başına
somut sınıf (TPC ) devralma adı verilir. Daha önce gösterildiği gibi, kişi, öğrenci ve eğitmen sınıfları için TPC
devralmayı uyguladıysanız, öğrenci ve eğitmen tabloları, devralındıktan sonra, devralma uygulandıktan sonra farklı
şekilde görünür.
TPC ve TPH devralma desenleri genellikle TPT devralma desenlerinden daha iyi performans sağlar, çünkü TPT
desenleri karmaşık JOIN sorgularına yol açabilir.
Bu öğreticide, TPH devralmanın nasıl uygulanacağı gösterilmektedir. TPH Entity Framework Core desteklediği tek
devralma modelidir. @No__t-0 sınıfı oluşturmak, Person ' ten türetmek için Instructor ve Student sınıflarını
değiştirin, yeni sınıfı DbContext ' e ekleyin ve bir geçiş oluşturun.

TIP
Aşağıdaki değişiklikleri yapmadan önce projenin bir kopyasını kaydetmeyi göz önünde bulundurun. Daha sonra sorunlarla
karşılaşırsanız ve baştan başlamak gerekirse, bu öğretici için yapılan adımları tersine çevirme veya tüm serinin başlangıcına geri
dönme yerine kaydedilen projeden başlamak daha kolay olacaktır.

Kişi sınıfını oluşturma


Modeller klasöründe Person.cs oluşturun ve şablon kodunu şu kodla değiştirin:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public abstract class Person
{
public int ID { get; set; }

[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}
}
}

Eğitmeni ve öğrenci 'yi güncelleştirme


Instructor.cs' de, kişi sınıfından eğitmen sınıfını türetirsiniz ve anahtar ve ad alanlarını kaldırın. Kod aşağıdaki örneğe
benzer şekilde görünür:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor : Person
{
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Student.cs' de aynı değişiklikleri yapın.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student : Person
{
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Modele kişi ekleme


Kişi varlık türünü SchoolContext.csöğesine ekleyin. Yeni satırlar vurgulanır.
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<CourseAssignment> CourseAssignments { get; set; }
public DbSet<Person> People { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Department>().ToTable("Department");
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");
modelBuilder.Entity<Person>().ToTable("Person");

modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
}
}
}

Bu, Entity Framework hiyerarşinin devralma devralınmasını yapılandırmak için gereklidir. Gördüğünüz gibi,
veritabanı güncelleştirildiği sırada öğrenci ve eğitmen tablolarının yerine bir kişi tablosu olacaktır.

Geçişleri oluşturma ve güncelleştirme


Değişikliklerinizi kaydedin ve projeyi derleyin. Ardından proje klasöründe komut penceresini açın ve aşağıdaki
komutu girin:

dotnet ef migrations add Inheritance

@No__t-0 komutunu henüz çalıştırmayın. Bu komut, eğitmen tablosunu bırakacak ve öğrenci tablosunu kişi olarak
yeniden adlandırdığı için kayıp veri oluşmasına neden olur. Varolan verileri korumak için özel kod sağlamanız
gerekir.
Geçişleri/<timestamp > _Devralma. cs ' i açın ve Up yöntemini aşağıdaki kodla değiştirin:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Enrollment_Student_StudentID",
table: "Enrollment");

migrationBuilder.DropIndex(name: "IX_Enrollment_StudentID", table: "Enrollment");

migrationBuilder.RenameTable(name: "Instructor", newName: "Person");


migrationBuilder.AddColumn<DateTime>(name: "EnrollmentDate", table: "Person", nullable: true);
migrationBuilder.AddColumn<string>(name: "Discriminator", table: "Person", nullable: false, maxLength: 128,
defaultValue: "Instructor");
migrationBuilder.AlterColumn<DateTime>(name: "HireDate", table: "Person", nullable: true);
migrationBuilder.AddColumn<int>(name: "OldId", table: "Person", nullable: true);

// Copy existing Student data into new Person table.


migrationBuilder.Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator,
OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId
FROM dbo.Student");
// Fix up existing relationships to match new PK's.
migrationBuilder.Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId =
Enrollment.StudentId AND Discriminator = 'Student')");

// Remove temporary key


migrationBuilder.DropColumn(name: "OldID", table: "Person");

migrationBuilder.DropTable(
name: "Student");

migrationBuilder.CreateIndex(
name: "IX_Enrollment_StudentID",
table: "Enrollment",
column: "StudentID");

migrationBuilder.AddForeignKey(
name: "FK_Enrollment_Person_StudentID",
table: "Enrollment",
column: "StudentID",
principalTable: "Person",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
}

Bu kod aşağıdaki veritabanı güncelleştirme görevlerini gerçekleştirir:


Yabancı anahtar kısıtlamalarını ve öğrenci tablosuna işaret eden dizinleri kaldırır.
Eğitmen tablosunu kişi olarak yeniden adlandırır ve öğrenci verilerini depolamak için gerekli değişiklikleri
yapar:
Öğrenciler için Nullable kayıt tarihi ekler.
Bir satırın bir öğrenci mi yoksa bir eğitmen mi olduğunu göstermek için ayrıştırıcı sütunu ekler.
Öğrenci satırlarında işe alma tarihleri olmadığından, HireDate null yapılabilir hale gelir.
Öğrencilere işaret eden yabancı anahtarları güncelleştirmek için kullanılacak geçici bir alan ekler. Öğrencileri
kişi tablosuna kopyaladığınızda, yeni birincil anahtar değerleri alırlar.
Öğrenci tablosundaki verileri kişi tablosuna kopyalar. Bu, öğrencilerden yeni birincil anahtar değerleri
atanmasını sağlar.
Öğrencilere işaret eden yabancı anahtar değerlerini düzeltir.
Yabancı anahtar kısıtlamalarını ve dizinleri yeniden oluşturur, şimdi bunları kişi tablosuna işaret eder.
(Birincil anahtar türü olarak tamsayı yerine GUID kullandıysanız, öğrenci birincil anahtar değerlerinin değiştirilmesi
gerekmez ve bu adımların bazıları atlanamaz.)
@No__t-0 komutunu çalıştırın:

dotnet ef database update

(Bir üretim sisteminde, önceki veritabanı sürümüne geri dönmek için bunu kullanmanız durumunda Down
yönteminde ilgili değişiklikleri yaparsınız. Bu öğreticide Down yöntemini kullanmayacağız.)

NOTE
Varolan verileri içeren bir veritabanında şema değişiklikleri yaparken başka hatalar almak mümkündür. Çözemiyoruz geçiş
hataları alırsanız, bağlantı dizesindeki veritabanı adını değiştirebilir veya veritabanını silebilirsiniz. Yeni bir veritabanı ile
geçirilecek veri yoktur ve Update-Database komutunun hatasız tamamlanabilmesi daha olasıdır. Veritabanını silmek için, SSOX
kullanın veya database drop CLı komutunu çalıştırın.

Uygulamayı test etme


Uygulamayı çalıştırın ve çeşitli sayfaları deneyin. Her şey, daha önce olduğu gibi çalışmaktadır.
SQL Server Nesne Gezgini, veri bağlantıları/SchoolContext ve ardından Tablolar' ı genişletin ve öğrenci ve
eğitmen tablolarının bir kişi tablosu ile değiştirildiğini görürsünüz. Kişi tablosu tasarımcısını açın ve öğrencinin ve
eğitmen tablolarında kullanılan tüm sütunları olduğunu görürsünüz.

Kişi tablosuna sağ tıklayın ve ardından tablo verilerini göster ' e tıklayarak ayrıştırıcı sütununu görüntüleyin.
Kodu edinin
Tamamlanmış uygulamayı indirin veya görüntüleyin.

Ek kaynaklar
Entity Framework Core devralma hakkında daha fazla bilgi için bkz. Devralma.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Veritabanına devralma eşlenmiş
Kişi sınıfı oluşturuldu
Güncelleştirilmiş eğitmen ve öğrenci
Modele kişi eklendi
Geçişleri oluşturma ve güncelleştirme
Uygulama test edildi
Çeşitli görece gelişmiş Entity Framework senaryolarını nasıl işleyeceğinizi öğrenmek için sonraki öğreticiye
ilerleyin.
İleri: gelişmiş konular
Öğretici: Gelişmiş senaryolar hakkında bilgi edinin-EF
Core ASP.NET MVC
11.10.2019 • 22 minutes to read • Edit Online

Önceki öğreticide, tablo başına devralma devralmayı uyguladık. Bu öğreticide, Entity Framework Core kullanan
ASP.NET Core Web uygulamaları geliştirme hakkında temel bilgileri aşdığınızda dikkat etmeniz yararlı olan birkaç
konu sunulmaktadır.
Bu öğreticide şunları yaptınız:
Ham SQL sorguları gerçekleştirme
Varlıkları döndürmek için bir sorgu çağırın
Başka türler döndürmek için bir sorgu çağırın
Güncelleştirme sorgusu çağırma
SQL sorgularını inceleyin
Soyutlama katmanı oluşturma
Otomatik değişiklik algılama hakkında bilgi edinin
EF Core kaynak kodu ve geliştirme planları hakkında bilgi edinin
Kodu basitleştirmek için dinamik LINQ kullanmayı öğrenin

Önkoşullar
Devralmayı Uygula

Ham SQL sorguları gerçekleştirme


Entity Framework kullanmanın avantajlarından biri, kodunuzun veri depolarken belirli bir yönteme çok
benzemesidir. Bunu sizin için SQL sorguları ve komutları oluşturarak yapar, bu da sizi kendiniz yazmak zorunda
kalmaktan kurtarır. Ancak el ile oluşturduğunuz belirli SQL sorgularını çalıştırmanız gerektiğinde olağanüstü
senaryolar vardır. Bu senaryolar için Entity Framework Code First API 'SI, SQL komutlarını doğrudan veritabanına
geçirmenize olanak sağlayan yöntemleri içerir. EF Core 1,0 ' de aşağıdaki seçenekleriniz vardır:
Varlık türleri döndüren sorgular için DbSet.FromSql yöntemini kullanın. Döndürülen nesneler DbSet nesnesi
tarafından beklenen türde olmalıdır ve izlemeyikapatmadığınız takdirde veritabanı bağlamı tarafından
otomatik olarak izlenir.
Sorgu olmayan komutlar için Database.ExecuteSqlCommand kullanın.
Varlık olmayan türleri döndüren bir sorgu çalıştırmanız gerekiyorsa, EF tarafından sunulan veritabanı bağlantısıyla
ADO.NET kullanabilirsiniz. Döndürülen veriler, varlık türlerini almak için bu yöntemi kullanıyor olsanız bile
veritabanı bağlamı tarafından izlenmez.
Her zaman doğru olduğu gibi, bir Web uygulamasında SQL komutları yürüttüğünüzde, sitenizi SQL ekleme
saldırılarına karşı korumak için önlemler almalısınız. Bunu yapmanın bir yolu, bir Web sayfası tarafından gönderilen
dizelerin SQL komutları olarak yorumlanamadığından emin olmak için parametreli sorgular kullanmaktır. Bu
öğreticide Kullanıcı girişini bir sorguyla tümleştirdiğinizde parametreli sorgular kullanacaksınız.

Varlıkları döndürmek için bir sorgu çağırın


@No__t-0 sınıfı, TEntity türünde bir varlık döndüren bir sorgu yürütmek için kullanabileceğiniz bir yöntem sağlar.
Bunun nasıl çalıştığını görmek için, Bölüm denetleyicisinin Details yönteminde kodu değiştirirsiniz.
DepartmentsController.cs' de, Details yönteminde, aşağıdaki vurgulanmış kodda gösterildiği gibi bir departmanı
alan kodu FromSql yöntem çağrısıyla değiştirin:

public async Task<IActionResult> Details(int? id)


{
if (id == null)
{
return NotFound();
}

string query = "SELECT * FROM Department WHERE DepartmentID = {0}";


var department = await _context.Departments
.FromSql(query, id)
.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync();

if (department == null)
{
return NotFound();
}

return View(department);
}

Yeni kodun doğru şekilde çalıştığını doğrulamak için Departmanlar sekmesini seçin ve sonra departmanlardan
birine ilişkin ayrıntıları izleyin.

Başka türler döndürmek için bir sorgu çağırın


Daha önce, yaklaşık bir kayıt tarihi için öğrenci sayısını gösteren hakkında sayfasında bir öğrenci istatistikleri
Kılavuzu oluşturdunuz. Öğrenciler varlık kümesindeki ( _context.Students ) verileri aldınız ve LINQ 'ı, sonuçları bir
EnrollmentDateGroup görünüm modeli nesneleri listesine eklemek için kullandınız. LINQ kullanmak yerine SQL 'in
kendisini yazmak istediğinizi varsayalım. Bunu yapmak için, varlık nesnelerinden başka bir şey döndüren bir SQL
sorgusu çalıştırmanız gerekir. EF Core 1,0 ' de, bunu yapmanın bir yolu ADO.NET kodunu yazıp EF 'ten veritabanı
bağlantısı almanızı sağlar.
HomeController.cs' de About yöntemini aşağıdaki kodla değiştirin:

public async Task<ActionResult> About()


{
List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>();
var conn = _context.Database.GetDbConnection();
try
{
await conn.OpenAsync();
using (var command = conn.CreateCommand())
{
string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
+ "FROM Person "
+ "WHERE Discriminator = 'Student' "
+ "GROUP BY EnrollmentDate";
command.CommandText = query;
DbDataReader reader = await command.ExecuteReaderAsync();

if (reader.HasRows)
{
while (await reader.ReadAsync())
{
var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount =
reader.GetInt32(1) };
groups.Add(row);
}
}
reader.Dispose();
}
}
finally
{
conn.Close();
}
return View(groups);
}

Using deyimleri ekleme:

using System.Data.Common;

Uygulamayı çalıştırın ve hakkında sayfasına gidin. Daha önce yaptığımız verileri görüntüler.

Güncelleştirme sorgusu çağırma


Contoso Üniversitesi yöneticilerinin veritabanında, her kurs için kredi sayısını değiştirme gibi genel değişiklikleri
gerçekleştirmesini istediğini varsayalım. Üniversitenin çok sayıda kursu varsa, bunların tümünü varlıklar olarak
almak ve tek tek değiştirmek verimsiz olur. Bu bölümde, kullanıcının tüm kurslar için kredi sayısını değiştirecek bir
faktör belirtmesini sağlayan bir Web sayfası uygulayacaksınız ve bir SQL UPDATE ifadesini yürüterek değişikliği
yaparsınız. Web sayfası aşağıdaki çizimde gösterildiği gibi görünür:

CoursesController.cs' de, HttpGet ve HttpPost için UpdateCourseCredits yöntemleri ekleyin:

public IActionResult UpdateCourseCredits()


{
return View();
}

[HttpPost]
public async Task<IActionResult> UpdateCourseCredits(int? multiplier)
{
if (multiplier != null)
{
ViewData["RowsAffected"] =
await _context.Database.ExecuteSqlCommandAsync(
"UPDATE Course SET Credits = Credits * {0}",
parameters: multiplier);
}
return View();
}

Denetleyici bir HttpGet isteğini işlediğinde, ViewData["RowsAffected"] ' a hiçbir şey döndürülmez ve görünüm,
önceki çizimde gösterildiği gibi boş bir metin kutusu ve bir Gönder düğmesi görüntüler.
Update düğmesine tıklandığında, HttpPost yöntemi çağırılır ve Multiplier metin kutusuna girilen değer vardır. Kod
daha sonra, bu güncelleştirmeleri güncelleştiren SQL 'i yürütür ve etkilenen satırların sayısını ViewData ' da
görünümüne döndürür. Görünüm bir RowsAffected değeri aldığında, güncelleştirilmiş satır sayısını görüntüler.
Çözüm Gezgini, Görünümler/kurslar klasörüne sağ tıklayın ve ardından > yeni öğe Ekle' ye tıklayın.
Yeni öğe Ekle iletişim kutusunda sol bölmede yüklü ASP.NET Core ' a tıklayın, Razor görünümü' ne tıklayın ve
yeni görünüm UpdateCourseCredits. cshtmlolarak adlandırın.
Views/kurslar/UpdateCourseCredits. cshtmliçinde, şablon kodunu şu kodla değiştirin:
@{
ViewBag.Title = "UpdateCourseCredits";
}

<h2>Update Course Credits</h2>

@if (ViewData["RowsAffected"] == null)


{
<form asp-action="UpdateCourseCredits">
<div class="form-actions no-color">
<p>
Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
</p>
<p>
<input type="submit" value="Update" class="btn btn-default" />
</p>
</div>
</form>
}
@if (ViewData["RowsAffected"] != null)
{
<p>
Number of rows updated: @ViewData["RowsAffected"]
</p>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>

@No__t-0 yöntemini, Kurslar sekmesini seçerek çalıştırın, sonra tarayıcının adres çubuğundaki URL 'nin sonuna
"/UpdateCourseCredits" ekleyin (örneğin: http://localhost:5813/Courses/UpdateCourseCredits ). Metin kutusuna bir
sayı girin:

Güncelleştir’e tıklayın. Etkilenen satır sayısını görürsünüz:


Düzeltilen kredi sayısına sahip kurslar listesini görmek için listeye geri ' ye tıklayın.
Üretim kodunun güncelleştirmelerin her zaman geçerli verilerle sonuçlandığına emin olun. Burada gösterilen
basitleştirilmiş kod, 5 ' ten fazla sayı ile sonuçlanacak kredilerin sayısını çarpamaz. (@No__t-0 özelliği bir
[Range(0, 5)] özniteliğine sahiptir.) Güncelleştirme sorgusu çalışır, ancak geçersiz veriler sistemin diğer
bölümlerinde, kredi sayısının 5 veya daha az olduğunu varsayacak beklenmedik sonuçlara neden olabilir.
Ham SQL sorguları hakkında daha fazla bilgi için bkz. Ham SQL sorguları.

SQL sorgularını inceleyin


Bazen veritabanına gönderilen gerçek SQL sorgularını görmeniz yararlı olabilir. ASP.NET Core için yerleşik günlük
işlevselliği, sorgular ve güncelleştirmeler için SQL içeren günlükleri yazmak üzere EF Core tarafından otomatik
olarak kullanılır. Bu bölümde, SQL günlüğe kaydetme işleminin bazı örneklerini görürsünüz.
StudentsController.cs ' i açın Details yöntemi if (student == null) ifadesinde bir kesme noktası ayarlayın.
Uygulamayı hata ayıklama modunda çalıştırın ve bir öğrenci için ayrıntılar sayfasına gidin.
Hata ayıklama çıkışını gösteren Çıkış penceresine gidin ve sorguyu görürsünüz:

Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (56ms) [Parameters=


[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [s].[ID], [s].[Discriminator], [s].[FirstName], [s].[LastName], [s].[EnrollmentDate]
FROM [Person] AS [s]
WHERE ([s].[Discriminator] = N'Student') AND ([s].[ID] = @__id_0)
ORDER BY [s].[ID]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (122ms) [Parameters=
[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT [s.Enrollments].[EnrollmentID], [s.Enrollments].[CourseID], [s.Enrollments].[Grade], [s.Enrollments].
[StudentID], [e.Course].[CourseID], [e.Course].[Credits], [e.Course].[DepartmentID], [e.Course].[Title]
FROM [Enrollment] AS [s.Enrollments]
INNER JOIN [Course] AS [e.Course] ON [s.Enrollments].[CourseID] = [e.Course].[CourseID]
INNER JOIN (
SELECT TOP(1) [s0].[ID]
FROM [Person] AS [s0]
WHERE ([s0].[Discriminator] = N'Student') AND ([s0].[ID] = @__id_0)
ORDER BY [s0].[ID]
) AS [t] ON [s.Enrollments].[StudentID] = [t].[ID]
ORDER BY [t].[ID]

Size beklenmedik bir şekilde bir sorun olduğunu fark edeceksiniz: SQL, kişi tablosundan 2 ' ye kadar satır ( TOP(2) )
seçer. @No__t-0 yöntemi sunucuda 1 satıra çözümlenmiyor. İşte şunları yapın:
Sorgu birden çok satır döndürürse, yöntemi null döndürür.
Sorgunun birden çok satır döndürüp döndürmeyeceğini anlamak için EF 'in en az 2 değerini döndürüp
döndürmediğini denetlemesi gerekir.
Çıkış penceresinde günlüğe kaydetme çıktısını almak için hata ayıklama modunu kullanmanız ve bir kesme
noktasında durdurmanız gerekmediğini unutmayın. Bu, çıkışa bakmak istediğiniz noktada günlüğe kaydetmeyi
durdurmak için kullanışlı bir yoldur. Bunu yapmazsanız, günlüğe kaydetme devam eder ve ilgilendiğiniz parçaları
bulmak için geri kaydırmanız gerekir.

Soyutlama katmanı oluşturma


Birçok geliştirici, Entity Framework ile çalışan kodun etrafında bir sarmalayıcı olarak depo ve iş birimi düzenlerini
uygulamak için kod yazar. Bu desenler, veri erişim katmanı ve bir uygulamanın iş mantığı katmanı arasında bir
soyutlama katmanı oluşturmak için tasarlanmıştır. Bu desenleri uygulamak, uygulamanızın veri deposundaki
değişikliklerden yalıtılmış hale getirmenize yardımcı olabilir ve otomatik birim testi veya test odaklı geliştirmeyi
(TDD ) kolaylaştırabilir. Ancak, bu desenleri uygulamak için ek kod yazmak, birkaç nedenden dolayı EF kullanan
uygulamalar için her zaman en iyi seçimdir:
EF bağlam sınıfının kendisi, veri deposuna özgü koddan kodunuzun kendisini uygular.
EF bağlam sınıfı, EF kullanarak yaptığınız veritabanı güncelleştirmeleri için bir iş birimi sınıfı işlevi görebilir.
EF, depo kodu yazmadan TDD uygulamaya yönelik özellikler içerir.
Deponun ve iş düzeni birimlerinin nasıl uygulanacağı hakkında bilgi için, Bu öğretici serisinin Entity Framework 5
sürümünebakın.
Entity Framework Core, test için kullanılabilecek bir bellek içi veritabanı sağlayıcısı uygular. Daha fazla bilgi için bkz.
InMemory Ile testetme.

Otomatik değişiklik algılama


Entity Framework bir varlığın geçerli değerlerini özgün değerlerle karşılaştırarak bir varlığın nasıl değiştiğini (ve bu
nedenle veritabanına gönderilmesi gereken güncelleştirmeleri) belirler. Özgün değerler, varlık sorgulandığında veya
eklendiğinde saklanır. Otomatik değişiklik algılamaya neden olan yöntemlerin bazıları şunlardır:
DbContext. SaveChanges
DbContext. Entry
ChangeTracker. Entries
Çok sayıda varlığı izliyorsanız ve bu yöntemlerden birini bir döngüde birçok kez çağırırsanız,
ChangeTracker.AutoDetectChangesEnabled özelliğini kullanarak otomatik değişikliği algılamayı geçici olarak kapatarak
önemli performans iyileştirmeleri alabilirsiniz. Örnek:

_context.ChangeTracker.AutoDetectChangesEnabled = false;

EF Core kaynak kodu ve geliştirme planları


Entity Framework Core kaynağı https://github.com/aspnet/EntityFrameworkCore' dir. EF Core deposu gecelik
derlemeler, sorun izleme, özellik özellikleri, tasarım toplantısı notları ve ileride geliştirmeye yönelik yol
haritasınıiçerir. Hataları dosyalayabilirsiniz veya bulabilir ve katkıda bulunabilirsiniz.
Kaynak kodu açık olsa da Entity Framework Core, Microsoft ürünü olarak tam olarak desteklenmektedir. Microsoft
Entity Framework ekibi, her bir yayının kalitesini sağlamak için, hangi katkıların kabul edildiğini denetler ve tüm kod
değişikliklerini sınar.

Mevcut veritabanından ters mühendislik


Mevcut bir veritabanından varlık sınıfları dahil bir veri modeline ters mühendislik uygulamak için Scaffold-
DbContext komutunu kullanın. Bkz. Başlangıç öğreticisi.

Kodu basitleştirmek için dinamik LINQ kullanma


Bu serideki üçüncü öğreticide , switch ifadesinde sabit kodlama sütun adları aracılığıyla LINQ kodunun nasıl
yazılacağı gösterilmektedir. Arasından seçim yapabileceğiniz iki sütun varsa, bu sorunsuz bir şekilde yapılır, ancak
çok sayıda sütununuzla karşılaşırsanız, kod ayrıntılı alabilir. Bu sorunu çözmek için, özelliğin adını dize olarak
belirtmek üzere EF.Property yöntemini kullanabilirsiniz. Bu yaklaşımı denemek için, StudentsController ' deki
Index yöntemini aşağıdaki kodla değiştirin.
public async Task<IActionResult> Index(
string sortOrder,
string currentFilter,
string searchString,
int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] =
String.IsNullOrEmpty(sortOrder) ? "LastName_desc" : "";
ViewData["DateSortParm"] =
sortOrder == "EnrollmentDate" ? "EnrollmentDate_desc" : "EnrollmentDate";

if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}

ViewData["CurrentFilter"] = searchString;

var students = from s in _context.Students


select s;

if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

if (string.IsNullOrEmpty(sortOrder))
{
sortOrder = "LastName";
}

bool descending = false;


if (sortOrder.EndsWith("_desc"))
{
sortOrder = sortOrder.Substring(0, sortOrder.Length - 5);
descending = true;
}

if (descending)
{
students = students.OrderByDescending(e => EF.Property<object>(e, sortOrder));
}
else
{
students = students.OrderBy(e => EF.Property<object>(e, sortOrder));
}

int pageSize = 3;
return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(),
pageNumber ?? 1, pageSize));
}

Bilgilendirme
Tom Dykstra ve Rick Anderson (Twitter @RickAndMSFT) bu öğreticiyi yazdı. ROWA Miller, Diego Vega ve kod
incelemeleri ile Entity Framework ekip yardımlı diğer üyeleri ve öğreticiler için kod yazarken oluşan sorunları
ayıkladık. John Parente ve Paul Goldman, 2,2 ASP.NET Core öğreticisini güncelleştirmeye çalıştı.
Sık karşılaşılan hataları giderme
Başka bir işlem tarafından kullanılan ContosoUniversity. dll
Hata iletisi:

Açılamıyor '... Bin\debug\netcoreapp1.0\contosoüniversıty.dll ' yazma için--' başka bir işlem tarafından
kullanıldığından, işlem '. ..\Bin\debug\netcoreapp1.0\contosoüniversı.dll ' dosyasına erişemiyor.

Çözümden
IIS Express sitesini durdurun. Windows sistemi tepsisine IIS Express bulun ve simgesine sağ tıklayın, Contoso
Üniversitesi sitesini seçin ve ardından siteyi durdur' a tıklayın.
Yukarı ve aşağı metotlarda kod olmadan geçiş yapı iskelesi
Olası neden:
EF CLı komutları, kod dosyalarını otomatik olarak kapatmaz ve kaydetmez. @No__t-0 komutunu çalıştırdığınızda
hiçbir değişiklik yaptıysanız, EF değişiklikleri bulamaz.
Çözümden
@No__t-0 komutunu çalıştırın, kod değişikliklerinizi kaydedin ve migrations add komutunu yeniden çalıştırın.
Veritabanı güncelleştirmesi çalıştırılırken hatalar oluştu
Varolan verileri içeren bir veritabanında şema değişiklikleri yaparken başka hatalar almak mümkündür.
Çözümleyemez geçiş hataları alırsanız, bağlantı dizesindeki veritabanı adını değiştirebilir veya veritabanını
silebilirsiniz. Yeni bir veritabanı ile geçirilecek veri yoktur ve Update-Database komutunun hatasız
tamamlanabilmesi çok daha yüksektir.
En basit yaklaşım, appSettings. JSONiçindeki veritabanını yeniden adlandırmanın bir veritabanıdır. @No__t-0 ' ı bir
sonraki sefer çalıştırdığınızda yeni bir veritabanı oluşturulur.
SSOX 'te bir veritabanını silmek için veritabanına sağ tıklayın, Sil' e tıklayın ve ardından veritabanını sil Iletişim
kutusunda varolan bağlantıları kapat ' ı seçin ve Tamam' a tıklayın.
CLı kullanarak bir veritabanını silmek için database drop CLı komutunu çalıştırın:

dotnet ef database drop

SQL Server örneği bulunurken hata oluştu


Hata Iletisi:

SQL Server ile bağlantı kurulmaya çalışılırken ağ ile ilişkili veya örneğe özgü bir hata oluştu. Sunucu
bulunamadı veya erişilebilir değildi. Örnek adının doğru olduğundan ve SQL Server uzak bağlantılara izin
verecek şekilde yapılandırıldığından emin olun. (sağlayıcı: SQL ağ arabirimleri, hata: 26-belirtilen sunucu/örnek
bulunurken hata oluştu)

Çözümden
Bağlantı dizesini denetleyin. Veritabanı dosyasını el ile sildiyseniz, oluşturma dizesindeki veritabanının adını yeni bir
veritabanı ile başlatılacak şekilde değiştirin.

Kodu edinin
Tamamlanmış uygulamayı indirin veya görüntüleyin.
Ek kaynaklar
EF Core hakkında daha fazla bilgi için Entity Framework Core belgelerinebakın. Bir kitap da kullanılabilir: Entity
Framework Core eylem.
Bir Web uygulamasını dağıtma hakkında daha fazla bilgi için bkz. ASP.NET Core barındırma ve dağıtma.
Kimlik doğrulama ve yetkilendirme gibi ASP.NET Core MVC ile ilgili diğer konular hakkında daha fazla bilgi için
bkz. ASP.NET Core’a Giriş.

Sonraki adımlar
Bu öğreticide şunları yaptınız:
Ham SQL sorguları gerçekleştiriliyor
Varlıkları döndürmek için sorgu çağrıldı
Diğer türleri döndürmek için sorgu çağrıldı
Bir güncelleştirme sorgusu çağrıldı
İncelenen SQL sorguları
Soyutlama katmanı oluşturma
Otomatik değişiklik algılama hakkında bilgi edinildi
EF Core kaynak kodu ve geliştirme planları hakkında bilgi edinildi
Kodu basitleştirmek için dinamik LINQ kullanımı öğrenildi
Bu, ASP.NET Core MVC uygulamasında Entity Framework Core kullanımı hakkında bu öğretici serisini tamamlar.
Bu seri yeni bir veritabanıyla çalıştı; bir alternatif, mevcut bir veritabanından bir modele tersine mühendislik
kullanmaktır.
Öğretici: MVC ile EF Core, var olan veritabanı
ASP.NET Core temelleri
8.11.2019 • 18 minutes to read • Edit Online

Bu makale, ASP.NET Core uygulamaları geliştirmeyi anlamak için önemli konulara genel bakış sağlar.

Başlangıç sınıfı
Startup sınıfı şu konumda:
Uygulamanın gerektirdiği hizmetler yapılandırıldı.
İstek işleme işlem hattı tanımlandı.
Hizmetler , uygulama tarafından kullanılan bileşenlerdir. Örneğin, bir günlük bileşeni bir hizmettir. Hizmetleri
yapılandırmak (veya kaydettirmek) için kod Startup.ConfigureServices yöntemine eklenir.
İstek işleme işlem hattı, bir dizi Ara yazılım bileşeni olarak oluşur. Örneğin, bir ara yazılım statik dosyalar için
istekleri işleyebilir veya HTTP isteklerini HTTPS 'ye yeniden yönlendirebilir. Her bir ara yazılım bir HttpContext
zaman uyumsuz işlemler gerçekleştirir ve sonra işlem hattında sonraki ara yazılımı çağırır ya da isteği sonlandırır.
İstek işleme işlem hattını yapılandırma kodu Startup.Configure yöntemine eklenir.
Örnek bir Startup sınıfı aşağıda verilmiştir:

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MovieDb")));
}

public void Configure(IApplicationBuilder app)


{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc();
}
}

Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama başlatma.

Bağımlılık ekleme (hizmetler)


ASP.NET Core, yapılandırılmış hizmetlerin bir uygulamanın sınıfları tarafından kullanılabilmesini sağlayan yerleşik
bir bağımlılık ekleme (dı) çerçevesine sahiptir. Bir sınıftaki hizmetin bir örneğini almanın bir yolu, gerekli türde bir
parametreye sahip bir Oluşturucu oluşturmaktır. Parametresi hizmet türü veya arabirim olabilir. Dı sistemi, çalışma
zamanında hizmeti sağlar.
İşte bir Entity Framework Core bağlam nesnesi almak için DI kullanan bir sınıf. Vurgulanan çizgi bir Oluşturucu
Ekleme örneğidir:
public class IndexModel : PageModel
{
private readonly RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovieContext context)


{
_context = context;
}
// ...
public async Task OnGetAsync()
{
var movies = from m in _context.Movies
select m;
Movies = await movies.ToListAsync();
}
}

Dı yerleşik olarak kullanılıyorsa, isterseniz Control (IOC ) kapsayıcısının bir üçüncü taraf Inversion öğesini
eklemenize olanak sağlamak üzere tasarlanmıştır.
Daha fazla bilgi için bkz. ASP.NET Core bağımlılık ekleme.

Ara yazılım
İstek işleme işlem hattı, bir dizi ara yazılım bileşeni olarak oluşur. Her bileşen bir HttpContext zaman uyumsuz
işlemler gerçekleştirir ve sonra işlem hattında sonraki ara yazılımı çağırır ya da isteği sonlandırır.
Kurala göre, Startup.Configure yönteminde Use... uzantısı yöntemini çağırarak işlem hattına bir ara yazılım
bileşeni eklenir. Örneğin, statik dosyaların işlenmesini etkinleştirmek için UseStaticFiles çağırın.
Aşağıdaki örnekteki vurgulanan kod, istek işleme işlem hattını yapılandırır:

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MovieDb")));
}

public void Configure(IApplicationBuilder app)


{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc();
}
}

ASP.NET Core, zengin bir yerleşik ara yazılım kümesi içerir ve özel ara yazılım yazabilirsiniz.
Daha fazla bilgi için bkz. ASP.NET Core ara yazılımı.

Ana bilgisayar
ASP.NET Core bir uygulama, başlangıçta bir konak oluşturur. Ana bilgisayar, uygulamanın tüm kaynaklarını
kapsülleyen bir nesnedir, örneğin:
Bir HTTP sunucusu uygulama
Ara yazılım bileşenleri
Günlüğe Kaydetme
IÇERIK
Yapılandırma
Uygulamanın tüm birbirine bağlı kaynaklarını tek bir nesnede dahil etmek için başlıca neden, yaşam süresi
yönetimi: uygulama başlatma ve düzgün kapanma üzerinde denetim.
İki konak mevcuttur: genel ana bilgisayar ve Web ana bilgisayarı. Genel ana bilgisayar önerilir ve Web konağı
yalnızca geriye dönük uyumluluk için kullanılabilir.
Bir konak oluşturma kodu Program.Main :

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>();
});
}

CreateDefaultBuilder ve ConfigureWebHostDefaults yöntemleri, aşağıdaki gibi yaygın olarak kullanılan


seçeneklerle bir konak yapılandırır:
Web sunucusu olarak Kestrel kullanın ve IIS tümleştirmesini etkinleştirin.
AppSettings. JSON, appSettings 'ten yapılandırma yükleyin . { Ortam adı}. JSON, ortam değişkenleri, komut
satırı bağımsız değişkenleri ve diğer yapılandırma kaynakları.
Günlüğe kaydetme çıkışını konsola ve hata ayıklama sağlayıcılarına gönderin.
Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
İki konak mevcuttur: Web Konağı ve genel ana bilgisayar. ASP.NET Core 2. x içinde, genel konak yalnızca Web dışı
senaryolar içindir.
Bir konak oluşturma kodu Program.Main :

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

CreateDefaultBuilder yöntemi, aşağıdaki gibi yaygın olarak kullanılan seçeneklere sahip bir konak yapılandırır:
Web sunucusu olarak Kestrel kullanın ve IIS tümleştirmesini etkinleştirin.
AppSettings. JSON, appSettings 'ten yapılandırma yükleyin . { Ortam adı}. JSON, ortam değişkenleri, komut
satırı bağımsız değişkenleri ve diğer yapılandırma kaynakları.
Günlüğe kaydetme çıkışını konsola ve hata ayıklama sağlayıcılarına gönderin.
Daha fazla bilgi için bkz. ASP.NET Core Web ana bilgisayarı.
Web dışı senaryolar
Genel ana bilgisayar, diğer uygulama türlerinin günlüğe kaydetme, bağımlılık ekleme (dı), yapılandırma ve
uygulama ömür yönetimi gibi çapraz kesme çerçevesi uzantıları kullanmasına izin verir. Daha fazla bilgi için bkz.
.NET genel ana bilgisayar ve ASP.NET Core içinde barındırılan hizmetlerle arka plan görevleri.

Sunucular
Bir ASP.NET Core uygulaması HTTP isteklerini dinlemek için HTTP sunucu uygulamasını kullanır. Sunucu, bir
HttpContext oluşan istek özellikleri kümesi olarak uygulamaya istekleri ister.

Windows
macOS
'Un
ASP.NET Core aşağıdaki sunucu uygulamalarını sağlar:
Kestrel , platformlar arası bir Web sunucusudur. Kestrel, genellikle IISkullanılarak ters bir ara sunucu
yapılandırmasında çalıştırılır. ASP.NET Core 2,0 veya üzeri sürümlerde, Kestrel doğrudan Internet 'e açık olan
bir genel kullanıma yönelik uç sunucu olarak çalıştırılabilir.
IIS HTTP sunucusu , IIS kullanan bir Windows sunucusudur. Bu sunucu ile, ASP.NET Core uygulaması ve IIS
aynı işlemde çalışır.
Http. sys , IIS ile kullanılmayan bir Windows sunucusudur.
Windows
macOS
'Un
ASP.NET Core aşağıdaki sunucu uygulamalarını sağlar:
Kestrel , platformlar arası bir Web sunucusudur. Kestrel, genellikle IISkullanılarak ters bir ara sunucu
yapılandırmasında çalıştırılır. ASP.NET Core 2,0 veya üzeri sürümlerde, Kestrel doğrudan Internet 'e açık olan
bir genel kullanıma yönelik uç sunucu olarak çalıştırılabilir.
Http. sys , IIS ile kullanılmayan bir Windows sunucusudur.
Daha fazla bilgi için bkz. ASP.NET Core Web sunucusu uygulamaları.

Yapılandırma
ASP.NET Core, ayarları sıralı bir yapılandırma sağlayıcıları kümesinden ad-değer çiftleri olarak alan bir
yapılandırma çerçevesi sağlar. . JSON dosyaları, . xml dosyaları, ortam değişkenleri ve komut satırı bağımsız
değişkenleri gibi çeşitli kaynaklar için yerleşik yapılandırma sağlayıcıları vardır. Ayrıca, özel yapılandırma
sağlayıcıları da yazabilirsiniz.
Örneğin, yapılandırmanın appSettings. JSON ve ortam değişkenlerinden geldiğini belirtebilirsiniz. Ardından,
ConnectionString değeri istendiğinde, Framework ilk olarak appSettings. JSON dosyasına bakar. Değer aynı
zamanda bir ortam değişkeninde bulunursa, ortam değişkeninin değeri öncelikli olur.
Parolalar gibi gizli yapılandırma verilerini yönetmek için ASP.NET Core bir gizli dizi Yöneticisi aracısağlar. Üretim
gizli dizileri için Azure Key Vaultönerilir.
Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Seçenekler
Mümkün olduğunda yapılandırma değerlerini depolamak ve almak için Seçenekler deseninin ASP.NET Core.
Seçenekler stili, ilişkili ayarların gruplarını temsil etmek için sınıfları kullanır.
Örneğin, aşağıdaki kod WebSockets seçeneklerini ayarlar:

var options = new WebSocketOptions


{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4096
};
app.UseWebSockets(options);

Daha fazla bilgi için bkz. ASP.NET Core için seçenek kalıbı.


Geliştirme, hazırlıkve üretimgibi yürütme ortamları, ASP.NET Core birinci sınıf kavramlardır.
ASPNETCORE_ENVIRONMENT ortam değişkenini ayarlayarak bir uygulamanın üzerinde çalıştığı ortamı belirtebilirsiniz.
ASP.NET Core, uygulamanın başlangıcında bu ortam değişkenini okur ve değeri bir IHostingEnvironment
uygulamasında depolar. Ortam nesnesi, uygulama tarafından her yerde DI aracılığıyla kullanılabilir.
Startup sınıfından aşağıdaki örnek kod, uygulamayı yalnızca geliştirmede çalıştırıldığında ayrıntılı hata bilgilerini
sunacak şekilde yapılandırır:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc();
}

Daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları kullanma.

Günlüğe Kaydetme
ASP.NET Core, çeşitli yerleşik ve üçüncü taraf günlük sağlayıcılarıyla birlikte çalışarak bir günlüğe kaydetme API
'sini destekler. Kullanılabilir sağlayıcılar şunları içerir:
Konsolu
Hata ayıklama
Windows üzerinde olay Izleme
Windows olay günlüğü
TraceSource
Azure App Service
Azure Application Insights
Dı ve çağrı günlüğü yöntemlerinden ILogger nesne alarak uygulamanın kodundaki her yerden günlükleri yazın.
Oluşturucu Ekleme ve günlük yöntemi çağrılarını vurgulanmış bir ILogger nesnesi kullanan örnek kod aşağıda
verilmiştir.

public class TodoController : ControllerBase


{
private readonly ILogger _logger;

public TodoController(ILogger<TodoController> logger)


{
_logger = logger;
}

[HttpGet("{id}", Name = "GetTodo")]


public ActionResult<TodoItem> GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
// Item lookup code removed.
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return item;
}
}

ILogger arabirimi, günlük sağlayıcısına istediğiniz sayıda alanı geçirmenize olanak sağlar. Alanlar genellikle bir
ileti dizesi oluşturmak için kullanılır, ancak sağlayıcı bunları bir veri deposuna ayrı alanlar olarak da gönderebilir. Bu
özellik, günlük sağlayıcılarının yapılandırılmış günlük olarak da bilinen anlam günlüğüuygulamasına olanak tanır.
Daha fazla bilgi için bkz. .NET Core ve ASP.NET Core oturum açma.

Yönlendirme
Yol , bir işleyiciye EŞLENMIŞ bir URL örüncidir. İşleyici genellikle bir Razor sayfası, MVC denetleyicisindeki bir
eylem yöntemi veya bir ara yazılım olur. ASP.NET Core yönlendirme, uygulamanız tarafından kullanılan URL 'Ler
üzerinde denetim sağlar.
Daha fazla bilgi için bkz. ASP.NET Core yönlendirme.

Hata işleme
ASP.NET Core, hataları işlemeye yönelik yerleşik özellikler içerir, örneğin:
Geliştirici özel durum sayfası
Özel hata sayfaları
Statik durum kodu sayfaları
Başlatma özel durum işleme
Daha fazla bilgi için bkz. ASP.NET Core hataları işleme.

HTTP isteğinde bulunma


IHttpClientFactory bir uygulama HttpClient örnekleri oluşturmak için kullanılabilir. Fabrika:
, Mantıksal HttpClient örneklerinin adlandırılması ve yapılandırılması için merkezi bir konum sağlar. Örneğin,
GitHub istemcisi kayıtlı ve GitHub 'a erişebilecek şekilde yapılandırılabilir. Varsayılan istemci, diğer amaçlar için
kaydedilebilir.
, Bir giden istek ara yazılım işlem hattı oluşturmak için birden çok temsilci seçme işleyicisinin kaydını ve
zincirlemeyi destekler. Bu düzen, ASP.NET Core gelen ara yazılım ardışık düzenine benzer. Bu model, önbelleğe
alma, hata işleme, serileştirme ve günlüğe kaydetme dahil olmak üzere HTTP istekleri etrafında çapraz kesme
sorunlarını yönetmek için bir mekanizma sağlar.
Geçici hata işleme için popüler bir üçüncü taraf kitaplığı olan Pollyile tümleşir.
HttpClient yaşam sürelerini el ile yönetirken gerçekleşen yaygın DNS sorunlarından kaçınmak için temel
HttpClientMessageHandler örneklerinin biriktirmesini ve ömrünü yönetir.
Fabrika tarafından oluşturulan istemcilerle gönderilen tüm istekler için yapılandırılabilir bir günlük deneyimi (
ILogger aracılığıyla) ekler.

Daha fazla bilgi için bkz. ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP istekleri yapın.

İçerik kökü
İçerik kökü, için temel yoldur:
Uygulamayı barındıran yürütülebilir dosya ( . exe).
Uygulamayı oluşturan derlenmiş derlemeler ( . dll).
Uygulama tarafından kullanılan kod olmayan içerik dosyaları, örneğin:
Razor dosyaları ( . cshtml, . Razor)
Yapılandırma dosyaları ( . JSON, . xml)
Veri dosyaları ( . db)
Web kökü, genellikle yayınlanan Wwwroot klasörü.
Geliştirme sırasında:
İçerik kökü, projenin kök dizinini varsayılan olarak belirler.
Projenin kök dizini şunu oluşturmak için kullanılır:
Uygulamanın, projenin kök dizinindeki kod olmayan içerik dosyalarının yolu.
Web kökü, genellikle projenin kök dizinindeki Wwwroot klasörü.
Konak oluşturulurkenalternatif bir içerik kök yolu belirtilebilir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Konak oluşturulurkenalternatif bir içerik kök yolu belirtilebilir. Daha fazla bilgi için bkz. ASP.NET Core Web ana
bilgisayarı.

Web kökü
Web kökü, genel, kod olmayan statik kaynak dosyalarının temel yoludur, örneğin:
Stil sayfaları ( . css)
JavaScript ( . js)
Görüntüler ( . png, . jpg)
Statik dosyalar yalnızca Web kök dizininden (ve alt dizinlerde) varsayılan olarak sunulur.
Web kök yolu varsayılan olarak {Content root}/Wwwrootolarak belirlenir, ancak konak oluşturulurkenfarklı bir
Web kökü belirtilebilir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Web kök yolu varsayılan olarak {Content root}/Wwwrootolarak belirlenir, ancak konak oluşturulurkenfarklı bir
Web kökü belirtilebilir. Daha fazla bilgi için bkz. Web root.
Proje dosyasındaki <içerik > proje öğesi ile Wwwroot 'da dosya yayımlamayı önleyin. Aşağıdaki örnek,
Wwwroot/yerel dizin ve alt dizinlerde içerik yayımlamayı engeller:
<ItemGroup>
<Content Update="wwwroot\local\**\*.*" CopyToPublishDirectory="Never" />
</ItemGroup>

Razor ( . cshtml) dosyalarında, tilde işareti ( ~/ ) Web köküne işaret eder. ~/ başlayan bir yol, sanal yololarak
adlandırılır.
Daha fazla bilgi için bkz. ASP.NET Core statik dosyalar.
ASP.NET Core 'de uygulama başlatma
6.12.2019 • 13 minutes to read • Edit Online

Rick Anderson, Tom Dykstra, Luke Lathamve Steve Smith


Startup sınıfı Hizmetleri ve uygulamanın istek ardışık düzenini yapılandırır.

Başlangıç sınıfı
ASP.NET Core uygulamalar, kuralına göre Startup adlı bir Startup sınıfını kullanır. Startup sınıfı:
İsteğe bağlı olarak, uygulamanın hizmetleriniyapılandırmak için bir ConfigureServices yöntemi içerir.
Hizmet, uygulama işlevselliği sağlayan yeniden kullanılabilir bir bileşendir. Hizmetler ConfigureServices
kaydedilir ve bağımlılık ekleme (dı) veya ApplicationServicesaracılığıyla uygulama genelinde tüketilebilir.
Uygulamanın istek işleme ardışık düzenini oluşturmak için bir Configure yöntemi içerir.
ConfigureServices ve Configure uygulama başlatıldığında ASP.NET Core çalışma zamanı tarafından
çağrılır:

public class Startup


{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
Yukarıdaki örnek Razor Pagesiçindir; MVC sürümü benzerdir.

public class Startup


{
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
...
}

// Use this method to configure the HTTP request pipeline.


public void Configure(IApplicationBuilder app)
{
...
}
}

Startup sınıfı, uygulamanın ana bilgisayarı yapılandırıldığında belirtilir. Startup sınıfı genellikle konak
Oluşturucu 'da Webhostbuilderextensions. UseStartup<tstartup > yöntemi çağırarak belirtilir:

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

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>();
});
}

Ana bilgisayar Startup sınıfı Oluşturucusu tarafından kullanılabilen hizmetleri sağlar. Uygulama
ConfigureServices aracılığıyla ek hizmetler ekler. Hem konak hem de uygulama hizmetleri Configure ve
uygulama genelinde kullanılabilir.
Genel ana bilgisayar (IHostBuilder) kullanılırken Startup oluşturucusuna yalnızca aşağıdaki hizmet türleri
eklenebilir:
IWebHostEnvironment
IHostEnvironment
IConfiguration
public class Startup
{
private readonly IWebHostEnvironment _env;

public Startup(IConfiguration configuration, IWebHostEnvironment env)


{
Configuration = configuration;
_env = env;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
if (_env.IsDevelopment())
{
}
else
{
}
}
}

Configure yöntemi çağrılana kadar çoğu hizmet kullanılamaz.


Ana bilgisayar Startup sınıfı Oluşturucusu tarafından kullanılabilen hizmetleri sağlar. Uygulama
ConfigureServices aracılığıyla ek hizmetler ekler. Hem konak hem de uygulama hizmetleri Configure ve
uygulama genelinde kullanılabilir.
Startup sınıfa bağımlılık ekleme 'nin yaygın bir kullanımı, şu ekleme işlemini kullanmaktır:
Hizmetleri ortama göre yapılandırmak için IHostingEnvironment.
yapılandırmayı okumak için IConfiguration.
Startup.ConfigureServices bir günlükçü oluşturmak için ILoggerFactory.
public class Startup
{
private readonly IHostingEnvironment _env;
private readonly IConfiguration _config;
private readonly ILoggerFactory _loggerFactory;

public Startup(IHostingEnvironment env, IConfiguration config,


ILoggerFactory loggerFactory)
{
_env = env;
_config = config;
_loggerFactory = loggerFactory;
}

public void ConfigureServices(IServiceCollection services)


{
var logger = _loggerFactory.CreateLogger<Startup>();

if (_env.IsDevelopment())
{
// Development service configuration

logger.LogInformation("Development environment");
}
else
{
// Non-development service configuration

logger.LogInformation("Environment: {EnvironmentName}", _env.EnvironmentName);


}

// Configuration is available during startup.


// Examples:
// _config["key"]
// _config["subsection:suboption1"]
}
}

Configure yöntemi çağrılana kadar çoğu hizmet kullanılamaz.


Çoklu başlangıç
Uygulama farklı ortamlarda ayrı Startup sınıfları tanımladığında (örneğin, StartupDevelopment ), çalışma
zamanında uygun Startup sınıfı seçilidir. Geçerli ortamla eşleşen ad sonekine sahip olan sınıf
önceliklendirilir. Uygulama geliştirme ortamında çalıştırıldıysanız ve hem bir Startup sınıfını hem de bir
StartupDevelopment sınıfını içeriyorsa StartupDevelopment sınıfı kullanılır. Daha fazla bilgi için bkz. birden çok
ortam kullanma.
Konak hakkında daha fazla bilgi için konağa bakın. Başlatma sırasında hataları işleme hakkında daha fazla
bilgi için bkz. Başlangıç özel durum işleme.

ConfigureServices yöntemi
ConfigureServices yöntemi:
İsteğe bağlı.
Uygulamanın hizmetlerini yapılandırmak için Configure yönteminden önce ana bilgisayar tarafından
çağırılır.
Yapılandırma seçeneklerinin kurala göre ayarlandığı yer.
Konak Startup Yöntemler çağrılmadan önce bazı hizmetleri yapılandırabilir. Daha fazla bilgi için bkz. ana
bilgisayar.
Önemli kurulum gerektiren özellikler için IServiceCollection Add{Service} uzantı yöntemleri vardır. Örneğin,
DbContext ekleyin , defaultıdentity ekleyin, entityframeworkmağazalarını ekleyin veRazorPages
ekleyin:

public class Startup


{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();

services.AddRazorPages();
}

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

// Add application services.


services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}

Hizmet kapsayıcısına hizmetleri eklemek, uygulama içinde ve Configure yönteminde kullanılabilir hale
getirir. Hizmetler, bağımlılık ekleme veya ApplicationServicesüzerinden çözümlenir.
SetCompatibilityVersion hakkında daha fazla bilgi için bkz. Setcompatibilityversion .

Configure yöntemi
Configure yöntemi, uygulamanın HTTP isteklerine nasıl yanıt verdiğini belirtmek için kullanılır. İstek ardışık
düzeni, bir IApplicationBuilder örneğine Ara yazılım bileşenleri eklenerek yapılandırılır. IApplicationBuilder
Configure yöntemi tarafından kullanılabilir, ancak hizmet kapsayıcısında kayıtlı değildir. Barındırma bir
IApplicationBuilder oluşturur ve doğrudan Configure geçirir.

ASP.NET Core şablonlar işlem hattını desteğiyle birlikte yapılandırır:


Geliştirici özel durum sayfası
Özel durum işleyicisi
HTTP katı taşıma güvenliği (HSTS )
HTTPS yönlendirmesi
Statik dosyalar
ASP.NET Core MVC ve Razor Pages
Genel Veri Koruma Yönetmeliği (GDPR )

public class Startup


{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}

Yukarıdaki örnek Razor Pagesiçindir; MVC sürümü benzerdir.


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc();
}

Her Use uzantısı yöntemi, istek ardışık düzenine bir veya daha fazla ara yazılım bileşeni ekler. Örneğin,
UseStaticFiles, ara yazılımı statik dosyalarısunacak şekilde yapılandırır.
İstek ardışık düzeninde bulunan her bir ara yazılım bileşeni, uygun olduğunda, zincirdeki bir sonraki bileşeni
çağırmaktan veya zincirde kısa bir süre sonra sağlanmasından sorumludur.
IWebHostEnvironment , ILoggerFactory veya ConfigureServices tanımlı herhangi bir şey gibi ek hizmetler
Configure yöntemi imzasında belirtilebilir. Bu hizmetler varsa eklenir.
IHostingEnvironment ve ILoggerFactory gibi ek hizmetler veya ConfigureServices tanımlı herhangi bir şey
Configure yöntemi imzasında belirtilebilir. Bu hizmetler varsa eklenir.
IApplicationBuilder kullanımı ve ara yazılım işleme sırası hakkında daha fazla bilgi için bkz. ASP.NET Core
ara yazılımı.

Hizmetleri başlatmadan yapılandırma


Startup sınıf kullanmadan Hizmetleri ve istek işleme işlem hattını yapılandırmak için, ConfigureServices
çağırın ve konak Oluşturucu üzerinde Configure kullanışlı yöntemler kullanın. ConfigureServices birden
çok çağrısı birbirine eklenir. Birden çok Configure yöntemi varsa, son Configure çağrısı kullanılır.
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.AddControllersWithViews();
})
.Configure(app =>
{
var loggerFactory = app.ApplicationServices
.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

logger.LogInformation("Logged in Configure");

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

var configValue = config["MyConfigKey"];


});
});
});
}
public class Program
{
public static IHostingEnvironment HostingEnvironment { get; set; }
public static IConfiguration Configuration { get; set; }

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
})
.ConfigureServices(services =>
{
...
})
.Configure(app =>
{
var loggerFactory = app.ApplicationServices
.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
var env = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

logger.LogInformation("Logged in Configure");

if (env.IsDevelopment())
{
...
}
else
{
...
}

var configValue = config["subsection:suboption1"];

...
});
}

Başlangıç filtreleriyle başlatmayı Genişlet


IStartupFilterkullanın:
Ara yazılımı, bir uygulamanın başlangıcında veya sonunda Use{Middleware} açık bir çağrı olmadan Ara
yazılım ardışık düzeni yapılandırma. IStartupFilter , ASP.NET Core tarafından, uygulama yazarının
varsayılan ara yazılımı açıkça kaydetmesini sağlamak zorunda kalmadan, işlem hattının başlangıcına
varsayılanlar eklemek için kullanılır. IStartupFilter , uygulama yazarı adına farklı bir bileşen çağrısının
Use{Middleware} izin verir.
Configure yöntemlerinin bir işlem hattı oluşturmak için. Itartupfilter. configure , bir ara yazılımı
kitaplıklar tarafından eklenen bir veya daha sonra çalışacak şekilde ayarlayabilir.
IStartupFilter , Action<IApplicationBuilder> alan ve döndüren Configureuygular. IApplicationBuilder, bir
uygulamanın istek işlem hattını yapılandırmak için bir sınıfı tanımlar. Daha fazla bilgi için bkz.
IApplicationBuilder ile bir ara yazılım işlem hattı oluşturma.
Her IStartupFilter , istek ardışık düzeninde bir veya daha fazla middlewares ekleyebilir. Filtreler, hizmet
kapsayıcısına eklendikleri sırada çağrılır. Filtreler bir sonraki filtreye denetimi geçirmeden önce veya sonra
bir ara yazılım ekleyebilir, böylece uygulama işlem hattının başına veya sonuna eklenir.
Aşağıdaki örnek, IStartupFilter bir ara yazılımı nasıl kaydedeceğinizi gösterir. RequestSetOptionsMiddleware
ara yazılım bir sorgu dizesi parametresinden bir seçenek değeri ayarlar:

public class RequestSetOptionsMiddleware


{
private readonly RequestDelegate _next;

public RequestSetOptionsMiddleware( RequestDelegate next )


{
_next = next;
}

// Test with https://localhost:5001/Privacy/?option=Hello


public async Task Invoke(HttpContext httpContext)
{
var option = httpContext.Request.Query["option"];

if (!string.IsNullOrWhiteSpace(option))
{
httpContext.Items["option"] = WebUtility.HtmlEncode(option);
}

await _next(httpContext);
}
}

RequestSetOptionsMiddleware RequestSetOptionsStartupFilter sınıfında yapılandırılır:

public class RequestSetOptionsStartupFilter : IStartupFilter


{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.UseMiddleware<RequestSetOptionsMiddleware>();
next(builder);
};
}
}
public class RequestSetOptionsMiddleware
{
private readonly RequestDelegate _next;
private IOptions<AppOptions> _injectedOptions;

public RequestSetOptionsMiddleware(
RequestDelegate next, IOptions<AppOptions> injectedOptions)
{
_next = next;
_injectedOptions = injectedOptions;
}

public async Task Invoke(HttpContext httpContext)


{
Console.WriteLine("RequestSetOptionsMiddleware.Invoke");

var option = httpContext.Request.Query["option"];

if (!string.IsNullOrWhiteSpace(option))
{
_injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
}

await _next(httpContext);
}
}

RequestSetOptionsMiddleware RequestSetOptionsStartupFilter sınıfında yapılandırılır:

public class RequestSetOptionsStartupFilter : IStartupFilter


{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.UseMiddleware<RequestSetOptionsMiddleware>();
next(builder);
};
}
}

IStartupFilter , ConfigureServiceshizmet kapsayıcısına kaydedilir.


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.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddTransient<IStartupFilter,
RequestSetOptionsStartupFilter>();
});
}

WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddTransient<IStartupFilter,
RequestSetOptionsStartupFilter>();
})
.UseStartup<Startup>()
.Build();

option için bir sorgu dizesi parametresi sağlandığında, ASP.NET Core ara yazılımı yanıtı oluşturmadan
önce, ara yazılım değer atamasını işler.
Ara yazılım yürütme sırası IStartupFilter kayıt sırasıyla ayarlanır:
Birden çok IStartupFilter uygulaması aynı nesnelerle etkileşime geçebilir. Sıralama önemliyse,
kendi IStartupFilter hizmet kayıtlarını, middlewares çalıştırmaları sırasıyla eşleşecek şekilde
sıralayın.
Kitaplıklar, IStartupFilter kayıtlı olan diğer uygulama ara yazılımı ile önce veya sonra çalışan bir
veya daha fazla IStartupFilter uygulaması olan ara yazılım ekleyebilir. Bir IStartupFilter ara
yazılım bir kitaplık IStartupFilter tarafından eklenmeden önce çağırmak için:
Kitaplık hizmet kapsayıcısına eklenmeden önce hizmet kaydını konumlandırın.
Daha sonra çağırmak için, kitaplık eklendikten sonra hizmet kaydını konumlandırın.

Başlangıçta bir dış derlemeden yapılandırma Ekle


IHostingStartup bir uygulama, uygulamanın Startup sınıfının dışında bir dış derlemeden başlangıçta bir
uygulamaya iyileştirmeler eklenmesine izin verir. Daha fazla bilgi için bkz. ASP.NET Core barındırma
başlangıç derlemeleri kullanma.

Ek kaynaklar
Ana bilgisayar
ASP.NET Core çoklu ortamları kullanma
ASP.NET Core ara yazılımı
.NET Core ve ASP.NET Core oturum açma
ASP.NET Core yapılandırma
ASP.NET Core bağımlılık
ekleme
24.11.2019 • 29 minutes to read • Edit Online

Steve Smith, Scott Adeve Luke Latham tarafından


ASP.NET Core, sınıflar ve bunların bağımlılıkları arasında
denetimin INVERSION (IoC ) elde etmek için bir teknik olan
bağımlılık ekleme (dı) yazılım tasarım modelini destekler.
MVC denetleyicileri içindeki bağımlılık eklenmesine özgü daha
fazla bilgi için bkz. ASP.NET core'da denetleyicilere bağımlılık
ekleme.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Bağımlılık eklenmesine genel bakış


Bağımlılık , başka bir nesnenin gerektirdiği herhangi bir
nesnedir. Aşağıdaki MyDependency sınıfını bir uygulamadaki
diğer sınıfların bağlı olduğu bir WriteMessage yöntemiyle
inceleyin:

public class MyDependency


{
public MyDependency()
{
}

public Task WriteMessage(string message)


{
Console.WriteLine(
$"MyDependency.WriteMessage called. Message:
{message}");

return Task.FromResult(0);
}
}

WriteMessage yöntemini bir sınıf için kullanılabilir hale


getirmek için MyDependency sınıfının bir örneği oluşturulabilir.
MyDependency sınıfı, IndexModel sınıfının bir bağımlılığı olur:

public class IndexModel : PageModel


{
MyDependency _dependency = new MyDependency();

public async Task OnGetAsync()


{
await _dependency.WriteMessage(
"IndexModel.OnGetAsync created this message.");
}
}
Sınıf oluşturur ve doğrudan MyDependency örneğine bağlıdır.
Kod bağımlılıkları (önceki örnekte olduğu gibi) sorunlu olur ve
aşağıdaki nedenlerden dolayı kaçınılması gerekir:
MyDependency farklı bir uygulamayla değiştirmek için, sınıfın
değiştirilmesi gerekir.
MyDependency bağımlılıklar içeriyorsa, sınıfı tarafından
yapılandırılması gerekir. MyDependency bağlı olarak, birden
çok sınıfa sahip büyük bir projede yapılandırma kodu
uygulama genelinde dağılmış hale gelir.
Bu uygulamanın birim testi zordur. Uygulama, bu yaklaşımla
mümkün olmayan bir sahte veya saplama MyDependency
sınıfı kullanmalıdır.
Bağımlılık ekleme bu sorunları şu şekilde giderir:
Bağımlılık uygulamasını soyutlamak için bir arabirim veya
temel sınıf kullanımı.
Bir hizmet kapsayıcısına bağımlılığın kaydı. ASP.NET Core
yerleşik bir hizmet kapsayıcısı sağlar IServiceProvider.
Hizmetler, uygulamanın Startup.ConfigureServices
yöntemine kaydedilir.
Hizmetin kullanıldığı sınıf oluşturucusuna ekleme . Çerçeve,
bağımlılığın bir örneğini oluşturma ve artık gerekli
olmadığında bu uygulamayı atma sorumluluğunu alır.
Örnek uygulamada, IMyDependency arabirimi hizmetin
uygulamaya sağladığı bir yöntemi tanımlar:

public interface IMyDependency


{
Task WriteMessage(string message);
}

public interface IMyDependency


{
Task WriteMessage(string message);
}

Bu arabirim somut bir tür tarafından uygulanır, MyDependency :


public class MyDependency : IMyDependency
{
private readonly ILogger<MyDependency> _logger;

public MyDependency(ILogger<MyDependency> logger)


{
_logger = logger;
}

public Task WriteMessage(string message)


{
_logger.LogInformation(
"MyDependency.WriteMessage called. Message:
{MESSAGE}",
message);

return Task.FromResult(0);
}
}

public class MyDependency : IMyDependency


{
private readonly ILogger<MyDependency> _logger;

public MyDependency(ILogger<MyDependency> logger)


{
_logger = logger;
}

public Task WriteMessage(string message)


{
_logger.LogInformation(
"MyDependency.WriteMessage called. Message:
{Message}",
message);

return Task.FromResult(0);
}
}

MyDependency kurucusunda bir ILogger<TCategoryName>


ister. Bağımlılık ekleme işlemini zincirleme bir biçimde
kullanmak olağan dışı değildir. Her istenen bağımlılık, kendi
bağımlılıklarını ister. Kapsayıcı grafikteki bağımlılıkları çözer ve
tamamen çözümlenen hizmeti döndürür. Çözümlenmesi
gereken, genellikle bağımlılık ağacı, bağımlılık grafiğiveya
nesne grafiğiolarak adlandırılan toplu bağımlılıklar kümesi.
IMyDependency ve ILogger<TCategoryName> , hizmet
kapsayıcısında kayıtlı olmalıdır. IMyDependency
Startup.ConfigureServices kaydedilir. ILogger<TCategoryName> ,
günlük soyut öğeler altyapısı tarafından kaydedilir. bu nedenle,
Framework tarafından varsayılan olarak kaydedilen Framework
tarafından sağlanmış bir hizmettir .
Kapsayıcı, (genel) açık türlerdenyararlanarak
ILogger<TCategoryName> çözer, her (genel) oluşturulan
türükaydetme ihtiyacını ortadan kaldırır:
services.AddSingleton(typeof(ILogger<T>),
typeof(Logger<T>));

Örnek uygulamada IMyDependency hizmeti somut tür


MyDependency kaydedilir. Kayıt, hizmet ömrünü tek bir isteğin
kullanım ömrüne göre kapsamlar. Hizmet yaşam süreleri bu
konunun ilerleyen kısımlarında açıklanmıştır.

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddScoped<IMyDependency, MyDependency>();
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new
Operation(Guid.Empty));

// OperationService depends on each of the other


Operation types.
services.AddTransient<OperationService,
OperationService>();
}

public void ConfigureServices(IServiceCollection services)


{

services.AddMvc().SetCompatibilityVersion(CompatibilityVersi
on.Version_2_2);

services.AddScoped<IMyDependency, MyDependency>();
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new
Operation(Guid.Empty));

// OperationService depends on each of the other


Operation types.
services.AddTransient<OperationService,
OperationService>();
}

NOTE
Her services.Add{SERVICE_NAME} uzantısı yöntemi Hizmetleri
ekler (ve potansiyel olarak yapılandırır). Örneğin
services.AddMvc() , Razor Pages ve MVC 'nin gerektirdiği
Hizmetleri ekler. Uygulamaların bu kuralı izlemesini öneririz. Hizmet
kaydı gruplarını kapsüllemek için uzantı yöntemlerini Microsoft.
Extensions. Dependencyınjection ad alanına yerleştirin.

Hizmetin Oluşturucusu string gibi yerleşik bir


türgerektiriyorsa, tür yapılandırma veya Seçenekler
düzeniyleeklenebilir:
public class MyDependency : IMyDependency
{
public MyDependency(IConfiguration config)
{
var myStringValue = config["MyStringKey"];

// Use myStringValue
}

...
}

Hizmetin bir örneği, hizmetin kullanıldığı ve özel bir alana


atandığı bir sınıfın Oluşturucusu aracılığıyla istenir. Alanı,
sınıfına gereken şekilde hizmete erişmek için kullanılır.
Örnek uygulamada, IMyDependency örneği istenir ve hizmetin
WriteMessage yöntemini çağırmak için kullanılır:

public class IndexModel : PageModel


{
private readonly IMyDependency _myDependency;

public IndexModel(
IMyDependency myDependency,
OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance
singletonInstanceOperation)
{
_myDependency = myDependency;
OperationService = operationService;
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation =
singletonInstanceOperation;
}

public OperationService OperationService { get; }


public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }

public async Task OnGetAsync()


{
await _myDependency.WriteMessage(
"IndexModel.OnGetAsync created this message.");
}
}
public class IndexModel : PageModel
{
private readonly IMyDependency _myDependency;

public IndexModel(
IMyDependency myDependency,
OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance
singletonInstanceOperation)
{
_myDependency = myDependency;
OperationService = operationService;
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation =
singletonInstanceOperation;
}

public OperationService OperationService { get; }


public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }

public async Task OnGetAsync()


{
await _myDependency.WriteMessage(
"IndexModel.OnGetAsync created this message.");
}
}

Başlangıca eklenen hizmetler


Genel ana bilgisayar (IHostBuilder) kullanılırken Startup
oluşturucusuna yalnızca aşağıdaki hizmet türleri eklenebilir:
IWebHostEnvironment
IHostEnvironment
IConfiguration
Hizmetler Startup.Configure eklenebilir:

public void Configure(IApplicationBuilder app,


IOptions<MyOptions> options)
{
...
}

Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama


başlatma.

Framework tarafından sunulan hizmetler


Startup.ConfigureServices yöntemi, uygulamanın kullandığı
hizmetlerin (Entity Framework Core ve ASP.NET Core MVC
gibi platform özellikleri de dahil) tanımlanmasından
sorumludur. Başlangıçta, ConfigureServices için belirtilen
IServiceCollection konağın nasıl yapılandırıldığınabağlı olarak
Framework tarafından tanımlanan hizmetlere sahiptir. Çerçeve
tarafından kaydedilmiş yüzlerce hizmete sahip olmak ASP.NET
Core şablona dayalı bir uygulama için sık görülen bir
durumdur. Aşağıdaki tabloda çerçeve kayıtlı hizmetlerden
oluşan küçük bir örnek listelenmiştir.

HIZMET TÜRÜ ÖMÜR

Microsoft.AspNetCore.Hosting.B Geçici
uilder.IApplicationBuilderFactory

IHostApplicationLifetime Adet

IWebHostEnvironment Adet

Microsoft.AspNetCore.Hosting.IS Adet
tartup

Microsoft.AspNetCore.Hosting.IS Geçici
tartupFilter

Microsoft.AspNetCore.Hosting.Se Adet
rver.IServer

Microsoft.AspNetCore.Http.IHttp Geçici
ContextFactory

Microsoft.Extensions.Logging.ILo Adet
gger<TCategoryName>

Microsoft.Extensions.Logging.ILo Adet
ggerFactory

Microsoft.Extensions.ObjectPool. Adet
ObjectPoolProvider

Microsoft.Extensions.Options.ICo Geçici
nfigureOptions<TOptions>

Microsoft.Extensions.Options.IOp Adet
tions<TOptions>

System.Diagnostics.DiagnosticSo Adet
urce

System.Diagnostics.DiagnosticLis Adet
tener
HIZMET TÜRÜ ÖMÜR

Microsoft.AspNetCore.Hosting.B Geçici
uilder.IApplicationBuilderFactory

Microsoft.AspNetCore.Hosting.IA Adet
pplicationLifetime

Microsoft.AspNetCore.Hosting.IH Adet
ostingEnvironment

Microsoft.AspNetCore.Hosting.IS Adet
tartup

Microsoft.AspNetCore.Hosting.IS Geçici
tartupFilter

Microsoft.AspNetCore.Hosting.Se Adet
rver.IServer

Microsoft.AspNetCore.Http.IHttp Geçici
ContextFactory

Microsoft.Extensions.Logging.ILo Adet
gger<TCategoryName>

Microsoft.Extensions.Logging.ILo Adet
ggerFactory

Microsoft.Extensions.ObjectPool. Adet
ObjectPoolProvider

Microsoft.Extensions.Options.ICo Geçici
nfigureOptions<TOptions>

Microsoft.Extensions.Options.IOp Adet
tions<TOptions>

System.Diagnostics.DiagnosticSo Adet
urce

System.Diagnostics.DiagnosticLis Adet
tener

Uzantı yöntemleriyle ek hizmetleri


kaydetme
Bir hizmet koleksiyonu genişletme yöntemi (ve gerekirse
bağımlı hizmetleri) kaydetmek için kullanılabilir olduğunda, bu
hizmet için gereken tüm hizmetleri kaydetmek üzere tek bir
Add{SERVICE_NAME} uzantısı yöntemi kullanmaktır. Aşağıdaki
kod, Adddbcontext<tcontext > ve AddIdentityCoreuzantı
yöntemlerini kullanarak kapsayıcıya ek hizmetler eklemenin bir
örneğidir.
public void ConfigureServices(IServiceCollection services)
{
...

services.AddDbContext<ApplicationDbContext>(options =>

options.UseSqlServer(Configuration.GetConnectionString("Defa
ultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

...
}

Daha fazla bilgi için API belgelerindeki ServiceCollection


sınıfına bakın.

Hizmet yaşam süreleri


Kayıtlı her hizmet için uygun bir yaşam süresi seçin. ASP.NET
Core hizmetler aşağıdaki yaşam süreleri ile yapılandırılabilir:
Geçici
Geçici ömür Hizmetleri (AddTransient), hizmet kapsayıcısından
her istenilişinde oluşturulur. Bu ömür, hafif ve durumsuz
hizmetler için en iyi şekilde kullanılır.
Yayıl
Kapsamlı ömür Hizmetleri (AddScoped), istemci isteği başına
bir kez oluşturulur (bağlantı).

WARNING
Bir ara yazılım içinde kapsamlı bir hizmet kullanırken, hizmeti
Invoke veya InvokeAsync yöntemine ekleyin. Oluşturucu
ekleme yoluyla ekleme, hizmeti tek bir gibi davranmaya zoryor.
Daha fazla bilgi için bkz. Özel ASP.NET Core ara yazılımı yaz.

Adet
Tek yaşam süresi Hizmetleri (AddSingleton), ilk istendiğinde
oluşturulur (veya Startup.ConfigureServices çalıştırıldığında ve
hizmet kaydıyla bir örnek belirtildiğinde). Her sonraki istek aynı
örneği kullanır. Uygulama tek davranış gerektiriyorsa, hizmet
kapsayıcısının hizmetin ömrünü yönetmesine izin verilmesi
önerilir. Tekil tasarım modelini uygulamayın ve nesnenin
sınıfındaki ömrünü yönetmek için Kullanıcı kodu sağlayın.

WARNING
Kapsamlı bir hizmetin tek bir bilgisayardan çözümlenmesi
tehlikelidir. Bu, sonraki istekleri işlerken hizmetin yanlış duruma
gelmesine neden olabilir.
Hizmet kayıt yöntemleri
Hizmet kayıt uzantısı yöntemleri, belirli senaryolarda yararlı
olan aşırı yüklemeler sunar.

OTOMATIK BIRDEN ÇOK GEÇIŞ


OBJECT UYGULAMALA BAĞIMSIZ
YÖNTEM ELDEN R DEĞIŞKENLERI

Add{LIFETIME} Evet Evet Hayır


<{SERVICE},
{IMPLEMENTATION}>
()
Örnek:
services.AddSingleton<IMyDep,
MyDep>();

Add{LIFETIME} Evet Evet Evet


<{SERVICE}>(sp =>
new
{IMPLEMENTATION})
Örnekler:
services.AddSingleton<IMyDep>
(sp => new MyDep());
services.AddSingleton<IMyDep>
(sp => new MyDep("A
string!"));

Add{LIFETIME} Evet Hayır Hayır


<{IMPLEMENTATION}>
()
Örnek:
services.AddSingleton<MyDep>
();

Hayır
AddSingleton<{SERVICE}> Evet Evet
(new {IMPLEMENTATION})
Örnekler:
services.AddSingleton<IMyDep>
(new MyDep());
services.AddSingleton<IMyDep>
(new MyDep("A string!"));

AddSingleton(newHayır Hayır Evet


{IMPLEMENTATION})
Örnekler:
services.AddSingleton(new
MyDep());
services.AddSingleton(new
MyDep("A string!"));

Tür çıkarma hakkında daha fazla bilgi için Hizmetler 'In aktiften
çıkarılması bölümüne bakın. Birden çok uygulama için yaygın
bir senaryo, test için bir sahte işlem türüdür.
TryAdd{LIFETIME} Yöntemler, zaten kayıtlı bir uygulama yoksa
hizmeti kaydeder.
Aşağıdaki örnekte, ilk satır IMyDependency için MyDependency
kaydettirir. IMyDependency zaten kayıtlı bir uygulamaya sahip
olduğundan ikinci satır etkisizdir:
services.AddSingleton<IMyDependency, MyDependency>();
// The following line has no effect:
services.TryAddSingleton<IMyDependency, DifferentDependency>
();

Daha fazla bilgi için bkz.


TryAdd
TryAddTransient
TryAddScoped
TryAddSingleton
TryAddEnumerable (ServiceDescriptor) yöntemleri yalnızca
aynı türdebir uygulama yoksa hizmeti kaydeder. Birden çok
hizmet IEnumerable<{SERVICE}> ile çözümlenir. Hizmetleri
kaydederken, geliştirici yalnızca aynı türden biri zaten
eklenmediyse bir örnek eklemek istemektedir. Genellikle, bu
yöntem, kapsayıcıda bir örneğin iki kopyasını kaydetmemek
için kitaplık yazarları tarafından kullanılır.
Aşağıdaki örnekte, ilk satır IMyDep1 için MyDep kaydettirir. İkinci
satır, IMyDep2 için MyDep kaydeder. IMyDep1 MyDep kayıtlı bir
uygulamasına zaten sahip olduğundan, üçüncü satırın etkisi
yoktur:

public interface IMyDep1 {}


public interface IMyDep2 {}

public class MyDep : IMyDep1, IMyDep2 {}

services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDep
1, MyDep>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDep
2, MyDep>());
// Two registrations of MyDep for IMyDep1 is avoided by the
following line:
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDep
1, MyDep>());

Oluşturucu Ekleme davranışı


Hizmetler, iki mekanizma tarafından çözülebilir:
IServiceProvider
ActivatorUtilities –, bağımlılık ekleme kapsayıcısına hizmet
kaydı olmadan nesne oluşturulmasına Izin verir.
ActivatorUtilities etiket yardımcıları, MVC denetleyicileri
ve model ciltler gibi kullanıcı tarafından ilgili soyutlamalar
ile kullanılır.
Oluşturucular bağımlılık ekleme tarafından sağlanmayan
bağımsız değişkenleri kabul edebilir, ancak bağımsız
değişkenlerin varsayılan değerleri ataması gerekir.
Hizmetler IServiceProvider veya ActivatorUtilities
tarafından çözümlendiğinde, Oluşturucu Ekleme ortak bir
Oluşturucu gerektirir.
Hizmetler ActivatorUtilities tarafından çözümlendiğinde,
Oluşturucu ekleme yalnızca bir adet geçerli oluşturucunun var
olmasını gerektirir. Oluşturucu aşırı yüklemeleri desteklenir,
ancak bağımsız değişkenleri bağımlılık ekleme tarafından
yerine yalnızca bir aşırı yükleme bulunabilir.

Entity Framework bağlamları


Entity Framework bağlamlar genellikle, Web uygulaması
veritabanı işlemleri normalde istemci isteği kapsamında
olduğundan kapsamlı ömür kullanılarak hizmet kapsayıcısına
eklenir. Veritabanı bağlamı kaydedilirken bir
Adddbcontext<tcontext > aşırı yüklemesi tarafından bir yaşam
süresi belirtilmemişse varsayılan yaşam süresi kapsamındadır.
Belirli bir yaşam süresinin Hizmetleri, hizmetten daha kısa bir
yaşam süresine sahip bir veritabanı bağlamı kullanmamalıdır.

Ömür ve kayıt seçenekleri


Ömür ve kayıt seçenekleri arasındaki farkı göstermek için,
görevleri benzersiz bir tanımlayıcıya sahip bir işlem olarak
temsil eden aşağıdaki arayüzleri göz önünde bulundurun
OperationId . Bir işlem hizmetinin yaşam süresinin aşağıdaki
arabirimler için nasıl yapılandırıldığına bağlı olarak kapsayıcı,
bir sınıf tarafından istendiğinde aynı ya da farklı bir hizmet
örneği sağlar:

public interface IOperation


{
Guid OperationId { get; }
}

public interface IOperationTransient : IOperation


{
}

public interface IOperationScoped : IOperation


{
}

public interface IOperationSingleton : IOperation


{
}

public interface IOperationSingletonInstance : IOperation


{
}
public interface IOperation
{
Guid OperationId { get; }
}

public interface IOperationTransient : IOperation


{
}

public interface IOperationScoped : IOperation


{
}

public interface IOperationSingleton : IOperation


{
}

public interface IOperationSingletonInstance : IOperation


{
}

Arabirimler Operation sınıfında uygulanır. Operation


Oluşturucusu bir GUID sağlanmamışsa bir GUID oluşturur:

public class Operation : IOperationTransient,


IOperationScoped,
IOperationSingleton,
IOperationSingletonInstance
{
public Operation() : this(Guid.NewGuid())
{
}

public Operation(Guid id)


{
OperationId = id;
}

public Guid OperationId { get; private set; }


}

public class Operation : IOperationTransient,


IOperationScoped,
IOperationSingleton,
IOperationSingletonInstance
{
public Operation() : this(Guid.NewGuid())
{
}

public Operation(Guid id)


{
OperationId = id;
}

public Guid OperationId { get; private set; }


}

Diğer türlerinin her birine bağlı olan bir


Operation
OperationService kaydedilir. Bağımlılık ekleme yoluyla
OperationService istendiğinde, her bir hizmetin yeni bir
örneğini ya da bağımlı hizmetin kullanım ömrü temelinde
mevcut bir örneği alır.
Kapsayıcıda istendiğinde geçici hizmetler oluşturulduğunda,
IOperationTransient hizmetinin OperationId
OperationService``OperationId farklıdır. OperationService ,
IOperationTransient sınıfının yeni bir örneğini alır. Yeni
örnek farklı bir OperationId verir.
İstemci isteği başına kapsamlı hizmetler oluşturulduğunda,
IOperationScoped hizmetinin OperationId istemci isteği
içindeki OperationService ile aynıdır. İstemci istekleri
arasında her iki hizmet de farklı bir OperationId değeri
paylaşır.
Tek ve tek örnekli hizmetler bir kez oluşturulduğunda ve
tüm istemci isteklerinde ve tüm hizmetlerde kullanıldığında,
OperationId tüm hizmet istekleri arasında sabittir.

public class OperationService


{
public OperationService(
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}

public IOperationTransient TransientOperation { get; }


public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }
}

public class OperationService


{
public OperationService(
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}

public IOperationTransient TransientOperation { get; }


public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }
}

Startup.ConfigureServices , her tür kapsayıcıya, adlandırılmış


ömrüne göre eklenir:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddScoped<IMyDependency, MyDependency>();
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new
Operation(Guid.Empty));

// OperationService depends on each of the other


Operation types.
services.AddTransient<OperationService,
OperationService>();
}

public void ConfigureServices(IServiceCollection services)


{

services.AddMvc().SetCompatibilityVersion(CompatibilityVersi
on.Version_2_2);

services.AddScoped<IMyDependency, MyDependency>();
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new
Operation(Guid.Empty));

// OperationService depends on each of the other


Operation types.
services.AddTransient<OperationService,
OperationService>();
}

IOperationSingletonInstance hizmeti, bilinen bir Guid.Empty


KIMLIĞIYLE belirli bir örnek kullanıyor. Bu tür kullanımda
olduğunda (GUID 'sinin tümü sıfırlardan tamamen) Bu bir şey
vardır.
Örnek uygulama, bireysel istekler içindeki ve içindeki nesne
yaşam sürelerini gösterir. Örnek uygulamanın IndexModel her
tür IOperation türü ve OperationService ister. Daha sonra
sayfa, tüm sayfa modeli sınıfının ve hizmetin OperationId
değerlerini özellik atamaları aracılığıyla görüntüler:
public class IndexModel : PageModel
{
private readonly IMyDependency _myDependency;

public IndexModel(
IMyDependency myDependency,
OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance
singletonInstanceOperation)
{
_myDependency = myDependency;
OperationService = operationService;
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation =
singletonInstanceOperation;
}

public OperationService OperationService { get; }


public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }

public async Task OnGetAsync()


{
await _myDependency.WriteMessage(
"IndexModel.OnGetAsync created this message.");
}
}
public class IndexModel : PageModel
{
private readonly IMyDependency _myDependency;

public IndexModel(
IMyDependency myDependency,
OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance
singletonInstanceOperation)
{
_myDependency = myDependency;
OperationService = operationService;
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation =
singletonInstanceOperation;
}

public OperationService OperationService { get; }


public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance
SingletonInstanceOperation { get; }

public async Task OnGetAsync()


{
await _myDependency.WriteMessage(
"IndexModel.OnGetAsync created this message.");
}
}

Aşağıdaki iki çıktıda iki isteğin sonuçları gösterilmektedir:


İlk istek:
Denetleyici işlemleri:
Geçici: d233e165-f417-469B -a866-1cf1935d2518
Kapsam: 5d997e2d-55f5-4a64-8388-51c4e3a1ad19
Tek: 01271bc1-9e31-48e7-8f7c-7261b040ded9
Örnek: 00000000-0000-0000-0000-000000000000
OperationService işlemler:
Geçici: c6b049eb-1318-4E31-90f1-eb2dd849ff64
Kapsam: 5d997e2d-55f5-4a64-8388-51c4e3a1ad19
Tek: 01271bc1-9e31-48e7-8f7c-7261b040ded9
Örnek: 00000000-0000-0000-0000-000000000000
İkinci istek:
Denetleyici işlemleri:
Geçici: b63bd538-0a37-4FF1-90ba-081c5138dda0
Kapsam: 31e820c5-4834-4d22-83fc-a60118acb9f4
Tek: 01271bc1-9e31-48e7-8f7c-7261b040ded9
Örnek: 00000000-0000-0000-0000-000000000000
OperationService işlemler:
Geçici: c4cbacb8-36a2-436d-81c8-8c1b78808aaf
Kapsam: 31e820c5-4834-4d22-83fc-a60118acb9f4
Tek: 01271bc1-9e31-48e7-8f7c-7261b040ded9
Örnek: 00000000-0000-0000-0000-000000000000
OperationId değerlerinden hangisinin bir istek içinde ve
istekler arasında değiştiğini gözlemleyin:
Geçici nesneler her zaman farklıdır. Hem birinci hem de
ikinci istemci isteklerinin geçici OperationId değeri hem
OperationService işlemleri hem de istemci istekleri için
farklıdır. Her hizmet isteğine ve istemci isteğine yeni bir
örnek sağlanır.
Kapsamlı nesneler istemci isteği içinde aynıdır ancak istemci
istekleri arasında farklıdır.
Tek nesneler her nesne için aynıdır ve
Startup.ConfigureServices bir Operation örneğinin
sağlanmadığına bakılmaksızın her istek vardır.

Ana bilgisayardan Hizmetleri çağır


Uygulamanın kapsamındaki bir kapsamlı hizmeti çözümlemek
için ıvicescopefactory. CreateScope ile bir IServiceScope
oluşturun. Bu yaklaşım, başlatma görevlerini çalıştırmak üzere
başlangıçta kapsamlı bir hizmete erişmek için yararlıdır.
Aşağıdaki örnek, Program.Main``MyScopedService için nasıl
bağlam alınacağını gösterir:
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

public class Program


{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

using (var serviceScope =


host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;

try
{
var serviceContext =
services.GetRequiredService<MyScopedService>();
// Use the context here
}
catch (Exception ex)
{
var logger =
services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred.");
}
}

await host.RunAsync();
}

public static IHostBuilder CreateHostBuilder(string[]


args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public class Program


{
public static async Task Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var serviceScope =


host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;

try
{
var serviceContext =
services.GetRequiredService<MyScopedService>();
// Use the context here
}
catch (Exception ex)
{
var logger =
services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred.");
}
}

await host.RunAsync();
}

public static IWebHostBuilder


CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

Kapsam doğrulaması
Uygulama geliştirme ortamında çalışırken, varsayılan hizmet
sağlayıcısı şunları doğrulamak için denetimler gerçekleştirir:
Kapsamlı hizmetler doğrudan veya dolaylı olarak kök hizmet
sağlayıcısından çözümlenmez.
Kapsamlı hizmetler doğrudan veya dolaylı olarak Singleton
'a eklenmiş değildir.
BuildServiceProvider çağrıldığında kök hizmet sağlayıcısı
oluşturulur. Kök hizmet sağlayıcısının ömrü, sağlayıcının
uygulamayla başladığı ve uygulama kapandığında bırakıldığı
uygulama/sunucunun yaşam süresine karşılık gelir.
Kapsamlı hizmetler kendilerini oluşturan kapsayıcı tarafından
atılmış. Kök kapsayıcıda kapsamlı bir hizmet oluşturulduysa,
hizmetin ömrü etkin şekilde tek başına yükseltilir çünkü
yalnızca uygulama/sunucu kapatıldığında kök kapsayıcı
tarafından atılmış olur. Hizmet kapsamlarını doğrulamak
BuildServiceProvider çağrıldığında bu durumları yakalar.
Daha fazla bilgi için bkz. ASP.NET Core Web ana bilgisayarı.

İstek Hizmetleri
HttpContext bir ASP.NET Core isteği içinde kullanılabilen
hizmetler, HttpContext. RequestServices koleksiyonu
aracılığıyla sunulur.
İstek Hizmetleri, uygulamanın bir parçası olarak yapılandırılan
ve istenen hizmetleri temsil eder. Nesneler bağımlılıklar
belirttiğinizde, bunlar ApplicationServices değil
RequestServices bulunan türler tarafından karşılanır.

Genellikle, uygulamanın bu özellikleri doğrudan


kullanmamalıdır. Bunun yerine, sınıfların Sınıf oluşturucuları
aracılığıyla gerektirdiği türleri isteyin ve çerçevenin
bağımlılıkları eklemesine izin verin. Bu, test etmek daha kolay
olan sınıfları oluşturur.

NOTE
RequestServices koleksiyonuna erişmek için Oluşturucu
parametreleri olarak bağımlılıklar istemeyi tercih edin.

Bağımlılık ekleme için tasarım hizmetleri


En iyi uygulamalar şunlardır:
Bağımlılıklarını almak için bağımlılık ekleme 'yi kullanmak
üzere Hizmetleri tasarlayın.
Durum bilgisi olan statik sınıflar ve Üyeler kullanmaktan
kaçının. Genel durum oluşturulmasını önlemek yerine, tek
tek Hizmetleri kullanmak için uygulamaları tasarlayın.
Hizmetler içindeki bağımlı sınıfların doğrudan
örneklenmesini önleyin. Doğrudan örnekleme kodu belirli
bir uygulamaya bağar.
Uygulama sınıflarını küçük, iyi bir şekilde ve kolayca test
edin.
Bir sınıfta çok fazla sayıda bağımlılık varsa, bu genellikle sınıfta
çok fazla sorumluluk olduğu ve tek sorumluluk ilkesini
(SRP )ihlal eden bir imzadır. Bazı sorumlulukları yeni bir sınıfa
taşıyarak sınıfı yeniden düzenleme girişimi. Razor Pages sayfa
modeli sınıfları ve MVC denetleyici sınıflarının UI kaygılarıyla
odaklanıp ilgilenmeyeceğini aklınızda bulundurun. İş kuralları
ve veri erişimi uygulama ayrıntıları, bu ayrı kaygılarauygun
sınıflarda tutulmalıdır.
Hizmetlerin elden çıkarılması
Kapsayıcı, oluşturduğu IDisposable türleri için Dispose çağırır.
Kapsayıcıda Kullanıcı kodu tarafından bir örnek eklenirse,
otomatik olarak atılamaz.
// Services that implement IDisposable:
public class Service1 : IDisposable {}
public class Service2 : IDisposable {}
public class Service3 : IDisposable {}

public interface ISomeService {}


public class SomeServiceImplementation : ISomeService,
IDisposable {}

public void ConfigureServices(IServiceCollection services)


{
// The container creates the following instances and
disposes them automatically:
services.AddScoped<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<ISomeService>(sp => new
SomeServiceImplementation());

// The container doesn't create the following instances,


so it doesn't dispose of
// the instances automatically:
services.AddSingleton<Service3>(new Service3());
services.AddSingleton(new Service3());
}

Varsayılan hizmet kapsayıcısı değiştirme


Yerleşik hizmet kapsayıcısı, çerçeve ihtiyaçlarına ve çoğu
tüketici uygulamasına hizmet vermek için tasarlanmıştır.
Yerleşik kapsayıcının desteklemediği belirli bir özelliğe
ihtiyacınız yoksa, yerleşik kapsayıcının kullanılması önerilir,
örneğin:
Özellik ekleme
Ada göre ekleme
Alt kapsayıcılar
Özel ömür yönetimi
yavaş başlatma için Func<T> desteği

Aşağıdaki 3. taraf kapsayıcıları ASP.NET Core uygulamalarla


kullanılabilir:
Autofac
Drıioc
Yetkisiz kullanım
Açık Inject
E
Stakıbox
Unity
İş parçacığı güvenliği
İş parçacığı güvenli Singleton Hizmetleri oluşturun. Tek bir
hizmetin geçici bir hizmete bağımlılığı varsa, geçici hizmet aynı
zamanda tek tek tarafından nasıl kullanıldığına bağlı olarak iş
parçacığı güvenliği de gerektirebilir.
Tek bir hizmetin fabrika yöntemi (örneğin,
AddSingleton<TService > (ısevicecollection,
Func<IServiceProvider, TService >), iş parçacığı açısından
güvenli olması gerekmez. Bir tür ( static ) Oluşturucusu gibi,
tek bir iş parçacığı tarafından bir kez çağrılması garanti edilir.

Öneriler
async/await ve Task tabanlı hizmet çözümlemesi
desteklenmez. C#zaman uyumsuz oluşturucuları
desteklemez; Bu nedenle, önerilen model hizmeti zaman
uyumlu olarak çözümledikten sonra zaman uyumsuz
yöntemler kullanmaktır.
Veri ve yapılandırmayı doğrudan hizmet kapsayıcısında
saklamaktan kaçının. Örneğin, bir kullanıcının alışveriş
sepeti genellikle hizmet kapsayıcısına eklenmemelidir.
Yapılandırma, Seçenekler modelinikullanmalıdır. Benzer
şekilde, yalnızca başka bir nesneye erişime izin vermek
için mevcut olan "veri sahibi" nesnelerinden kaçının. DI
aracılığıyla gerçek öğe istemek daha iyidir.
Hizmetlere statik erişimi önleyin (örneğin, başka bir
yerde kullanmak üzere, statik olarak yazılan
IApplicationBuilder. ApplicationServices ).
Hizmet bulucu desenininkullanmaktan kaçının. Örneğin,
yerine şunu kullandığınızda bir hizmet örneği elde etmek
için GetService çağırmayın:
Olmayan

public class MyClass()


{
public void MyMethod()
{
var optionsMonitor =

_services.GetService<IOptionsMonitor<MyOptions>>();
var option =
optionsMonitor.CurrentValue.Option;

...
}
}

Doğru:
public class MyClass
{
private readonly IOptionsMonitor<MyOptions>
_optionsMonitor;

public MyClass(IOptionsMonitor<MyOptions>
optionsMonitor)
{
_optionsMonitor = optionsMonitor;
}

public void MyMethod()


{
var option =
_optionsMonitor.CurrentValue.Option;

...
}
}

Önlemek için başka bir hizmet bulucu çeşitlemesi,


çalışma zamanında bağımlılıkları çözümleyen bir ekleme.
Bu uygulamalardan her ikisi de Denetim stratejilerini
geçersiz kılar .
HttpContext statik erişimden kaçının (örneğin,
ıhttpcontextaccessor. HttpContext).
Tüm öneri kümeleri gibi, bir öneriyi yok saymayı yok saymış
durumlarla karşılaşabilirsiniz. Özel durumlar genellikle
Framework içindeki özel durumlar—nadir olarak kullanılır.
Dı, statik/genel nesne erişim desenlerinin bir alternatifidir .
Statik nesne erişimi ile karıştırırsanız, dı 'nin avantajlarını fark
edemeyebilirsiniz.

Ek kaynaklar
ASP.NET core'da görünümlere bağımlılık ekleme
ASP.NET core'da denetleyicilere bağımlılık ekleme
ASP.NET core'da gereksinim işleyicilerine bağımlılık ekleme
ASP.NET Core Blazor bağımlılığı ekleme
ASP.NET Core 'de uygulama başlatma
ASP.NET Core 'de fabrika tabanlı ara yazılım etkinleştirmesi
Bağımlılık ekleme (MSDN ) ile ASP.NET Core temizleme
kodu yazma
Açık bağımlılıklar Ilkesi
Denetim kapsayıcıları ve bağımlılık ekleme deseninin
Inversion 'ı (Marwler)
ASP.NET Core DI 'de birden çok arabirime sahip bir hizmeti
kaydetme
ASP.NET Core ara yazılımı
26.11.2019 • 21 minutes to read • Edit Online

By Rick Anderson ve Steve Smith


Ara yazılım, istekleri ve yanıtları işlemek için bir uygulama ardışık düzenine çevrilmiş yazılımdır. Her
bileşen:
İsteğin işlem hattında sonraki bileşene geçirilip geçemeyeceğini seçer.
İşlem hattındaki sonraki bileşenden önce ve sonra iş gerçekleştirebilir.
İstek işlem hattını oluşturmak için istek temsilcileri kullanılır. İstek temsilcileri her HTTP isteğini işler.
İstek temsilcileri Run, Mapve Use uzantı yöntemleri kullanılarak yapılandırılır. Tek bir istek temsilcisi, bir
anonim Yöntem (çevrimiçi ara yazılım olarak adlandırılır) olarak satır içinde belirtilebilir veya yeniden
kullanılabilir bir sınıfta tanımlanabilir. Bu yeniden kullanılabilir sınıflar ve satır içi anonim yöntemler, Ara
yazılım bileşenleriolarak da adlandırılan ara yazılımlar. İstek ardışık düzeninde bulunan her bir ara
yazılım bileşeni, işlem hattındaki bir sonraki bileşeni çağırmaktan veya işlem hattının kısa süreli olarak
sağlanmasından sorumludur. Bir ara yazılım kısa devre dışı bırakıldığında, bu, diğer ara yazılımların
isteği işlemesini önlediği için Terminal ara yazılımı olarak adlandırılır.
ASP.NET Core ara yazılıma HTTP işleyicileri ve modülleri geçirme, ASP.NET Core ve ASP.NET 4. x
içindeki istek işlem hatları arasındaki farkı açıklar ve ek ara yazılım örnekleri sağlar.

IApplicationBuilder ile bir ara yazılım işlem hattı oluşturma


ASP.NET Core isteği ardışık düzeni, bir dizi istekten oluşur ve bunlardan sonra çağırılır. Aşağıdaki
diyagramda kavram gösterilmektedir. Yürütmenin iş parçacığı siyah okları izler.

Her temsilci bir sonraki temsilciden önce ve sonra işlemleri gerçekleştirebilir. Özel durum işleme
temsilcileri işlem hattında erken çağrılmalıdır, bu sayede işlem hattının sonraki aşamalarında oluşan
özel durumları yakalayabilirler.
Mümkün olan en basit ASP.NET Core uygulaması, tüm istekleri işleyen tek bir istek temsilcisi kurar. Bu
durum gerçek bir istek işlem hattı içermez. Bunun yerine, her HTTP isteğine yanıt olarak tek bir anonim
işlev çağırılır.

public class Startup


{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}

İlk Run temsilci, işlem hattını sonlandırır.


Birden çok istek temsilciyi Useile birlikte zinciri. next parametresi, ardışık düzendeki bir sonraki
temsilciyi temsil eder. Ardışık düzen, sonraki parametreyi çağırarak işlem hattı için kısa devre dışı
bırakabilirsiniz. Aşağıdaki örnekte gösterildiği gibi genellikle sonraki temsilciden önce ve sonra
eylemler gerçekleştirebilirsiniz:

public class Startup


{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>


{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}

Bir temsilci bir sonraki temsilciye bir istek iletmezse, istek ardışık düzenini, kısadevre olarak
gerçekleştirmektir. Gereksiz çalışmayı önlediği için kısa devre, genellikle tercih edilir. Örneğin, statik
dosya ara yazılımı , bir statik dosya için bir isteği işleyerek ve işlem hattının geri kalanını
gerçekleştirerek bir Terminal ara yazılımı görevi görebilir. Daha fazla işlemeyi sonlandıran ara yazılım,
next.Invoke deyimlerinden sonra kodu işlerken işlem hattına eklenen ara yazılımlar. Ancak, zaten
gönderilmiş bir yanıta yazma girişimi hakkında aşağıdaki uyarıya bakın.

WARNING
İstemciye yanıt gönderildikten sonra next.Invoke çağırmayın. Yanıt başladıktan sonra HttpResponse
değişiklikler özel durum oluşturur. Örneğin, üstbilgileri ayarlama ve durum kodu gibi değişiklikler özel durum
oluşturur. next çağrıldıktan sonra yanıt gövdesine yazma:
Protokol ihlaline neden olabilir. Örneğin, belirtilen Content-Length daha fazla yazma.
Gövde biçimi bozulabilir. Örneğin, bir CSS dosyasına bir HTML altbilgisi yazma.
HasStarted, üstbilgilerin gönderilip gönderilmediğini veya gövdenin yazıldığını göstermek için faydalı bir ipucu.

Ara yazılım sırası


Ara yazılım bileşenlerinin Startup.Configure yöntemi içinde eklendiği sıra, ara yazılım bileşenlerinin
isteklerde çağrıldığı sırayı ve yanıtın ters sırasını tanımlar. Sıra, güvenlik, performans ve işlevsellik
açısından önemlidir .
Aşağıdaki Startup.Configure yöntemi, güvenlikle ilgili ara yazılım bileşenlerini önerilen sırayla ekler:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();

app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();

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

Önceki kodda:
Bireysel kullanıcılar hesaplarıyla yeni bir Web uygulaması oluştururken eklenmemiş olan ara
yazılım, yorum yapılır.
Her ara yazılımın bu tam sıra, ancak birçok do olması gerekmez. Örneğin, UseCors ,
UseAuthentication ve UseAuthorization gösterilen sırayla gelmelidir.

Aşağıdaki Startup.Configure yöntemi, genel uygulama senaryoları için ara yazılım bileşenleri ekler:
1. Özel durum/hata işleme
Uygulama geliştirme ortamında çalıştığında:
Geliştirici özel durum sayfası ara yazılımı (UseDeveloperExceptionPage) uygulama
çalışma zamanı hatalarını raporlar.
Veritabanı hata sayfası ara yazılımı veritabanı çalışma zamanı hatalarını raporlar.
Uygulama, üretim ortamında çalıştığında:
Özel durum Işleyici ara yazılımı (UseExceptionHandler) aşağıdaki middlewares
oluşturulan özel durumları yakalar.
HTTP katı aktarım güvenliği Protokolü (HSTS ) ara yazılımı (UseHsts)
Strict-Transport-Security üstbilgisini ekler.
2. HTTPS yeniden yönlendirme ara yazılımı (UseHttpsRedirection) HTTP isteklerini HTTPS 'ye
yönlendirir.
3. Statik dosya ara yazılımı (UseStaticFiles) statik dosyaları ve kısa devre dışı istek işlemeyi döndürür.
4. Tanımlama bilgisi Ilkesi ara yazılımı (UseCookiePolicy) uygulamayı AB Genel Veri Koruma
Yönetmeliği (GDPR ) düzenlemelerine uyar.
5. İstekleri yönlendirmek için ara yazılım ( UseRouting ).
6. Kimlik doğrulama ara yazılımı (UseAuthentication), güvenli kaynaklara erişim izni vermeden önce
kullanıcının kimliğini doğrulamaya çalışır.
7. Yetkilendirme ara yazılımı ( UseAuthorization ), bir kullanıcıya güvenli kaynaklara erişim yetkisi verir.
8. Oturum ara yazılımı (UseSession) oturum durumunu oluşturur ve korur. Uygulama oturum
durumunu kullanıyorsa, tanımlama bilgisi Ilkesi ara yazılımı ve MVC ara yazılımı öncesinde oturum
ara yazılımını çağırın.
9. İstek ardışık düzenine Razor Pages uç noktaları eklemek için uç nokta yönlendirme ara yazılımı (
MapRazorPages``UseEndpoints ).

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}

Yukarıdaki örnek kodda, her bir ara yazılım uzantısı yöntemi Microsoft.AspNetCore.Builder ad alanı
aracılığıyla IApplicationBuilder gösterilir.
UseExceptionHandler, işlem hattına eklenen ilk ara yazılım bileşenidir. Bu nedenle, özel durum Işleyicisi
ara yazılımı sonraki çağrılarında oluşan tüm özel durumları yakalar.
Statik dosya ara yazılımı, geri kalan bileşenlere geçmeden istekleri ve kısa devre dışı bırakabilirsiniz. bu
sayede işlem hattının başlarında çağrılır. Statik dosya ara yazılımı yetkilendirme denetimleri
sağlamaz. Wwwrootaltındakiler de dahil olmak üzere statik dosya ara yazılımı tarafından sunulan tüm
dosyalar herkese açık bir şekilde sunulur. Statik dosyaların güvenliğini sağlamaya yönelik bir yaklaşım
için bkz. ASP.NET Core statik dosyalar.
İstek statik dosya ara yazılımı tarafından işlenmemişse, kimlik doğrulaması yapan kimlik doğrulama ara
yazılım (UseAuthentication) üzerinden geçirilir. Kimlik doğrulaması kısa devre dışı kimliği
doğrulanmamış istekler değildir. Kimlik doğrulama ara yazılımı isteklerin kimliğini doğrulayabilse de,
yetkilendirme (ve reddetme) yalnızca MVC, belirli bir Razor sayfası veya MVC denetleyicisi ve eylemi
seçerse oluşur.
Aşağıdaki örnek, yanıt sıkıştırma ara yazılımı ile önce statik dosya isteklerinin statik dosya ara yazılımı
tarafından işlendiği bir ara yazılım sırasını gösterir. Statik dosyalar bu ara yazılım sırasıyla sıkıştırılmaz.
Razor Pages yanıtları sıkıştırılabilirler.

public void Configure(IApplicationBuilder app)


{
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();

app.UseResponseCompression();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
// app.UseSession();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

Önceki kodda:
Bireysel kullanıcılar hesaplarıyla yeni bir Web uygulaması oluştururken eklenmemiş olan ara
yazılım, yorum yapılır.
Her ara yazılımın bu tam sıra, ancak birçok do olması gerekmez. Örneğin, UseCors ve
UseAuthentication gösterilen sırada olmalıdır.

Aşağıdaki Startup.Configure yöntemi, genel uygulama senaryoları için ara yazılım bileşenleri ekler:
1. Özel durum/hata işleme
Uygulama geliştirme ortamında çalıştığında:
Geliştirici özel durum sayfası ara yazılımı (UseDeveloperExceptionPage) uygulama
çalışma zamanı hatalarını raporlar.
Veritabanı hata sayfası ara yazılımı (
Microsoft.AspNetCore.Builder.DatabaseErrorPageExtensions.UseDatabaseErrorPage )
veritabanı çalışma zamanı hatalarını raporlar.
Uygulama, üretim ortamında çalıştığında:
Özel durum Işleyici ara yazılımı (UseExceptionHandler) aşağıdaki middlewares
oluşturulan özel durumları yakalar.
HTTP katı aktarım güvenliği Protokolü (HSTS ) ara yazılımı (UseHsts)
Strict-Transport-Security üstbilgisini ekler.
2. HTTPS yeniden yönlendirme ara yazılımı (UseHttpsRedirection) HTTP isteklerini HTTPS 'ye
yönlendirir.
3. Statik dosya ara yazılımı (UseStaticFiles) statik dosyaları ve kısa devre dışı istek işlemeyi döndürür.
4. Tanımlama bilgisi Ilkesi ara yazılımı (UseCookiePolicy) uygulamayı AB Genel Veri Koruma
Yönetmeliği (GDPR ) düzenlemelerine uyar.
5. Kimlik doğrulama ara yazılımı (UseAuthentication), güvenli kaynaklara erişim izni vermeden önce
kullanıcının kimliğini doğrulamaya çalışır.
6. Oturum ara yazılımı (UseSession) oturum durumunu oluşturur ve korur. Uygulama oturum
durumunu kullanıyorsa, tanımlama bilgisi Ilkesi ara yazılımı ve MVC ara yazılımı öncesinde oturum
ara yazılımını çağırın.
7. MVC (UseMvc) istek ardışık düzenine MVC eklemek için.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseSession();
app.UseMvc();
}

Yukarıdaki örnek kodda, her bir ara yazılım uzantısı yöntemi Microsoft.AspNetCore.Builder ad alanı
aracılığıyla IApplicationBuilder gösterilir.
UseExceptionHandler, işlem hattına eklenen ilk ara yazılım bileşenidir. Bu nedenle, özel durum Işleyicisi
ara yazılımı sonraki çağrılarında oluşan tüm özel durumları yakalar.
Statik dosya ara yazılımı, geri kalan bileşenlere geçmeden istekleri ve kısa devre dışı bırakabilirsiniz. bu
sayede işlem hattının başlarında çağrılır. Statik dosya ara yazılımı yetkilendirme denetimleri
sağlamaz. Wwwrootaltındakiler de dahil olmak üzere statik dosya ara yazılımı tarafından sunulan tüm
dosyalar herkese açık bir şekilde sunulur. Statik dosyaların güvenliğini sağlamaya yönelik bir yaklaşım
için bkz. ASP.NET Core statik dosyalar.
İstek statik dosya ara yazılımı tarafından işlenmemişse, kimlik doğrulaması yapan kimlik doğrulama ara
yazılım (UseAuthentication) üzerinden geçirilir. Kimlik doğrulaması kısa devre dışı kimliği
doğrulanmamış istekler değildir. Kimlik doğrulama ara yazılımı isteklerin kimliğini doğrulayabilse de,
yetkilendirme (ve reddetme) yalnızca MVC, belirli bir Razor sayfası veya MVC denetleyicisi ve eylemi
seçerse oluşur.
Aşağıdaki örnek, yanıt sıkıştırma ara yazılımı ile önce statik dosya isteklerinin statik dosya ara yazılımı
tarafından işlendiği bir ara yazılım sırasını gösterir. Statik dosyalar bu ara yazılım sırasıyla sıkıştırılmaz.
UseMvcWithDefaultRoute MVC yanıtları sıkıştırılabilirler.

public void Configure(IApplicationBuilder app)


{
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();

app.UseResponseCompression();

app.UseMvcWithDefaultRoute();
}

Kullanın, çalıştırın ve eşleyin


Use, Runve Mapkullanarak HTTP işlem hattını yapılandırın. Use yöntemi, işlem hattı kısa devre dışı
olabilir (yani, bir next isteği temsilcisi çağırmazsa). Run bir kuraldır ve bazı ara yazılım bileşenleri,
işlem hattının sonunda çalışan Run[Middleware] Yöntemler sunabilir.
Map uzantıları, işlem hattının dallanması için bir kural olarak kullanılır. Map , istek ardışık düzenini,
verilen istek yolunun eşleşenleri temelinde dallandırır. İstek yolu verilen yol ile başlıyorsa, dal yürütülür.

public class Startup


{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}

private static void HandleMapTest2(IApplicationBuilder app)


{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}

public void Configure(IApplicationBuilder app)


{
app.Map("/map1", HandleMapTest1);

app.Map("/map2", HandleMapTest2);

app.Run(async context =>


{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}

Aşağıdaki tabloda, önceki kodu kullanarak http://localhost:1234 gelen istekler ve yanıtlar


gösterilmektedir.
İSTEK YANIT

localhost: 1234 Eşleme olmayan temsilciden Merhaba.

localhost: 1234/Map1 Eşleme testi 1

localhost: 1234/MAP2 Eşleme testi 2

localhost: 1234/map3 Eşleme olmayan temsilciden Merhaba.

Map kullanıldığında, eşleşen yol kesimleri HttpRequest.Path kaldırılır ve her istek için
HttpRequest.PathBase eklenir.

MapWhen, belirtilen koşulun sonucuna göre istek ardışık düzenini dallandırır. Func<HttpContext, bool>
türündeki herhangi bir koşul, istekleri işlem hattının yeni bir dalına eşlemek için kullanılabilir. Aşağıdaki
örnekte, bir sorgu dizesi değişkeninin varlığını algılamak için bir koşul kullanılır branch :

public class Startup


{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}

public void Configure(IApplicationBuilder app)


{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);

app.Run(async context =>


{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}

Aşağıdaki tabloda, önceki kodu kullanarak http://localhost:1234 gelen istekler ve yanıtlar


gösterilmektedir.

İSTEK YANIT

localhost: 1234 Eşleme olmayan temsilciden Merhaba.

localhost: 1234/? dalı = ana Kullanılan dal = ana

Map iç içe geçirmeyi destekler, örneğin:


app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});

Map aynı anda birden çok kesimde eşleşir:

public class Startup


{
private static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map multiple segments.");
});
}

public void Configure(IApplicationBuilder app)


{
app.Map("/map1/seg1", HandleMultiSeg);

app.Run(async context =>


{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}

Yerleşik ara yazılım


ASP.NET Core aşağıdaki ara yazılım bileşenleriyle birlikte gönderilir. Order sütunu, istek işleme ardışık
düzeninde ara yazılım yerleştirme ve ara yazılımın istek işlemeyi sonlandırabilecekleri koşullar
bölümünde notlar sağlar. Bir ara yazılım, istek işlem hattının ne kadar kısa süreli olduğunu ve daha fazla
aşağı akış ara yazılımı bir isteği işlemesini engelliyorsa, bu, Terminal ara yazılımıolarak adlandırılır. Kısa
devre oluşturma hakkında daha fazla bilgi için, IApplicationBuilder ile bir ara yazılım işlem hattı
oluşturma bölümüne bakın.

ARA YAZILIM AÇIKLAMA SIPARIŞ VERME

Kimlik doğrulaması Kimlik doğrulama desteği sağlar. HttpContext.User önce. OAuth


geri çağırmaları için Terminal.

Tanımlama bilgisi Ilkesi Kişisel bilgileri depolamak için Tanımlama bilgilerini veren ara
kullanıcılardan onay izler ve yazılım öncesi. Örnekler:
secure ve SameSite gibi Authentication, Session, MVC
tanımlama bilgisi alanları için en (TempData).
düşük standartları uygular.

CORS Çıkış noktaları arası kaynak CORS kullanan bileşenlerden önce.


paylaşımını yapılandırır.
ARA YAZILIM AÇIKLAMA SIPARIŞ VERME

Tanılama Geliştirici özel durum sayfası, özel Hata oluşturan bileşenlerden önce.
durum işleme, durum kodu sayfaları Özel durumlar için Terminal veya
ve yeni uygulamalar için varsayılan yeni uygulamalar için varsayılan
Web sayfası sağlayan çeşitli ayrı Web sayfasına hizmet sunma.
middlewares.

İletilen üstbilgiler Proxy üst bilgilerini geçerli istek Güncelleştirilmiş alanları kullanan
üzerine iletir. bileşenlerden önce. Örnekler:
Scheme, Host, istemci IP, yöntem.

Sistem durumu denetimi ASP.NET Core uygulamasının sistem Bir istek bir sistem durumu
durumunu ve bağımlılıklarını denetimi uç noktasıyla eşleşiyorsa
denetler (örneğin, veritabanı Terminal.
kullanılabilirliğini denetleme).

HTTP yöntemini geçersiz kılma Gelen POST isteğinin yöntemi Güncelleştirilmiş yöntemini kullanan
geçersiz kılmasına izin verir. bileşenlerden önce.

HTTPS yönlendirmesi Tüm HTTP isteklerini HTTPS 'ye URL 'YI kullanan bileşenlerden önce.
yeniden yönlendirin.

HTTP katı taşıma güvenliği (HSTS) Özel bir yanıt üst bilgisi ekleyen Yanıtlar gönderilmeden önce ve
güvenlik geliştirme ara yazılımı. istekleri değiştiren bileşenler.
Örnekler: Iletilen üstbilgiler, URL
yeniden yazma.

MVC MVC/Razor Pages ile istekleri işler. Bir istek bir rota ile eşleşiyorsa
Terminal.

OWıN OWIN tabanlı uygulamalar, OWıN ara yazılımı isteği tam olarak
sunucular ve ara yazılım ile birlikte işliyorsa Terminal.
çalışma.

Yanıtları Önbelleğe Alma Yanıtları önbelleğe almak için destek Önbelleğe alma gerektiren
sağlar. bileşenlerden önce.

Yanıt sıkıştırması Yanıtları sıkıştırmak için destek Sıkıştırma gerektiren bileşenlerden


sağlar. önce.

Yerelleştirme iste Yerelleştirme desteği sağlar. Yerelleştirmenin önemli


bileşenlerinden önce.

Uç nokta yönlendirme İstek yollarını tanımlar ve kısıtlar. Eşleşen yolların terminali.

Oturum Kullanıcı oturumlarını yönetmek için Oturum gerektiren bileşenlerden


destek sağlar. önce.

Statik dosyalar Statik dosyaları ve dizin taramayı Bir istek bir dosyayla eşleşiyorsa
sunma desteği sağlar. Terminal.

URL yeniden yazma URL 'Leri yeniden yazma ve istekleri URL 'YI kullanan bileşenlerden önce.
yeniden yönlendirme desteği sağlar.

WebSockets WebSockets protokolünü WebSocket isteklerini kabul etmek


etkinleştirilir. için gereken bileşenlerden önce.
ARA YAZILIM AÇIKLAMA SIPARIŞ VERME

Ek kaynaklar
Özel ASP.NET Core ara yazılımı yaz
ASP.NET Core ara yazılıma HTTP işleyicileri ve modülleri geçirme
ASP.NET Core 'de uygulama başlatma
ASP.NET core'da istek özellikleri
ASP.NET Core 'de fabrika tabanlı ara yazılım etkinleştirmesi
ASP.NET Core bir üçüncü taraf kapsayıcısı ile ara yazılım etkinleştirme
.NET genel ana bilgisayar
3.12.2019 • 34 minutes to read • Edit Online

Bu makalede .NET Core genel ana bilgisayarı (HostBuilder) tanıtılmakta ve nasıl kullanılacağına ilişkin
yönergeler sunulmaktadır.

Ana bilgisayar nedir?


Ana bilgisayar , bir uygulamanın kaynaklarını kapsülleyen bir nesnedir, örneğin:
Bağımlılık ekleme (dı)
Günlüğe Kaydetme
Yapılandırma
IHostedService uygulamalar

Bir konak başlatıldığında, DI kapsayıcısında bulduğu IHostedService her bir uygulamada


IHostedService.StartAsync çağırır. Bir Web uygulamasında, IHostedService uygulamalarından biri, http
sunucu uygulamasıBaşlatan bir Web hizmetidir.
Uygulamanın tüm birbirine bağlı kaynaklarını tek bir nesnede dahil etmek için başlıca neden, yaşam süresi
yönetimi: uygulama başlatma ve düzgün kapanma üzerinde denetim.
3,0 ' den önceki ASP.NET Core sürümlerinde, Web ana BILGISAYARı http iş yükleri için kullanılır. Web ana
bilgisayarı artık Web uygulamaları için önerilmez ve yalnızca geriye dönük uyumluluk için kullanılabilir
durumda kalır.

Konak ayarlama
Konak genellikle Program sınıfındaki kodla yapılandırılır, oluşturulur ve çalıştırılır. Main yöntemi:
Bir Oluşturucu nesnesi oluşturmak ve yapılandırmak için bir CreateHostBuilder yöntemi çağırır.
Oluşturucu nesnesinde Build ve Run yöntemleri çağırır.
İşte, tek bir IHostedService uygulama olarak dı kapsayıcısına eklenen HTTP olmayan bir iş yükü için
program.cs kodu.

public class Program


{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}

Bir HTTP iş yükü için Main yöntemi aynıdır ancak CreateHostBuilder ConfigureWebHostDefaults çağırır:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Uygulama Entity Framework Core kullanıyorsa CreateHostBuilder yönteminin adını veya imzasını
değiştirmeyin. Entity Framework Core araçları , uygulamayı çalıştırmadan Konağı yapılandıran bir
CreateHostBuilder yöntemi bulmayı bekler. Daha fazla bilgi için bkz. Tasarım zamanı DbContext
oluşturma.

Varsayılan Oluşturucu ayarları


CreateDefaultBuilder yöntemi:
İçerik kökünü GetCurrentDirectorytarafından döndürülen yola ayarlar.
Ana bilgisayar yapılandırmasını şuradan yükler:
"DOTNET_" önekli ortam değişkenleri.
Komut satırı bağımsız değişkenleri.
Uygulama yapılandırmasını şuradan yükler:
appSettings. JSON.
appSettings. {Environment}. JSON.
Uygulama Development ortamda çalıştığında gizli dizi Yöneticisi .
Ortam değişkenleri.
Komut satırı bağımsız değişkenleri.
Aşağıdaki günlük sağlayıcılarını ekler:
Konsolu
Hata ayıklama
EventSource
Olay günlüğü (yalnızca Windows üzerinde çalışırken)
Ortam geliştirme sırasında kapsam doğrulaması ve bağımlılık doğrulaması etkinleştirilir.
ConfigureWebHostDefaults yöntemi:
"ASPNETCORE_" önekli ortam değişkenlerinden ana bilgisayar yapılandırmasını yükler.
Kestrel sunucusunu Web sunucusu olarak ayarlar ve uygulamanın barındırma yapılandırma
sağlayıcılarını kullanarak yapılandırır. Kestrel sunucusunun varsayılan seçenekleri için bkz. ASP.NET
Core Web sunucusu uygulamasını Kestrel.
Ana bilgisayar filtreleme ara yazılımıekler.
ASPNETCORE_FORWARDEDHEADERS_ENABLED = true ise Iletilen üstbilgiler ara yazılımı ekler.
IIS tümleştirmesini etkinleştirilir. IIS varsayılan seçenekleri için bkz. IIS ile Windows üzerinde ASP.NET
Core barındırma.
Bu makalenin ilerleyen kısımlarında Web Apps bölümlerine yönelik tüm uygulama türleri ve ayarlarının
ayarları, varsayılan Oluşturucu ayarlarının nasıl geçersiz kılınacağını göstermektedir.

Framework tarafından sunulan hizmetler


Kayıtlı hizmetler otomatik olarak şunları içerir:
Ihostapplicationlifetime
Ihostlifetime
Ihostenvironment/ıwebhostenvironment
Framework tarafından sunulan hizmetler hakkında daha fazla bilgi için bkz. ASP.NET Core bağımlılık
ekleme.

Ihostapplicationlifetime
Başlatma sonrası ve düzgün kapanma görevlerini işlemek için IHostApplicationLifetime (eski adıyla
IApplicationLifetime ) hizmeti herhangi bir sınıfa ekleyin. Arabirimdeki üç özellik, uygulama başlatma ve
uygulama durdurma olay işleyicisi yöntemlerini kaydetmek için kullanılan iptal belirteçleridir. Arabirim
Ayrıca bir StopApplication yöntemi içerir.
Aşağıdaki örnek, IHostApplicationLifetime olaylarını kaydeden bir IHostedService uygulamasıdır:

internal class LifetimeEventsHostedService : IHostedService


{
private readonly ILogger _logger;
private readonly IHostApplicationLifetime _appLifetime;

public LifetimeEventsHostedService(
ILogger<LifetimeEventsHostedService> logger,
IHostApplicationLifetime appLifetime)
{
_logger = logger;
_appLifetime = appLifetime;
}

public Task StartAsync(CancellationToken cancellationToken)


{
_appLifetime.ApplicationStarted.Register(OnStarted);
_appLifetime.ApplicationStopping.Register(OnStopping);
_appLifetime.ApplicationStopped.Register(OnStopped);

return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)


{
return Task.CompletedTask;
}

private void OnStarted()


{
_logger.LogInformation("OnStarted has been called.");

// Perform post-startup activities here


}

private void OnStopping()


{
_logger.LogInformation("OnStopping has been called.");

// Perform on-stopping activities here


}

private void OnStopped()


{
_logger.LogInformation("OnStopped has been called.");

// Perform post-stopped activities here


}
}
Ihostlifetime
IHostLifetime uygulama, ana bilgisayar başladığında ve durdurulduğunda kontrol eder. Kaydedilen son
uygulama kullanılır.
Microsoft.Extensions.Hosting.Internal.ConsoleLifetime varsayılan IHostLifetime uygulamasıdır.
ConsoleLifetime :
CTRL + C/SIGINT veya SIGDÖNEM için dinler ve StopApplication, başlatma işlemini başlatmak için
çağırır.
RunAsync ve Waitforshutdownasyncgibi uzantıları kaldırır.

Ihostenvironment
IHostEnvironment hizmetini bir sınıfa ekleyin ve aşağıdakiler hakkında bilgi alın:
ApplicationName
EnvironmentName
Contentrootyolu
Web uygulamaları, IHostEnvironment devralan ve WebRootPathekleyen IWebHostEnvironment arabirimini
uygular.

Konak yapılandırması
Konak yapılandırması, IHostEnvironment uygulamasının özellikleri için kullanılır.
Konak yapılandırması, ConfigureAppConfigurationiçinde Hostbuildercontext. Configuration içinden
kullanılabilir. ConfigureAppConfiguration sonra, HostBuilderContext.Configuration uygulama
yapılandırması ile değiştirilmiştir.
Konak yapılandırması eklemek için IHostBuilder ConfigureHostConfiguration çağırın.
ConfigureHostConfiguration , eklenebilir sonuçlarla birden çok kez çağrılabilir. Ana bilgisayar, belirli bir
anahtardaki bir değeri en son belirleyen seçeneği kullanır.
Ön ek DOTNET_ ve komut satırı bağımsız değişkenlerine sahip ortam değişkeni sağlayıcısı,
CreateDefaultBuilder tarafından eklenir. Web Apps için ASPNETCORE_ ön ekine sahip ortam değişkeni
sağlayıcısı eklenir. Ortam değişkenleri okurken ön ek kaldırılır. Örneğin, ASPNETCORE_ENVIRONMENT için
ortam değişkeni değeri environment anahtar için ana bilgisayar yapılandırma değeri haline gelir.
Aşağıdaki örnek ana bilgisayar yapılandırması oluşturur:

// using Microsoft.Extensions.Configuration;

Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile("hostsettings.json", optional: true);
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
configHost.AddCommandLine(args);
});

Uygulama yapılandırması
Uygulama yapılandırması, IHostBuilder ConfigureAppConfiguration çağırarak oluşturulur.
ConfigureAppConfiguration , eklenebilir sonuçlarla birden çok kez çağrılabilir. Uygulama, belirli bir
anahtardaki bir değeri en son belirleyen seçeneği kullanır.
ConfigureAppConfiguration tarafından oluşturulan yapılandırma, sonraki işlemler ve DI hizmeti olarak,
Hostbuildercontext. Configuration konumunda kullanılabilir. Konak yapılandırması, uygulama
yapılandırmasına de eklenir.
Daha fazla bilgi için ASP.NET Core yapılandırmakonusuna bakın.

Tüm uygulama türleri için ayarlar


Bu bölüm, hem HTTP hem de HTTP olmayan iş yükleri için uygulanan konak ayarlarını listeler. Varsayılan
olarak, bu ayarları yapılandırmak için kullanılan ortam değişkenlerinin bir DOTNET_ veya ASPNETCORE_
öneki olabilir.
ApplicationName
Ihostenvironment. ApplicationName özelliği konak oluşturma sırasında konak yapılandırmasından
ayarlanır.
Anahtar: ApplicationName
Tür: dize
Varsayılan: uygulamanın giriş noktasını içeren derlemenin adı. Ortam değişkeni:
<PREFIX_>APPLICATIONNAME

Bu değeri ayarlamak için ortam değişkenini kullanın.


Contentrootyolu
Ihostenvironment. ContentRootPath özelliği, konağın içerik dosyalarını aramaya başladığı yeri belirler. Yol
yoksa, ana bilgisayar başlatılamaz.
Anahtar: contentroot
Tür: dize
Varsayılan: uygulama derlemesinin bulunduğu klasör.
Ortam değişkeni: <PREFIX_>CONTENTROOT
Bu değeri ayarlamak için, ortam değişkenini kullanın veya IHostBuilder``UseContentRoot çağırın:

Host.CreateDefaultBuilder(args)
.UseContentRoot("c:\\content-root")
//...

Daha fazla bilgi için bkz.


Temel bilgiler: Içerik kökü
WebRoot
environmentName
Ihostenvironment. EnvironmentName özelliği herhangi bir değere ayarlanabilir. Çerçeve tanımlı değerler
Development , Staging ve Production içerir. Değerler büyük/küçük harfe duyarlı değildir.

Anahtar: ortam
Tür: dize
Varsayılan: üretim
Ortam değişkeni: <PREFIX_>ENVIRONMENT

Bu değeri ayarlamak için, ortam değişkenini kullanın veya IHostBuilder``UseEnvironment çağırın:


Host.CreateDefaultBuilder(args)
.UseEnvironment("Development")
//...

ShutdownTimeout
Hostoptions. shutdowntimeout StopAsynciçin zaman aşımını ayarlar. Varsayılan değer beş saniyedir.
Zaman aşımı süresi boyunca ana bilgisayar:
Ihostapplicationlifetime. Applicationdurduruluyortetikler.
Üzerinde durmayacak hizmetler için barındırılan Hizmetleri durdurma ve hataları günlüğe kaydetme
girişimleri.
Tüm barındırılan hizmetler durmadan önce zaman aşımı süresi dolarsa, uygulama kapandığında kalan
etkin hizmetler durdurulur. Hizmetler, işlemeyi tamamlamadıklarında bile durur. Hizmetlerin durdurulması
için ek süre gerekiyorsa, zaman aşımını artırın.
Anahtar: shutdowntimeoutseconds
Tür: int
Varsayılan: 5 saniye ortam değişkeni: <PREFIX_>SHUTDOWNTIMEOUTSECONDS

Bu değeri ayarlamak için, ortam değişkenini kullanın veya HostOptions yapılandırın. Aşağıdaki örnek,
zaman aşımını 20 saniye olarak ayarlar:

Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
});

Web Apps ayarları


Bazı konak ayarları yalnızca HTTP iş yükleri için geçerlidir. Varsayılan olarak, bu ayarları yapılandırmak için
kullanılan ortam değişkenlerinin bir DOTNET_ veya ASPNETCORE_ öneki olabilir.
IWebHostBuilder genişletme yöntemleri bu ayarlar için kullanılabilir. Uzantı yöntemlerinin nasıl
çağrılacağını gösteren kod örnekleri, aşağıdaki örnekte olduğu gibi webBuilder bir IWebHostBuilder
örneği olduğunu varsayar:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.CaptureStartupErrors(true);
webBuilder.UseStartup<Startup>();
});

CaptureStartupErrors
false , başlangıç sırasında hata durumunda çıkış sırasında hatalar oluştu. true , ana bilgisayar başlangıç
sırasında özel durumları yakalar ve sunucuyu başlatmaya çalışır.
Anahtar: capturestartuperrors
Tür: bool ( true veya 1 )
Varsayılan: uygulama IIS arkasındaki Kestrel ile çalıştırılmadığı müddetçe false varsayılan olarak true .
Ortam değişkeni: <PREFIX_>CAPTURESTARTUPERRORS
Bu değeri ayarlamak için yapılandırma veya çağrı CaptureStartupErrors kullanın:

webBuilder.CaptureStartupErrors(true);

DetailedErrors
Etkinleştirildiğinde veya ortam Development olduğunda, uygulama ayrıntılı hataları yakalar.
Anahtar: detailederrors
Tür: bool ( true veya 1 )
Varsayılan: false
Ortam değişkeni: <PREFIX_>_DETAILEDERRORS
Bu değeri ayarlamak için yapılandırma veya çağrı UseSetting kullanın:

webBuilder.UseSetting(WebHostDefaults.DetailedErrorsKey, "true");

HostingStartupAssemblies
Başlangıçta yüklenecek başlangıç derlemelerinin barındırılması için noktalı virgülle ayrılmış bir dize.
Yapılandırma değeri boş bir dize olarak varsayılan olsa da, barındırma başlangıç derlemeleri her zaman
uygulamanın derlemesini içerir. Barındırma başlangıç derlemeleri sağlandığında, uygulama başlangıç
sırasında ortak hizmetlerini oluşturduğunda yükleme için uygulamanın derlemesine eklenir.
Anahtar: hostingStartupAssemblies
Tür: dize
Varsayılan: boş dize
Ortam değişkeni: <PREFIX_>_HOSTINGSTARTUPASSEMBLIES
Bu değeri ayarlamak için yapılandırma veya çağrı UseSetting kullanın:

webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2");

HostingStartupExcludeAssemblies
Başlangıçta dışlamak üzere başlangıç derlemelerinin barındırılması için noktalı virgülle ayrılmış bir dize.
Anahtar: hostingstartupexcludeassemblies
Tür: dize
Varsayılan: boş dize
Ortam değişkeni: <PREFIX_>_HOSTINGSTARTUPEXCLUDEASSEMBLIES
Bu değeri ayarlamak için yapılandırma veya çağrı UseSetting kullanın:

webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2");

HTTPS_Port
HTTPS yeniden yönlendirme bağlantı noktası. Https zorlamabölümünde kullanılır.
Anahtar: https_port
Tür: dize
Varsayılan: varsayılan değer ayarlı değildir.
Ortam değişkeni: <PREFIX_>HTTPS_PORT

Bu değeri ayarlamak için yapılandırma veya çağrı UseSetting kullanın:

webBuilder.UseSetting("https_port", "8080");

Tercih Hostingurl 'Leri


Konağın IServer uygulamayla yapılandırılanlar yerine IWebHostBuilder ile yapılandırılan URL 'lerde
dinleme yapıp kullanmayacağını belirtir.
Anahtar: preferhostingurl 'leri
Tür: bool ( true veya 1 )
Varsayılan: true
Ortam değişkeni: <PREFIX_>_PREFERHOSTINGURLS
Bu değeri ayarlamak için, ortam değişkenini kullanın veya PreferHostingUrls çağırın:

webBuilder.PreferHostingUrls(false);

Koruyucu Thostınstartup
Uygulamanın derlemesi tarafından yapılandırılan başlatma derlemelerinin barındırılması dahil olmak
üzere, barındırma başlangıç derlemelerinin otomatik yüklenmesini engeller. Daha fazla bilgi için bkz.
ASP.NET Core barındırma başlangıç derlemeleri kullanma.
Anahtar: koruyucu thostingstartup
Tür: bool ( true veya 1 )
Varsayılan: false
Ortam değişkeni: <PREFIX_>_PREVENTHOSTINGSTARTUP
Bu değeri ayarlamak için, ortam değişkenini kullanın veya UseSetting çağırın:

webBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true");

StartupAssembly
Startup sınıfını aramak için bütünleştirilmiş kod.

Anahtar: startupassembly
Tür: dize
Varsayılan: uygulamanın derlemesi
Ortam değişkeni: <PREFIX_>STARTUPASSEMBLY
Bu değeri ayarlamak için, ortam değişkenini kullanın veya UseStartup çağırın. UseStartup , bir derleme adı
( string ) veya bir tür ( TStartup ) alabilir. Birden çok UseStartup yöntemi çağrılırsa, son bir öncelik alır.

webBuilder.UseStartup("StartupAssemblyName");

webBuilder.UseStartup<Startup>();

URL'ler
Sunucu istekleri için dinlemesi gereken bağlantı noktaları ve protokollerle, noktalı virgülle ayrılmış IP
adresleri listesi veya ana bilgisayar adresleri. Örneğin, http://localhost:123 . Sunucunun belirtilen
bağlantı noktasını ve Protokolü (örneğin, http://*:5000 ) kullanarak herhangi bir IP adresi veya ana
bilgisayar için istekleri dinlemesi gerektiğini belirtmek için "*" kullanın. Protokol ( http:// veya https:// )
her URL 'ye dahil olmalıdır. Desteklenen biçimler sunucular arasında farklılık gösterir.
Anahtar: URL 'ler
Tür: dize
Varsayılan: http://localhost:5000 ve https://localhost:5001
Ortam değişkeni: <PREFIX_>URLS
Bu değeri ayarlamak için, ortam değişkenini kullanın veya UseUrls çağırın:

webBuilder.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002");

Kestrel kendi uç nokta yapılandırması API 'sine sahiptir. Daha fazla bilgi için bkz. ASP.NET Core Web
sunucusu uygulamasını Kestrel.
WebRoot
Uygulamanın statik varlıklarının göreli yolu.
Anahtar: Webroot
Tür: dize
Varsayılan: varsayılan wwwroot . {Content root}/Wwwroot yolu var olmalıdır. Yol yoksa, Hayır-op dosya
sağlayıcısı kullanılır.
Ortam değişkeni: <PREFIX_>WEBROOT
Bu değeri ayarlamak için, ortam değişkenini kullanın veya UseWebRoot çağırın:

webBuilder.UseWebRoot("public");

Daha fazla bilgi için bkz.


Temel bilgiler: Web kökü
Contentrootyolu

Konak ömrünü yönetme


Uygulamayı başlatmak ve durdurmak için oluşturulan IHost uygulamasındaki Yöntemleri çağırın. Bu
yöntemler, hizmet kapsayıcısında kayıtlı olan tüm IHostedService uygulamalarını etkiler.
Çalıştır
Run uygulamayı çalıştırır ve konak kapanana kadar çağıran iş parçacığını engeller.
RunAsync
RunAsync uygulamayı çalıştırır ve iptal belirteci veya kapanışı tetiklendiğinde tamamlayan bir Task
döndürür.
RunConsoleAsync
RunConsoleAsync, konsol desteği sağlar, Konağı oluşturur ve başlatır ve CTRL + C/SIGINT ya da
SIGDÖNEM 'in kapatılmasını bekler.
Başlangıç
Start Konağı zaman uyumlu olarak başlatır.
StartAsync
StartAsync, Konağı başlatır ve iptal belirteci veya kapanışı tetiklendiğinde tamamlanmış bir Task döndürür.
WaitForStartAsync, StartAsync başlangıcında çağrılır ve bu, devam etmeden önce tamamlanana kadar
bekler. Bu, bir dış olay tarafından sinyallene kadar başlatmayı geciktirmek için kullanılabilir.
StopAsync
StopAsync, belirtilen zaman aşımı süresi içinde Konağı durdurmaya çalışır.
Waitforkapatması
WaitForShutdown, CTRL + C/SIGINT veya SIGTERM gibi ıhostlifetime tarafından kapanmadan, çağıran
iş parçacığını engeller.
WaitForShutdownAsync
WaitForShutdownAsync, verilen belirteç aracılığıyla kapalı tetiklendiğinde ve StopAsyncçağıran bir Task
döndürür.
Dış denetim
Ana bilgisayar ömrünün doğrudan denetimi dışarıdan çağrılabilen yöntemler kullanılarak sağlanabilir:

public class Program


{
private IHost _host;

public Program()
{
_host = new HostBuilder()
.Build();
}

public async Task StartAsync()


{
_host.StartAsync();
}

public async Task StopAsync()


{
using (_host)
{
await _host.StopAsync(TimeSpan.FromSeconds(5));
}
}
}

ASP.NET Core uygulamalar bir konağı yapılandırıp başlatır. Ana bilgisayar, uygulama başlatma ve ömür
yönetiminden sorumludur.
Bu makalede, HTTP isteklerini işlemeyin uygulamalar için kullanılan ASP.NET Core genel ana bilgisayar
(HostBuilder) ele alınmaktadır.
Genel konağın amacı, daha geniş bir konak senaryolarını etkinleştirmek üzere Web ana bilgisayar API
'sinden HTTP işlem hattını ayırmak için kullanılır. Yapılandırma, bağımlılık ekleme (dı) ve günlüğe
kaydetme gibi çapraz kesme özelliğinden genel ana bilgisayar avantajı temel alınarak mesajlaşma, arka
plan görevleri ve diğer HTTP olmayan iş yükleri.
Genel ana bilgisayar ASP.NET Core 2,1 ' de yenidir ve Web barındırma senaryolarında uygun değildir.
Web barındırma senaryolarında Web konağınıkullanın. Genel ana bilgisayar gelecek bir sürümdeki Web
konağını değiştirecek ve hem HTTP hem de HTTP olmayan senaryolarda birincil ana bilgisayar API 'SI
olarak görev yapacak.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Örnek uygulamayı Visual Studio Code' de çalıştırırken, dış veya tümleşik bir Terminalkullanın. Örneği bir
internalConsole çalıştırmayın.
Konsolu Visual Studio Code ayarlamak için:
1. . Vscode/Launch. JSON dosyasını açın.
2. .NET Core başlatma (konsol) yapılandırmasında konsol girişini bulun. Değeri externalTerminal ya
da integratedTerminal olarak ayarlayın.

Giriş
Genel ana bilgisayar kitaplığı Microsoft.Extensions.Hosting ad alanında kullanılabilir ve Microsoft.
Extensions. Hosting paketi tarafından sağlanır. Microsoft.Extensions.Hosting paketi Microsoft.
AspNetCore. app metapackage 'e dahildir (ASP.NET Core 2,1 veya üzeri).
IHostedService, kod yürütmeye yönelik giriş noktasıdır. Her bir IHostedService uygulama,
ConfigureServices 'de hizmet kaydısırasında yürütülür. StartAsync, konak başlatıldığında her
IHostedService çağrılır ve konak düzgün şekilde kapandığında StopAsync ters kayıt sırasında çağrılır.

Konak ayarlama
IHostBuilder, kitaplıkların ve uygulamaların Konağı başlatmak, derlemek ve çalıştırmak için kullandığı ana
bileşendir:

public static async Task Main(string[] args)


{
var host = new HostBuilder()
.Build();

await host.RunAsync();
}

Seçenekler
HostOptions IHostseçeneklerini yapılandırın.
Kapatılma zaman aşımı
ShutdownTimeout, StopAsynczaman aşımını ayarlar. Varsayılan değer beş saniyedir.
Program.Main ' deki aşağıdaki seçenek yapılandırması, varsayılan beş saniyelik kapatılma zaman aşımını
20 saniyeye yükseltir:

var host = new HostBuilder()


.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
})
.Build();

Varsayılan hizmetler
Aşağıdaki hizmetler konak başlatma sırasında kaydedilir:
Ortam (IHostingEnvironment)
HostBuilderContext
Yapılandırma (IConfiguration)
IApplicationLifetime ( Microsoft.Extensions.Hosting.Internal.ApplicationLifetime )
IHostLifetime ( Microsoft.Extensions.Hosting.Internal.ConsoleLifetime )
IHost
Seçenekler (AddOptions)
Günlüğe kaydetme (AddLogging)

Konak yapılandırması
Ana bilgisayar yapılandırması şu şekilde oluşturulur:
İçerik kökünü ve ortamıayarlamak için IHostBuilder uzantı yöntemleri çağrılıyor.
ConfigureHostConfigurationiçindeki yapılandırma sağlayıcılarından yapılandırma okunuyor.
Uzantı yöntemleri
Uygulama anahtarı (ad)
Ihostingenvironment. ApplicationName özelliği konak oluşturma sırasında konak yapılandırmasından
ayarlanır. Değeri açıkça ayarlamak için, Hostdefaults. ApplicationKeykullanın:
Anahtar: ApplicationName
Tür: dize
Varsayılan: uygulamanın giriş noktasını içeren derlemenin adı.
Şunu kullanarak ayarla: HostBuilderContext.HostingEnvironment.ApplicationName
Ortam değişkeni: <PREFIX_>APPLICATIONNAME ( <PREFIX_> isteğe bağlı ve Kullanıcı tanımlı)
İçerik kökü
Bu ayar, konağın içerik dosyalarını aramaya başladığı yeri belirler.
Anahtar: contentroot
Tür: dize
Varsayılan: uygulama derlemesinin bulunduğu klasörü varsayılan olarak belirler.
Şunu kullanarak ayarla: UseContentRoot
Ortam değişkeni: <PREFIX_>CONTENTROOT ( <PREFIX_> isteğe bağlı ve Kullanıcı tanımlı)
Yol yoksa, ana bilgisayar başlatılamaz.

var host = new HostBuilder()


.UseContentRoot("c:\\<content-root>")

Daha fazla bilgi için bkz. temel bilgiler: içerik kökü.


Ortam
Uygulamanın ortamınıayarlar.
Anahtar: ortam
Tür: dize
Varsayılan: üretim
Şunu kullanarak ayarla: UseEnvironment
Ortam değişkeni: <PREFIX_>ENVIRONMENT ( <PREFIX_> isteğe bağlı ve Kullanıcı tanımlı)
Ortam herhangi bir değere ayarlanabilir. Çerçeve tanımlı değerler Development , Staging ve Production
içerir. Değerler büyük/küçük harfe duyarlı değildir.
var host = new HostBuilder()
.UseEnvironment(EnvironmentName.Development)

ConfigureHostConfiguration
ConfigureHostConfiguration, ana bilgisayar için bir IConfiguration oluşturmak üzere bir
IConfigurationBuilder kullanır. Konak yapılandırması, uygulamanın derleme sürecinde kullanılmak üzere
IHostingEnvironment başlatmak için kullanılır.
ConfigureHostConfiguration, eklenebilir sonuçlarla birden çok kez çağrılabilir. Ana bilgisayar, belirli bir
anahtardaki bir değeri en son belirleyen seçeneği kullanır.
Varsayılan olarak hiçbir sağlayıcı dahil değildir. Uygulamanın ConfigureHostConfigurationgereken her
türlü yapılandırma sağlayıcısını açıkça belirtmeniz gerekir, örneğin:
Dosya yapılandırması (örneğin, HostSettings. JSON dosyasından).
Ortam değişkeni yapılandırması.
Komut satırı bağımsız değişken yapılandırması.
Diğer tüm gerekli yapılandırma sağlayıcıları.
Konağın dosya yapılandırması, uygulamanın temel yolu SetBasePath ve ardından dosya yapılandırma
sağlayıcılarındanbirine yapılan bir çağrı tarafından belirtilerek etkinleştirilir. Örnek uygulama bir JSON
dosyası, HostSettings. JSONkullanır ve dosyanın konak yapılandırma ayarlarını kullanmak için
AddJsonFile çağırır.
Konağın ortam değişkeni yapılandırmasını eklemek için konak oluşturucu üzerinde
AddEnvironmentVariables çağırın. AddEnvironmentVariables , Kullanıcı tanımlı isteğe bağlı bir ön eki kabul
eder. Örnek uygulama PREFIX_ önekini kullanır. Ortam değişkenleri okurken ön ek kaldırılır. Örnek
uygulamanın ana bilgisayarı yapılandırıldığında, PREFIX_ENVIRONMENT için ortam değişkeni değeri
environment anahtar için ana bilgisayar yapılandırma değeri olur.

Visual Studio kullanırken veya dotnet run bir uygulama çalıştırırken geliştirme sırasında,
Özellikler/launchsettings. JSON dosyasında ortam değişkenleri ayarlanabilir. Visual Studio Code,
geliştirme sırasında . vscode/Launch. JSON dosyasında ortam değişkenleri ayarlanabilir. Daha fazla bilgi
için bkz. ASP.NET Core çoklu ortamları kullanma.
Komut satırı yapılandırması , AddCommandLineçağırarak eklenir. Komut satırı yapılandırması, önceki
yapılandırma sağlayıcıları tarafından belirtilen yapılandırmayı geçersiz kılmak için komut satırı bağımsız
değişkenlerine izin vermek üzere en son eklenir.
HostSettings. JSON:

{
"environment": "Development"
}

Ek yapılandırma ApplicationName ve contentroot anahtarlarıyla birlikte etkinleştirilebilir.


ConfigureHostConfigurationkullanarak HostBuilder yapılandırma örneği:
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile("hostsettings.json", optional: true);
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
configHost.AddCommandLine(args);
})

ConfigureAppConfiguration
Uygulama yapılandırması, IHostBuilder uygulamasındaki ConfigureAppConfiguration çağırarak
oluşturulur. ConfigureAppConfiguration, uygulama için bir IConfiguration oluşturmak üzere bir
IConfigurationBuilder kullanır. ConfigureAppConfiguration, eklenebilir sonuçlarla birden çok kez
çağrılabilir. Uygulama, belirli bir anahtardaki bir değeri en son belirleyen seçeneği kullanır.
ConfigureAppConfiguration tarafından oluşturulan yapılandırma, sonraki işlemler ve Servicesiçin
Hostbuildercontext. Configuration ' da kullanılabilir.
Uygulama yapılandırması, Configurehostconfigurationtarafından belirtilen konak yapılandırmasını
otomatik olarak alır.
ConfigureAppConfigurationkullanarak örnek uygulama yapılandırması:

var host = new HostBuilder()


.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddJsonFile("appsettings.json", optional: true);
configApp.AddJsonFile(
$"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json",
optional: true);
configApp.AddEnvironmentVariables(prefix: "PREFIX_");
configApp.AddCommandLine(args);
})

appSettings. JSON:

{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

appSettings. Development. JSON:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
appSettings. Production. JSON:

{
"Logging": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
}
}

Ayar dosyalarını çıkış dizinine taşımak için, ayarlar dosyalarını proje dosyasında MSBuild proje öğeleri
olarak belirtin. Örnek uygulama, JSON uygulama ayarları dosyalarını ve HostSettings. JSON dosyasını şu
<Content> öğesiyle taşıdıkça:

<ItemGroup>
<Content Include="**\*.json" Exclude="bin\**\*;obj\**\*"
CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

NOTE
AddJsonFile ve AddEnvironmentVariables gibi yapılandırma uzantısı yöntemleri, Microsoft. Extensions.
Configuration. JSON ve Microsoft. Extensions. Configuration. EnvironmentVariablesgibi ek NuGet paketleri
gerektirir. Uygulama Microsoft. AspNetCore. app metapackage'i kullanmadığı takdirde, bu paketlerin temel
Microsoft. Extensions. Configuration paketine ek olarak projeye eklenmesi gerekir. Daha fazla bilgi için bkz. ASP.NET
Core yapılandırma.

ConfigureServices
ConfigureServices, uygulamanın bağımlılık ekleme kapsayıcısına hizmet ekler. ConfigureServices,
eklenebilir sonuçlarla birden çok kez çağrılabilir.
Barındırılan hizmet, IHostedService arabirimini uygulayan bir arka plan görevi mantığı içeren bir sınıftır.
Daha fazla bilgi için bkz. ASP.NET Core içinde barındırılan hizmetlerle arka plan görevleri.
Örnek uygulama , yaşam süresi olayları, LifetimeEventsHostedService ve zaman aşımına uğramış bir arka
plan görevi olan TimedHostedService uygulamaya bir hizmet eklemek için AddHostedService uzantısı
yöntemini kullanır:

var host = new HostBuilder()


.ConfigureServices((hostContext, services) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
// Development service configuration
}
else
{
// Non-development service configuration
}

services.AddHostedService<LifetimeEventsHostedService>();
services.AddHostedService<TimedHostedService>();
})
ConfigureLogging
ConfigureLogging, belirtilen ILoggingBuilderyapılandırmak için bir temsilci ekler. ConfigureLogging,
eklenebilir sonuçlarla birden çok kez çağrılabilir.

var host = new HostBuilder()


.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
configLogging.AddDebug();
})

UseConsoleLifetime
UseConsoleLifetime, CTRL + C/SIGINT veya SIGTERIM dinler ve StopApplication çağırarak, bu işlemi
başlatmak için çağırır. RunAsync ve Waitforshutdownasyncgibi uzantıları kaldırır. UseConsoleLifetime
Microsoft.Extensions.Hosting.Internal.ConsoleLifetime varsayılan ömür uygulamasıyla önceden
kaydedilir. Kaydedilen son yaşam süresi kullanılır.

var host = new HostBuilder()


.UseConsoleLifetime()

Kapsayıcı yapılandırması
Diğer kapsayıcıları takmayı desteklemek için, ana bilgisayar bir
IServiceProviderFactory<TContainerBuilder>kabul edebilir. Fabrika sağlamak, dı kapsayıcı kaydının bir
parçası değildir, ancak bunun yerine somut dı kapsayıcısını oluşturmak için kullanılan bir konak iç sıdır.
Useserviceproviderfactory (ıvıceproviderfactory<TContainerBuilder>) , uygulamanın hizmet sağlayıcısını
oluşturmak için kullanılan varsayılan fabrikası geçersiz kılar.
Özel kapsayıcı yapılandırması ConfigureContainer yöntemi tarafından yönetilir. ConfigureContainer,
temel ana bilgisayar API 'sinin üstünde kapsayıcıyı yapılandırmak için kesin olarak belirlenmiş bir deneyim
sağlar. ConfigureContainer, eklenebilir sonuçlarla birden çok kez çağrılabilir.
Uygulama için bir hizmet kapsayıcısı oluşturun:

namespace GenericHostSample
{
internal class ServiceContainer
{
}
}

Hizmet kapsayıcısı fabrikası sağlama:


using System;
using Microsoft.Extensions.DependencyInjection;

namespace GenericHostSample
{
internal class ServiceContainerFactory :
IServiceProviderFactory<ServiceContainer>
{
public ServiceContainer CreateBuilder(
IServiceCollection services)
{
return new ServiceContainer();
}

public IServiceProvider CreateServiceProvider(


ServiceContainer containerBuilder)
{
throw new NotImplementedException();
}
}
}

Fabrika 'yi kullanın ve uygulama için özel hizmet kapsayıcısını yapılandırın:

var host = new HostBuilder()


.UseServiceProviderFactory<ServiceContainer>(new ServiceContainerFactory())
.ConfigureContainer<ServiceContainer>((hostContext, container) =>
{
})

Genişletilebilirlik
Konak genişletilebilirliği IHostBuilderuzantı yöntemleriyle gerçekleştirilir. Aşağıdaki örnek, bir genişletme
yönteminin ASP.NET Core içinde barındırılan hizmetlerle arka plan görevlerigösterilen
Timedhostedservice örneği ile bir IHostBuilder uygulamasını nasıl genişlettiğini gösterir.

var host = new HostBuilder()


.UseHostedService<TimedHostedService>()
.Build();

await host.StartAsync();

Uygulama, T geçirilen barındırılan hizmeti kaydetmek için UseHostedService uzantısı yöntemini


oluşturur:

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

public static class Extensions


{
public static IHostBuilder UseHostedService<T>(this IHostBuilder hostBuilder)
where T : class, IHostedService, IDisposable
{
return hostBuilder.ConfigureServices(services =>
services.AddHostedService<T>());
}
}
Konağı yönetme
IHost uygulaması, hizmet kapsayıcısında kayıtlı IHostedService uygulamalarını başlatma ve durdurma
sorumluluğundadır.
Çalıştır
Run uygulamayı çalıştırır ve konak kapanana kadar çağıran iş parçacığını engeller:

public class Program


{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();

host.Run();
}
}

RunAsync
RunAsync uygulamayı çalıştırır ve iptal belirteci veya kapanışı tetiklendiğinde tamamlayan bir Task
döndürür:

public class Program


{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();

await host.RunAsync();
}
}

RunConsoleAsync
RunConsoleAsync, konsol desteği sağlar, Konağı oluşturur ve başlatır ve CTRL + C/SIGINT ya da
SIGDÖNEM 'in kapatılmasını bekler.

public class Program


{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder();

await hostBuilder.RunConsoleAsync();
}
}

Başlangıç ve StopAsync
Start Konağı zaman uyumlu olarak başlatır.
StopAsync, belirtilen zaman aşımı süresi içinde Konağı durdurmaya çalışır.
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();

using (host)
{
host.Start();

await host.StopAsync(TimeSpan.FromSeconds(5));
}
}
}

StartAsync ve StopAsync
StartAsync uygulamayı başlatır.
StopAsync uygulamayı sonlandırır.

public class Program


{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();

using (host)
{
await host.StartAsync();

await host.StopAsync();
}
}
}

Waitforkapatması
WaitForShutdown, Microsoft.Extensions.Hosting.Internal.ConsoleLifetime (CTRL + C/SIGINT veya
SIGTERIM dinler) gibi IHostLifetimearacılığıyla tetiklenir. WaitForShutdown StopAsyncçağırır.

public class Program


{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();

using (host)
{
host.Start();

host.WaitForShutdown();
}
}
}

WaitForShutdownAsync
WaitForShutdownAsync, verilen belirteç aracılığıyla kapalı tetiklendiğinde ve StopAsyncçağıran bir Task
döndürür.
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();

using (host)
{
await host.StartAsync();

await host.WaitForShutdownAsync();
}

}
}

Dış denetim
Ana bilgisayarın dış denetimine, dışarıdan çağrılabilen yöntemler kullanılarak ulaşılabilecek:

public class Program


{
private IHost _host;

public Program()
{
_host = new HostBuilder()
.Build();
}

public async Task StartAsync()


{
_host.StartAsync();
}

public async Task StopAsync()


{
using (_host)
{
await _host.StopAsync(TimeSpan.FromSeconds(5));
}
}
}

WaitForStartAsync, StartAsyncbaşlangıcında çağrılır ve bu, devam etmeden önce tamamlanana kadar


bekler. Bu, bir dış olay tarafından sinyallene kadar başlatmayı geciktirmek için kullanılabilir.

Ihostingenvironment arabirimi
IHostingEnvironment, uygulamanın barındırma ortamı hakkında bilgi sağlar. Özelliklerini ve uzantı
yöntemlerini kullanmak için IHostingEnvironment almak üzere Oluşturucu Ekleme kullanın:
public class MyClass
{
private readonly IHostingEnvironment _env;

public MyClass(IHostingEnvironment env)


{
_env = env;
}

public void DoSomething()


{
var environmentName = _env.EnvironmentName;
}
}

Daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları kullanma.

Iapplicationlifetime arabirimi
IApplicationLifetime, düzgün kapanma istekleri dahil olmak üzere başlatma sonrası ve kapanma
etkinliklerine izin verir. Arabirimdeki üç özellik, başlangıç ve kapalı olayları tanımlayan Action yöntemlerini
kaydetmek için kullanılan iptal belirteçleridir.

İPTAL BELIRTECI TETIKLENDIĞI ZAMAN…

ApplicationStarted Konak tam olarak başlatıldı.

ApplicationStopped Ana bilgisayar düzgün kapanma işlemini tamamlıyor. Tüm


isteklerin işlenmesi gerekir. Bu olay tamamlanana kadar
kapalı bloklar.

ApplicationStopping Ana bilgisayar düzgün bir şekilde kapanma


gerçekleştiriyor. İstekler hala işliyor olabilir. Bu olay
tamamlanana kadar kapalı bloklar.

Constructor-IApplicationLifetime hizmetini herhangi bir sınıfa ekleyin. Örnek uygulama , olayları


kaydetmek için bir LifetimeEventsHostedService sınıfına (bir IHostedService uygulaması) Oluşturucu
ekleme işlemini kullanır.
LifetimeEventsHostedService.cs:
internal class LifetimeEventsHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly IApplicationLifetime _appLifetime;

public LifetimeEventsHostedService(
ILogger<LifetimeEventsHostedService> logger,
IApplicationLifetime appLifetime)
{
_logger = logger;
_appLifetime = appLifetime;
}

public Task StartAsync(CancellationToken cancellationToken)


{
_appLifetime.ApplicationStarted.Register(OnStarted);
_appLifetime.ApplicationStopping.Register(OnStopping);
_appLifetime.ApplicationStopped.Register(OnStopped);

return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)


{
return Task.CompletedTask;
}

private void OnStarted()


{
_logger.LogInformation("OnStarted has been called.");

// Perform post-startup activities here


}

private void OnStopping()


{
_logger.LogInformation("OnStopping has been called.");

// Perform on-stopping activities here


}

private void OnStopped()


{
_logger.LogInformation("OnStopped has been called.");

// Perform post-stopped activities here


}
}

StopApplication, uygulamanın sonlandırılmasını ister. Aşağıdaki sınıf, sınıfın Shutdown yöntemi


çağrıldığında bir uygulamayı düzgün bir şekilde kapatmak için StopApplication kullanır:
public class MyClass
{
private readonly IApplicationLifetime _appLifetime;

public MyClass(IApplicationLifetime appLifetime)


{
_appLifetime = appLifetime;
}

public void Shutdown()


{
_appLifetime.StopApplication();
}
}

Ek kaynaklar
ASP.NET Core içinde barındırılan hizmetlerle arka plan görevleri
ASP.NET Core Web ana bilgisayarı
23.11.2019 • 29 minutes to read • Edit Online

ASP.NET Core uygulamalar bir Konağıyapılandırıp başlatır. Uygulama başlatma ve ömür yönetimi için konak
sorumludur. Ana bilgisayar, en azından bir sunucu ve bir istek işleme işlem hattı yapılandırır.Konak, günlüğe
kaydetme, bağımlılık ekleme ve yapılandırma de ayarlayabilir.
Bu makalede, yalnızca geriye dönük uyumluluk için kullanılabilen Web ana bilgisayarı ele alınmaktadır. Genel
ana bilgisayar tüm uygulama türleri için önerilir.
Bu makale, Web uygulamalarını barındırmak için olan Web konağını ele alır. Diğer uygulama türleri için genel
Konağıkullanın.

Konak ayarlama
Iwebhostbuilder'ın bir örneğini kullanarak bir konak oluşturun. Bu genellikle uygulamanın giriş noktasında
Main yöntemi olarak gerçekleştirilir.

Proje şablonlarında, Main program.cs' de bulunur. Tipik bir uygulama, bir konak ayarlamaya başlamak için
Createdefaultbuilder çağırır:

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

CreateDefaultBuilder çağıran kod, Oluşturucu nesnesinde Run çağıran Main koddan ayıran
CreateWebHostBuilder adlı bir yöntemde bulunur. Entity Framework Core araçlarınıkullanıyorsanız bu ayrım
gereklidir. Araçlar, uygulamayı çalıştırmadan ana bilgisayarı yapılandırmak için tasarım zamanında
çağırabilecekleri bir CreateWebHostBuilder yöntemi bulmayı bekler. Diğer bir seçenek de
IDesignTimeDbContextFactory uygulamaktır. Daha fazla bilgi için bkz. Tasarım zamanı DbContext oluşturma.

CreateDefaultBuilder aşağıdaki görevleri gerçekleştirir:


Kestrel sunucusunu, uygulamanın barındırma yapılandırma sağlayıcılarını kullanarak Web sunucusu olarak
yapılandırır. Kestrel sunucusunun varsayılan seçenekleri için bkz. ASP.NET Core Web sunucusu
uygulamasını Kestrel.
İçerik kökünü Directory. GetCurrentDirectorytarafından döndürülen yola ayarlar.
Ana bilgisayar yapılandırmasını şuradan yükler:
ASPNETCORE_ ön eki olan ortam değişkenleri (örneğin, ASPNETCORE_ENVIRONMENT ).
Komut satırı bağımsız değişkenleri.
Aşağıdaki sırayla uygulama yapılandırmasını yükler:
appSettings. JSON.
appSettings. {Environment}. JSON.
Uygulama, giriş derlemesini kullanarak Development ortamda çalıştırıldığında gizli Yöneticisi .
Ortam değişkenleri.
Komut satırı bağımsız değişkenleri.
Konsol ve hata ayıklama çıkışı için günlüğe kaydetmeyi yapılandırır. Günlüğe kaydetme, bir appSettings.
JSON veya appSettings 'in günlük yapılandırma bölümünde belirtilen günlük filtreleme kurallarını içerir . {
Environment}. JSON dosyası.
ASP.NET Core MODÜLÜYLEIIS 'nin arkasında çalışırken, CreateDefaultBuilder , uygulamanın temel
adresini ve bağlantı noktasını yapılandıran IIS tümleştirmesinimümkün bir şekilde yapılandırır. IIS
tümleştirmesi, uygulamayı başlatma hatalarını yakalamayade yapılandırır. IIS varsayılan seçenekleri için bkz.
IIS ile Windows üzerinde ASP.NET Core barındırma.
Uygulamanın ortamı geliştirme ise, Serviceprovideroptions. ValidateScopes öğesini true olarak ayarlar.
Daha fazla bilgi için bkz. kapsam doğrulaması.
CreateDefaultBuilder tarafından tanımlanan yapılandırma, Configureappconfiguration, configureloggingve
ıwebhostbuilder'ın diğer yöntemleri ve genişletme yöntemleri tarafından geçersiz kılınabilir ve genişletilebilir.
Birkaç örnek aşağıda verilmiştir:
Configureappconfiguration , uygulama için ek IConfiguration belirtmek için kullanılır. Aşağıdaki
ConfigureAppConfiguration çağrısı, appSettings. xml dosyasına uygulama yapılandırmasını dahil etmek
için bir temsilci ekler. ConfigureAppConfiguration birden çok kez çağrılabilir. Bu yapılandırmanın ana
bilgisayar için (örneğin, sunucu URL 'Leri veya ortam) uygulanmadığını unutmayın. Konak yapılandırma
değerleri bölümüne bakın.

WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
})
...

Aşağıdaki ConfigureLogging çağrısı, en düşük günlük düzeyi (Setminimumlevel) değerini LogLevel.


Warningolarak yapılandırmak için bir temsilci ekler. Bu ayar appSettings 'teki ayarları geçersiz kılar .
Development. JSON ( LogLevel.Debug ) ve appSettings. Production. JSON ( LogLevel.Error )
CreateDefaultBuilder tarafından yapılandırıldı. ConfigureLogging birden çok kez çağrılabilir.

WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Warning);
})
...

Aşağıdaki ConfigureKestrel çağrısı varsayılan limitleri geçersiz kılar . MaxRequestBodySize , Kestrel


CreateDefaultBuilder tarafından yapılandırıldığında oluşturulan 30.000.000 bayttan oluşur:

WebHost.CreateDefaultBuilder(args)
.ConfigureKestrel((context, options) =>
{
options.Limits.MaxRequestBodySize = 20000000;
});

Aşağıdaki UseKestrel çağrısı, varsayılan limitleri geçersiz kılar . MaxRequestBodySize , Kestrel


CreateDefaultBuilder tarafından yapılandırıldığında oluşturulan 30.000.000 bayttan oluşur:
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.Limits.MaxRequestBodySize = 20000000;
});

İçerik kökü , konağın MVC görünüm dosyaları gibi içerik dosyalarını arayacağı yeri belirler. Uygulama, projenin
kök klasöründen başlatıldığında, projenin kök klasörü içerik kökü olarak kullanılır. Bu, Visual Studio 'da ve
DotNet yeni şablonlardakullanılan varsayılandır.
Uygulama yapılandırması hakkında daha fazla bilgi için bkz. ASP.NET Core yapılandırma.

NOTE
Statik CreateDefaultBuilder yönteminin kullanılmasına alternatif olarak, Webhostbuilder 'dan bir konak oluşturmak,
ASP.NET Core 2. x ile desteklenen bir yaklaşımdır.

Bir ana bilgisayar ayarlanırken, yapılandırma ve ConfigureServices yöntemleri bulunabilir. Bir Startup sınıfı
belirtilmişse, bir Configure yöntemi tanımlamalıdır. Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama
başlatma. ConfigureServices birden çok çağrısı birbirine eklenir. WebHostBuilder Configure veya UseStartup
birden çok çağrı önceki ayarların yerini alır.

Ana bilgisayar yapılandırma değerleri


Webhostbuilder , ana bilgisayar yapılandırma değerlerini ayarlamak için aşağıdaki yaklaşımları kullanır:
ASPNETCORE_{configurationKey} biçimindeki ortam değişkenlerini içeren konak Oluşturucu yapılandırması.
Örneğin: ASPNETCORE_ENVIRONMENT
Usecontentroot ve useconfiguration gibi uzantılar ( geçersiz kılma yapılandırması bölümüne bakın).
Usesetting ve ilişkili anahtar. UseSetting ile bir değer ayarlarken, değer türünden bağımsız olarak bir dize
olarak ayarlanır.
Konak, bir değeri en son ayarlayan seçeneği kullanır. Daha fazla bilgi için, sonraki bölümde yapılandırmayı
geçersiz kılma bölümüne bakın.
Uygulama anahtarı (ad)
IWebHostEnvironment.ApplicationName özelliği, konak oluşturma sırasında Usestartup veya Configure
çağrıldığında otomatik olarak ayarlanır. Değer, uygulamanın giriş noktasını içeren derlemenin adına ayarlanır.
Değeri açıkça ayarlamak için Webhostdefaults. ApplicationKeykullanın:
Konak oluşturma sırasında Usestartup veya Configure çağrıldığında, ıhostingenvironment. ApplicationName
özelliği otomatik olarak ayarlanır. Değer, uygulamanın giriş noktasını içeren derlemenin adına ayarlanır. Değeri
açıkça ayarlamak için Webhostdefaults. ApplicationKeykullanın:
Anahtar: ApplicationName
Tür: dize
Varsayılan: uygulamanın giriş noktasını içeren derlemenin adı.
Şunu kullanarak ayarla: UseSetting
Ortam değişkeni: ASPNETCORE_APPLICATIONNAME

WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
Yakalama başlatma hataları
Bu ayar, başlatma hatalarının yakalanmasını denetler.
Anahtar: capturestartuperrors
Tür: bool ( true veya 1 )
Varsayılan: uygulama IIS arkasındaki Kestrel ile çalıştırılmadığı müddetçe false varsayılan olarak true .
Şunu kullanarak ayarla: CaptureStartupErrors
Ortam değişkeni: ASPNETCORE_CAPTURESTARTUPERRORS
false , başlangıç sırasında hata durumunda çıkış sırasında hatalar oluştu. true , ana bilgisayar başlangıç
sırasında özel durumları yakalar ve sunucuyu başlatmaya çalışır.

WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)

İçerik kökü
Bu ayar ASP.NET Core içerik dosyalarını aramaya başladığı yeri belirler.
Anahtar: contentroot
Tür: dize
Varsayılan: uygulama derlemesinin bulunduğu klasörü varsayılan olarak belirler.
Şunu kullanarak ayarla: UseContentRoot
Ortam değişkeni: ASPNETCORE_CONTENTROOT
İçerik kökü, Web kökününtemel yolu olarak da kullanılır. İçerik kök yolu yoksa, ana bilgisayar başlatılamaz.

WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")

Daha fazla bilgi için bkz.:


Temel bilgiler: Içerik kökü
Web kökü
Ayrıntılı hatalar
Ayrıntılı hataların yakalanıp yakalanmayacağını belirler.
Anahtar: detailederrors
Tür: bool ( true veya 1 )
Varsayılan: false
Şunu kullanarak ayarla: UseSetting
Ortam değişkeni: ASPNETCORE_DETAILEDERRORS
Etkinleştirildiğinde (veya ortam Development olarak ayarlandığında), uygulama ayrıntılı özel durumları yakalar.

WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

Ortam
Uygulamanın ortamını ayarlar.
Anahtar: ortam
Tür: dize
Varsayılan: üretim
Şunu kullanarak ayarla: UseEnvironment
Ortam değişkeni: ASPNETCORE_ENVIRONMENT
Ortam herhangi bir değere ayarlanabilir. Çerçeve tanımlı değerler Development , Staging ve Production içerir.
Değerler büyük/küçük harfe duyarlı değildir. Varsayılan olarak, ortam ASPNETCORE_ENVIRONMENT ortam
değişkeninden okunurdur. Visual Studiokullanılırken, launchsettings. JSON dosyasında ortam değişkenleri
ayarlanabilir. Daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları kullanma.

WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)

Başlangıç derlemelerini barındırma


Uygulamanın barındırma başlangıç derlemelerini ayarlar.
Anahtar: hostingStartupAssemblies
Tür: dize
Varsayılan: boş dize
Şunu kullanarak ayarla: UseSetting
Ortam değişkeni: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
Başlangıçta yüklenecek başlangıç derlemelerinin barındırılması için noktalı virgülle ayrılmış bir dize.
Yapılandırma değeri boş bir dize olarak varsayılan olsa da, barındırma başlangıç derlemeleri her zaman
uygulamanın derlemesini içerir. Barındırma başlangıç derlemeleri sağlandığında, uygulama başlangıç sırasında
ortak hizmetlerini oluşturduğunda yükleme için uygulamanın derlemesine eklenir.

WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

HTTPS bağlantı noktası


HTTPS yeniden yönlendirme bağlantı noktasını ayarlayın. Https zorlamabölümünde kullanılır.
Anahtar: https_port türü: dize varsayılan: varsayılan değer ayarlı değildir. Şunu kullanarak ayarla:
UseSetting ortam değişkeni: ASPNETCORE_HTTPS_PORT

WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")

Barındırma başlatma derlemeleri dışlama


Başlangıçta dışlamak üzere başlangıç derlemelerinin barındırılması için noktalı virgülle ayrılmış bir dize.
Anahtar: hostingstartupexcludeassemblies
Tür: dize
Varsayılan: boş dize
Şunu kullanarak ayarla: UseSetting
Ortam değişkeni: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

Barındırma URL 'Lerini tercih et


Konağın IServer uygulamayla yapılandırılanlar yerine WebHostBuilder ile yapılandırılan URL 'lerde dinleme
yapıp kullanmayacağını belirtir.
Anahtar: preferhostingurl 'leri
Tür: bool ( true veya 1 )
Varsayılan: true
Şunu kullanarak ayarla: PreferHostingUrls
Ortam değişkeni: ASPNETCORE_PREFERHOSTINGURLS

WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(false)

Barındırma başlangıcını engelle


Uygulamanın derlemesi tarafından yapılandırılan başlatma derlemelerinin barındırılması dahil olmak üzere,
barındırma başlangıç derlemelerinin otomatik yüklenmesini engeller. Daha fazla bilgi için bkz. ASP.NET Core
barındırma başlangıç derlemeleri kullanma.
Anahtar: koruyucu thostingstartup
Tür: bool ( true veya 1 )
Varsayılan: false
Şunu kullanarak ayarla: UseSetting
Ortam değişkeni: ASPNETCORE_PREVENTHOSTINGSTARTUP

WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

Sunucu URL 'Leri


Sunucunun istekler için dinlemesi gereken bağlantı noktaları ve protokoller içeren IP adreslerini veya ana
bilgisayar adreslerini gösterir.
Anahtar: URL 'ler
Tür: dize
Varsayılan: http://localhost:5000
Şunu kullanarak ayarla: UseUrls
Ortam değişkeni: ASPNETCORE_URLS
Noktalı virgülle ayrılmış olarak ayarlayın (;) sunucunun yanıtlaması gereken URL ön eklerinin listesi. Örneğin:
http://localhost:123 Sunucunun belirtilen bağlantı noktasını ve Protokolü (örneğin, http://*:5000 )
kullanarak herhangi bir IP adresi veya ana bilgisayar için istekleri dinlemesi gerektiğini belirtmek için "*"
kullanın. Protokol ( http:// veya https:// ) her URL 'ye dahil olmalıdır. Desteklenen biçimler sunucular
arasında farklılık gösterir.

WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

Kestrel kendi uç nokta yapılandırması API 'sine sahiptir. Daha fazla bilgi için bkz. ASP.NET Core Web sunucusu
uygulamasını Kestrel.
Kapatılma zaman aşımı
Web konağının kapanması için beklenecek süreyi belirtir.
Anahtar: shutdowntimeoutseconds
Tür: int
Varsayılan: 5
Şunu kullanarak ayarla: UseShutdownTimeout
Ortam değişkeni: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
Anahtar, UseSetting (örneğin, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10") ) bir int kabul etse de,
useshutdowntimeout genişletme yöntemi bir TimeSpanalır.
Zaman aşımı süresi boyunca barındırma:
Iapplicationlifetime. Applicationdurduruluyoröğesini tetikler.
Üzerinde durmayacak hizmetlerin hatalarını günlüğe kaydetmek için barındırılan hizmetleri durdurmaya
çalışır.
Tüm barındırılan hizmetler durmadan önce zaman aşımı süresi dolarsa, uygulama kapandığında kalan etkin
hizmetler durdurulur. Hizmetler, işlemeyi tamamlamadıklarında bile durur. Hizmetlerin durdurulması için ek
süre gerekiyorsa, zaman aşımını artırın.

WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))

Başlangıç derlemesi
Startup sınıfı için arama yapılacak derlemeyi belirler.

Anahtar: startupassembly
Tür: dize
Varsayılan: uygulamanın derlemesi
Şunu kullanarak ayarla: UseStartup
Ortam değişkeni: ASPNETCORE_STARTUPASSEMBLY
Ada ( string ) veya türe ( TStartup ) göre derlemeye başvurulabilir. Birden çok UseStartup yöntemi çağrılırsa,
son bir öncelik alır.

WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")

WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()

Web kökü
Uygulamanın statik varlıklarının göreli yolunu ayarlar.
Anahtar: Webroot
Tür: dize
Varsayılan: varsayılan wwwroot . {Content root}/Wwwroot yolu var olmalıdır. Yol yoksa, Hayır-op dosya
sağlayıcısı kullanılır.
Şunu kullanarak ayarla: UseWebRoot
Ortam değişkeni: ASPNETCORE_WEBROOT

WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")

Daha fazla bilgi için bkz.:


Temel bilgiler: Web kökü
İçerik kökü

Geçersiz kılma yapılandırması


Web konağını yapılandırmak için yapılandırma kullanın. Aşağıdaki örnekte, konak yapılandırması isteğe bağlı
olarak bir HostSettings. JSON dosyasında belirtilir. HostSettings. JSON dosyasından yüklenen herhangi bir
yapılandırma komut satırı bağımsız değişkenleri tarafından geçersiz kılınabilir. Oluşturulan yapılandırma (
config ), Konağı Useconfigurationile yapılandırmak için kullanılır. IWebHostBuilder yapılandırması uygulamanın
yapılandırmasına eklenir, ancak— ConfigureAppConfiguration IWebHostBuilder yapılandırmasını etkilemez.
HostSettings. JSON config ile UseUrls tarafından belirtilen yapılandırmayı geçersiz kılma, komut satırı
bağımsız değişkeni yapılandırma saniyesi:

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.json", optional: true)
.AddCommandLine(args)
.Build();

return WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000")
.UseConfiguration(config)
.Configure(app =>
{
app.Run(context =>
context.Response.WriteAsync("Hello, World!"));
});
}
}

HostSettings. JSON:

{
urls: "http://*:5005"
}

NOTE
Useconfiguration uzantı yöntemi şu anda GetSection tarafından döndürülen bir yapılandırma bölümünü ayrıştırma
özelliğine sahip değil (örneğin, .UseConfiguration(Configuration.GetSection("section")) . GetSection yöntemi,
yapılandırma anahtarlarını istenen bölüme süzer ancak bölüm adını anahtarlar üzerinde bırakır (örneğin, section:urls ,
section:environment ). UseConfiguration yöntemi, anahtarların WebHostBuilder anahtarlarla eşleşmesini bekler
(örneğin, urls , environment ). Anahtarlarda bölüm adının varlığı, bölümün değerlerinin konak yapılandırmasını engeller.
Bu soruna önümüzdeki sürümlerden birinde çözüm getirilecektir. Daha fazla bilgi ve geçici çözüm için bkz . yapılandırma
bölümünü WebHostBuilder 'A geçirme. UseConfiguration tam anahtarları kullanır.
UseConfiguration , anahtarları yalnızca belirtilen IConfiguration ana bilgisayar Oluşturucu yapılandırmasına kopyalar.
Bu nedenle, JSON, INI ve XML ayarları dosyaları için reloadOnChange: true ayarlamanın hiçbir etkisi yoktur.
Belirli bir URL 'de çalıştırılacak Konağı belirtmek için, DotNet çalıştırmasıyürütürken istenen değer bir komut
isteminden geçirilebilir. Komut satırı bağımsız değişkeni, HostSettings. JSON dosyasından urls değerini
geçersiz kılar ve sunucu 8080 numaralı bağlantı noktasını dinler:

dotnet run --urls "http://*:8080"

Konağı yönetme
Çalıştırma
Run yöntemi, Web uygulamasını başlatır ve konak kapanana kadar çağıran iş parçacığını engeller:

host.Run();

Start
Start yöntemini çağırarak Konağı engellenmeyen bir şekilde çalıştırın:

using (host)
{
host.Start();
Console.ReadLine();
}

Start yöntemine bir URL listesi geçirilirse, belirtilen URL 'Leri dinler:

var urls = new List<string>()


{
"http://*:5000",
"http://localhost:5001"
};

var host = new WebHostBuilder()


.UseKestrel()
.UseStartup<Startup>()
.Start(urls.ToArray());

using (host)
{
Console.ReadLine();
}

Uygulama, statik bir kolaylık yöntemi kullanarak CreateDefaultBuilder önceden yapılandırılmış varsayılan
değerlerini kullanarak yeni bir konak başlatabilir ve başlatabilir. Bu yöntemler, konsol çıktısı olmadan sunucuyu
başlatır ve Waitforkapatmadan bir kesme (CTRL -C/sigint veya sigterim) bekler:
Başlat (RequestDelegate uygulaması)
RequestDelegate ile başlayın:

using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))


{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
"Merhaba Dünya!" yanıtını almak için http://localhost:5000 tarayıcıda bir istek yapın kesme (CTRL -C/SIGINT
veya SIGTERM ) verilene kadar blok WaitForShutdown . Uygulama Console.WriteLine iletisini görüntüler ve bir
tuş basışını, çıkış için bekler.
Başlangıç (dize URL 'si, RequestDelegate uygulaması)
Bir URL ve RequestDelegate başlayın:

using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))


{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}

Uygulamanın http://localhost:8080 yanıt vermesi dışında, Başlangıç (RequestDelegate uygulaması) ile


aynı sonucu üretir.
Başlat (eylem<ıroutebuilder > routeBuilder)
Yönlendirme ara yazılımını kullanmak için bir IRouteBuilder örneği (Microsoft. AspNetCore. Routing) kullanın:

using (var host = WebHost.Start(router => router


.MapGet("hello/{name}", (req, res, data) =>
res.WriteAsync($"Hello, {data.Values["name"]}!"))
.MapGet("buenosdias/{name}", (req, res, data) =>
res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
.MapGet("throw/{message?}", (req, res, data) =>
throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
.MapGet("{greeting}/{name}", (req, res, data) =>
res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
.MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}

Aşağıdaki tarayıcı isteklerini örnekle birlikte kullanın:

İSTEK YANIT

http://localhost:5000/hello/Martin Merhaba, martın!

http://localhost:5000/buenosdias/Catrina Buenos dias, Catrina!

http://localhost:5000/throw/ooops! "Ooops!" dizesiyle bir özel durum oluşturur

http://localhost:5000/throw "Uh oh!" dizesiyle bir özel durum oluşturur

http://localhost:5000/Sante/Kevin Sante, Kevin!

http://localhost:5000 Merhaba Dünya!

kesme (CTRL -C/SIGINT veya SIGTERM ) verilene kadar blok WaitForShutdown . Uygulama Console.WriteLine
iletisini görüntüler ve bir tuş basışını, çıkış için bekler.
Başlangıç (dize URL 'si, eylem<ıroutebuilder > routeBuilder)
Bir URL ve IRouteBuilder örneği kullanın:

using (var host = WebHost.Start("http://localhost:8080", router => router


.MapGet("hello/{name}", (req, res, data) =>
res.WriteAsync($"Hello, {data.Values["name"]}!"))
.MapGet("buenosdias/{name}", (req, res, data) =>
res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
.MapGet("throw/{message?}", (req, res, data) =>
throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
.MapGet("{greeting}/{name}", (req, res, data) =>
res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
.MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
Console.WriteLine("Use Ctrl-C to shut down the host...");
host.WaitForShutdown();
}

Uygulamanın http://localhost:8080 yanıt vermesi dışında, Başlangıç (eylem<ıroutebuilder >


routebuilder) ile aynı sonucu üretir.
StartWith (Action<IApplicationBuilder > App)
IApplicationBuilder yapılandırmak için bir temsilci sağlayın:

using (var host = WebHost.StartWith(app =>


app.Use(next =>
{
return async context =>
{
await context.Response.WriteAsync("Hello World!");
};
})))
{
Console.WriteLine("Use Ctrl-C to shut down the host...");
host.WaitForShutdown();
}

"Merhaba Dünya!" yanıtını almak için http://localhost:5000 tarayıcıda bir istek yapın kesme (CTRL -C/SIGINT
veya SIGTERM ) verilene kadar blok WaitForShutdown . Uygulama Console.WriteLine iletisini görüntüler ve bir
tuş basışını, çıkış için bekler.
StartWith (dize URL 'si, Action<IApplicationBuilder > App)
IApplicationBuilder yapılandırmak için bir URL ve temsilci sağlayın:

using (var host = WebHost.StartWith("http://localhost:8080", app =>


app.Use(next =>
{
return async context =>
{
await context.Response.WriteAsync("Hello World!");
};
})))
{
Console.WriteLine("Use Ctrl-C to shut down the host...");
host.WaitForShutdown();
}

Uygulamanın http://localhost:8080 yanıt vermesi dışında, StartWith ile aynı sonucu üretir
(Action<IApplicationBuilder > App) .
Iwebhostenvironment arabirimi
IWebHostEnvironment arabirimi, uygulamanın Web barındırma ortamı hakkında bilgi sağlar. Özelliklerini ve
uzantı yöntemlerini kullanmak için IWebHostEnvironment almak üzere Oluşturucu Ekleme kullanın:

public class CustomFileReader


{
private readonly IWebHostEnvironment _env;

public CustomFileReader(IWebHostEnvironment env)


{
_env = env;
}

public string ReadFile(string filePath)


{
var fileProvider = _env.WebRootFileProvider;
// Process the file here
}
}

Uygulamayı ortama göre başlangıçta yapılandırmak için kural tabanlı bir yaklaşım kullanılabilir. Alternatif
olarak, ConfigureServices kullanım için Startup oluşturucusuna IWebHostEnvironment ekleyin:

public class Startup


{
public Startup(IWebHostEnvironment env)
{
HostingEnvironment = env;
}

public IWebHostEnvironment HostingEnvironment { get; }

public void ConfigureServices(IServiceCollection services)


{
if (HostingEnvironment.IsDevelopment())
{
// Development configuration
}
else
{
// Staging/Production configuration
}

var contentRootPath = HostingEnvironment.ContentRootPath;


}
}

NOTE
IsDevelopment uzantısı yöntemine ek olarak, IWebHostEnvironment IsStaging , IsProduction ve
IsEnvironment(string environmentName) yöntemleri sunar. Daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları
kullanma.

IWebHostEnvironment hizmeti ayrıca işlem ardışık düzenini ayarlamak için doğrudan Configure yöntemine
eklenebilir:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// In Development, use the Developer Exception Page
app.UseDeveloperExceptionPage();
}
else
{
// In Staging/Production, route exceptions to /error
app.UseExceptionHandler("/error");
}

var contentRootPath = env.ContentRootPath;


}

IWebHostEnvironment , özel Ara yazılımoluştururken Invoke yöntemine eklenebilir:

public async Task Invoke(HttpContext context, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}

var contentRootPath = env.ContentRootPath;


}

Ihostingenvironment arabirimi
Ihostingenvironment arabirimi , uygulamanın Web barındırma ortamı hakkında bilgi sağlar. Özelliklerini ve
uzantı yöntemlerini kullanmak için IHostingEnvironment almak üzere Oluşturucu Ekleme kullanın:

public class CustomFileReader


{
private readonly IHostingEnvironment _env;

public CustomFileReader(IHostingEnvironment env)


{
_env = env;
}

public string ReadFile(string filePath)


{
var fileProvider = _env.WebRootFileProvider;
// Process the file here
}
}

Uygulamayı ortama göre başlangıçta yapılandırmak için kural tabanlı bir yaklaşım kullanılabilir. Alternatif
olarak, ConfigureServices kullanım için Startup oluşturucusuna IHostingEnvironment ekleyin:
public class Startup
{
public Startup(IHostingEnvironment env)
{
HostingEnvironment = env;
}

public IHostingEnvironment HostingEnvironment { get; }

public void ConfigureServices(IServiceCollection services)


{
if (HostingEnvironment.IsDevelopment())
{
// Development configuration
}
else
{
// Staging/Production configuration
}

var contentRootPath = HostingEnvironment.ContentRootPath;


}
}

NOTE
IsDevelopment uzantısı yöntemine ek olarak, IHostingEnvironment IsStaging , IsProduction ve
IsEnvironment(string environmentName) yöntemleri sunar. Daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları
kullanma.

IHostingEnvironment hizmeti ayrıca işlem ardışık düzenini ayarlamak için doğrudan Configure yöntemine
eklenebilir:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
// In Development, use the Developer Exception Page
app.UseDeveloperExceptionPage();
}
else
{
// In Staging/Production, route exceptions to /error
app.UseExceptionHandler("/error");
}

var contentRootPath = env.ContentRootPath;


}

IHostingEnvironment , özel Ara yazılımoluştururken Invoke yöntemine eklenebilir:


public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}

var contentRootPath = env.ContentRootPath;


}

Ihostapplicationlifetime arabirimi
IHostApplicationLifetime , başlatma sonrası ve kapalı etkinlikler için izin verir. Arabirimdeki üç özellik, başlangıç
ve kapalı olayları tanımlayan Action yöntemlerini kaydetmek için kullanılan iptal belirteçleridir.

İPTAL BELIRTECI TETIKLENDIĞI ZAMAN…

ApplicationStarted Konak tam olarak başlatıldı.

ApplicationStopped Ana bilgisayar düzgün kapanma işlemini tamamlıyor. Tüm


isteklerin işlenmesi gerekir. Bu olay tamamlanana kadar
kapalı bloklar.

ApplicationStopping Ana bilgisayar düzgün bir şekilde kapanma gerçekleştiriyor.


İstekler hala işliyor olabilir. Bu olay tamamlanana kadar kapalı
bloklar.
public class Startup
{
public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime)
{
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);

Console.CancelKeyPress += (sender, eventArgs) =>


{
appLifetime.StopApplication();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}

private void OnStarted()


{
// Perform post-startup activities here
}

private void OnStopping()


{
// Perform on-stopping activities here
}

private void OnStopped()


{
// Perform post-stopped activities here
}
}

StopApplication , uygulamanın sonlandırılmasını ister. Aşağıdaki sınıf, sınıfın Shutdown yöntemi çağrıldığında
bir uygulamayı düzgün bir şekilde kapatmak için StopApplication kullanır:

public class MyClass


{
private readonly IHostApplicationLifetime _appLifetime;

public MyClass(IHostApplicationLifetime appLifetime)


{
_appLifetime = appLifetime;
}

public void Shutdown()


{
_appLifetime.StopApplication();
}
}

Iapplicationlifetime arabirimi
Iapplicationlifetime , başlatma sonrası ve kapalı etkinlikler için izin verir. Arabirimdeki üç özellik, başlangıç ve
kapalı olayları tanımlayan Action yöntemlerini kaydetmek için kullanılan iptal belirteçleridir.

İPTAL BELIRTECI TETIKLENDIĞI ZAMAN…

ApplicationStarted Konak tam olarak başlatıldı.


İPTAL BELIRTECI TETIKLENDIĞI ZAMAN…

Applicationdurdurulan Ana bilgisayar düzgün kapanma işlemini tamamlıyor. Tüm


isteklerin işlenmesi gerekir. Bu olay tamamlanana kadar
kapalı bloklar.

Applicationdurduruluyor Ana bilgisayar düzgün bir şekilde kapanma gerçekleştiriyor.


İstekler hala işliyor olabilir. Bu olay tamamlanana kadar kapalı
bloklar.

public class Startup


{
public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
{
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);

Console.CancelKeyPress += (sender, eventArgs) =>


{
appLifetime.StopApplication();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}

private void OnStarted()


{
// Perform post-startup activities here
}

private void OnStopping()


{
// Perform on-stopping activities here
}

private void OnStopped()


{
// Perform post-stopped activities here
}
}

StopApplication , uygulamanın sonlandırılmasını ister. Aşağıdaki sınıf, sınıfın Shutdown yöntemi çağrıldığında
bir uygulamayı düzgün bir şekilde kapatmak için StopApplication kullanır:

public class MyClass


{
private readonly IApplicationLifetime _appLifetime;

public MyClass(IApplicationLifetime appLifetime)


{
_appLifetime = appLifetime;
}

public void Shutdown()


{
_appLifetime.StopApplication();
}
}

Kapsam doğrulaması
Createdefaultbuilder , uygulamanın ortamı geliştirmede true Için serviceprovideroptions. validatescopes
öğesini ayarlar.
ValidateScopes true olarak ayarlandığında, varsayılan hizmet sağlayıcı aşağıdakileri doğrulamak için
denetimler gerçekleştirir:
Kapsamlı hizmetler doğrudan veya dolaylı olarak kök hizmet sağlayıcısından çözümlenmez.
Kapsamlı hizmetler doğrudan veya dolaylı olarak Singleton 'a eklenmiş değildir.
Buildserviceprovider çağrıldığında kök hizmet sağlayıcısı oluşturulur. Kök hizmet sağlayıcısının ömrü,
sağlayıcının uygulamayla başladığı ve uygulama kapandığında bırakıldığı uygulama/sunucunun yaşam süresine
karşılık gelir.
Kapsamlı hizmetler kendilerini oluşturan kapsayıcı tarafından atılmış. Kök kapsayıcıda kapsamlı bir hizmet
oluşturulduysa, hizmetin ömrü etkin şekilde tek başına yükseltilir çünkü yalnızca uygulama/sunucu
kapatıldığında kök kapsayıcı tarafından atılmış olur. Hizmet kapsamlarını doğrulamak BuildServiceProvider
çağrıldığında bu durumları yakalar.
Üretim ortamında da dahil olmak üzere kapsamları her zaman doğrulamak için, ana bilgisayar Oluşturucu 'da
Serviceprovideroptions 'ı usedefaultserviceprovider ile yapılandırın:

WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})

Ek kaynaklar
IIS ile Windows üzerinde ASP.NET Core barındırma
NGINX ile Linux üzerinde ana bilgisayar ASP.NET Core
Apache ile Linux üzerinde ASP.NET Core barındırma
Windows hizmetinde konak ASP.NET Core
ASP.NET Core Web sunucusu uygulamaları
26.11.2019 • 13 minutes to read • Edit Online

Tom Dykstra, Steve Smith, Stephen halterve Chris 'e göre


ASP.NET Core bir uygulama, işlem içi HTTP sunucu uygulamasıyla çalışır. Sunucu uygulaması, HTTP isteklerini
dinler ve bir HttpContextoluşan istek özellikleri kümesi olarak bunları uygulamaya sunar.

Kestrel
Kestrel, ASP.NET Core projesi şablonları tarafından belirtilen varsayılan Web sunucusudur.
Kestrel kullanın:
Kendi başına bir uç sunucu olarak, Internet dahil olmak üzere istekleri doğrudan bir ağdan işleme.

Internet Information Services (IIS ), NGINXveya Apachegibi bir ters ara sunucuile. Ters proxy sunucusu,
Internet 'ten gelen HTTP isteklerini alır ve Kestrel 'e iletir.

Ters ara sunucu—sahip veya olmayan—barındırma yapılandırması desteklenir.


Kestrel yapılandırma kılavuzu ve Kestrel 'in bir ters proxy yapılandırmasında ne zaman kullanılacağı hakkında
bilgi için bkz. ASP.NET Core Web sunucusu uygulamasını Kestrel.
Windows
macOS
'Un
ASP.NET Core aşağıdakiler ile birlikte gelir:
Kestrel sunucusu varsayılan, platformlar arası http sunucu uygulamasıdır.
IIS HTTP sunucusu, IIS için bir işlem içi sunucusudur .
Http. sys sunucusu , http. sys çekırdek sürücüsünü ve http sunucusu API'sini temel alan bir yalnızca Windows
HTTP sunucusudur.
IIS veya IIS Expresskullanırken, uygulama şu şekilde çalışır:
IIS çalışan işlemiyle aynı işlemde ( işlem içi barındırma modeli) IIS HTTP sunucusu ile. Işlem içi önerilen
yapılandırmadır.
Bir işlemde, IIS çalışan işleminden ( işlem dışı barındırma modeli) Kestrel sunucusuylaayırın.
ASP.NET Core modülü , IIS ile Işlem ıçı IIS HTTP sunucusu ya da Kestrel arasında yerel IIS isteklerini işleyen
yerel bir IIS modülüdür. Daha fazla bilgi için bkz. ASP.NET Core Modülü.
Barındırma modelleri
ASP.NET Core bir uygulama, işlem içi barındırma kullanarak IIS çalışan işlemiyle aynı işlemde çalışır. İşlem içi
barındırma, istek dışı barındırmak için gelişmiş performans sağlar çünkü istekler, giden ağ trafiği ile aynı
makineye geri döndürülen bir ağ arabirimidir. IIS, Windows Işlem etkinleştirme hizmeti (was)ile işlem
yönetimini işler.
İşlem dışı barındırma kullanma, ASP.NET Core uygulamalar IIS çalışan işleminden ayrı bir işlemde çalışır ve
modül işlem yönetimini işler. Modül, ilk istek ulaştığında ASP.NET Core uygulama için işlemi başlatır ve
kapanırsa veya kilitlenirse uygulamayı yeniden başlatır. Bu aslında, Windows Işlem etkinleştirme hizmeti
(was)tarafından yönetilen işlem içi uygulamalarla birlikte görülen davranışdır.
Daha fazla bilgi ve yapılandırma kılavuzu için aşağıdaki konulara bakın:
IIS ile Windows üzerinde ASP.NET Core barındırma
ASP.NET Core Modülü
Windows
macOS
'Un
ASP.NET Core aşağıdakiler ile birlikte gelir:
Kestrel sunucusu , platformlar arası varsayılan HTTP sunucusudur.
Http. sys sunucusu , http. sys çekırdek sürücüsünü ve http sunucusu API'sini temel alan bir yalnızca Windows
HTTP sunucusudur.
IIS veya IIS Expresskullanırken, uygulama IIS çalışan işleminden (işlem dışı) Kestrel sunucusuile ayrı bir işlemde
çalışır.
ASP.NET Core uygulamalar IIS çalışan işleminden ayrı bir işlemde çalıştığından, modül işlem yönetimini işler.
Modül, ilk istek ulaştığında ASP.NET Core uygulama için işlemi başlatır ve kapanırsa veya kilitlenirse
uygulamayı yeniden başlatır. Bu aslında, Windows Işlem etkinleştirme hizmeti (was)tarafından yönetilen işlem içi
uygulamalarla birlikte görülen davranışdır.
Aşağıdaki diyagramda IIS, ASP.NET Core modülü ve işlem dışı barındırılan bir uygulama arasındaki ilişki
gösterilmektedir:

İstekler Web 'den çekirdek modu HTTP. sys sürücüsüne ulaşır. Sürücü, istekleri Web sitesinin yapılandırılmış
bağlantı noktasında IIS 'ye yönlendirir, genellikle 80 (HTTP ) veya 443 (HTTPS ). Modül, 80 veya 443 numaralı
bağlantı noktası olmayan uygulama için rastgele bir bağlantı noktasında istekleri Kestrel 'e iletir.
Modül, başlangıç sırasında bir ortam değişkeni aracılığıyla bağlantı noktasını belirtir ve IIS tümleştirme ara
yazılımı sunucuyu http://localhost:{port} dinlemek üzere yapılandırır. Ek denetimler gerçekleştirilir ve
modülünden kaynaklanmayan istekler reddedilir. Modül HTTPS iletmeyi desteklemez, bu nedenle istekler
HTTPS üzerinden IIS tarafından alınsa bile HTTP üzerinden iletilir.
Kestrel, isteği modülden başlattıktan sonra, istek ASP.NET Core ara yazılım ardışık düzenine gönderilir. Ara
yazılım ardışık düzeni isteği işler ve uygulamanın mantığına bir HttpContext örneği olarak geçirir. IIS
tümleştirmesi tarafından eklenen ara yazılım, isteği Kestrel iletmek için düzen, uzak IP ve pathbase 'i hesaba göre
güncelleştirir. Uygulamanın yanıtı IIS 'e geri geçirilir ve bu, isteği başlatan HTTP istemcisine geri gönderilir.
IIS ve ASP.NET Core modülü yapılandırma kılavuzu için aşağıdaki konulara bakın:
IIS ile Windows üzerinde ASP.NET Core barındırma
ASP.NET Core Modülü
Kestrel ile NGINX
Linux üzerinde NGINX 'i Kestrel için ters proxy sunucusu olarak kullanma hakkında daha fazla bilgi için bkz.
NGINX ile Linux üzerinde ana bilgisayar ASP.NET Core.
Kestrel ile Apache
Linux üzerinde Apache 'yi Kestrel için ters proxy sunucusu olarak kullanma hakkında daha fazla bilgi için bkz.
Apache ile Linux üzerinde ASP.NET Core barındırma.

HTTP.sys
ASP.NET Core uygulamalar Windows üzerinde çalışıyorsa, HTTP. sys, Kestrel için bir alternatiftir. Kestrel
genellikle en iyi performans için önerilir. HTTP. sys, uygulamanın Internet 'e açık olduğu senaryolarda ve gerekli
yetenekler HTTP. sys tarafından desteklenir, ancak Kestrel değildir. Daha fazla bilgi için bkz. ASP.NET Core 'de
HTTP. sys Web sunucusu uygulama.

HTTP. sys, yalnızca bir iç ağa açık olan uygulamalar için de kullanılabilir.

HTTP. sys yapılandırma kılavuzu için bkz. ASP.NET Core 'de HTTP. sys Web sunucusu uygulama.

ASP.NET Core Server altyapısı


Startup.Configure yönteminde kullanılabilen IApplicationBuilder IFeatureCollectiontürü ServerFeatures
özelliğini kullanıma sunar. Kestrel ve HTTP. sys, her biri IServerAddressesFeaturetek bir özelliği kullanıma sunar,
ancak farklı sunucu uygulamaları ek işlevsellik sergilede gösterebilir.
IServerAddressesFeature , sunucu uygulamasının çalışma zamanında hangi bağlantı noktasını bağladığına ilişkin
bilgi edinmek için kullanılabilir.

Özel sunucular
Yerleşik sunucular uygulamanın gereksinimlerini karşılamıyorsa, özel bir sunucu uygulaması oluşturulabilir. .Net
Için açık Web arabirimi (OWıN ) Kılavuzu , nowintabanlı IServer uygulamasının nasıl yazılacağını gösterir.
Yalnızca uygulamanın kullandığı Özellik arabirimleri uygulama gerektirir, ancak en az bir IHttpRequestFeature ve
IHttpResponseFeature desteklenmelidir.

Sunucu başlatma
Tümleşik geliştirme ortamı (IDE ) veya düzenleyici uygulamayı başlattığında sunucu başlatılır:
Visual Studio – başlatma profilleri, uygulamayı ve sunucuyu IIS Express/ASP.NET Core modülü veya
konsolu ile başlatmak için kullanılabilir.
Visual Studio Code – uygulama ve sunucu, CoreCLR hata ayıklayıcısını etkinleştiren Omnisharptarafından
başlatılır.
Mac için Visual Studio – uygulama ve sunucu mono geçici modda hata ayıklayıcıtarafından başlatılır.
Uygulamanın, projenin klasöründeki bir komut isteminden başlatılması sırasında DotNet Run uygulamayı ve
sunucuyu (yalnızca Kestrel ve http. sys) başlatır. Yapılandırma, Debug (varsayılan) veya Release olarak ayarlanan
-c|--configuration seçeneği tarafından belirtilir.

Launchsettings. JSON dosyası, dotnet run Ile veya Visual Studio gibi araç halinde yerleşik bir hata ayıklayıcı ile
bir uygulama başlatırken yapılandırma sağlar. Başlatma profilleri bir Launchsettings. JSON dosyasında varsa,
dotnet run komutuyla --launch-profile {PROFILE NAME} seçeneğini kullanın veya Visual Studio 'da profili seçin.
Daha fazla bilgi için bkz. DotNet Run ve .NET Core Distribution paketleme.

HTTP/2 desteği
Http/2 aşağıdaki dağıtım senaryolarında ASP.NET Core desteklenir:
Kestrel
İşletim sistemi
Windows Server 2016/Windows 10 veya üzeri†
OpenSSL 1.0.2 veya üzerini içeren Linux (örneğin, Ubuntu 16,04 veya üzeri)
HTTP/2, gelecek sürümlerde macOS 'ta desteklenecektir.
Hedef Framework: .NET Core 2,2 veya üzeri
HTTP.sys
Windows Server 2016/Windows 10 veya üzeri
Hedef Framework: HTTP. sys dağıtımları için geçerli değildir.
IIS (işlem içi)
Windows Server 2016/Windows 10 veya üzeri; IIS 10 veya üzeri
Hedef Framework: .NET Core 2,2 veya üzeri
IIS (işlem dışı)
Windows Server 2016/Windows 10 veya üzeri; IIS 10 veya üzeri
Herkese açık uç sunucu bağlantıları HTTP/2 kullanır, ancak Kestrel ile ters proxy bağlantısı HTTP/1.1
kullanır.
Hedef Framework: IIS işlem dışı dağıtımlar için geçerli değildir.
†Kestrel Windows Server 2012 R2 ve Windows 8.1 üzerinde HTTP/2 için sınırlı destek içerir. Bu işletim
sistemlerinde kullanılabilir olan desteklenen TLS şifre paketlerinin listesi sınırlı olduğundan destek sınırlıdır. TLS
bağlantılarının güvenliğini sağlamak için Eliptik Eğri dijital Imza algoritması (ECDSA) kullanılarak oluşturulan bir
sertifika gerekli olabilir.
HTTP.sys
Windows Server 2016/Windows 10 veya üzeri
Hedef Framework: HTTP. sys dağıtımları için geçerli değildir.
IIS (işlem dışı)
Windows Server 2016/Windows 10 veya üzeri; IIS 10 veya üzeri
Herkese açık uç sunucu bağlantıları HTTP/2 kullanır, ancak Kestrel ile ters proxy bağlantısı HTTP/1.1
kullanır.
Hedef Framework: IIS işlem dışı dağıtımlar için geçerli değildir.
Bir HTTP/2 bağlantısı, uygulama katmanı protokol anlaşması (ALPN ) ve TLS 1,2 veya üstünü kullanmalıdır.
Daha fazla bilgi için, sunucu dağıtım senaryolarınıza ait konulara bakın.
Ek kaynaklar
ASP.NET Core Web sunucusu uygulamasını Kestrel
ASP.NET Core Modülü
IIS ile Windows üzerinde ASP.NET Core barındırma
ASP.NET Core uygulamalarını Azure App Service dağıtma
NGINX ile Linux üzerinde ana bilgisayar ASP.NET Core
Apache ile Linux üzerinde ASP.NET Core barındırma
ASP.NET Core 'de HTTP. sys Web sunucusu uygulama
ASP.NET Core yapılandırma
6.11.2019 • 52 minutes to read • Edit Online

Luke Latham tarafından


ASP.NET Core içindeki uygulama yapılandırması, yapılandırma
sağlayıcılarıtarafından belirlenen anahtar-değer çiftlerini temel alır. Yapılandırma
sağlayıcıları yapılandırma verilerini çeşitli yapılandırma kaynaklarından anahtar-değer
çiftlerine okur:
Azure Key Vault
Azure Uygulama yapılandırması
Komut satırı bağımsız değişkenleri
Özel sağlayıcılar (yüklü veya oluşturulmuş)
Dizin dosyaları
Ortam değişkenleri
Bellek içi .NET nesneleri
Ayarlar dosyaları
Ortak yapılandırma sağlayıcısı senaryoları için yapılandırma paketleri ( Microsoft.
Extensions. Configuration), Framework tarafından örtük olarak dahil edilir.
Ortak yapılandırma sağlayıcısı senaryoları için yapılandırma paketleri ( Microsoft.
Extensions. Configuration), Microsoft. Aspnetcore. app metapackageiçinde bulunur.
Örnek uygulamada ve aşağıdaki kod örnekleri Microsoft.Extensions.Configuration ad
alanını kullanır:

using Microsoft.Extensions.Configuration;

Seçenekler stili , bu konuda açıklanan yapılandırma kavramlarının bir uzantısıdır.


Seçenekler, ilgili ayarların gruplarını temsil etmek için sınıfları kullanır. Daha fazla bilgi
için bkz. ASP.NET Core için seçenek kalıbı.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Uygulama yapılandırmasına karşı konak


Uygulama yapılandırıldıktan ve başlatılmadan önce, bir konak yapılandırılır ve
başlatılır. Ana bilgisayar, uygulama başlatma ve ömür yönetiminden sorumludur.Hem
uygulama hem de ana bilgisayar, bu konuda açıklanan yapılandırma sağlayıcıları
kullanılarak yapılandırılır. Ana bilgisayar yapılandırma anahtar-değer çiftleri,
uygulamanın yapılandırmasına de dahildir. Konak oluşturulduğunda yapılandırma
sağlayıcılarının nasıl kullanıldığı ve yapılandırma kaynaklarının konak
yapılandırmasını nasıl etkilediği hakkında daha fazla bilgi için bkz. ASP.NET Core
temelleri.

Varsayılan yapılandırma
ASP.NET Core DotNet yeni şablonlara dayalı Web Apps, bir konak oluştururken
CreateDefaultBuilder çağırır. CreateDefaultBuilder , uygulama için aşağıdaki sırayla
varsayılan yapılandırmayı sağlar:
Genel ana bilgisayarkullanan uygulamalar için aşağıdakiler geçerlidir. Web
konağınıkullanırken varsayılan yapılandırmayla ilgili ayrıntılar için, bu konunun
ASP.NET Core 2,2 sürümünebakın.
Ana bilgisayar yapılandırması şuradan sağlanır:
Ortam değişkenleri, ortam değişkenleri yapılandırma sağlayıcısıkullanılarak
DOTNET_ (örneğin, DOTNET_ENVIRONMENT ) ön ekine sahiptir. Yapılandırma
anahtar-değer çiftleri yüklendiğinde önek ( DOTNET_ ) çıkarılır.
Komut satırı yapılandırma sağlayıcısınıkullanan komut satırı bağımsız
değişkenleri.
Web ana bilgisayar varsayılan yapılandırması oluşturuldu (
ConfigureWebHostDefaults ):
Kestrel, Web sunucusu olarak kullanılır ve uygulamanın yapılandırma
sağlayıcıları kullanılarak yapılandırılır.
Konak filtreleme ara yazılımı ekleyin.
ASPNETCORE_FORWARDEDHEADERS_ENABLED ortam değişkeni true olarak
ayarlandıysa, Iletilen üstbilgiler ara yazılımı ekleyin.
IIS tümleştirmesini etkinleştirin.
Uygulama yapılandırması şuradan sağlanır:
dosya yapılandırma sağlayıcısınıkullanarak appSettings. JSON .
appSettings. Dosya yapılandırma sağlayıcısıkullanılarak {Environment}.
JSON.
Uygulama, giriş derlemesini kullanarak Development ortamda
çalıştırıldığında gizli Yöneticisi .
Ortam değişkenleri yapılandırma sağlayıcısınıkullanarak ortam değişkenleri.
Komut satırı yapılandırma sağlayıcısınıkullanan komut satırı bağımsız
değişkenleri.
ASP.NET Core DotNet yeni şablonlara dayalı Web Apps, bir konak oluştururken
CreateDefaultBuilder çağırır. CreateDefaultBuilder , uygulama için aşağıdaki sırayla
varsayılan yapılandırmayı sağlar:
Web ana bilgisayarıkullanan uygulamalar için aşağıdakiler geçerlidir. Genel ana
bilgisayarıkullanırken varsayılan yapılandırmayla ilgili ayrıntılar için, Bu konunun en
son sürümünebakın.
Ana bilgisayar yapılandırması şuradan sağlanır:
Ortam değişkenleri, ortam değişkenleri yapılandırma sağlayıcısıkullanılarak
ASPNETCORE_ (örneğin, ASPNETCORE_ENVIRONMENT ) ön ekine sahiptir.
Yapılandırma anahtar-değer çiftleri yüklendiğinde önek ( ASPNETCORE_ )
çıkarılır.
Komut satırı yapılandırma sağlayıcısınıkullanan komut satırı bağımsız
değişkenleri.
Uygulama yapılandırması şuradan sağlanır:
dosya yapılandırma sağlayıcısınıkullanarak appSettings. JSON .
appSettings. Dosya yapılandırma sağlayıcısıkullanılarak {Environment}.
JSON.
Uygulama, giriş derlemesini kullanarak Development ortamda
çalıştırıldığında gizli Yöneticisi .
Ortam değişkenleri yapılandırma sağlayıcısınıkullanarak ortam değişkenleri.
Komut satırı yapılandırma sağlayıcısınıkullanan komut satırı bağımsız
değişkenleri.

Güvenlik
Hassas yapılandırma verilerini güvenli hale getirmek için aşağıdaki uygulamaları
benimseyin:
Yapılandırma sağlayıcısı kodunda veya düz metin yapılandırma dosyalarında
parolaları veya diğer hassas verileri hiçbir şekilde depolamayin.
Geliştirme veya test ortamlarında üretim gizli dizileri kullanmayın.
Yanlışlıkla bir kaynak kodu deposuna uygulanamazlar için proje dışındaki gizli
dizileri belirtin.
Daha fazla bilgi için aşağıdaki konulara bakın:
ASP.NET Core çoklu ortamları kullanma
ASP.NET Core sürümünde geliştirme sırasında uygulama gizli dizileri güvenli
depolama –, hassas verileri depolamak için ortam değişkenlerini kullanma
hakkında öneriler Içerir. Gizli dizi Yöneticisi, Kullanıcı gizli dizilerini yerel sistemdeki
bir JSON dosyasında depolamak için dosya yapılandırma sağlayıcısını kullanır.
Dosya yapılandırma sağlayıcısı, bu konunun ilerleyen kısımlarında açıklanmıştır.
Azure Key Vault ASP.NET Core uygulamalar için uygulama gizli dizilerini güvenli bir
şekilde depolar. Daha fazla bilgi için bkz. ASP.NET Core Azure Key Vault yapılandırma
sağlayıcısı.

Hiyerarşik yapılandırma verileri


Yapılandırma API 'SI, hiyerarşik verileri yapılandırma anahtarlarında bir sınırlayıcı
kullanımıyla birlikte düzleştirerek hiyerarşik yapılandırma verilerini muhafaza ediyor.
Aşağıdaki JSON dosyasında, iki bölümün yapılandırılmış hiyerarşisinde dört anahtar
mevcuttur:

{
"section0": {
"key0": "value",
"key1": "value"
},
"section1": {
"key0": "value",
"key1": "value"
}
}

Dosya yapılandırmaya okunduğu zaman, yapılandırma kaynağının özgün hiyerarşik


veri yapısını sürdürmek için benzersiz anahtarlar oluşturulur. Bölüm ve anahtarlar,
özgün yapıyı sürdürmek için iki nokta üst üste ( : ) kullanımıyla düzleştirilir:
section0:key0
section0: KEY1
section1:key0
Section1: KEY1
GetSection ve GetChildren yöntemleri, yapılandırma verilerinde bir bölümün
bölümlerini ve alt öğelerini yalıtmak için kullanılabilir. Bu yöntemler daha sonra
GetSection, GetChildren ve Existsiçinde açıklanmıştır.

Kurallar
Kaynaklar ve sağlayıcılar
Uygulama başlangıcında yapılandırma kaynakları, yapılandırma sağlayıcılarının
belirtilme sırasına göre okundu.
Değişiklik algılamayı uygulayan yapılandırma sağlayıcılarının, temel alınan bir ayar
değiştirildiğinde yapılandırmayı yeniden yükleme yeteneği vardır. Örneğin, dosya
yapılandırma sağlayıcısı (Bu konunun ilerleyen kısımlarında açıklanmıştır) ve Azure
Key Vault yapılandırma sağlayıcısı değişiklik algılamayı uygular.
IConfiguration, uygulamanın bağımlılık ekleme (dı) kapsayıcısında kullanılabilir.
IConfiguration, sınıfın yapılandırmasını elde etmek için bir Razor Pages PageModel
eklenebilir:

public class IndexModel : PageModel


{
private readonly IConfiguration _config;

public IndexModel(IConfiguration config)


{
_config = config;
}

// The _config local variable is used to obtain configuration


// throughout the class.
}

Yapılandırma sağlayıcıları, ana bilgisayar tarafından ayarlandıklarında


kullanılamadığından, DI 'yi kullanamaz.
Belirlenmesine
Yapılandırma anahtarları aşağıdaki kuralları benimseyin:
Anahtarlar büyük/küçük harfe duyarlıdır. Örneğin, ConnectionString ve
connectionstring denk anahtarlar olarak değerlendirilir.
Aynı anahtar için bir değer aynı veya farklı yapılandırma sağlayıcıları tarafından
ayarlandıysa, anahtardaki en son değer kullanılan değerdir.
Hiyerarşik anahtarlar
Yapılandırma API 'SI içinde, tüm platformlarda bir iki nokta ayırıcı ( : )
kullanılır.
Ortam değişkenlerinde, tüm platformlarda bir iki nokta ayırıcı çalışmayabilir.
Çift alt çizgi ( __ ) tüm platformlar tarafından desteklenir ve otomatik olarak
iki nokta olarak dönüştürülür.
Azure Key Vault hiyerarşik anahtarlar ayırıcı olarak -- (iki tire) kullanır.
Gizli dizileri uygulamanın yapılandırmasına yüklendiğinde tirelerin yerini iki
nokta ile değiştirmek için kod sağlamanız gerekir.
ConfigurationBinder, yapılandırma anahtarlarındaki dizi dizinlerini kullanan
nesnelere dizileri bağlamayı destekler. Dizi bağlama, diziyi bir sınıfa bağlama
bölümünde açıklanmıştır.
Değerler
Yapılandırma değerleri aşağıdaki kuralları benimseyin:
Değerler dizelerdir.
Null değerler yapılandırmada saklanamaz veya nesnelere bağlanabilir.

sağlayıcılarla
Aşağıdaki tabloda ASP.NET Core uygulamalar için kullanılabilen yapılandırma
sağlayıcıları gösterilmektedir.

SAĞLAYICI … YAPILANDIRMA SAĞLAR

Azure Key Vault yapılandırma sağlayıcısı Azure Key Vault


(güvenlik konuları)

Azure uygulama yapılandırma sağlayıcısı Azure Uygulama yapılandırması


(Azure belgeleri)

Komut satırı yapılandırma sağlayıcısı Komut satırı parametreleri

Özel yapılandırma sağlayıcısı Özel kaynak

Ortam değişkenleri yapılandırma sağlayıcısı Ortam değişkenleri

Dosya yapılandırma sağlayıcısı Dosyalar (ıNı, JSON, XML)

Dosya başına anahtar yapılandırma sağlayıcısı Dizin dosyaları

Bellek yapılandırma sağlayıcısı Bellek içi Koleksiyonlar

Kullanıcı gizli dizileri (gizli yönetici) (güvenlik Kullanıcı profili dizinindeki dosya
konuları)

Yapılandırma kaynakları, başlangıçta yapılandırma sağlayıcılarının belirtilme sırasına


göre okundu. Bu konuda açıklanan yapılandırma sağlayıcıları, kodunuzun onları
düzenleyebilir sırada değil alfabetik sırayla açıklanmıştır. Kodunuzda yapılandırma
sağlayıcılarını, temeldeki yapılandırma kaynakları için önceliklerinize uyacak şekilde
sıralayın.
Yapılandırma sağlayıcılarının tipik bir sırası şunlardır:
1. Dosyalar (appSettings. JSON, appSettings. { Environment}. JSON, {Environment}
uygulamanın geçerli barındırma ortamıdır.
2. Azure Key Vault
3. Kullanıcı gizli dizileri (gizli yönetici) (yalnızca geliştirme ortamı)
4. Ortam değişkenleri
5. Komut satırı bağımsız değişkenleri
Ortak bir uygulama, komut satırı bağımsız değişkenlerinin diğer sağlayıcılar
tarafından ayarlanan yapılandırmayı geçersiz kılmasını sağlamak üzere komut satırı
yapılandırma sağlayıcısını bir sağlayıcı serisinde en son konumlandırmaktır.
Önceki sağlayıcı dizisi, CreateDefaultBuilder ile yeni bir konak Oluşturucu
başlattığınızda kullanılır. Daha fazla bilgi için varsayılan yapılandırma bölümüne bakın.
Konak oluşturucuyu ConfigureHostConfiguration ile
yapılandırma
Konak oluşturucuyu yapılandırmak için ConfigureHostConfiguration çağırın ve
yapılandırmayı sağlayın. ConfigureHostConfiguration , derleme sürecinde daha sonra
kullanmak üzere IHostEnvironment başlatmak için kullanılır.
ConfigureHostConfiguration , eklenebilir sonuçlarla birden çok kez çağrılabilir.

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(config =>
{
var dict = new Dictionary<string, string>
{
{"MemoryCollectionKey1", "value1"},
{"MemoryCollectionKey2", "value2"}
};

config.AddInMemoryCollection(dict);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Konak oluşturucuyu UseConfiguration ile


yapılandırma
Konak oluşturucuyu yapılandırmak için, yapılandırma ile konak Oluşturucu üzerinde
UseConfiguration çağırın.

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var dict = new Dictionary<string, string>
{
{"MemoryCollectionKey1", "value1"},
{"MemoryCollectionKey2", "value2"}
};

var config = new ConfigurationBuilder()


.AddInMemoryCollection(dict)
.Build();

return WebHost.CreateDefaultBuilder(args)
.UseConfiguration(config)
.UseStartup<Startup>();
}

ConfigureAppConfiguration
CreateDefaultBuilder tarafından otomatik olarak eklenenlere ek olarak, uygulamanın
yapılandırma sağlayıcılarını belirlemek için konak oluştururken
ConfigureAppConfiguration çağırın:
public class Program
{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
public class Program
{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.UseStartup<Startup>();
}

Önceki yapılandırmayı komut satırı bağımsız değişkenleriyle geçersiz kıl


Komut satırı bağımsız değişkenleriyle geçersiz kılınabilen uygulama yapılandırması
sağlamak için AddCommandLine son ' u çağırın:

.ConfigureAppConfiguration((hostingContext, config) =>


{
// Call other providers here
config.AddCommandLine(args);
})

CreateDefaultBuilder tarafından eklenen sağlayıcıları kaldır


CreateDefaultBuilder tarafından eklenen sağlayıcıları kaldırmak için, önce
ılisteationbuilder. Sources üzerinde clear öğesini çağırın:

.ConfigureAppConfiguration((hostingContext, config) =>


{
config.Sources.Clear();
// Add providers here
})

Uygulama başlatma sırasında yapılandırmayı kullan


ConfigureAppConfiguration içinde uygulamaya sağlanan yapılandırma, uygulamanın
başlangıcında Startup.ConfigureServices dahil olmak üzere kullanılabilir. Daha fazla
bilgi için başlatma sırasında erişim yapılandırması bölümüne bakın.
Komut satırı yapılandırma sağlayıcısı
CommandLineConfigurationProvider, çalışma zamanında komut satırı bağımsız
değişkeni anahtar-değer çiftinden yapılandırma yükler.
Komut satırı yapılandırmasını etkinleştirmek için, AddCommandLine uzantısı yöntemi
bir ConfigurationBuilder örneğinde çağrılır.
AddCommandLine , CreateDefaultBuilder(string []) çağrıldığında otomatik olarak
çağrılır. Daha fazla bilgi için varsayılan yapılandırma bölümüne bakın.
CreateDefaultBuilder de yüklenir:
AppSettings. JSON ve appSettings 'ten isteğe bağlı yapılandırma . { Environment}.
JSON dosyaları.
Geliştirme ortamında Kullanıcı gizli dizileri (gizli yönetici) .
Ortam değişkenleri.
CreateDefaultBuilder , komut satırı yapılandırma sağlayıcısını en son ekler. Diğer
sağlayıcılar tarafından ayarlanan çalışma zamanında geçersiz kılma yapılandırmasında
komut satırı bağımsız değişkenleri geçirildi.
CreateDefaultBuilder ana bilgisayar oluşturulduğunda davranır. Bu nedenle,
CreateDefaultBuilder tarafından etkinleştirilen komut satırı yapılandırması konağın
nasıl yapılandırıldığını etkileyebilir.
ASP.NET Core şablonlarına dayalı uygulamalar için, AddCommandLine
CreateDefaultBuilder tarafından zaten çağırılır. Ek yapılandırma sağlayıcıları eklemek
ve bu sağlayıcılardan yapılandırmayı komut satırı bağımsız değişkenleriyle geçersiz
kılmak için, ConfigureAppConfiguration 'de uygulamanın ek sağlayıcılarını çağırın ve
AddCommandLine son ' u çağırın.

.ConfigureAppConfiguration((hostingContext, config) =>


{
// Call other providers here
config.AddCommandLine(args);
})

Örnek
Örnek uygulama, AddCommandLine bir çağrı içeren konağı oluşturmak için
CreateDefaultBuilder statik kolaylık yönteminden yararlanır.

1. Projenin dizininde bir komut istemi açın.


2. dotnet run komutuna bir komut satırı bağımsız değişkeni sağlayın,
dotnet run CommandLineKey=CommandLineValue .
3. Uygulama çalıştıktan sonra, http://localhost:5000 konumundaki uygulamaya bir
tarayıcı açın.
4. Çıktının dotnet run için belirtilen yapılandırma komut satırı bağımsız değişkeni
için anahtar-değer çiftini içerdiğini gözlemleyin.
Arguments
Değer bir eşittir işareti ( = ) izlemelidir veya değer bir boşluk izleyen anahtarın bir ön
eki ( -- veya / ) olmalıdır. Eşittir işareti kullanılırsa değer gerekli değildir (örneğin,
CommandLineKey= ).
ANAHTAR ÖN EKI ÖRNEK

Ön ek yok CommandLineKey1=value1

İki kısa çizgi ( -- ) --CommandLineKey2=value2 ,


--CommandLineKey2 value2

Eğik çizgi ( / ) /CommandLineKey3=value3 ,


/CommandLineKey3 value3

Aynı komut içinde, bir boşluk kullanan anahtar-değer çiftleri ile bir eşittir işareti
kullanan komut satırı bağımsız değişkeni anahtar-değer çiftlerini karıştırmayın.
Örnek komutlar:

dotnet run CommandLineKey1=value1 --CommandLineKey2=value2 /CommandLineKey3=value3


dotnet run --CommandLineKey1 value1 /CommandLineKey2 value2
dotnet run CommandLineKey1= CommandLineKey2=value2

Eşleme Değiştir
Anahtar eşlemeleri anahtar adı değiştirme mantığına izin verir. Yapılandırmayı bir
ConfigurationBuilder ile el ile oluşturduğunuzda, AddCommandLine yöntemine
anahtar değiştirme sözlüğü sağlayabilirsiniz.
Anahtar eşlemeleri sözlüğü kullanıldığında, sözlük bir komut satırı bağımsız değişkeni
tarafından sunulan anahtarla eşleşen bir anahtar için denetlenir. Komut satırı anahtarı
sözlükte bulunursa, sözlük değeri (anahtar değiştirme), anahtar-değer çiftini
uygulamanın yapılandırmasına ayarlamak için geri geçirilir. Tek tire ( - ) ön eki olan
herhangi bir komut satırı anahtarı için bir anahtar eşlemesi gereklidir.
Anahtar eşlemeleri sözlük anahtarı kuralları:
Anahtarlar tireyle ( - ) veya çift tireyle başlamalıdır ( -- ).
Anahtar eşlemeleri sözlüğü yinelenen anahtarlar içermemelidir.
Anahtar eşlemeleri sözlüğü oluşturun. Aşağıdaki örnekte, iki anahtar eşlemesi
oluşturulur:

public static readonly Dictionary<string, string> _switchMappings =


new Dictionary<string, string>
{
{ "-CLKey1", "CommandLineKey1" },
{ "-CLKey2", "CommandLineKey2" }
};

Konak oluşturulduğunda, anahtar eşlemeleri sözlüğüne AddCommandLine çağırın:

.ConfigureAppConfiguration((hostingContext, config) =>


{
config.AddCommandLine(args, _switchMappings);
})

Anahtar eşlemeleri kullanan uygulamalar için CreateDefaultBuilder çağrısı bağımsız


değişkenleri iletmemelidir. CreateDefaultBuilder yönteminin AddCommandLine çağrısı,
eşlenmiş anahtarlar içermez ve anahtar eşleme sözlüğünü CreateDefaultBuilder 'e
iletmenin bir yolu yoktur. Çözüm CreateDefaultBuilder bağımsız değişkenleri
geçirmektir, ancak ConfigurationBuilder yönteminin AddCommandLine yönteminin hem
bağımsız değişkenleri hem de anahtar eşleme sözlüğünü işlemesini sağlamak için.
Anahtar eşlemeleri sözlüğü oluşturulduktan sonra, aşağıdaki tabloda gösterilen
verileri içerir.

ANAHTAR DEĞER

-CLKey1 CommandLineKey1

-CLKey2 CommandLineKey2

Uygulama başlatılırken anahtar eşlenmiş anahtarlar kullanılıyorsa, yapılandırma


sözlük tarafından sağlanan anahtardaki yapılandırma değerini alır:

dotnet run -CLKey1=value1 -CLKey2=value2

Önceki komutu çalıştırdıktan sonra, yapılandırma aşağıdaki tabloda gösterilen


değerleri içerir.

ANAHTAR DEĞER

CommandLineKey1 value1

CommandLineKey2 value2

Ortam değişkenleri yapılandırma sağlayıcısı


EnvironmentVariablesConfigurationProvider, çalışma zamanında anahtar-değer
çiftlerinde bulunan yapılandırmayı yükler.
Ortam değişkenleri yapılandırmasını etkinleştirmek için, ConfigurationBuilder bir
örneği üzerinde AddEnvironmentVariables uzantısı metodunu çağırın.
Ortam değişkenlerinde hiyerarşik anahtarlarla çalışırken, bir iki nokta ayırıcı ( : ) tüm
platformlarda çalışmayabilir (örneğin, Bash). Çift alt çizgi ( __ ) tüm platformlar
tarafından desteklenir ve otomatik olarak iki nokta ile değiştirilmiştir.
Azure App Service , Azure portalında ortam değişkenleri yapılandırma sağlayıcısını
kullanarak uygulama yapılandırmasını geçersiz kılabileceğiniz ortam değişkenlerini
ayarlamanıza izin verir. Daha fazla bilgi için bkz. Azure uygulamaları: Azure portalını
kullanarak uygulama yapılandırmasını geçersiz kılma.
AddEnvironmentVariables , genel ana bilgisayarla yeni bir konak Oluşturucu
başlatıldığında ve CreateDefaultBuilder çağrıldığında, ana bilgisayar yapılandırması
için DOTNET_ ön eki eklenmiş ortam değişkenlerini yüklemek için kullanılır. Daha fazla
bilgi için varsayılan yapılandırma bölümüne bakın.
AddEnvironmentVariables , Web ana bilgisayarıyla yeni bir ana bilgisayar Oluşturucu
başlatıldığında ve CreateDefaultBuilder çağrıldığında, ana bilgisayar yapılandırması
için ASPNETCORE_ ön eki eklenmiş ortam değişkenlerini yüklemek için kullanılır. Daha
fazla bilgi için varsayılan yapılandırma bölümüne bakın.
CreateDefaultBuilder de yüklenir:
Önek olmadan AddEnvironmentVariables çağırarak, ön eki edilmemiş ortam
değişkenlerinden uygulama yapılandırması.
AppSettings. JSON ve appSettings 'ten isteğe bağlı yapılandırma . { Environment}.
JSON dosyaları.
Geliştirme ortamında Kullanıcı gizli dizileri (gizli yönetici) .
Komut satırı bağımsız değişkenleri.
Ortam değişkenleri yapılandırma sağlayıcısı, Kullanıcı gizli dizileri ve appSettings
dosyalarından yapılandırma kurulduktan sonra çağrılır. Bu konumda sağlayıcıyı
çağırmak, çalışma zamanında ortam değişkenlerinin Kullanıcı parolaları ve
appSettings dosyaları tarafından ayarlanan yapılandırmayı geçersiz kılmak için
okumasına izin verir.
Ek ortam değişkenlerinden uygulama yapılandırması sağlamanız gerekiyorsa,
uygulamanın ConfigureAppConfiguration ek sağlayıcılarını çağırın ve önekiyle birlikte
AddEnvironmentVariables çağırın.

.ConfigureAppConfiguration((hostingContext, config) =>


{
// Call additional providers here as needed.
// Call AddEnvironmentVariables last if you need to allow
// environment variables to override values from other
// providers.
config.AddEnvironmentVariables(prefix: "PREFIX_");
})
}

Örnek
Örnek uygulama, AddEnvironmentVariables bir çağrı içeren konağı oluşturmak için
CreateDefaultBuilder statik kolaylık yönteminden yararlanır.
1. Örnek uygulamayı çalıştırın. http://localhost:5000 konumundaki uygulamaya bir
tarayıcı açın.
2. Çıktının ENVIRONMENT ortam değişkeni için anahtar-değer çiftini içerdiğini
gözlemleyin. Değer, uygulamanın çalıştığı ortamı yansıtır, genellikle yerel olarak
çalışırken Development .

Uygulama kısaltması tarafından oluşturulan ortam değişkenlerinin listesini tutmak


için, uygulama ortam değişkenlerini filtreler. Örnek uygulamanın Pages/Index. cshtml.
cs dosyasına bakın.
Uygulama için kullanılabilir tüm ortam değişkenlerini göstermek istiyorsanız,
Pages/Index. cshtml. cs ' deki FilteredConfiguration aşağıdaki gibi değiştirin:

FilteredConfiguration = _config.AsEnumerable();

Ön Ekler
Uygulama yapılandırmasına yüklenen ortam değişkenleri, AddEnvironmentVariables
yöntemine bir ön ek sağladığınız zaman filtrelenir. Örneğin, önek CUSTOM_ ortam
değişkenlerini filtrelemek için, yapılandırma sağlayıcısına öneki sağlayın:
var config = new ConfigurationBuilder()
.AddEnvironmentVariables("CUSTOM_")
.Build();

Yapılandırma anahtar-değer çiftleri oluşturulduğunda ön ek çıkarılır.


Konak Oluşturucu oluşturulduğunda, ana bilgisayar yapılandırması ortam
değişkenleri tarafından sağlanır. Bu ortam değişkenleri için kullanılan önek hakkında
daha fazla bilgi için varsayılan yapılandırma bölümüne bakın.
Bağlantı dizesi önekleri
Yapılandırma API 'SI, uygulama ortamı için Azure bağlantı dizelerini yapılandırma ile
ilgili dört bağlantı dizesi ortam değişkeni için özel işlem kuralları içerir.
AddEnvironmentVariables için bir önek sağlanmazsa, tabloda gösterilen öneklere sahip
ortam değişkenleri uygulamaya yüklenir.

BAĞLANTI DIZESI ÖNEKI SAĞLAYICI

CUSTOMCONNSTR_ Özel sağlayıcı

MYSQLCONNSTR_ MySQL

SQLAZURECONNSTR_ Azure SQL veritabanı

SQLCONNSTR_ SQL Server

Bir ortam değişkeni keşfedildiğinde ve tabloda gösterilen dört önekle yapılandırmaya


yüklendiğinde:
Yapılandırma anahtarı, ortam değişkeni öneki kaldırılarak ve bir yapılandırma
anahtarı bölümü ( ConnectionStrings ) eklenerek oluşturulur.
Veritabanı bağlantı sağlayıcısını temsil eden yeni bir yapılandırma anahtar-değer
çifti oluşturulur ( CUSTOMCONNSTR_ hariç, belirtilen sağlayıcı olmayan).

DÖNÜŞTÜRÜLEN SAĞLAYICI YAPILANDIRMA


ORTAM DEĞIŞKENI ANAHTARI YAPILANDIRMA ANAHTARI GIRIŞI

CUSTOMCONNSTR_<KEY> ConnectionStrings:<KEY> Yapılandırma girişi


oluşturulmamış.

MYSQLCONNSTR_<KEY> ConnectionStrings:<KEY> Anahtar:


ConnectionStrings:
<KEY>_ProviderName
:
Değer:
MySql.Data.MySqlClient

SQLAZURECONNSTR_<KEY> ConnectionStrings:<KEY> Anahtar:


ConnectionStrings:
<KEY>_ProviderName
:
Değer:
System.Data.SqlClient
DÖNÜŞTÜRÜLEN SAĞLAYICI YAPILANDIRMA
ORTAM DEĞIŞKENI ANAHTARI YAPILANDIRMA ANAHTARI GIRIŞI

SQLCONNSTR_<KEY> ConnectionStrings:<KEY> Anahtar:


ConnectionStrings:
<KEY>_ProviderName
:
Değer:
System.Data.SqlClient

Dosya yapılandırma sağlayıcısı


FileConfigurationProvider, dosya sisteminden yapılandırma yüklemeye yönelik temel
sınıftır. Aşağıdaki yapılandırma sağlayıcıları belirli dosya türlerine ayrılmıştır:
INı yapılandırma sağlayıcısı
JSON yapılandırma sağlayıcısı
XML yapılandırma sağlayıcısı
INı yapılandırma sağlayıcısı
IniConfigurationProvider, çalışma zamanında ıNı dosyası anahtar-değer çiftlerinden
yapılandırmayı yükler.
INI dosya yapılandırmasını etkinleştirmek için bir ConfigurationBuilder örneğinde
AddIniFile uzantısı metodunu çağırın.
İki nokta üst üste, ıNı dosya yapılandırmasındaki bir bölüm sınırlayıcısı olarak
kullanılabilir.
Aşırı yüklemeler belirtmeye izin ver:
Dosyanın isteğe bağlı olup olmadığı.
Dosya değişirse yapılandırmanın yeniden yüklenip yüklenmediğini belirtir.
Dosyaya erişmek için kullanılan IFileProvider.
Uygulamanın yapılandırmasını belirtmek için konak oluştururken
ConfigureAppConfiguration çağırın:

.ConfigureAppConfiguration((hostingContext, config) =>


{
config.AddIniFile(
"config.ini", optional: true, reloadOnChange: true);
})

Bir ıNı yapılandırma dosyasına genel bir örnek:


[section0]
key0=value
key1=value

[section1]
subsection:key=value

[section2:subsection0]
key=value

[section2:subsection1]
key=value

Önceki yapılandırma dosyası value aşağıdaki anahtarları yükler:


section0:key0
section0: KEY1
Section1: alt bölüm: anahtar
section2: subsection0: anahtar
section2: subsection1: anahtar
JSON yapılandırma sağlayıcısı
JsonConfigurationProvider, çalışma zamanı sırasında JSON dosya anahtar-değer
çiftlerinden yapılandırmayı yükler.
JSON dosya yapılandırmasını etkinleştirmek için, ConfigurationBuilder bir örneği
üzerinde AddJsonFile uzantısı metodunu çağırın.
Aşırı yüklemeler belirtmeye izin ver:
Dosyanın isteğe bağlı olup olmadığı.
Dosya değişirse yapılandırmanın yeniden yüklenip yüklenmediğini belirtir.
Dosyaya erişmek için kullanılan IFileProvider.
CreateDefaultBuilder ile yeni bir ana bilgisayar Oluşturucu başlattığınızda
AddJsonFile otomatik olarak iki kez çağrılır. Yöntemi, yapılandırmayı şuradan
yüklemek için çağrılır:
appSettings. json – bu dosya ilk kez okundu. Dosyanın ortam sürümü, appSettings.
JSON dosyası tarafından belirtilen değerleri geçersiz kılabilir.
appSettings. {Environment}. JSON – dosyanın ortam sürümü
ıhostingenvironment. EnvironmentNametemel alınarak yüklenir.
Daha fazla bilgi için varsayılan yapılandırma bölümüne bakın.
CreateDefaultBuilder de yüklenir:
Ortam değişkenleri.
Geliştirme ortamında Kullanıcı gizli dizileri (gizli yönetici) .
Komut satırı bağımsız değişkenleri.
JSON yapılandırma sağlayıcısı önce oluşturulur. Bu nedenle, Kullanıcı gizli dizileri,
ortam değişkenleri ve komut satırı bağımsız değişkenleri, appSettings dosyaları
tarafından ayarlanan yapılandırmayı geçersiz kılar.
Ana bilgisayarı derlerken, appSettings. JSON ve appSettings dışındaki dosyalar için
uygulamanın yapılandırmasını belirtecek ConfigureAppConfiguration çağrısı yapın . {
Environment}. JSON:

.ConfigureAppConfiguration((hostingContext, config) =>


{
config.AddJsonFile(
"config.json", optional: true, reloadOnChange: true);
})

Örnek
Örnek uygulama, AddJsonFileiki çağrı içeren konağı oluşturmak için
CreateDefaultBuilder statik kolaylık yönteminden yararlanır. Yapılandırma
appSettings. JSON ve appSettings 'ten yüklendi . { Environment}. JSON.
1. Örnek uygulamayı çalıştırın. http://localhost:5000 konumundaki uygulamaya bir
tarayıcı açın.
2. Çıktının, ortama bağlı olarak tabloda gösterilen yapılandırma için anahtar-değer
çiftleri içerdiğini gözlemleyin. Günlüğe kaydetme yapılandırma anahtarları
hiyerarşik ayırıcı olarak iki nokta ( : ) kullanır.

ANAHTAR GELIŞTIRME DEĞERI ÜRETIM DEĞERI

Günlüğe kaydetme: Bilgiler Bilgiler


LogLevel: System

Günlüğe kaydetme: Bilgiler Bilgiler


LogLevel: Microsoft

Günlüğe kaydetme: Hata ayıklama Hata


LogLevel: default

Allowedkonakları * *

XML yapılandırma sağlayıcısı


XmlConfigurationProvider, çalışma zamanında XML dosya anahtar-değer çiftinden
yapılandırma yükler.
XML dosya yapılandırmasını etkinleştirmek için, ConfigurationBuilder bir örneği
üzerinde AddXmlFile uzantısı metodunu çağırın.
Aşırı yüklemeler belirtmeye izin ver:
Dosyanın isteğe bağlı olup olmadığı.
Dosya değişirse yapılandırmanın yeniden yüklenip yüklenmediğini belirtir.
Dosyaya erişmek için kullanılan IFileProvider.
Yapılandırma anahtar-değer çiftleri oluşturulduğunda yapılandırma dosyasının kök
düğümü yok sayılır. Dosyada bir belge türü tanımı (DTD ) veya ad alanı belirtmeyin.
Uygulamanın yapılandırmasını belirtmek için konak oluştururken
ConfigureAppConfiguration çağırın:
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddXmlFile(
"config.xml", optional: true, reloadOnChange: true);
})

XML yapılandırma dosyaları, yinelenen bölümler için farklı öğe adları kullanabilir:

<?xml version="1.0" encoding="UTF-8"?>


<configuration>
<section0>
<key0>value</key0>
<key1>value</key1>
</section0>
<section1>
<key0>value</key0>
<key1>value</key1>
</section1>
</configuration>

Önceki yapılandırma dosyası value aşağıdaki anahtarları yükler:


section0:key0
section0: KEY1
section1:key0
Section1: KEY1
Aynı öğe adını kullanan tekrarlanan öğeler, name özniteliği öğeleri ayırt etmek için
kullanılırsa çalışır:

<?xml version="1.0" encoding="UTF-8"?>


<configuration>
<section name="section0">
<key name="key0">value</key>
<key name="key1">value</key>
</section>
<section name="section1">
<key name="key0">value</key>
<key name="key1">value</key>
</section>
</configuration>

Önceki yapılandırma dosyası value aşağıdaki anahtarları yükler:


Bölüm: section0: Key: Key0
Bölüm: section0: Key: KEY1
Bölüm: Section1: Key: Key0
Bölüm: Section1: Key: KEY1
Öznitelikler, değerler sağlamak için kullanılabilir:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<key attribute="value" />
<section>
<key attribute="value" />
</section>
</configuration>

Önceki yapılandırma dosyası value aşağıdaki anahtarları yükler:


anahtar: öznitelik
Section: Key: özniteliği

Dosya başına anahtar yapılandırma sağlayıcısı


KeyPerFileConfigurationProvider, dizin dosyalarını yapılandırma anahtar-değer çiftleri
olarak kullanır. Anahtar, dosya adıdır. Değer, dosyanın içeriğini içerir. Dosya başına
anahtar yapılandırma sağlayıcısı Docker barındırma senaryolarında kullanılır.
Dosya başına anahtar yapılandırması 'nı etkinleştirmek için, ConfigurationBuilder bir
örneği üzerinde AddKeyPerFile uzantısı metodunu çağırın. Dosyaların directoryPath
mutlak bir yol olmalıdır.
Aşırı yüklemeler belirtmeye izin ver:
Kaynağı yapılandıran bir Action<KeyPerFileConfigurationSource> temsilcisi.
Dizinin isteğe bağlı olup olmadığını ve dizinin yolunu belirtir.
Çift alt çizgi ( __ ), dosya adlarında bir yapılandırma anahtarı sınırlayıcısı olarak
kullanılır. Örneğin, Logging__LogLevel__System dosya adı Logging:LogLevel:System
yapılandırma anahtarını üretir.
Uygulamanın yapılandırmasını belirtmek için konak oluştururken
ConfigureAppConfiguration çağırın:

.ConfigureAppConfiguration((hostingContext, config) =>


{
var path = Path.Combine(
Directory.GetCurrentDirectory(), "path/to/files");
config.AddKeyPerFile(directoryPath: path, optional: true);
})

Bellek yapılandırma sağlayıcısı


MemoryConfigurationProvider, yapılandırma anahtar-değer çiftleri olarak bellek içi
koleksiyon kullanır.
Bellek içi koleksiyon yapılandırmasını etkinleştirmek için, ConfigurationBuilder bir
örneği üzerinde AddInMemoryCollection uzantısı metodunu çağırın.
Yapılandırma sağlayıcısı bir IEnumerable<KeyValuePair<String,String>> başlatılabilir.
Uygulamanın yapılandırmasını belirtmek için Konağı derlerken
ConfigureAppConfiguration çağrısı yapın.

Aşağıdaki örnekte bir yapılandırma sözlüğü oluşturulur:


public static readonly Dictionary<string, string> _dict =
new Dictionary<string, string>
{
{"MemoryCollectionKey1", "value1"},
{"MemoryCollectionKey2", "value2"}
};

Sözlük, yapılandırmayı sağlamak için bir AddInMemoryCollection çağrısıyla kullanılır:

.ConfigureAppConfiguration((hostingContext, config) =>


{
config.AddInMemoryCollection(_dict);
})

GetValue
Configurationciltçi. GetValue <T > , belirli bir anahtarla yapılandırmadan tek bir değer
ayıklar ve belirtilen koleksiyon olmayan türe dönüştürür. Aşırı yükleme varsayılan bir
değeri kabul eder.
Aşağıdaki örnek:
Anahtar NumberKey , yapılandırmadan dize değerini ayıklar. Yapılandırma
anahtarlarında NumberKey bulunmazsa, varsayılan 99 değeri kullanılır.
Değeri bir int olarak türler.
Değeri, sayfanın kullanımı için NumberConfig özelliği içinde depolar.

public class IndexModel : PageModel


{
public IndexModel(IConfiguration config)
{
_config = config;
}

public int NumberConfig { get; private set; }

public void OnGet()


{
NumberConfig = _config.GetValue<int>("NumberKey", 99);
}
}

GetSection, GetChildren ve Exists


İzleyen örnekler için aşağıdaki JSON dosyasını göz önünde bulundurun. İki bölüm
arasında dört anahtar bulunur ve bunlardan biri alt bölümleri çifti içerir:
{
"section0": {
"key0": "value",
"key1": "value"
},
"section1": {
"key0": "value",
"key1": "value"
},
"section2": {
"subsection0" : {
"key0": "value",
"key1": "value"
},
"subsection1" : {
"key0": "value",
"key1": "value"
}
}
}

Dosya yapılandırmaya okunduğu zaman yapılandırma değerlerini tutmak için


aşağıdaki benzersiz hiyerarşik anahtarlar oluşturulur:
section0:key0
section0: KEY1
section1:key0
Section1: KEY1
section2:subsection0:key0
section2: subsection0: KEY1
section2:subsection1:key0
section2: subsection1: KEY1
GetSection
Iconation. GetSection , belirtilen alt bölüm anahtarıyla bir yapılandırma alt bölümü
ayıklar.
yalnızca anahtar-değer çiftlerini içeren bir IConfigurationSection
section1
döndürmek için GetSection çağırın ve bölüm adını sağlayın:

var configSection = _config.GetSection("section1");

configSection bir değer, yalnızca bir anahtar ve yol yoktur.


Benzer şekilde, section2:subsection0 anahtarlar için değerleri almak için, GetSection
çağırın ve Bölüm yolunu sağlayın:

var configSection = _config.GetSection("section2:subsection0");

GetSection hiçbir şekilde null döndürmez. Eşleşen bir bölüm bulunamazsa boş bir
IConfigurationSection döndürülür.

GetSection eşleşen bir bölüm döndürdüğünde Value doldurulmuyor. Bölüm mevcut


olduğunda bir Key ve Path döndürülür.
GetChildren
section2 üzerinde Iconation. GetChildren çağrısı, şunları içeren bir
IEnumerable<IConfigurationSection> edinir:

subsection0
subsection1

var configSection = _config.GetSection("section2");

var children = configSection.GetChildren();

Bulunur
Bir yapılandırma bölümünün mevcut olup olmadığını anlamak için
Configurationextensions. Exists kullanın:

var sectionExists = _config.GetSection("section2:subsection2").Exists();

Örnek veriler verildiğinde, yapılandırma verilerinde bir section2:subsection2 bölümü


olmadığından sectionExists false .

Bir sınıfa bağlama


Yapılandırma, Seçenekler modelinikullanarak ilgili ayarların gruplarını temsil eden
sınıflara bağlanabilir. Daha fazla bilgi için bkz. ASP.NET Core için seçenek kalıbı.
Yapılandırma değerleri dizeler olarak döndürülür, ancak Bind çağrısı poco nesnelerinin
oluşturulmasını mümkün yapar.
Örnek uygulama bir Starship modeli içerir (modeller/Başlangıçgönder. cs):

public class Starship


{
public string Name { get; set; }
public string Registry { get; set; }
public string Class { get; set; }
public decimal Length { get; set; }
public bool Commissioned { get; set; }
}

public class Starship


{
public string Name { get; set; }
public string Registry { get; set; }
public string Class { get; set; }
public decimal Length { get; set; }
public bool Commissioned { get; set; }
}

Starsevk. JSON dosyasının starship bölümü, örnek uygulama yapılandırmayı


yüklemek Için JSON yapılandırma sağlayıcısını kullandığında yapılandırmayı
oluşturur:
{
"starship": {
"name": "USS Enterprise",
"registry": "NCC-1701",
"class": "Constitution",
"length": 304.8,
"commissioned": false
},
"trademark": "Paramount Pictures Corp. http://www.paramount.com"
}

{
"starship": {
"name": "USS Enterprise",
"registry": "NCC-1701",
"class": "Constitution",
"length": 304.8,
"commissioned": false
},
"trademark": "Paramount Pictures Corp. http://www.paramount.com"
}

Aşağıdaki yapılandırma anahtar-değer çiftleri oluşturulur:

ANAHTAR DEĞER

starsevk: ad USS kurumsal

starsevk: kayıt defteri NCC-1701

starsevk: sınıfı Anaytion

başlangıçgönder: Uzunluk 304,8

starsevkiyat: Commissioned False

dır Paramount resimleri Corp.


https://www.paramount.com

Örnek uygulama, starship anahtarıyla GetSection çağırır. starship anahtar-değer


çiftleri yalıtılmıştır. Bind yöntemi, Starship sınıfının bir örneğinde geçen alt bölümde
çağrılır. Örnek değerlerini bağladıktan sonra örnek, işleme için bir özelliğe atanır:

var starship = new Starship();


_config.GetSection("starship").Bind(starship);
Starship = starship;

var starship = new Starship();


_config.GetSection("starship").Bind(starship);
Starship = starship;

Bir nesne grafiğine bağlama


Bind, tüm POCO nesne grafiğini bağlama yeteneğine sahiptir.
Örnek, nesne grafı Metadata ve Actors sınıfları (modeller/TvShow. cs) içeren bir
TvShow modeli içerir:

public class TvShow


{
public Metadata Metadata { get; set; }
public Actors Actors { get; set; }
public string Legal { get; set; }
}

public class Metadata


{
public string Series { get; set; }
public string Title { get; set; }
public DateTime AirDate { get; set; }
public int Episodes { get; set; }
}

public class Actors


{
public string Names { get; set; }
}

public class TvShow


{
public Metadata Metadata { get; set; }
public Actors Actors { get; set; }
public string Legal { get; set; }
}

public class Metadata


{
public string Series { get; set; }
public string Title { get; set; }
public DateTime AirDate { get; set; }
public int Episodes { get; set; }
}

public class Actors


{
public string Names { get; set; }
}

Örnek uygulama, yapılandırma verilerini içeren bir tvshow. xml dosyasına sahiptir:

<?xml version="1.0" encoding="UTF-8"?>


<configuration>
<tvshow>
<metadata>
<series>Dr. Who</series>
<title>The Sun Makers</title>
<airdate>11/26/1977</airdate>
<episodes>4</episodes>
</metadata>
<actors>
<names>Tom Baker, Louise Jameson, John Leeson</names>
</actors>
<legal>(c)1977 BBC https://www.bbc.co.uk/programmes/b006q2x0</legal>
</tvshow>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<tvshow>
<metadata>
<series>Dr. Who</series>
<title>The Sun Makers</title>
<airdate>11/26/1977</airdate>
<episodes>4</episodes>
</metadata>
<actors>
<names>Tom Baker, Louise Jameson, John Leeson</names>
</actors>
<legal>(c)1977 BBC https://www.bbc.co.uk/programmes/b006q2x0</legal>
</tvshow>
</configuration>

Yapılandırma, Bind yöntemi ile TvShow nesne grafiğinin tamamına bağlanır.


Bağlantılı örnek, işleme için bir özelliğe atandı:

var tvShow = new TvShow();


_config.GetSection("tvshow").Bind(tvShow);
TvShow = tvShow;

Configurationciltçi. Get <T > bağlar ve belirtilen türü döndürür. Get<T> , Bind
kullanmaktan daha uygundur. Aşağıdaki kod, ilişkili örneğin işleme için kullanılan
özelliğe doğrudan atanmasını sağlayan önceki örnekle Get<T> nasıl kullanacağınızı
gösterir:

TvShow = _config.GetSection("tvshow").Get<TvShow>();

TvShow = _config.GetSection("tvshow").Get<TvShow>();

Bir diziyi sınıfa bağlama


Örnek uygulama, bu bölümde açıklanan kavramları gösterir.
Bind, yapılandırma anahtarlarındaki dizi dizinlerini kullanan nesnelere dizileri
bağlamayı destekler. Sayısal anahtar segmentini ( :0: , :1: , … :{n}: ) sunan
herhangi bir dizi biçimi, bir POCO sınıf dizisine dizi bağlama özelliğine sahiptir.

NOTE
Bağlama, kural tarafından sağlanır. Dizi bağlamayı uygulamak için özel yapılandırma
sağlayıcıları gerekli değildir.

Bellek içi dizi işleme


Aşağıdaki tabloda gösterilen yapılandırma anahtarlarını ve değerlerini göz önünde
bulundurun.

ANAHTAR DEĞER

dizi: girdiler: 0 value0


ANAHTAR DEĞER

dizi: girdiler: 1 value1

dizi: girdiler: 2 value2

dizi: girdiler: 4 value4

dizi: girdiler: 5 value5

Bu anahtarlar ve değerler, bellek yapılandırma sağlayıcısı kullanılarak örnek


uygulamaya yüklenir:

public class Program


{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
public class Program
{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.UseStartup<Startup>();
}

Dizi, Dizin #3 için bir değer atlar. Yapılandırma Bağlayıcısı, null değerleri bağlama veya
bağlantılı nesnelerde null girişler oluşturma yeteneğine sahip değildir. Bu, bu diziyi bir
nesneye bağlamanın sonucu gösterildiği sırada bir süre açık hale gelir.
Örnek uygulamada, bir POCO sınıfı, bağlantılı yapılandırma verilerini tutmak için
kullanılabilir:

public class ArrayExample


{
public string[] Entries { get; set; }
}

public class ArrayExample


{
public string[] Entries { get; set; }
}

Yapılandırma verileri nesnesine bağlanır:

var arrayExample = new ArrayExample();


_config.GetSection("array").Bind(arrayExample);

Configurationciltçi. Get <T > sözdizimi de kullanılabilir ve bu da daha küçük kod elde
edilebilir:
ArrayExample = _config.GetSection("array").Get<ArrayExample>();

ArrayExample = _config.GetSection("array").Get<ArrayExample>();

ArrayExample bir örneği olan bağlantılı nesne, yapılandırmadan dizi verilerini alır.

ARRAYEXAMPLE.ENTRIES DIZINI ARRAYEXAMPLE.ENTRIES DEĞERI

0 value0

1. value1

2 value2

3 value4

4 value5

İlişkili nesnedeki Dizin #3, array:4 yapılandırma anahtarı ve value4 değeri için
yapılandırma verilerini tutar. Bir diziyi içeren yapılandırma verileri bağlandığında,
yapılandırma anahtarlarındaki dizi dizinleri yalnızca nesne oluşturulurken
yapılandırma verilerini yinelemek için kullanılır. Yapılandırma verilerinde null değer
korunmaz ve bir yapılandırma anahtarlarındaki bir dizi bir veya daha fazla dizini
atlamazsanız, bağlantılı nesnede NULL değerli bir giriş oluşturulmaz.
Yapılandırmada doğru anahtar-değer çiftini üreten herhangi bir yapılandırma
sağlayıcısı tarafından ArrayExample örneğine bağlamadan önce dizin #3 için eksik
yapılandırma öğesi sağlanabilir. Örnek, eksik anahtar-değer çiftine sahip ek bir JSON
yapılandırma sağlayıcısı içeriyorsa, ArrayExample.Entries tam yapılandırma dizisiyle
eşleşir:
missing_value. JSON:

{
"array:entries:3": "value3"
}

ConfigureAppConfiguration :

config.AddJsonFile(
"missing_value.json", optional: false, reloadOnChange: false);

Tabloda gösterilen anahtar-değer çifti, yapılandırmaya yüklendi.

ANAHTAR DEĞER

dizi: girdiler: 3 value3

ArrayExample sınıf örneği, JSON yapılandırma sağlayıcısı Dizin #3 ' ün girdisini


içeriyorsa, ArrayExample.Entries dizisi değeri içerir.
ARRAYEXAMPLE.ENTRIES DIZINI ARRAYEXAMPLE.ENTRIES DEĞERI

0 value0

1. value1

2 value2

3 value3

4 value4

5 value5

JSON dizi işleme


JSON dosyası bir dizi içeriyorsa, sıfır tabanlı bölüm diziniyle dizi öğeleri için
yapılandırma anahtarları oluşturulur. Aşağıdaki yapılandırma dosyasında, subsection
bir dizidir:

{
"json_array": {
"key": "valueA",
"subsection": [
"valueB",
"valueC",
"valueD"
]
}
}

{
"json_array": {
"key": "valueA",
"subsection": [
"valueB",
"valueC",
"valueD"
]
}
}

JSON yapılandırma sağlayıcısı, yapılandırma verilerini aşağıdaki anahtar-değer


çiftlerine okur:

ANAHTAR DEĞER

json_array: anahtar değer EA

json_array: alt bölüm: 0 valueB

json_array: alt bölüm: 1 değer EC

json_array: alt bölüm: 2 Değerler

Örnek uygulamada, yapılandırma anahtar-değer çiftlerini bağlamak için aşağıdaki


POCO sınıfı kullanılabilir:

public class JsonArrayExample


{
public string Key { get; set; }
public string[] Subsection { get; set; }
}

public class JsonArrayExample


{
public string Key { get; set; }
public string[] Subsection { get; set; }
}

Bağlamadan sonra, JsonArrayExample.Key valueA değerini tutar. Alt bölüm değerleri,


Subsection POCO dizisi özelliğinde depolanır.

JSONARRAYEXAMPLE.SUBSECTION DIZINI JSONARRAYEXAMPLE.SUBSECTION DEĞERI

0 valueB

1. değer EC

2 Değerler

Özel yapılandırma sağlayıcısı


Örnek uygulama, Entity Framework (EF )kullanarak bir veritabanından yapılandırma
anahtar-değer çiftlerini okuyan temel bir yapılandırma sağlayıcısı oluşturmayı gösterir.
Sağlayıcı aşağıdaki özelliklere sahiptir:
EF bellek içi veritabanı, tanıtım amacıyla kullanılır. Bağlantı dizesi gerektiren bir
veritabanını kullanmak için, başka bir yapılandırma sağlayıcısından bağlantı
dizesini sağlamak üzere ikincil ConfigurationBuilder uygulayın.
Sağlayıcı bir veritabanı tablosunu başlangıçta yapılandırmaya okur. Sağlayıcı, her
anahtar temelinde veritabanını sorgulayamaz.
Değişiklik değişikliği uygulanmadı, bu nedenle uygulama başladıktan sonra
veritabanının güncelleştirilmesi uygulamanın yapılandırması üzerinde hiçbir etkiye
sahip değildir.
Yapılandırma değerlerini veritabanında depolamak için bir EFConfigurationValue
varlığı tanımlayın.
Modeller/EFConfigurationValue. cs:

public class EFConfigurationValue


{
public string Id { get; set; }
public string Value { get; set; }
}

Yapılandırılan değerleri depolamak ve erişmek için bir EFConfigurationContext


ekleyin.
Efconfigurationprovider/EFConfigurationContext. cs:

public class EFConfigurationContext : DbContext


{
public EFConfigurationContext(DbContextOptions options) : base(options)
{
}

public DbSet<EFConfigurationValue> Values { get; set; }


}

IConfigurationSourceuygulayan bir sınıf oluşturun.


Efconfigurationprovider/EFConfigurationSource. cs:

public class EFConfigurationSource : IConfigurationSource


{
private readonly Action<DbContextOptionsBuilder> _optionsAction;

public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)


{
_optionsAction = optionsAction;
}

public IConfigurationProvider Build(IConfigurationBuilder builder)


{
return new EFConfigurationProvider(_optionsAction);
}
}

ConfigurationProviderdevralan özel yapılandırma sağlayıcısını oluşturun.


Yapılandırma sağlayıcısı boş olduğunda veritabanını başlatır. Yapılandırma anahtarları
büyük/küçük harfe duyarsızolduğundan, veritabanını başlatmak için kullanılan sözlük,
büyük/küçük harf duyarsız karşılaştırıcı (StringComparer. OrdinalIgnoreCase) ile
oluşturulur.
Efconfigurationprovider/efconfigurationprovider. cs:
public class EFConfigurationProvider : ConfigurationProvider
{
public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
{
OptionsAction = optionsAction;
}

Action<DbContextOptionsBuilder> OptionsAction { get; }

// Load config data from EF DB.


public override void Load()
{
var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

OptionsAction(builder);

using (var dbContext = new EFConfigurationContext(builder.Options))


{
dbContext.Database.EnsureCreated();

Data = !dbContext.Values.Any()
? CreateAndSaveDefaultValues(dbContext)
: dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
}
}

private static IDictionary<string, string> CreateAndSaveDefaultValues(


EFConfigurationContext dbContext)
{
// Quotes (c)2005 Universal Pictures: Serenity
// https://www.uphe.com/movies/serenity
var configValues =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "quote1", "I aim to misbehave." },
{ "quote2", "I swallowed a bug." },
{ "quote3", "You can't stop the signal, Mal." }
};

dbContext.Values.AddRange(configValues
.Select(kvp => new EFConfigurationValue
{
Id = kvp.Key,
Value = kvp.Value
})
.ToArray());

dbContext.SaveChanges();

return configValues;
}
}

AddEFConfiguration uzantısı yöntemi, yapılandırma kaynağının bir


ConfigurationBuilder eklenmesine izin verir.
Uzantılar/EntityFrameworkExtensions. cs:
public static class EntityFrameworkExtensions
{
public static IConfigurationBuilder AddEFConfiguration(
this IConfigurationBuilder builder,
Action<DbContextOptionsBuilder> optionsAction)
{
return builder.Add(new EFConfigurationSource(optionsAction));
}
}

Aşağıdaki kod, program.csiçinde özel EFConfigurationProvider nasıl kullanacağınızı


gösterir:

public class Program


{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}

Modeller/EFConfigurationValue. cs:

public class EFConfigurationValue


{
public string Id { get; set; }
public string Value { get; set; }
}

Yapılandırılan değerleri depolamak ve erişmek için bir EFConfigurationContext


ekleyin.
Efconfigurationprovider/EFConfigurationContext. cs:

public class EFConfigurationContext : DbContext


{
public EFConfigurationContext(DbContextOptions options) : base(options)
{
}

public DbSet<EFConfigurationValue> Values { get; set; }


}

IConfigurationSourceuygulayan bir sınıf oluşturun.


Efconfigurationprovider/EFConfigurationSource. cs:

public class EFConfigurationSource : IConfigurationSource


{
private readonly Action<DbContextOptionsBuilder> _optionsAction;

public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)


{
_optionsAction = optionsAction;
}

public IConfigurationProvider Build(IConfigurationBuilder builder)


{
return new EFConfigurationProvider(_optionsAction);
}
}

ConfigurationProviderdevralan özel yapılandırma sağlayıcısını oluşturun.


Yapılandırma sağlayıcısı boş olduğunda veritabanını başlatır.
Efconfigurationprovider/efconfigurationprovider. cs:
public class EFConfigurationProvider : ConfigurationProvider
{
public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
{
OptionsAction = optionsAction;
}

Action<DbContextOptionsBuilder> OptionsAction { get; }

// Load config data from EF DB.


public override void Load()
{
var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

OptionsAction(builder);

using (var dbContext = new EFConfigurationContext(builder.Options))


{
dbContext.Database.EnsureCreated();

Data = !dbContext.Values.Any()
? CreateAndSaveDefaultValues(dbContext)
: dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
}
}

private static IDictionary<string, string> CreateAndSaveDefaultValues(


EFConfigurationContext dbContext)
{
// Quotes (c)2005 Universal Pictures: Serenity
// https://www.uphe.com/movies/serenity
var configValues =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "quote1", "I aim to misbehave." },
{ "quote2", "I swallowed a bug." },
{ "quote3", "You can't stop the signal, Mal." }
};

dbContext.Values.AddRange(configValues
.Select(kvp => new EFConfigurationValue
{
Id = kvp.Key,
Value = kvp.Value
})
.ToArray());

dbContext.SaveChanges();

return configValues;
}
}

AddEFConfiguration uzantısı yöntemi, yapılandırma kaynağının bir


ConfigurationBuilder eklenmesine izin verir.
Uzantılar/EntityFrameworkExtensions. cs:
public static class EntityFrameworkExtensions
{
public static IConfigurationBuilder AddEFConfiguration(
this IConfigurationBuilder builder,
Action<DbContextOptionsBuilder> optionsAction)
{
return builder.Add(new EFConfigurationSource(optionsAction));
}
}

Aşağıdaki kod, program.csiçinde özel EFConfigurationProvider nasıl kullanacağınızı


gösterir:

public class Program


{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(arrayDict);
config.AddJsonFile(
"json_array.json", optional: false, reloadOnChange: false);
config.AddJsonFile(
"starship.json", optional: false, reloadOnChange: false);
config.AddXmlFile(
"tvshow.xml", optional: false, reloadOnChange: false);
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddCommandLine(args);
})
.UseStartup<Startup>();
}

Başlangıç sırasında yapılandırmaya erişim


Startup.ConfigureServicesyapılandırma değerlerine erişmek için Startup
oluşturucusuna IConfiguration ekleyin. Startup.Configure yapılandırmaya erişmek
için IConfiguration doğrudan yönteme ekleyin ya da oluşturucuyu kullanarak örneği
kullanın:
public class Startup
{
private readonly IConfiguration _config;

public Startup(IConfiguration config)


{
_config = config;
}

public void ConfigureServices(IServiceCollection services)


{
var value = _config["key"];
}

public void Configure(IApplicationBuilder app, IConfiguration config)


{
var value = config["key"];
}
}

Başlangıç kolaylığı yöntemlerini kullanarak yapılandırmaya erişme örneği için bkz.


uygulama başlatma: kullanışlı yöntemler.

Razor Pages sayfasında veya MVC görünümünde


erişim yapılandırması
Razor Pages sayfasındaki veya MVC görünümündeki yapılandırma ayarlarına erişmek
için, Microsoft. Extensions. Configuration ad alanı için bir using yönergesi ( C#
başvuru: using yönergesi) ekleyin ve sayfa ya da görünüme IConfiguration ekleyin.
Razor Pages sayfasında:

@page
@model IndexModel
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<!DOCTYPE html>
<html lang="en">
<head>
<title>Index Page</title>
</head>
<body>
<h1>Access configuration in a Razor Pages page</h1>
<p>Configuration value for 'key': @Configuration["key"]</p>
</body>
</html>

MVC görünümünde:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<!DOCTYPE html>
<html lang="en">
<head>
<title>Index View</title>
</head>
<body>
<h1>Access configuration in an MVC view</h1>
<p>Configuration value for 'key': @Configuration["key"]</p>
</body>
</html>

Bir dış derlemeden yapılandırma Ekle


IHostingStartup bir uygulama, uygulamanın Startup sınıfının dışında bir dış
derlemeden başlangıçta bir uygulamaya iyileştirmeler eklenmesine izin verir. Daha
fazla bilgi için bkz. ASP.NET Core barındırma başlangıç derlemeleri kullanma.

Ek kaynaklar
ASP.NET Core için seçenek kalıbı
ASP.NET Core için seçenek kalıbı
6.12.2019 • 55 minutes to read • Edit Online

Tarafından Luke Latham


Seçenekler stili, ilişkili ayarların gruplarını temsil etmek için sınıfları kullanır. Yapılandırma ayarları senaryo
tarafından ayrı sınıflara ayrılmışsa, uygulama iki önemli yazılım mühendisliği ilkelerine uyar:
Yapılandırma ayarlarına bağlı olan arabirim ayırma ilkesi (ISS ) veya kapsülleme – senaryoları (sınıflar)
yalnızca kullandıkları yapılandırma ayarlarına bağlıdır.
Uygulamanın farklı parçaları için – ayarlarının ayrılması, birbirine bağımlı değildir veya birbirlerine
aktarılmaz.
Seçenekler Ayrıca yapılandırma verilerini doğrulamaya yönelik bir mekanizma sağlar. Daha fazla bilgi için
Seçenekler doğrulama bölümüne bakın.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Paket
Microsoft. Extensions. Options. ConfigurationExtensions paketine ASP.NET Core uygulamalarında örtük
olarak başvurulur.

Seçenekler arabirimleri
IOptionsMonitor<TOptions>, TOptions örnekleri için seçenekleri almak ve seçenek bildirimlerini yönetmek
için kullanılır. IOptionsMonitor<TOptions> aşağıdaki senaryoları destekler:
Değişiklik bildirimleri
Adlandırılmış seçenekler
Yeniden yüklenebilir yapılandırma
Seçmeli seçenekler geçersiz kılma (IOptionsMonitorCache<TOptions>)
Yapılandırma sonrası senaryolar, tüm IConfigureOptions<TOptions> yapılandırma oluştuktan sonra
seçenekleri ayarlamanıza veya değiştirmenize olanak sağlar.
IOptionsFactory<TOptions> yeni seçenek örnekleri oluşturmaktan sorumludur. Tek bir Create yöntemi vardır.
Varsayılan uygulama tüm kayıtlı IConfigureOptions<TOptions> ve IPostConfigureOptions<TOptions> alır ve
önce tüm yapılandırmaların, ardından yapılandırma sonrası sonrasında çalıştırılır.
IConfigureNamedOptions<TOptions> ve IConfigureOptions<TOptions> arasında ayrım yapar ve yalnızca
uygun arabirimi çağırır.
IOptionsMonitorCache<TOptions>, IOptionsMonitor<TOptions> tarafından TOptions örnekleri önbelleğe
almak için kullanılır. IOptionsMonitorCache<TOptions>, değer yeniden hesaplanabilmesi için izleyici içindeki
seçenek örneklerini geçersiz kılar (TryRemove). Değerler, TryAddile el ile tanıtılamaz. Clear yöntemi, tüm
adlandırılmış örneklerin isteğe bağlı olarak yeniden oluşturulması gerektiğinde kullanılır.
IOptionsSnapshot<TOptions>, her istekte seçeneklerin yeniden hesaplanması gereken senaryolarda
faydalıdır. Daha fazla bilgi için bkz. ıoptionssnapshot ile yapılandırma verilerini yeniden yükleme bölümü.
IOptions<TOptions>, seçenekleri desteklemek için kullanılabilir. Ancak, IOptions<TOptions> önceki
IOptionsMonitor<TOptions>senaryolarını desteklemez. Zaten IOptions<TOptions> arabirimini kullanan
mevcut çerçeveler ve kitaplıklarda IOptions<TOptions> kullanmaya devam edebilir ve
IOptionsMonitor<TOptions>tarafından sağlanmış senaryolara gerek kalmaz.

Genel Seçenekler yapılandırması


Genel Seçenekler yapılandırması örnek uygulamada #1 olarak gösterilmiştir.
Bir seçenek sınıfı ortak parametresiz bir Oluşturucu ile soyut olmamalıdır. Aşağıdaki MyOptions sınıfında,
Option1 ve Option2 iki özelliği vardır. Varsayılan değerleri ayarlama isteğe bağlıdır, ancak aşağıdaki örnekteki
sınıf oluşturucusu Option1 varsayılan değerini ayarlar. Option2 , özelliği doğrudan başlatarak varsayılan değer
kümesine sahiptir (modeller/MyOptions. cs):

public class MyOptions


{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

MyOptions sınıfı, Configure ve yapılandırmayla bağlantılı olarak hizmet kapsayıcısına eklenir:

// Example #1: General configuration


// Register the Configuration instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);

Aşağıdaki sayfa modeli, ayarlara erişmek için IOptionsMonitor<TOptions> ile Oluşturucu bağımlılığı ekleme
işlemini kullanır (Sayfalar/Index. cshtml. cs):

private readonly MyOptions _options;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #1: Simple options


var option1 = _options.Option1;
var option2 = _options.Option2;
SimpleOptions = $"option1 = {option1}, option2 = {option2}";

Örneğin appSettings. JSON dosyası option1 ve option2 değerlerini belirtir:


{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini gösteren bir dize
döndürür:

option1 = value1_from_json, option2 = -1

NOTE
Bir ayarlar dosyasından seçenek yapılandırması 'nı yüklemek için özel bir ConfigurationBuilder kullanırken, temel yolun
doğru şekilde ayarlandığını onaylayın:

var configBuilder = new ConfigurationBuilder()


.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true);
var config = configBuilder.Build();

services.Configure<MyOptions>(config);

Ayarlar dosyasından CreateDefaultBuilderaracılığıyla seçenek yapılandırması yüklenirken taban yolunu açıkça ayarlama
gerekli değildir.

Bir temsilciyle basit seçenekleri yapılandırma


Basit seçeneklerin bir temsilciyle yapılandırılması, örnek uygulamada #2 örnek olarak gösterilmiştir.
Seçenek değerlerini ayarlamak için bir temsilci kullanın. Örnek uygulama MyOptionsWithDelegateConfig sınıfını
kullanır (modeller/MyOptionsWithDelegateConfig. cs):

public class MyOptionsWithDelegateConfig


{
public MyOptionsWithDelegateConfig()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

Aşağıdaki kodda, hizmet kapsayıcısına ikinci bir IConfigureOptions<TOptions> hizmeti eklenir.


MyOptionsWithDelegateConfig ile bağlamayı yapılandırmak için bir temsilci kullanır:
// Example #2: Options bound and configured by a delegate
services.Configure<MyOptionsWithDelegateConfig>(myOptions =>
{
myOptions.Option1 = "value1_configured_by_delegate";
myOptions.Option2 = 500;
});

Index.cshtml.cs:

private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #2: Options configured by delegate


var delegate_config_option1 = _optionsWithDelegateConfig.Option1;
var delegate_config_option2 = _optionsWithDelegateConfig.Option2;
SimpleOptionsWithDelegateConfig =
$"delegate_option1 = {delegate_config_option1}, " +
$"delegate_option2 = {delegate_config_option2}";

Birden çok yapılandırma sağlayıcısı ekleyebilirsiniz. Yapılandırma sağlayıcıları NuGet paketlerinde


kullanılabilir ve kayıtlı oldukları sırayla uygulanır. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Her Configure çağrısı, hizmet kapsayıcısına bir IConfigureOptions<TOptions> hizmeti ekler. Yukarıdaki
örnekte, Option1 ve Option2 değerlerinin ikisi de appSettings. JSONiçinde belirtilmiştir, ancak Option1 ve
Option2 değerleri yapılandırılan temsilci tarafından geçersiz kılınır.

Birden fazla yapılandırma hizmeti etkinleştirildiğinde, son yapılandırma kaynağı WINS ' i ve yapılandırma
değerini ayarlar. Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini
gösteren bir dize döndürür:

delegate_option1 = value1_configured_by_delegate, delegate_option2 = 500

Alt seçenekler yapılandırması


Alt seçenekler yapılandırması örnek uygulamada #3 örnek olarak gösterilmiştir.
Uygulamalar, uygulamadaki belirli senaryo gruplarına (sınıflar) ait seçenek sınıfları oluşturmamalıdır.
Uygulamanın yapılandırma değerleri gerektiren bölümlerinin yalnızca kullandıkları yapılandırma değerlerine
erişimi olmalıdır.
Seçenekleri yapılandırmaya bağlama sırasında, seçenek türündeki her bir özellik property[:sub-property:]
formun bir yapılandırma anahtarına bağlanır. Örneğin, MyOptions.Option1 özelliği appSettings. JSONiçindeki
option1 özelliğinden okunan anahtar Option1 bağımlıdır.

Aşağıdaki kodda, hizmet kapsayıcısına üçüncü bir IConfigureOptions<TOptions> hizmeti eklenir.


MySubOptions appSettings. JSON dosyasının subsection bölümüne bağlar:

// Example #3: Suboptions


// Bind options using a sub-section of the appsettings.json file.
services.Configure<MySubOptions>(Configuration.GetSection("subsection"));

GetSection yöntemi Microsoft.Extensions.Configuration ad alanını gerektirir.


Örneğin appSettings. JSON dosyası, suboption1 ve suboption2 için anahtarlar içeren bir subsection üyesini
tanımlar:

{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

MySubOptions sınıfı, Seçenekler değerlerini tutmak için özellikleri, SubOption1 ve SubOption2 tanımlar
(modeller/Myalt seçenekler. cs):

public class MySubOptions


{
public MySubOptions()
{
// Set default values.
SubOption1 = "value1_from_ctor";
SubOption2 = 5;
}

public string SubOption1 { get; set; }


public int SubOption2 { get; set; }
}

Sayfa modelinin OnGet yöntemi, Seçenekler değerleriyle (Pages/Index. cshtml. cs) bir dize döndürür:

private readonly MySubOptions _subOptions;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #3: Suboptions


var subOption1 = _subOptions.SubOption1;
var subOption2 = _subOptions.SubOption2;
SubOptions = $"subOption1 = {subOption1}, subOption2 = {subOption2}";

Uygulama çalıştırıldığında OnGet yöntemi, alt sınıf değerlerini gösteren bir dize döndürür:

subOption1 = subvalue1_from_json, subOption2 = 200

Seçeneklere ekleme
Seçenekler ekleme, örnek uygulamada #4 olarak gösterilmiştir.
IOptionsMonitor<TOptions> içine ekle:
@inject Razor yönergesi ile Razor sayfası veya MVC görünümü.
Bir sayfa veya görünüm modeli.
Örnek uygulamadan alınan aşağıdaki örnek, bir sayfa modeline IOptionsMonitor<TOptions>
(Sayfalar/Index. cshtml. cs):

private readonly MyOptions _options;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #4: Bind options directly to the page


MyOptions = _options;
Örnek uygulama, @inject yönergeyle IOptionsMonitor<MyOptions> nasıl ekleneceğini gösterir:

@page
@model IndexModel
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<MyOptions> OptionsAccessor
@{
ViewData["Title"] = "Options Sample";
}

<h1>@ViewData["Title"]</h1>

Uygulama çalıştırıldığında, seçenek değerleri işlenen sayfada gösterilir:

Ioptionssnapshot ile yapılandırma verilerini yeniden yükleme


Yapılandırma verilerini IOptionsSnapshot<TOptions> ile yeniden yükleme örnek uygulamada örnek #5
gösterilmiştir.
IOptionsSnapshot<TOptions>kullanarak, erişilen ve isteğin ömrü boyunca önbelleğe alınan istekler her istek
için bir kez hesaplanır.
IOptionsMonitor ve IOptionsSnapshot arasındaki fark şudur:
IOptionsMonitor , geçerli seçenek değerlerini her zaman alan, özellikle de tek bağımlılıklarda yararlı olan
bir tek hizmettir .
IOptionsSnapshot kapsamlı bir hizmettir ve IOptionsSnapshot<T> nesnesinin oluşturulduğu sırada
seçeneklerin anlık görüntüsünü sağlar. Seçenekler anlık görüntüleri geçici ve kapsamlı bağımlılıklarla
kullanılmak üzere tasarlanmıştır.
Aşağıdaki örnek, appSettings. JSON değişikliklerinden sonra yeni bir IOptionsSnapshot<TOptions> nasıl
oluşturulduğunu gösterir (Pages/Index. cshtml. cs). Sunucu için birden çok istek, dosya değiştirilene ve
yapılandırma yeniden yükleninceye kadar appSettings. JSON dosyası tarafından belirtilen sabit değerler
döndürüyor.

private readonly MyOptions _snapshotOptions;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #5: Snapshot options


var snapshotOption1 = _snapshotOptions.Option1;
var snapshotOption2 = _snapshotOptions.Option2;
SnapshotOptions =
$"snapshot option1 = {snapshotOption1}, " +
$"snapshot option2 = {snapshotOption2}";

Aşağıdaki görüntüde, appSettings. JSON dosyasından yüklenen ilk option1 ve option2 değerleri
gösterilmektedir:

snapshot option1 = value1_from_json, snapshot option2 = -1

AppSettings. JSON dosyasındaki değerleri value1_from_json UPDATED ve 200 olacak şekilde değiştirin.
AppSettings. JSON dosyasını kaydedin. Seçenekler değerlerinin güncelleştirildiğini görmek için tarayıcıyı
yenileyin:

snapshot option1 = value1_from_json UPDATED, snapshot option2 = 200

IController Enamedooptıons ile adlandırılmış seçenekler desteği


IConfigureNamedOptions<TOptions> ile adlandırılmış seçenekler, örnek uygulamada 6 #örnek olarak
gösterilmiştir.
Adlandırılmış seçenekler desteği, uygulamanın adlandırılmış seçenek yapılandırmalarının ayırt etmesine izin
verir. Örnek uygulamada, adlandırılmış Seçenekler OptionsServiceCollectionExtensions. configureile
bildirilmiştir ve bu, <TOptions > ' i çağırır. Uzantı yöntemini Yapılandır:

// Example #6: Named options (named_options_1)


// Register the ConfigurationBuilder instance which MyOptions binds against.
// Specify that the options loaded from configuration are named
// "named_options_1".
services.Configure<MyOptions>("named_options_1", Configuration);

// Example #6: Named options (named_options_2)


// Specify that the options loaded from the MyOptions class are named
// "named_options_2".
// Use a delegate to configure option values.
services.Configure<MyOptions>("named_options_2", myOptions =>
{
myOptions.Option1 = "named_options_2_value1_from_action";
});
Örnek uygulama, Get (Pages/Index. cshtml. cs) adlı adlandırılmış seçeneklere erişir:

private readonly MyOptions _named_options_1;


private readonly MyOptions _named_options_2;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #6: Named options


var named_options_1 =
$"named_options_1: option1 = {_named_options_1.Option1}, " +
$"option2 = {_named_options_1.Option2}";
var named_options_2 =
$"named_options_2: option1 = {_named_options_2.Option1}, " +
$"option2 = {_named_options_2.Option2}";
NamedOptions = $"{named_options_1} {named_options_2}";

Örnek uygulama çalıştırıldığında, adlandırılmış seçenekler döndürülür:

named_options_1: option1 = value1_from_json, option2 = -1


named_options_2: option1 = named_options_2_value1_from_action, option2 = 5

named_options_1 değerler, appSettings. JSON dosyasından yüklenen yapılandırmadan sağlanır.


named_options_2 değerleri tarafından sağlanır:
Option1 için ConfigureServices named_options_2 temsilcisi.
MyOptions sınıfı tarafından sağlanmış Option2 için varsayılan değer.

Tüm seçenekleri ConfigureAll yöntemiyle yapılandırma


Tüm seçenek örneklerini ConfigureAll yöntemiyle yapılandırın. Aşağıdaki kod, ortak bir değere sahip tüm
yapılandırma örnekleri için Option1 yapılandırır. Startup.ConfigureServices yöntemine el ile aşağıdaki kodu
ekleyin:

services.ConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "ConfigureAll replacement value";
});

Kodu ekledikten sonra örnek uygulamayı çalıştırmak aşağıdaki sonucu verir:

named_options_1: option1 = ConfigureAll replacement value, option2 = -1


named_options_2: option1 = ConfigureAll replacement value, option2 = 5
NOTE
Tüm seçenekler adlandırılmış örneklerdir. Mevcut IConfigureOptions<TOptions> örnekleri,
string.Empty``Options.DefaultName örneğini hedefleyecek şekilde değerlendirilir.
IConfigureNamedOptions<TOptions> Ayrıca IConfigureOptions<TOptions>uygular. IOptionsFactory<TOptions>
varsayılan uygulamasının her birini uygun şekilde kullanma mantığı vardır. null adlandırılmış seçenek, belirli bir
adlandırılmış örnek yerine tüm adlandırılmış örnekleri hedeflemek için kullanılır (ConfigureAll ve PostConfigureAll bu
kuralı kullanın).

Seçenekno Oluşturucu API 'SI


OptionsBuilder<TOptions>, TOptions örnekleri yapılandırmak için kullanılır. OptionsBuilder , sonraki
çağrıların tümünde olmak yerine ilk AddOptions<TOptions>(string optionsName) çağrısına yalnızca tek bir
parametre olan adlandırılmış seçenekleri oluşturmayı kolaylaştırır. Seçenekler doğrulaması ve hizmet
bağımlılıklarını kabul eden ConfigureOptions aşırı yüklemeler yalnızca OptionsBuilder ile kullanılabilir.

// Options.DefaultName = "" is used.


services.AddOptions<MyOptions>().Configure(o => o.Property = "default");

services.AddOptions<MyOptions>("optionalName")
.Configure(o => o.Property = "named");

Ayarları yapılandırmak için dı hizmetlerini kullanma


Seçenekleri iki şekilde yapılandırırken, bağımlılık ekleme işleminden diğer hizmetlere erişebilirsiniz:
<TOptions > ' nin Options Builder'da yapılandırılması için bir yapılandırma temsilcisi geçirin. <bir
TOptions > seçenek Oluşturucusu , seçenekleri yapılandırmak için en fazla beş hizmeti kullanmanıza
olanak sağlayan, yapılandırma yüklerini sağlar:

services.AddOptions<MyOptions>("optionalName")
.Configure<Service1, Service2, Service3, Service4, Service5>(
(o, s, s2, s3, s4, s5) =>
o.Property = DoSomethingWith(s, s2, s3, s4, s5));

IConfigureOptions<TOptions> veya IConfigureNamedOptions<TOptions> uygulayan ve türü bir


hizmet olarak kaydeden kendi türünü oluşturun.
Bir hizmetin oluşturulması daha karmaşık olduğundan, yapılandırmakiçin bir yapılandırma temsilcisinin
geçirilmesini öneririz. Kendi türünü oluşturmak, Yapılandır'ı kullandığınızda çerçevenin sizin için yaptığı işe
eşdeğerdir. Yapılandırma çağrısı, belirtilen genel hizmet türlerini kabul eden bir oluşturucuya sahip olan geçici
genel IConfigureNamedOptions<TOptions>kaydeder.

Seçenekler doğrulaması
Seçenekler doğrulaması seçenekler yapılandırıldığında seçenekleri doğrulamanızı sağlar. Seçenekler
geçerliyse true döndüren ve geçerli değillerse false bir doğrulama yöntemiyle Validate çağırın:
// Registration
services.AddOptions<MyOptions>("optionalOptionsName")
.Configure(o => { }) // Configure the options
.Validate(o => YourValidationShouldReturnTrueIfValid(o),
"custom error");

// Consumption
var monitor = services.BuildServiceProvider()
.GetService<IOptionsMonitor<MyOptions>>();

try
{
var options = monitor.Get("optionalOptionsName");
}
catch (OptionsValidationException e)
{
// e.OptionsName returns "optionalOptionsName"
// e.OptionsType returns typeof(MyOptions)
// e.Failures returns a list of errors, which would contain
// "custom error"
}

Önceki örnekte, adlandırılmış seçenekler örneği optionalOptionsName olarak ayarlanır. Varsayılan Seçenekler
örneği Options.DefaultName .
Seçenekler örneği oluşturulduğunda doğrulama çalıştırılır. Seçenek Örneğinizde, ilk kez erişildiğinde
doğrulamanın başarılı olması garanti edilir.

IMPORTANT
Seçenekler, Seçenekler başlangıçta yapılandırıldıktan ve doğrulandıktan sonra seçeneklerindeki değişikliklere karşı
koruma yapmaz.

Validate yöntemi bir kabul eder. Doğrulamayı tamamen özelleştirmek için, şunları
Func<TOptions, bool>
sağlayan IValidateOptions<TOptions> uygulayın:
Birden çok seçenek türünün doğrulanması:
class ValidateTwo : IValidateOptions<Option1>, IValidationOptions<Option2>
Başka bir seçenek türüne bağlı olan doğrulama:
public DependsOnAnotherOptionValidator(IOptionsMonitor<AnotherOption> options)

IValidateOptions şunları doğrular:


Belirli bir adlandırılmış seçenekler örneği.
name null tüm seçenekler.

Arabirimin uygulanınızdan bir ValidateOptionsResult döndürün:

public interface IValidateOptions<TOptions> where TOptions : class


{
ValidateOptionsResult Validate(string name, TOptions options);
}

Veri ek açıklaması tabanlı doğrulama, OptionsBuilder<TOptions> ValidateDataAnnotations yöntemi çağırarak


Microsoft. Extensions. Options. DataAnnotation paketinden kullanılabilir.
Microsoft.Extensions.Options.DataAnnotations ASP.NET Core uygulamalarda örtülü olarak başvurulur.
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.DependencyInjection;

private class AnnotatedOptions


{
[Required]
public string Required { get; set; }

[StringLength(5, ErrorMessage = "Too long.")]


public string StringLength { get; set; }

[Range(-5, 5, ErrorMessage = "Out of range.")]


public int IntRange { get; set; }
}

[Fact]
public void CanValidateDataAnnotations()
{
var services = new ServiceCollection();
services.AddOptions<AnnotatedOptions>()
.Configure(o =>
{
o.StringLength = "111111";
o.IntRange = 10;
o.Custom = "nowhere";
})
.ValidateDataAnnotations();

var sp = services.BuildServiceProvider();

var error = Assert.Throws<OptionsValidationException>(() =>


sp.GetRequiredService<IOptionsMonitor<AnnotatedOptions>>().CurrentValue);
ValidateFailure<AnnotatedOptions>(error, Options.DefaultName, 1,
"DataAnnotation validation failed for members Required " +
"with the error 'The Required field is required.'.",
"DataAnnotation validation failed for members StringLength " +
"with the error 'Too long.'.",
"DataAnnotation validation failed for members IntRange " +
"with the error 'Out of range.'.");
}

Eager doğrulaması (başlangıçta hızlı başarısız), gelecek bir sürüm için dikkate alınmaz.

Yapılandırma sonrası seçenekler


Yapılandırma sonrası IPostConfigureOptions<TOptions>ayarlayın. Tüm IConfigureOptions<TOptions>
yapılandırma oluştuktan sonra yapılandırma sonrası çalıştırmalar:

services.PostConfigure<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});

PostConfigure, adlandırılmış seçenekleri yapılandırmak için kullanılabilir:

services.PostConfigure<MyOptions>("named_options_1", myOptions =>


{
myOptions.Option1 = "post_configured_option1_value";
});

Tüm yapılandırma örneklerini yapılandırmak için PostConfigureAll kullanın:


services.PostConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});

Başlangıç sırasında seçeneklere erişme


IOptions<TOptions> ve IOptionsMonitor<TOptions> Startup.Configure kullanılabilir, çünkü Hizmetleri
Configure Yöntemi yürütülmeden önce oluşturulmuştur.

public void Configure(IApplicationBuilder app,


IOptionsMonitor<MyOptions> optionsAccessor)
{
var option1 = optionsAccessor.CurrentValue.Option1;
}

Startup.ConfigureServices IOptions<TOptions> veya IOptionsMonitor<TOptions> kullanmayın. Hizmet


kayıtlarının sıralaması nedeniyle tutarsız bir seçenek durumu var olabilir.
Seçenekler stili, ilişkili ayarların gruplarını temsil etmek için sınıfları kullanır. Yapılandırma ayarları senaryo
tarafından ayrı sınıflara ayrılmışsa, uygulama iki önemli yazılım mühendisliği ilkelerine uyar:
Yapılandırma ayarlarına bağlı olan arabirim ayırma ilkesi (ISS ) veya kapsülleme – senaryoları (sınıflar)
yalnızca kullandıkları yapılandırma ayarlarına bağlıdır.
Uygulamanın farklı parçaları için – ayarlarının ayrılması, birbirine bağımlı değildir veya birbirlerine
aktarılmaz.
Seçenekler Ayrıca yapılandırma verilerini doğrulamaya yönelik bir mekanizma sağlar. Daha fazla bilgi için
Seçenekler doğrulama bölümüne bakın.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Microsoft. AspNetCore. app metapackage 'e başvurun veya Microsoft. Extensions. Options.
configurationextensions paketine bir paket başvurusu ekleyin.

Seçenekler arabirimleri
IOptionsMonitor<TOptions>, TOptions örnekleri için seçenekleri almak ve seçenek bildirimlerini yönetmek
için kullanılır. IOptionsMonitor<TOptions> aşağıdaki senaryoları destekler:
Değişiklik bildirimleri
Adlandırılmış seçenekler
Yeniden yüklenebilir yapılandırma
Seçmeli seçenekler geçersiz kılma (IOptionsMonitorCache<TOptions>)
Yapılandırma sonrası senaryolar, tüm IConfigureOptions<TOptions> yapılandırma oluştuktan sonra
seçenekleri ayarlamanıza veya değiştirmenize olanak sağlar.
IOptionsFactory<TOptions> yeni seçenek örnekleri oluşturmaktan sorumludur. Tek bir Create yöntemi vardır.
Varsayılan uygulama tüm kayıtlı IConfigureOptions<TOptions> ve IPostConfigureOptions<TOptions> alır ve
önce tüm yapılandırmaların, ardından yapılandırma sonrası sonrasında çalıştırılır.
IConfigureNamedOptions<TOptions> ve IConfigureOptions<TOptions> arasında ayrım yapar ve yalnızca
uygun arabirimi çağırır.
IOptionsMonitorCache<TOptions>, IOptionsMonitor<TOptions> tarafından TOptions örnekleri önbelleğe
almak için kullanılır. IOptionsMonitorCache<TOptions>, değer yeniden hesaplanabilmesi için izleyici içindeki
seçenek örneklerini geçersiz kılar (TryRemove). Değerler, TryAddile el ile tanıtılamaz. Clear yöntemi, tüm
adlandırılmış örneklerin isteğe bağlı olarak yeniden oluşturulması gerektiğinde kullanılır.
IOptionsSnapshot<TOptions>, her istekte seçeneklerin yeniden hesaplanması gereken senaryolarda
faydalıdır. Daha fazla bilgi için bkz. ıoptionssnapshot ile yapılandırma verilerini yeniden yükleme bölümü.
IOptions<TOptions>, seçenekleri desteklemek için kullanılabilir. Ancak, IOptions<TOptions> önceki
IOptionsMonitor<TOptions>senaryolarını desteklemez. Zaten IOptions<TOptions> arabirimini kullanan
mevcut çerçeveler ve kitaplıklarda IOptions<TOptions> kullanmaya devam edebilir ve
IOptionsMonitor<TOptions>tarafından sağlanmış senaryolara gerek kalmaz.

Genel Seçenekler yapılandırması


Genel Seçenekler yapılandırması örnek uygulamada #1 olarak gösterilmiştir.
Bir seçenek sınıfı ortak parametresiz bir Oluşturucu ile soyut olmamalıdır. Aşağıdaki MyOptions sınıfında,
Option1 ve Option2 iki özelliği vardır. Varsayılan değerleri ayarlama isteğe bağlıdır, ancak aşağıdaki örnekteki
sınıf oluşturucusu Option1 varsayılan değerini ayarlar. Option2 , özelliği doğrudan başlatarak varsayılan değer
kümesine sahiptir (modeller/MyOptions. cs):

public class MyOptions


{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

MyOptions sınıfı, Configure ve yapılandırmayla bağlantılı olarak hizmet kapsayıcısına eklenir:

// Example #1: General configuration


// Register the Configuration instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);

Aşağıdaki sayfa modeli, ayarlara erişmek için IOptionsMonitor<TOptions> ile Oluşturucu bağımlılığı ekleme
işlemini kullanır (Sayfalar/Index. cshtml. cs):

private readonly MyOptions _options;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #1: Simple options


var option1 = _options.Option1;
var option2 = _options.Option2;
SimpleOptions = $"option1 = {option1}, option2 = {option2}";

Örneğin appSettings. JSON dosyası option1 ve option2 değerlerini belirtir:

{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini gösteren bir dize
döndürür:

option1 = value1_from_json, option2 = -1

NOTE
Bir ayarlar dosyasından seçenek yapılandırması 'nı yüklemek için özel bir ConfigurationBuilder kullanırken, temel yolun
doğru şekilde ayarlandığını onaylayın:

var configBuilder = new ConfigurationBuilder()


.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true);
var config = configBuilder.Build();

services.Configure<MyOptions>(config);

Ayarlar dosyasından CreateDefaultBuilderaracılığıyla seçenek yapılandırması yüklenirken taban yolunu açıkça ayarlama
gerekli değildir.
Bir temsilciyle basit seçenekleri yapılandırma
Basit seçeneklerin bir temsilciyle yapılandırılması, örnek uygulamada #2 örnek olarak gösterilmiştir.
Seçenek değerlerini ayarlamak için bir temsilci kullanın. Örnek uygulama MyOptionsWithDelegateConfig sınıfını
kullanır (modeller/MyOptionsWithDelegateConfig. cs):

public class MyOptionsWithDelegateConfig


{
public MyOptionsWithDelegateConfig()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

Aşağıdaki kodda, hizmet kapsayıcısına ikinci bir IConfigureOptions<TOptions> hizmeti eklenir.


MyOptionsWithDelegateConfig ile bağlamayı yapılandırmak için bir temsilci kullanır:

// Example #2: Options bound and configured by a delegate


services.Configure<MyOptionsWithDelegateConfig>(myOptions =>
{
myOptions.Option1 = "value1_configured_by_delegate";
myOptions.Option2 = 500;
});

Index.cshtml.cs:

private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #2: Options configured by delegate


var delegate_config_option1 = _optionsWithDelegateConfig.Option1;
var delegate_config_option2 = _optionsWithDelegateConfig.Option2;
SimpleOptionsWithDelegateConfig =
$"delegate_option1 = {delegate_config_option1}, " +
$"delegate_option2 = {delegate_config_option2}";

Birden çok yapılandırma sağlayıcısı ekleyebilirsiniz. Yapılandırma sağlayıcıları NuGet paketlerinde


kullanılabilir ve kayıtlı oldukları sırayla uygulanır. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Her Configure çağrısı, hizmet kapsayıcısına bir IConfigureOptions<TOptions> hizmeti ekler. Yukarıdaki
örnekte, Option1 ve Option2 değerlerinin ikisi de appSettings. JSONiçinde belirtilmiştir, ancak Option1 ve
Option2 değerleri yapılandırılan temsilci tarafından geçersiz kılınır.

Birden fazla yapılandırma hizmeti etkinleştirildiğinde, son yapılandırma kaynağı WINS ' i ve yapılandırma
değerini ayarlar. Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini
gösteren bir dize döndürür:

delegate_option1 = value1_configured_by_delegate, delegate_option2 = 500

Alt seçenekler yapılandırması


Alt seçenekler yapılandırması örnek uygulamada #3 örnek olarak gösterilmiştir.
Uygulamalar, uygulamadaki belirli senaryo gruplarına (sınıflar) ait seçenek sınıfları oluşturmamalıdır.
Uygulamanın yapılandırma değerleri gerektiren bölümlerinin yalnızca kullandıkları yapılandırma değerlerine
erişimi olmalıdır.
Seçenekleri yapılandırmaya bağlama sırasında, seçenek türündeki her bir özellik property[:sub-property:]
formun bir yapılandırma anahtarına bağlanır. Örneğin, MyOptions.Option1 özelliği appSettings. JSONiçindeki
option1 özelliğinden okunan anahtar Option1 bağımlıdır.

Aşağıdaki kodda, hizmet kapsayıcısına üçüncü bir IConfigureOptions<TOptions> hizmeti eklenir.


MySubOptions appSettings. JSON dosyasının subsection bölümüne bağlar:

// Example #3: Suboptions


// Bind options using a sub-section of the appsettings.json file.
services.Configure<MySubOptions>(Configuration.GetSection("subsection"));

GetSection yöntemi Microsoft.Extensions.Configuration ad alanını gerektirir.


Örneğin appSettings. JSON dosyası, suboption1 ve suboption2 için anahtarlar içeren bir subsection üyesini
tanımlar:

{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

MySubOptions sınıfı, Seçenekler değerlerini tutmak için özellikleri, SubOption1 ve SubOption2 tanımlar
(modeller/Myalt seçenekler. cs):
public class MySubOptions
{
public MySubOptions()
{
// Set default values.
SubOption1 = "value1_from_ctor";
SubOption2 = 5;
}

public string SubOption1 { get; set; }


public int SubOption2 { get; set; }
}

Sayfa modelinin OnGet yöntemi, Seçenekler değerleriyle (Pages/Index. cshtml. cs) bir dize döndürür:

private readonly MySubOptions _subOptions;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #3: Suboptions


var subOption1 = _subOptions.SubOption1;
var subOption2 = _subOptions.SubOption2;
SubOptions = $"subOption1 = {subOption1}, subOption2 = {subOption2}";

Uygulama çalıştırıldığında OnGet yöntemi, alt sınıf değerlerini gösteren bir dize döndürür:

subOption1 = subvalue1_from_json, subOption2 = 200

Seçeneklere ekleme
Seçenekler ekleme, örnek uygulamada #4 olarak gösterilmiştir.
IOptionsMonitor<TOptions> içine ekle:
@inject Razor yönergesi ile Razor sayfası veya MVC görünümü.
Bir sayfa veya görünüm modeli.
Örnek uygulamadan alınan aşağıdaki örnek, bir sayfa modeline IOptionsMonitor<TOptions>
(Sayfalar/Index. cshtml. cs):

private readonly MyOptions _options;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #4: Bind options directly to the page


MyOptions = _options;

Örnek uygulama, @inject yönergeyle IOptionsMonitor<MyOptions> nasıl ekleneceğini gösterir:

@page
@model IndexModel
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<MyOptions> OptionsAccessor
@{
ViewData["Title"] = "Options Sample";
}

<h1>@ViewData["Title"]</h1>

Uygulama çalıştırıldığında, seçenek değerleri işlenen sayfada gösterilir:

Ioptionssnapshot ile yapılandırma verilerini yeniden yükleme


Yapılandırma verilerini IOptionsSnapshot<TOptions> ile yeniden yükleme örnek uygulamada örnek #5
gösterilmiştir.
IOptionsSnapshot<TOptions>kullanarak, erişilen ve isteğin ömrü boyunca önbelleğe alınan istekler her istek
için bir kez hesaplanır.
IOptionsMonitor ve IOptionsSnapshot arasındaki fark şudur:
IOptionsMonitor , geçerli seçenek değerlerini her zaman alan, özellikle de tek bağımlılıklarda yararlı olan
bir tek hizmettir .
IOptionsSnapshot kapsamlı bir hizmettir ve IOptionsSnapshot<T> nesnesinin oluşturulduğu sırada
seçeneklerin anlık görüntüsünü sağlar. Seçenekler anlık görüntüleri geçici ve kapsamlı bağımlılıklarla
kullanılmak üzere tasarlanmıştır.
Aşağıdaki örnek, appSettings. JSON değişikliklerinden sonra yeni bir IOptionsSnapshot<TOptions> nasıl
oluşturulduğunu gösterir (Pages/Index. cshtml. cs). Sunucu için birden çok istek, dosya değiştirilene ve
yapılandırma yeniden yükleninceye kadar appSettings. JSON dosyası tarafından belirtilen sabit değerler
döndürüyor.

private readonly MyOptions _snapshotOptions;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #5: Snapshot options


var snapshotOption1 = _snapshotOptions.Option1;
var snapshotOption2 = _snapshotOptions.Option2;
SnapshotOptions =
$"snapshot option1 = {snapshotOption1}, " +
$"snapshot option2 = {snapshotOption2}";

Aşağıdaki görüntüde, appSettings. JSON dosyasından yüklenen ilk option1 ve option2 değerleri
gösterilmektedir:

snapshot option1 = value1_from_json, snapshot option2 = -1

AppSettings. JSON dosyasındaki değerleri value1_from_json UPDATED ve 200 olacak şekilde değiştirin.
AppSettings. JSON dosyasını kaydedin. Seçenekler değerlerinin güncelleştirildiğini görmek için tarayıcıyı
yenileyin:

snapshot option1 = value1_from_json UPDATED, snapshot option2 = 200

IController Enamedooptıons ile adlandırılmış seçenekler desteği


IConfigureNamedOptions<TOptions> ile adlandırılmış seçenekler, örnek uygulamada 6 #örnek olarak
gösterilmiştir.
Adlandırılmış seçenekler desteği, uygulamanın adlandırılmış seçenek yapılandırmalarının ayırt etmesine izin
verir. Örnek uygulamada, adlandırılmış Seçenekler OptionsServiceCollectionExtensions. configureile
bildirilmiştir ve bu, <TOptions > ' i çağırır. Uzantı yöntemini Yapılandır:
// Example #6: Named options (named_options_1)
// Register the ConfigurationBuilder instance which MyOptions binds against.
// Specify that the options loaded from configuration are named
// "named_options_1".
services.Configure<MyOptions>("named_options_1", Configuration);

// Example #6: Named options (named_options_2)


// Specify that the options loaded from the MyOptions class are named
// "named_options_2".
// Use a delegate to configure option values.
services.Configure<MyOptions>("named_options_2", myOptions =>
{
myOptions.Option1 = "named_options_2_value1_from_action";
});

Örnek uygulama, Get (Pages/Index. cshtml. cs) adlı adlandırılmış seçeneklere erişir:

private readonly MyOptions _named_options_1;


private readonly MyOptions _named_options_2;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #6: Named options


var named_options_1 =
$"named_options_1: option1 = {_named_options_1.Option1}, " +
$"option2 = {_named_options_1.Option2}";
var named_options_2 =
$"named_options_2: option1 = {_named_options_2.Option1}, " +
$"option2 = {_named_options_2.Option2}";
NamedOptions = $"{named_options_1} {named_options_2}";

Örnek uygulama çalıştırıldığında, adlandırılmış seçenekler döndürülür:

named_options_1: option1 = value1_from_json, option2 = -1


named_options_2: option1 = named_options_2_value1_from_action, option2 = 5

named_options_1 değerler, appSettings. JSON dosyasından yüklenen yapılandırmadan sağlanır.


named_options_2 değerleri tarafından sağlanır:
Option1 için ConfigureServices named_options_2 temsilcisi.
MyOptions sınıfı tarafından sağlanmış Option2 için varsayılan değer.

Tüm seçenekleri ConfigureAll yöntemiyle yapılandırma


Tüm seçenek örneklerini ConfigureAll yöntemiyle yapılandırın. Aşağıdaki kod, ortak bir değere sahip tüm
yapılandırma örnekleri için Option1 yapılandırır. Startup.ConfigureServices yöntemine el ile aşağıdaki kodu
ekleyin:

services.ConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "ConfigureAll replacement value";
});

Kodu ekledikten sonra örnek uygulamayı çalıştırmak aşağıdaki sonucu verir:

named_options_1: option1 = ConfigureAll replacement value, option2 = -1


named_options_2: option1 = ConfigureAll replacement value, option2 = 5

NOTE
Tüm seçenekler adlandırılmış örneklerdir. Mevcut IConfigureOptions<TOptions> örnekleri,
string.Empty``Options.DefaultName örneğini hedefleyecek şekilde değerlendirilir.
IConfigureNamedOptions<TOptions> Ayrıca IConfigureOptions<TOptions>uygular. IOptionsFactory<TOptions>
varsayılan uygulamasının her birini uygun şekilde kullanma mantığı vardır. null adlandırılmış seçenek, belirli bir
adlandırılmış örnek yerine tüm adlandırılmış örnekleri hedeflemek için kullanılır (ConfigureAll ve PostConfigureAll bu
kuralı kullanın).

Seçenekno Oluşturucu API 'SI


OptionsBuilder<TOptions>, TOptions örnekleri yapılandırmak için kullanılır. OptionsBuilder , sonraki
çağrıların tümünde olmak yerine ilk AddOptions<TOptions>(string optionsName) çağrısına yalnızca tek bir
parametre olan adlandırılmış seçenekleri oluşturmayı kolaylaştırır. Seçenekler doğrulaması ve hizmet
bağımlılıklarını kabul eden ConfigureOptions aşırı yüklemeler yalnızca OptionsBuilder ile kullanılabilir.

// Options.DefaultName = "" is used.


services.AddOptions<MyOptions>().Configure(o => o.Property = "default");

services.AddOptions<MyOptions>("optionalName")
.Configure(o => o.Property = "named");

Ayarları yapılandırmak için dı hizmetlerini kullanma


Seçenekleri iki şekilde yapılandırırken, bağımlılık ekleme işleminden diğer hizmetlere erişebilirsiniz:
<TOptions > ' nin Options Builder'da yapılandırılması için bir yapılandırma temsilcisi geçirin. <bir
TOptions > seçenek Oluşturucusu , seçenekleri yapılandırmak için en fazla beş hizmeti kullanmanıza
olanak sağlayan, yapılandırma yüklerini sağlar:

services.AddOptions<MyOptions>("optionalName")
.Configure<Service1, Service2, Service3, Service4, Service5>(
(o, s, s2, s3, s4, s5) =>
o.Property = DoSomethingWith(s, s2, s3, s4, s5));

IConfigureOptions<TOptions> veya IConfigureNamedOptions<TOptions> uygulayan ve türü bir


hizmet olarak kaydeden kendi türünü oluşturun.
Bir hizmetin oluşturulması daha karmaşık olduğundan, yapılandırmakiçin bir yapılandırma temsilcisinin
geçirilmesini öneririz. Kendi türünü oluşturmak, Yapılandır'ı kullandığınızda çerçevenin sizin için yaptığı işe
eşdeğerdir. Yapılandırma çağrısı, belirtilen genel hizmet türlerini kabul eden bir oluşturucuya sahip olan geçici
genel IConfigureNamedOptions<TOptions>kaydeder.

Seçenekler doğrulaması
Seçenekler doğrulaması seçenekler yapılandırıldığında seçenekleri doğrulamanızı sağlar. Seçenekler
geçerliyse true döndüren ve geçerli değillerse false bir doğrulama yöntemiyle Validate çağırın:

// Registration
services.AddOptions<MyOptions>("optionalOptionsName")
.Configure(o => { }) // Configure the options
.Validate(o => YourValidationShouldReturnTrueIfValid(o),
"custom error");

// Consumption
var monitor = services.BuildServiceProvider()
.GetService<IOptionsMonitor<MyOptions>>();

try
{
var options = monitor.Get("optionalOptionsName");
}
catch (OptionsValidationException e)
{
// e.OptionsName returns "optionalOptionsName"
// e.OptionsType returns typeof(MyOptions)
// e.Failures returns a list of errors, which would contain
// "custom error"
}

Önceki örnekte, adlandırılmış seçenekler örneği optionalOptionsName olarak ayarlanır. Varsayılan Seçenekler
örneği Options.DefaultName .
Seçenekler örneği oluşturulduğunda doğrulama çalıştırılır. Seçenek Örneğinizde, ilk kez erişildiğinde
doğrulamanın başarılı olması garanti edilir.

IMPORTANT
Seçenekler, Seçenekler başlangıçta yapılandırıldıktan ve doğrulandıktan sonra seçeneklerindeki değişikliklere karşı
koruma yapmaz.

Validate yöntemi bir kabul eder. Doğrulamayı tamamen özelleştirmek için, şunları
Func<TOptions, bool>
sağlayan IValidateOptions<TOptions> uygulayın:
Birden çok seçenek türünün doğrulanması:
class ValidateTwo : IValidateOptions<Option1>, IValidationOptions<Option2>
Başka bir seçenek türüne bağlı olan doğrulama:
public DependsOnAnotherOptionValidator(IOptionsMonitor<AnotherOption> options)

IValidateOptions şunları doğrular:


Belirli bir adlandırılmış seçenekler örneği.
name null tüm seçenekler.

Arabirimin uygulanınızdan bir ValidateOptionsResult döndürün:


public interface IValidateOptions<TOptions> where TOptions : class
{
ValidateOptionsResult Validate(string name, TOptions options);
}

Veri ek açıklaması tabanlı doğrulama, OptionsBuilder<TOptions> ValidateDataAnnotations yöntemi çağırarak


Microsoft. Extensions. Options. DataAnnotation paketinden kullanılabilir.
Microsoft.Extensions.Options.DataAnnotations , Microsoft. AspNetCore. app metapackageiçinde bulunur.

using Microsoft.Extensions.DependencyInjection;

private class AnnotatedOptions


{
[Required]
public string Required { get; set; }

[StringLength(5, ErrorMessage = "Too long.")]


public string StringLength { get; set; }

[Range(-5, 5, ErrorMessage = "Out of range.")]


public int IntRange { get; set; }
}

[Fact]
public void CanValidateDataAnnotations()
{
var services = new ServiceCollection();
services.AddOptions<AnnotatedOptions>()
.Configure(o =>
{
o.StringLength = "111111";
o.IntRange = 10;
o.Custom = "nowhere";
})
.ValidateDataAnnotations();

var sp = services.BuildServiceProvider();

var error = Assert.Throws<OptionsValidationException>(() =>


sp.GetRequiredService<IOptionsMonitor<AnnotatedOptions>>().CurrentValue);
ValidateFailure<AnnotatedOptions>(error, Options.DefaultName, 1,
"DataAnnotation validation failed for members Required " +
"with the error 'The Required field is required.'.",
"DataAnnotation validation failed for members StringLength " +
"with the error 'Too long.'.",
"DataAnnotation validation failed for members IntRange " +
"with the error 'Out of range.'.");
}

Eager doğrulaması (başlangıçta hızlı başarısız), gelecek bir sürüm için dikkate alınmaz.

Yapılandırma sonrası seçenekler


Yapılandırma sonrası IPostConfigureOptions<TOptions>ayarlayın. Tüm IConfigureOptions<TOptions>
yapılandırma oluştuktan sonra yapılandırma sonrası çalıştırmalar:

services.PostConfigure<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});
PostConfigure, adlandırılmış seçenekleri yapılandırmak için kullanılabilir:

services.PostConfigure<MyOptions>("named_options_1", myOptions =>


{
myOptions.Option1 = "post_configured_option1_value";
});

Tüm yapılandırma örneklerini yapılandırmak için PostConfigureAll kullanın:

services.PostConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});

Başlangıç sırasında seçeneklere erişme


IOptions<TOptions> ve IOptionsMonitor<TOptions> Startup.Configure kullanılabilir, çünkü Hizmetleri
Configure Yöntemi yürütülmeden önce oluşturulmuştur.

public void Configure(IApplicationBuilder app, IOptionsMonitor<MyOptions> optionsAccessor)


{
var option1 = optionsAccessor.CurrentValue.Option1;
}

Startup.ConfigureServices IOptions<TOptions> veya IOptionsMonitor<TOptions> kullanmayın. Hizmet


kayıtlarının sıralaması nedeniyle tutarsız bir seçenek durumu var olabilir.
Seçenekler stili, ilişkili ayarların gruplarını temsil etmek için sınıfları kullanır. Yapılandırma ayarları senaryo
tarafından ayrı sınıflara ayrılmışsa, uygulama iki önemli yazılım mühendisliği ilkelerine uyar:
Yapılandırma ayarlarına bağlı olan arabirim ayırma ilkesi (ISS ) veya kapsülleme – senaryoları (sınıflar)
yalnızca kullandıkları yapılandırma ayarlarına bağlıdır.
Uygulamanın farklı parçaları için – ayarlarının ayrılması, birbirine bağımlı değildir veya birbirlerine
aktarılmaz.
Seçenekler Ayrıca yapılandırma verilerini doğrulamaya yönelik bir mekanizma sağlar. Daha fazla bilgi için
Seçenekler doğrulama bölümüne bakın.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Microsoft. AspNetCore. app metapackage 'e başvurun veya Microsoft. Extensions. Options.
configurationextensions paketine bir paket başvurusu ekleyin.

Seçenekler arabirimleri
IOptionsMonitor<TOptions>, TOptions örnekleri için seçenekleri almak ve seçenek bildirimlerini yönetmek
için kullanılır. IOptionsMonitor<TOptions> aşağıdaki senaryoları destekler:
Değişiklik bildirimleri
Adlandırılmış seçenekler
Yeniden yüklenebilir yapılandırma
Seçmeli seçenekler geçersiz kılma (IOptionsMonitorCache<TOptions>)
Yapılandırma sonrası senaryolar, tüm IConfigureOptions<TOptions> yapılandırma oluştuktan sonra
seçenekleri ayarlamanıza veya değiştirmenize olanak sağlar.
IOptionsFactory<TOptions> yeni seçenek örnekleri oluşturmaktan sorumludur. Tek bir Create yöntemi vardır.
Varsayılan uygulama tüm kayıtlı IConfigureOptions<TOptions> ve IPostConfigureOptions<TOptions> alır ve
önce tüm yapılandırmaların, ardından yapılandırma sonrası sonrasında çalıştırılır.
IConfigureNamedOptions<TOptions> ve IConfigureOptions<TOptions> arasında ayrım yapar ve yalnızca
uygun arabirimi çağırır.
IOptionsMonitorCache<TOptions>, IOptionsMonitor<TOptions> tarafından TOptions örnekleri önbelleğe
almak için kullanılır. IOptionsMonitorCache<TOptions>, değer yeniden hesaplanabilmesi için izleyici içindeki
seçenek örneklerini geçersiz kılar (TryRemove). Değerler, TryAddile el ile tanıtılamaz. Clear yöntemi, tüm
adlandırılmış örneklerin isteğe bağlı olarak yeniden oluşturulması gerektiğinde kullanılır.
IOptionsSnapshot<TOptions>, her istekte seçeneklerin yeniden hesaplanması gereken senaryolarda
faydalıdır. Daha fazla bilgi için bkz. ıoptionssnapshot ile yapılandırma verilerini yeniden yükleme bölümü.
IOptions<TOptions>, seçenekleri desteklemek için kullanılabilir. Ancak, IOptions<TOptions> önceki
IOptionsMonitor<TOptions>senaryolarını desteklemez. Zaten IOptions<TOptions> arabirimini kullanan
mevcut çerçeveler ve kitaplıklarda IOptions<TOptions> kullanmaya devam edebilir ve
IOptionsMonitor<TOptions>tarafından sağlanmış senaryolara gerek kalmaz.

Genel Seçenekler yapılandırması


Genel Seçenekler yapılandırması örnek uygulamada #1 olarak gösterilmiştir.
Bir seçenek sınıfı ortak parametresiz bir Oluşturucu ile soyut olmamalıdır. Aşağıdaki MyOptions sınıfında,
Option1 ve Option2 iki özelliği vardır. Varsayılan değerleri ayarlama isteğe bağlıdır, ancak aşağıdaki örnekteki
sınıf oluşturucusu Option1 varsayılan değerini ayarlar. Option2 , özelliği doğrudan başlatarak varsayılan değer
kümesine sahiptir (modeller/MyOptions. cs):

public class MyOptions


{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

MyOptions sınıfı, Configure ve yapılandırmayla bağlantılı olarak hizmet kapsayıcısına eklenir:

// Example #1: General configuration


// Register the Configuration instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);

Aşağıdaki sayfa modeli, ayarlara erişmek için IOptionsMonitor<TOptions> ile Oluşturucu bağımlılığı ekleme
işlemini kullanır (Sayfalar/Index. cshtml. cs):

private readonly MyOptions _options;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #1: Simple options


var option1 = _options.Option1;
var option2 = _options.Option2;
SimpleOptions = $"option1 = {option1}, option2 = {option2}";

Örneğin appSettings. JSON dosyası option1 ve option2 değerlerini belirtir:

{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini gösteren bir dize
döndürür:

option1 = value1_from_json, option2 = -1

NOTE
Bir ayarlar dosyasından seçenek yapılandırması 'nı yüklemek için özel bir ConfigurationBuilder kullanırken, temel yolun
doğru şekilde ayarlandığını onaylayın:

var configBuilder = new ConfigurationBuilder()


.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true);
var config = configBuilder.Build();

services.Configure<MyOptions>(config);

Ayarlar dosyasından CreateDefaultBuilderaracılığıyla seçenek yapılandırması yüklenirken taban yolunu açıkça ayarlama
gerekli değildir.
Bir temsilciyle basit seçenekleri yapılandırma
Basit seçeneklerin bir temsilciyle yapılandırılması, örnek uygulamada #2 örnek olarak gösterilmiştir.
Seçenek değerlerini ayarlamak için bir temsilci kullanın. Örnek uygulama MyOptionsWithDelegateConfig sınıfını
kullanır (modeller/MyOptionsWithDelegateConfig. cs):

public class MyOptionsWithDelegateConfig


{
public MyOptionsWithDelegateConfig()
{
// Set default value.
Option1 = "value1_from_ctor";
}

public string Option1 { get; set; }


public int Option2 { get; set; } = 5;
}

Aşağıdaki kodda, hizmet kapsayıcısına ikinci bir IConfigureOptions<TOptions> hizmeti eklenir.


MyOptionsWithDelegateConfig ile bağlamayı yapılandırmak için bir temsilci kullanır:

// Example #2: Options bound and configured by a delegate


services.Configure<MyOptionsWithDelegateConfig>(myOptions =>
{
myOptions.Option1 = "value1_configured_by_delegate";
myOptions.Option2 = 500;
});

Index.cshtml.cs:

private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #2: Options configured by delegate


var delegate_config_option1 = _optionsWithDelegateConfig.Option1;
var delegate_config_option2 = _optionsWithDelegateConfig.Option2;
SimpleOptionsWithDelegateConfig =
$"delegate_option1 = {delegate_config_option1}, " +
$"delegate_option2 = {delegate_config_option2}";

Birden çok yapılandırma sağlayıcısı ekleyebilirsiniz. Yapılandırma sağlayıcıları NuGet paketlerinde


kullanılabilir ve kayıtlı oldukları sırayla uygulanır. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Her Configure çağrısı, hizmet kapsayıcısına bir IConfigureOptions<TOptions> hizmeti ekler. Yukarıdaki
örnekte, Option1 ve Option2 değerlerinin ikisi de appSettings. JSONiçinde belirtilmiştir, ancak Option1 ve
Option2 değerleri yapılandırılan temsilci tarafından geçersiz kılınır.

Birden fazla yapılandırma hizmeti etkinleştirildiğinde, son yapılandırma kaynağı WINS ' i ve yapılandırma
değerini ayarlar. Uygulama çalıştırıldığında, sayfa modelinin OnGet yöntemi, seçenek sınıfı değerlerini
gösteren bir dize döndürür:

delegate_option1 = value1_configured_by_delegate, delegate_option2 = 500

Alt seçenekler yapılandırması


Alt seçenekler yapılandırması örnek uygulamada #3 örnek olarak gösterilmiştir.
Uygulamalar, uygulamadaki belirli senaryo gruplarına (sınıflar) ait seçenek sınıfları oluşturmamalıdır.
Uygulamanın yapılandırma değerleri gerektiren bölümlerinin yalnızca kullandıkları yapılandırma değerlerine
erişimi olmalıdır.
Seçenekleri yapılandırmaya bağlama sırasında, seçenek türündeki her bir özellik property[:sub-property:]
formun bir yapılandırma anahtarına bağlanır. Örneğin, MyOptions.Option1 özelliği appSettings. JSONiçindeki
option1 özelliğinden okunan anahtar Option1 bağımlıdır.

Aşağıdaki kodda, hizmet kapsayıcısına üçüncü bir IConfigureOptions<TOptions> hizmeti eklenir.


MySubOptions appSettings. JSON dosyasının subsection bölümüne bağlar:

// Example #3: Suboptions


// Bind options using a sub-section of the appsettings.json file.
services.Configure<MySubOptions>(Configuration.GetSection("subsection"));

GetSection yöntemi Microsoft.Extensions.Configuration ad alanını gerektirir.


Örneğin appSettings. JSON dosyası, suboption1 ve suboption2 için anahtarlar içeren bir subsection üyesini
tanımlar:

{
"option1": "value1_from_json",
"option2": -1,
"subsection": {
"suboption1": "subvalue1_from_json",
"suboption2": 200
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

MySubOptions sınıfı, Seçenekler değerlerini tutmak için özellikleri, SubOption1 ve SubOption2 tanımlar
(modeller/Myalt seçenekler. cs):
public class MySubOptions
{
public MySubOptions()
{
// Set default values.
SubOption1 = "value1_from_ctor";
SubOption2 = 5;
}

public string SubOption1 { get; set; }


public int SubOption2 { get; set; }
}

Sayfa modelinin OnGet yöntemi, Seçenekler değerleriyle (Pages/Index. cshtml. cs) bir dize döndürür:

private readonly MySubOptions _subOptions;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #3: Suboptions


var subOption1 = _subOptions.SubOption1;
var subOption2 = _subOptions.SubOption2;
SubOptions = $"subOption1 = {subOption1}, subOption2 = {subOption2}";

Uygulama çalıştırıldığında OnGet yöntemi, alt sınıf değerlerini gösteren bir dize döndürür:

subOption1 = subvalue1_from_json, subOption2 = 200

Bir görünüm modeli veya doğrudan görünüm ekleme ile belirtilen


seçenekler
Bir görünüm modeli veya doğrudan görünüm ekleme ile sunulan seçenekler örnek uygulamada #4 olarak
gösterilmiştir.
Seçenekler, bir görünüm modelinde veya IOptionsMonitor<TOptions> ekleme tarafından doğrudan bir
görünüme (Pages/Index. cshtml. cs) sağlanabilir.

private readonly MyOptions _options;


public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #4: Bind options directly to the page


MyOptions = _options;

Örnek uygulama, @inject yönergeyle IOptionsMonitor<MyOptions> nasıl ekleneceğini gösterir:

@page
@model IndexModel
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<MyOptions> OptionsAccessor
@{
ViewData["Title"] = "Options Sample";
}

<h1>@ViewData["Title"]</h1>

Uygulama çalıştırıldığında, seçenek değerleri işlenen sayfada gösterilir:

Ioptionssnapshot ile yapılandırma verilerini yeniden yükleme


Yapılandırma verilerini IOptionsSnapshot<TOptions> ile yeniden yükleme örnek uygulamada örnek #5
gösterilmiştir.
IOptionsSnapshot<TOptions>, minimum işleme yüküyle yeniden yükleme seçeneklerini destekler.
Seçenekler erişildiğinde ve isteğin ömrü boyunca önbelleğe alındığında her istek için bir kez hesaplanır.
Aşağıdaki örnek, appSettings. JSON değişikliklerinden sonra yeni bir IOptionsSnapshot<TOptions> nasıl
oluşturulduğunu gösterir (Pages/Index. cshtml. cs). Sunucu için birden çok istek, dosya değiştirilene ve
yapılandırma yeniden yükleninceye kadar appSettings. JSON dosyası tarafından belirtilen sabit değerler
döndürüyor.

private readonly MyOptions _snapshotOptions;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #5: Snapshot options


var snapshotOption1 = _snapshotOptions.Option1;
var snapshotOption2 = _snapshotOptions.Option2;
SnapshotOptions =
$"snapshot option1 = {snapshotOption1}, " +
$"snapshot option2 = {snapshotOption2}";

Aşağıdaki görüntüde, appSettings. JSON dosyasından yüklenen ilk option1 ve option2 değerleri
gösterilmektedir:

snapshot option1 = value1_from_json, snapshot option2 = -1

AppSettings. JSON dosyasındaki değerleri value1_from_json UPDATED ve 200 olacak şekilde değiştirin.
AppSettings. JSON dosyasını kaydedin. Seçenekler değerlerinin güncelleştirildiğini görmek için tarayıcıyı
yenileyin:

snapshot option1 = value1_from_json UPDATED, snapshot option2 = 200

IController Enamedooptıons ile adlandırılmış seçenekler desteği


IConfigureNamedOptions<TOptions> ile adlandırılmış seçenekler, örnek uygulamada 6 #örnek olarak
gösterilmiştir.
Adlandırılmış seçenekler desteği, uygulamanın adlandırılmış seçenek yapılandırmalarının ayırt etmesine izin
verir. Örnek uygulamada, adlandırılmış Seçenekler OptionsServiceCollectionExtensions. configureile
bildirilmiştir ve bu, <TOptions > ' i çağırır. Uzantı yöntemini Yapılandır:
// Example #6: Named options (named_options_1)
// Register the ConfigurationBuilder instance which MyOptions binds against.
// Specify that the options loaded from configuration are named
// "named_options_1".
services.Configure<MyOptions>("named_options_1", Configuration);

// Example #6: Named options (named_options_2)


// Specify that the options loaded from the MyOptions class are named
// "named_options_2".
// Use a delegate to configure option values.
services.Configure<MyOptions>("named_options_2", myOptions =>
{
myOptions.Option1 = "named_options_2_value1_from_action";
});

Örnek uygulama, Get (Pages/Index. cshtml. cs) adlı adlandırılmış seçeneklere erişir:

private readonly MyOptions _named_options_1;


private readonly MyOptions _named_options_2;

public IndexModel(
IOptionsMonitor<MyOptions> optionsAccessor,
IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
IOptionsMonitor<MySubOptions> subOptionsAccessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor,
IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
_options = optionsAccessor.CurrentValue;
_optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
_subOptions = subOptionsAccessor.CurrentValue;
_snapshotOptions = snapshotOptionsAccessor.Value;
_named_options_1 = namedOptionsAccessor.Get("named_options_1");
_named_options_2 = namedOptionsAccessor.Get("named_options_2");
}

// Example #6: Named options


var named_options_1 =
$"named_options_1: option1 = {_named_options_1.Option1}, " +
$"option2 = {_named_options_1.Option2}";
var named_options_2 =
$"named_options_2: option1 = {_named_options_2.Option1}, " +
$"option2 = {_named_options_2.Option2}";
NamedOptions = $"{named_options_1} {named_options_2}";

Örnek uygulama çalıştırıldığında, adlandırılmış seçenekler döndürülür:

named_options_1: option1 = value1_from_json, option2 = -1


named_options_2: option1 = named_options_2_value1_from_action, option2 = 5

named_options_1 değerler, appSettings. JSON dosyasından yüklenen yapılandırmadan sağlanır.


named_options_2 değerleri tarafından sağlanır:
Option1 için ConfigureServices named_options_2 temsilcisi.
MyOptions sınıfı tarafından sağlanmış Option2 için varsayılan değer.

Tüm seçenekleri ConfigureAll yöntemiyle yapılandırma


Tüm seçenek örneklerini ConfigureAll yöntemiyle yapılandırın. Aşağıdaki kod, ortak bir değere sahip tüm
yapılandırma örnekleri için Option1 yapılandırır. Startup.ConfigureServices yöntemine el ile aşağıdaki kodu
ekleyin:

services.ConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "ConfigureAll replacement value";
});

Kodu ekledikten sonra örnek uygulamayı çalıştırmak aşağıdaki sonucu verir:

named_options_1: option1 = ConfigureAll replacement value, option2 = -1


named_options_2: option1 = ConfigureAll replacement value, option2 = 5

NOTE
Tüm seçenekler adlandırılmış örneklerdir. Mevcut IConfigureOptions<TOptions> örnekleri,
string.Empty``Options.DefaultName örneğini hedefleyecek şekilde değerlendirilir.
IConfigureNamedOptions<TOptions> Ayrıca IConfigureOptions<TOptions>uygular. IOptionsFactory<TOptions>
varsayılan uygulamasının her birini uygun şekilde kullanma mantığı vardır. null adlandırılmış seçenek, belirli bir
adlandırılmış örnek yerine tüm adlandırılmış örnekleri hedeflemek için kullanılır (ConfigureAll ve PostConfigureAll bu
kuralı kullanın).

Seçenekno Oluşturucu API 'SI


OptionsBuilder<TOptions>, TOptions örnekleri yapılandırmak için kullanılır. OptionsBuilder , sonraki
çağrıların tümünde olmak yerine ilk AddOptions<TOptions>(string optionsName) çağrısına yalnızca tek bir
parametre olan adlandırılmış seçenekleri oluşturmayı kolaylaştırır. Seçenekler doğrulaması ve hizmet
bağımlılıklarını kabul eden ConfigureOptions aşırı yüklemeler yalnızca OptionsBuilder ile kullanılabilir.

// Options.DefaultName = "" is used.


services.AddOptions<MyOptions>().Configure(o => o.Property = "default");

services.AddOptions<MyOptions>("optionalName")
.Configure(o => o.Property = "named");

Ayarları yapılandırmak için dı hizmetlerini kullanma


Seçenekleri iki şekilde yapılandırırken, bağımlılık ekleme işleminden diğer hizmetlere erişebilirsiniz:
<TOptions > ' nin Options Builder'da yapılandırılması için bir yapılandırma temsilcisi geçirin. <bir
TOptions > seçenek Oluşturucusu , seçenekleri yapılandırmak için en fazla beş hizmeti kullanmanıza
olanak sağlayan, yapılandırma yüklerini sağlar:

services.AddOptions<MyOptions>("optionalName")
.Configure<Service1, Service2, Service3, Service4, Service5>(
(o, s, s2, s3, s4, s5) =>
o.Property = DoSomethingWith(s, s2, s3, s4, s5));

IConfigureOptions<TOptions> veya IConfigureNamedOptions<TOptions> uygulayan ve türü bir


hizmet olarak kaydeden kendi türünü oluşturun.
Bir hizmetin oluşturulması daha karmaşık olduğundan, yapılandırmakiçin bir yapılandırma temsilcisinin
geçirilmesini öneririz. Kendi türünü oluşturmak, Yapılandır'ı kullandığınızda çerçevenin sizin için yaptığı işe
eşdeğerdir. Yapılandırma çağrısı, belirtilen genel hizmet türlerini kabul eden bir oluşturucuya sahip olan geçici
genel IConfigureNamedOptions<TOptions>kaydeder.

Yapılandırma sonrası seçenekler


Yapılandırma sonrası IPostConfigureOptions<TOptions>ayarlayın. Tüm IConfigureOptions<TOptions>
yapılandırma oluştuktan sonra yapılandırma sonrası çalıştırmalar:

services.PostConfigure<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});

PostConfigure, adlandırılmış seçenekleri yapılandırmak için kullanılabilir:

services.PostConfigure<MyOptions>("named_options_1", myOptions =>


{
myOptions.Option1 = "post_configured_option1_value";
});

Tüm yapılandırma örneklerini yapılandırmak için PostConfigureAll kullanın:

services.PostConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});

Başlangıç sırasında seçeneklere erişme


IOptions<TOptions> ve IOptionsMonitor<TOptions> Startup.Configure kullanılabilir, çünkü Hizmetleri
Configure Yöntemi yürütülmeden önce oluşturulmuştur.

public void Configure(IApplicationBuilder app, IOptionsMonitor<MyOptions> optionsAccessor)


{
var option1 = optionsAccessor.CurrentValue.Option1;
}

Startup.ConfigureServices IOptions<TOptions> veya IOptionsMonitor<TOptions> kullanmayın. Hizmet


kayıtlarının sıralaması nedeniyle tutarsız bir seçenek durumu var olabilir.

Ek kaynaklar
ASP.NET Core yapılandırma
ASP.NET Core çoklu ortamları kullanma
9.12.2019 • 29 minutes to read • Edit Online

Tarafından Rick Anderson


ASP.NET Core, bir ortam değişkeni kullanarak çalışma zamanı ortamı temelinde uygulama davranışını
yapılandırır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Ortamlar
ASP.NET Core, uygulama başlangıcında ASPNETCORE_ENVIRONMENT ortam değişkenini okur ve değeri
ıwebhostenvironment. EnvironmentNameiçinde depolar. ASPNETCORE_ENVIRONMENT herhangi bir değere
ayarlanabilir, ancak Framework tarafından üç değer sağlanır:
Development
Staging
Production (varsayılan)

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))


{
app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();
app.UseMvc();
}

Yukarıdaki kod:
ASPNETCORE_ENVIRONMENT Development olarak ayarlandığında, UseDeveloperExceptionPage çağırır.
ASPNETCORE_ENVIRONMENT değeri aşağıdakilerden birini ayarladığınızda Useexceptionhandler ' i
çağırır:
Staging
Production
Staging_2

Ortam etiketi Yardımcısı , öğesinde biçimlendirme eklemek veya dışlamak için


IHostingEnvironment.EnvironmentName değerini kullanır:
<environment include="Development">
<div>&lt;environment include="Development"&gt;</div>
</environment>
<environment exclude="Development">
<div>&lt;environment exclude="Development"&gt;</div>
</environment>
<environment include="Staging,Development,Staging_2">
<div>
&lt;environment include="Staging,Development,Staging_2"&gt;
</div>
</environment>

Windows ve macOS 'ta, ortam değişkenleri ve değerleri büyük/küçük harfe duyarlı değildir. Linux ortam
değişkenleri ve değerleri varsayılan olarak büyük/küçük harfe duyarlıdır .
Geliştirme
Geliştirme ortamı, üretimde gösterilmemelidir özellikleri etkinleştirebilir. Örneğin, ASP.NET Core
Şablonlar geliştirme ortamında Geliştirici özel durum sayfasını etkinleştirir.
Yerel makine geliştirme ortamı, projenin Properties\launchSettings.JSON dosyasında ayarlanabilir.
Launchsettings. JSON geçersiz kılma değerlerini sistem ortamında ayarlanan ortam değerleri.
Aşağıdaki JSON, bir Launchsettings. JSON dosyasından üç profil gösterir:

{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54339/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_My_Environment": "1",
"ASPNETCORE_DETAILEDERRORS": "1",
"ASPNETCORE_ENVIRONMENT": "Staging"
}
},
"EnvironmentsSample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Staging"
},
"applicationUrl": "http://localhost:54340/"
},
"Kestrel Staging": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_My_Environment": "1",
"ASPNETCORE_DETAILEDERRORS": "1",
"ASPNETCORE_ENVIRONMENT": "Staging"
},
"applicationUrl": "http://localhost:51997/"
}
}
}
NOTE
Launchsettings. JSON içindeki applicationUrl özelliği sunucu URL 'lerinin bir listesini belirtebilir. Listedeki URL
'Ler arasında noktalı virgül kullanın:

"EnvironmentsSample": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}

Uygulama DotNet çalıştırmasıile başlatıldığında, "commandName": "Project" ilk profili kullanılır.


commandName değeri, başlatılacak Web sunucusunu belirtir. commandName aşağıdakilerden biri olabilir:

IISExpress
IIS
Project (Kestrel Başlatan)

Bir uygulama DotNet çalıştırmasıile başlatıldığında:


Launchsettings. JSON varsa okundu. launchsettings. JSON geçersiz kılma ortamı değişkenlerine
environmentVariables ayarları.
Barındırma ortamı görüntülenir.
Aşağıdaki çıktıda, DotNet çalıştırmasıile başlatılan bir uygulama gösterilmektedir:

PS C:\Websites\EnvironmentsSample> dotnet run


Using launch settings from C:\Websites\EnvironmentsSample\Properties\launchSettings.json...
Hosting environment: Staging
Content root path: C:\Websites\EnvironmentsSample
Now listening on: http://localhost:54340
Application started. Press Ctrl+C to shut down.

Visual Studio proje özellikleri hata ayıklama sekmesi, launchsettings. JSON dosyasını düzenlemek için bir
GUI sağlar:
Proje profillerinde yapılan değişiklikler, Web sunucusu yeniden başlatılana kadar etkili olmayabilir.Kestrel,
ortamında yapılan değişiklikleri algılayabilmesi için yeniden başlatılmalıdır.

WARNING
Launchsettings. JSON gizli dizileri depolamamamalıdır. Gizli anahtar geliştirme için gizli dizileri depolamak için gizli
dizi Yöneticisi aracı kullanılabilir.

Visual Studio Codekullanırken, ortam değişkenleri . vscode/Launch. JSON dosyasında ayarlanabilir.


Aşağıdaki örnek, Development için ortamı ayarlar:

{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",

... additional VS Code configuration settings ...

"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
]
}

Uygulama dotnet run Özellikler/launchSettings. JSONile aynı şekilde başlatılırken, projedeki bir .
vscode/Launch. JSON dosyası okunamaz. Geliştirme sırasında Launchsettings. JSON dosyası olmayan bir
uygulama başlatırken, ortam değişkeni veya bir komut satırı bağımsız değişkeni olan ortamı dotnet run
komutuna ayarlayın.
Üretim
Üretim ortamının güvenliği, performansı ve uygulama sağlamlık düzeyini en üst düzeye çıkarmak için
yapılandırılması gerekir. Geliştirmeden farklı bazı yaygın ayarlar şunlardır:
Önbelleği.
İstemci tarafı kaynaklar paketlenmiş, küçültülmüş ve potansiyel olarak bir CDN 'den sunulan.
Tanılama hata sayfaları devre dışı.
Kolay hata sayfaları etkin.
Üretim günlüğü ve izleme etkin. Örneğin, Application Insights.

Ortamı ayarlama
Bir ortam değişkeni veya platform ayarıyla test için belirli bir ortam ayarlamak genellikle yararlıdır. Ortam
ayarlanmamışsa, çoğu hata ayıklama özelliğini devre dışı bırakan Production varsayılan olarak ayarlanır.
Ortamı ayarlama yöntemi işletim sistemine bağlıdır.
Konak yapılandırıldığında, uygulama tarafından okunan son ortam ayarı, uygulamanın ortamını belirler.
Uygulama çalışırken uygulamanın ortamı değiştirilemez.
Ortam değişkeni veya platform ayarı
Azure uygulama hizmeti
Azure App Serviceortamında ortamı ayarlamak için aşağıdaki adımları gerçekleştirin:
1. Uygulama Hizmetleri dikey penceresinden uygulamayı seçin.
2. Ayarlar grubunda, uygulama ayarları dikey penceresini seçin.
3. Uygulama ayarları alanında yeni ayar Ekle' yi seçin.
4. Ad giriniçin ASPNETCORE_ENVIRONMENT sağlayın. Değer giriniçin ortamı sağlayın (örneğin, Staging ).
5. Ortam ayarının, dağıtım yuvaları takas edildiğinde geçerli yuvada kalmasını istiyorsanız, yuva ayarı
onay kutusunu işaretleyin. Daha fazla bilgi için bkz. Azure belgeleri: hangi ayarları değiştirmiş?.
6. Dikey pencerenin en üstünde Kaydet ' i seçin.
Azure App Service, Azure portal bir uygulama ayarı (ortam değişkeni) eklendikten, değiştirildikten veya
silindikten sonra uygulamayı otomatik olarak yeniden başlatır.
Windows
Uygulama DotNet çalıştırmasıkullanılarak başlatıldığında geçerli oturumun ASPNETCORE_ENVIRONMENT
ayarlamak için aşağıdaki komutlar kullanılır:
Komut istemi

set ASPNETCORE_ENVIRONMENT=Development

PowerShell

$Env:ASPNETCORE_ENVIRONMENT = "Development"

Bu komutlar yalnızca geçerli pencere için etkili olur. Pencere kapatıldığında, ASPNETCORE_ENVIRONMENT ayarı
varsayılan ayar veya makine değerine geri döner.
Windows 'da genel değeri ayarlamak için aşağıdaki yaklaşımlardan birini kullanın:
Sistem > gelişmiş sistem ayarları > denetim masası 'nı açın ve ASPNETCORE_ENVIRONMENT
değerini ekleyin veya düzenleyin:
Bir yönetim komut istemi açın ve setx komutunu kullanın veya bir yönetim PowerShell komut
istemi açın ve [Environment]::SetEnvironmentVariable kullanın:
Komut istemi

setx ASPNETCORE_ENVIRONMENT Development /M

/M anahtarı, ortam değişkenini sistem düzeyinde ayarlamaya yönelik olduğunu gösterir. /M


anahtarı kullanılmazsa, ortam değişkeni Kullanıcı hesabı için ayarlanır.
PowerShell

[Environment]::SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development", "Machine")

Machine seçenek değeri, ortam değişkeninin sistem düzeyinde ayarlandığını gösterir. Seçenek
değeri User olarak değiştirilirse, ortam değişkeni Kullanıcı hesabı için ayarlanır.

ASPNETCORE_ENVIRONMENT ortam değişkeni genel olarak ayarlandığında, değer ayarlandıktan sonra açılan
herhangi bir komut penceresinde dotnet run için geçerli olur.
Web. config
ASPNETCORE_ENVIRONMENT ortam değişkenini Web. configile ayarlamak için, ASP.NET Core Modülüortam
değişkenlerini ayarlama bölümüne bakın.
Proje dosyası veya yayımlama profili
WINDOWS IIS dağıtımları için: <EnvironmentName> özelliğini Publish profile (. pubxml) veya proje
dosyasına ekleyin. Bu yaklaşım, proje yayımlandığında Web. config içinde ortamı ayarlar:
<PropertyGroup>
<EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

IIS uygulama havuzu başına


Yalıtılmış uygulama havuzunda çalışan bir uygulamanın ASPNETCORE_ENVIRONMENT ortam değişkenini
ayarlamak için (IIS 10,0 veya üzeri sürümlerde desteklenir), ortam değişkenlerinin
<environmentVariables> konusunun Appcmd. exe komut bölümüne bakın. ASPNETCORE_ENVIRONMENT ortam
değişkeni bir uygulama havuzu için ayarlandığında, değeri sistem düzeyindeki bir ayarı geçersiz kılar.

IMPORTANT
IIS 'de bir uygulama barındırırken ve ASPNETCORE_ENVIRONMENT ortam değişkenini ekleyerek veya değiştirirken, yeni
değerin uygulamalar tarafından çekilmek için aşağıdaki yaklaşımlardan birini kullanın:
net stop was /y ve ardından komut isteminden net start w3svc yürütün.
Sunucuyu yeniden başlatın.

macOS
MacOS için geçerli ortamın ayarlanması, uygulamayı çalıştırırken satır içinde gerçekleştirilebilir:

ASPNETCORE_ENVIRONMENT=Development dotnet run

Alternatif olarak, uygulamayı çalıştırmadan önce ortamı export ayarlayın:

export ASPNETCORE_ENVIRONMENT=Development

Makine düzeyinde ortam değişkenleri . bashrc veya . bash_profile dosyasında ayarlanır. Herhangi bir metin
düzenleyicisini kullanarak dosyayı düzenleyin. Aşağıdaki ifadeyi ekleyin:

export ASPNETCORE_ENVIRONMENT=Development

Linux
Linux distros için, oturum tabanlı değişken ayarları ve makine düzeyindeki ortam ayarları için bash_profile
dosyası için bir komut isteminde export komutunu kullanın.
Kodda ortam ayarlama
Konağı oluştururken UseEnvironment çağırın. Bkz. .NET genel ana bilgisayar.
Ortama göre yapılandırma
Yapılandırmayı ortama göre yüklemek için şunları yapmanızı öneririz:
appSettings dosyaları (appSettings. { Environment}. JSON ). Bkz. ASP.NET Core yapılandırma.
Ortam değişkenleri (uygulamanın barındırıldığı her bir sistemde ayarlanır). Bkz. .NET genel ana
bilgisayar ve ASP.NET Core sürümünde geliştirme sırasında uygulama gizli dizileri güvenli depolama.
Gizli dizi Yöneticisi (yalnızca geliştirme ortamında). Bkz. ASP.NET Core sürümünde geliştirme sırasında
uygulama gizli dizileri güvenli depolama.

Ortam tabanlı başlangıç sınıfı ve yöntemleri


Iwebhostenvironment 'ı başlatmaya ekleme. configure
IWebHostEnvironment Startup.Configure ekleme. Bu yaklaşım, uygulama yalnızca, ortam başına en az
kod farklılığı olan birkaç ortam için Startup.Configure ayarlamayı gerektirdiğinde yararlıdır.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
// Development environment code
}
else
{
// Code for all other environments
}
}

Başlangıç sınıfına ıwebhostenvironment ekleme


Startup oluşturucusuna IWebHostEnvironment ekleyin. Bu yaklaşım, uygulama her ortam için en az kod
farklılığı olan birkaç ortam için Startup yapılandırmayı gerektirdiğinde yararlıdır.
Aşağıdaki örnekte:
Ortam _env alanında tutulur.
_env , ConfigureServices ve Configure uygulamanın ortamına göre başlangıç yapılandırmasını
uygulamak için kullanılır.

public class Startup


{
private readonly IWebHostEnvironment _env;

public Startup(IWebHostEnvironment env)


{
_env = env;
}

public void ConfigureServices(IServiceCollection services)


{
if (_env.IsDevelopment())
{
// Development environment code
}
else if (_env.IsStaging())
{
// Staging environment code
}
else
{
// Code for all other environments
}
}

public void Configure(IApplicationBuilder app)


{
if (_env.IsDevelopment())
{
// Development environment code
}
else
{
// Code for all other environments
}
}
}
Başlangıç sınıfı kuralları
ASP.NET Core bir uygulama başlatıldığında, Başlangıç sınıfı uygulamayı önyükleme. Uygulama farklı
ortamlar için ayrı Startup sınıfları tanımlayabilir (örneğin, StartupDevelopment ). Uygun Startup sınıfı
çalışma zamanında seçildi. Geçerli ortamla eşleşen ad sonekine sahip olan sınıf önceliklendirilir. Eşleşen bir
Startup{EnvironmentName} sınıfı bulunamazsa, Startup sınıfı kullanılır. Bu yaklaşım, uygulama başına çok
sayıda kod farklılığı olan birkaç ortam için başlangıç yapılandırması gerektirdiğinde yararlıdır.
Ortam tabanlı Startup sınıfları uygulamak için, kullanımdaki her ortam için bir Startup{EnvironmentName}
sınıfı ve bir geri dönüş Startup sınıfı oluşturun:

// Startup class to use in the Development environment


public class StartupDevelopment
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

// Startup class to use in the Production environment


public class StartupProduction
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

// Fallback Startup class


// Selected if the environment doesn't match a Startup{EnvironmentName} class
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

Derleme adını kabul eden Usestartup (ıwebhostbuilder, String) aşırı yüklemesini kullanın:

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;

return WebHost.CreateDefaultBuilder(args)
.UseStartup(assemblyName);
}
Başlangıç yöntemi kuralları
Yapılandırma ve ConfigureServices , form Configure<EnvironmentName> ve
Configure<EnvironmentName>Services ortama özgü sürümlerini destekler. Bu yaklaşım, uygulama başına çok
sayıda kod farklılığı olan birkaç ortam için başlangıç yapılandırması gerektirdiğinde yararlıdır.

public class Startup


{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
StartupConfigureServices(services);
}

public void ConfigureStagingServices(IServiceCollection services)


{
StartupConfigureServices(services);
}

private void StartupConfigureServices(IServiceCollection services)


{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))


{
app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();
app.UseMvc();
}

public void ConfigureStaging(IApplicationBuilder app, IHostingEnvironment env)


{
if (!env.IsStaging())
{
throw new Exception("Not staging.");
}

app.UseExceptionHandler("/Error");
app.UseStaticFiles();
app.UseMvc();
}
}

Ek kaynaklar
ASP.NET Core 'de uygulama başlatma
ASP.NET Core yapılandırma
Tarafından Rick Anderson
ASP.NET Core, bir ortam değişkeni kullanarak çalışma zamanı ortamı temelinde uygulama davranışını
yapılandırır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Ortamlar
ASP.NET Core, uygulama başlangıcında ASPNETCORE_ENVIRONMENT ortam değişkenini okur ve değeri
ıhostingenvironment. EnvironmentNameiçinde depolar. ASPNETCORE_ENVIRONMENT herhangi bir değere
ayarlanabilir, ancak Framework tarafından üç değer sağlanır:
Development
Staging
Production (varsayılan)

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))


{
app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();
app.UseMvc();
}

Yukarıdaki kod:
ASPNETCORE_ENVIRONMENT Development olarak ayarlandığında, UseDeveloperExceptionPage çağırır.
ASPNETCORE_ENVIRONMENT değeri aşağıdakilerden birini ayarladığınızda Useexceptionhandler ' i
çağırır:
Staging
Production
Staging_2

Ortam etiketi Yardımcısı , öğesinde biçimlendirme eklemek veya dışlamak için


IHostingEnvironment.EnvironmentName değerini kullanır:

<environment include="Development">
<div>&lt;environment include="Development"&gt;</div>
</environment>
<environment exclude="Development">
<div>&lt;environment exclude="Development"&gt;</div>
</environment>
<environment include="Staging,Development,Staging_2">
<div>
&lt;environment include="Staging,Development,Staging_2"&gt;
</div>
</environment>
Windows ve macOS 'ta, ortam değişkenleri ve değerleri büyük/küçük harfe duyarlı değildir. Linux ortam
değişkenleri ve değerleri varsayılan olarak büyük/küçük harfe duyarlıdır .
Geliştirme
Geliştirme ortamı, üretimde gösterilmemelidir özellikleri etkinleştirebilir. Örneğin, ASP.NET Core
Şablonlar geliştirme ortamında Geliştirici özel durum sayfasını etkinleştirir.
Yerel makine geliştirme ortamı, projenin Properties\launchSettings.JSON dosyasında ayarlanabilir.
Launchsettings. JSON geçersiz kılma değerlerini sistem ortamında ayarlanan ortam değerleri.
Aşağıdaki JSON, bir Launchsettings. JSON dosyasından üç profil gösterir:

{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54339/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_My_Environment": "1",
"ASPNETCORE_DETAILEDERRORS": "1",
"ASPNETCORE_ENVIRONMENT": "Staging"
}
},
"EnvironmentsSample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Staging"
},
"applicationUrl": "http://localhost:54340/"
},
"Kestrel Staging": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_My_Environment": "1",
"ASPNETCORE_DETAILEDERRORS": "1",
"ASPNETCORE_ENVIRONMENT": "Staging"
},
"applicationUrl": "http://localhost:51997/"
}
}
}
NOTE
Launchsettings. JSON içindeki applicationUrl özelliği sunucu URL 'lerinin bir listesini belirtebilir. Listedeki URL
'Ler arasında noktalı virgül kullanın:

"EnvironmentsSample": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}

Uygulama DotNet çalıştırmasıile başlatıldığında, "commandName": "Project" ilk profili kullanılır.


commandName değeri, başlatılacak Web sunucusunu belirtir. commandName aşağıdakilerden biri olabilir:

IISExpress
IIS
Project (Kestrel Başlatan)

Bir uygulama DotNet çalıştırmasıile başlatıldığında:


Launchsettings. JSON varsa okundu. launchsettings. JSON geçersiz kılma ortamı değişkenlerine
environmentVariables ayarları.
Barındırma ortamı görüntülenir.
Aşağıdaki çıktıda, DotNet çalıştırmasıile başlatılan bir uygulama gösterilmektedir:

PS C:\Websites\EnvironmentsSample> dotnet run


Using launch settings from C:\Websites\EnvironmentsSample\Properties\launchSettings.json...
Hosting environment: Staging
Content root path: C:\Websites\EnvironmentsSample
Now listening on: http://localhost:54340
Application started. Press Ctrl+C to shut down.

Visual Studio proje özellikleri hata ayıklama sekmesi, launchsettings. JSON dosyasını düzenlemek için bir
GUI sağlar:
Proje profillerinde yapılan değişiklikler, Web sunucusu yeniden başlatılana kadar etkili olmayabilir.Kestrel,
ortamında yapılan değişiklikleri algılayabilmesi için yeniden başlatılmalıdır.

WARNING
Launchsettings. JSON gizli dizileri depolamamamalıdır. Gizli anahtar geliştirme için gizli dizileri depolamak için gizli
dizi Yöneticisi aracı kullanılabilir.

Visual Studio Codekullanırken, ortam değişkenleri . vscode/Launch. JSON dosyasında ayarlanabilir.


Aşağıdaki örnek, Development için ortamı ayarlar:

{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",

... additional VS Code configuration settings ...

"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
]
}

Uygulama dotnet run Özellikler/launchSettings. JSONile aynı şekilde başlatılırken, projedeki bir .
vscode/Launch. JSON dosyası okunamaz. Geliştirme sırasında Launchsettings. JSON dosyası olmayan bir
uygulama başlatırken, ortam değişkeni veya bir komut satırı bağımsız değişkeni olan ortamı dotnet run
komutuna ayarlayın.
Üretim
Üretim ortamının güvenliği, performansı ve uygulama sağlamlık düzeyini en üst düzeye çıkarmak için
yapılandırılması gerekir. Geliştirmeden farklı bazı yaygın ayarlar şunlardır:
Önbelleği.
İstemci tarafı kaynaklar paketlenmiş, küçültülmüş ve potansiyel olarak bir CDN 'den sunulan.
Tanılama hata sayfaları devre dışı.
Kolay hata sayfaları etkin.
Üretim günlüğü ve izleme etkin. Örneğin, Application Insights.

Ortamı ayarlama
Bir ortam değişkeni veya platform ayarıyla test için belirli bir ortam ayarlamak genellikle yararlıdır. Ortam
ayarlanmamışsa, çoğu hata ayıklama özelliğini devre dışı bırakan Production varsayılan olarak ayarlanır.
Ortamı ayarlama yöntemi işletim sistemine bağlıdır.
Konak yapılandırıldığında, uygulama tarafından okunan son ortam ayarı, uygulamanın ortamını belirler.
Uygulama çalışırken uygulamanın ortamı değiştirilemez.
Ortam değişkeni veya platform ayarı
Azure uygulama hizmeti
Azure App Serviceortamında ortamı ayarlamak için aşağıdaki adımları gerçekleştirin:
1. Uygulama Hizmetleri dikey penceresinden uygulamayı seçin.
2. Ayarlar grubunda, uygulama ayarları dikey penceresini seçin.
3. Uygulama ayarları alanında yeni ayar Ekle' yi seçin.
4. Ad giriniçin ASPNETCORE_ENVIRONMENT sağlayın. Değer giriniçin ortamı sağlayın (örneğin, Staging ).
5. Ortam ayarının, dağıtım yuvaları takas edildiğinde geçerli yuvada kalmasını istiyorsanız, yuva ayarı
onay kutusunu işaretleyin. Daha fazla bilgi için bkz. Azure belgeleri: hangi ayarları değiştirmiş?.
6. Dikey pencerenin en üstünde Kaydet ' i seçin.
Azure App Service, Azure portal bir uygulama ayarı (ortam değişkeni) eklendikten, değiştirildikten veya
silindikten sonra uygulamayı otomatik olarak yeniden başlatır.
Windows
Uygulama DotNet çalıştırmasıkullanılarak başlatıldığında geçerli oturumun ASPNETCORE_ENVIRONMENT
ayarlamak için aşağıdaki komutlar kullanılır:
Komut istemi

set ASPNETCORE_ENVIRONMENT=Development

PowerShell

$Env:ASPNETCORE_ENVIRONMENT = "Development"

Bu komutlar yalnızca geçerli pencere için etkili olur. Pencere kapatıldığında, ASPNETCORE_ENVIRONMENT ayarı
varsayılan ayar veya makine değerine geri döner.
Windows 'da genel değeri ayarlamak için aşağıdaki yaklaşımlardan birini kullanın:
Sistem > gelişmiş sistem ayarları > denetim masası 'nı açın ve ASPNETCORE_ENVIRONMENT
değerini ekleyin veya düzenleyin:
Bir yönetim komut istemi açın ve setx komutunu kullanın veya bir yönetim PowerShell komut
istemi açın ve [Environment]::SetEnvironmentVariable kullanın:
Komut istemi

setx ASPNETCORE_ENVIRONMENT Development /M

/M anahtarı, ortam değişkenini sistem düzeyinde ayarlamaya yönelik olduğunu gösterir. /M


anahtarı kullanılmazsa, ortam değişkeni Kullanıcı hesabı için ayarlanır.
PowerShell

[Environment]::SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development", "Machine")

Machine seçenek değeri, ortam değişkeninin sistem düzeyinde ayarlandığını gösterir. Seçenek
değeri User olarak değiştirilirse, ortam değişkeni Kullanıcı hesabı için ayarlanır.
ASPNETCORE_ENVIRONMENT ortam değişkeni genel olarak ayarlandığında, değer ayarlandıktan sonra açılan
herhangi bir komut penceresinde dotnet run için geçerli olur.
Web. config
ASPNETCORE_ENVIRONMENT ortam değişkenini Web. configile ayarlamak için, ASP.NET Core Modülüortam
değişkenlerini ayarlama bölümüne bakın.
Proje dosyası veya yayımlama profili
WINDOWS IIS dağıtımları için: <EnvironmentName> özelliğini Publish profile (. pubxml) veya proje
dosyasına ekleyin. Bu yaklaşım, proje yayımlandığında Web. config içinde ortamı ayarlar:
<PropertyGroup>
<EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

IIS uygulama havuzu başına


Yalıtılmış uygulama havuzunda çalışan bir uygulamanın ASPNETCORE_ENVIRONMENT ortam değişkenini
ayarlamak için (IIS 10,0 veya üzeri sürümlerde desteklenir), ortam değişkenlerinin
<environmentVariables> konusunun Appcmd. exe komut bölümüne bakın. ASPNETCORE_ENVIRONMENT ortam
değişkeni bir uygulama havuzu için ayarlandığında, değeri sistem düzeyindeki bir ayarı geçersiz kılar.

IMPORTANT
IIS 'de bir uygulama barındırırken ve ASPNETCORE_ENVIRONMENT ortam değişkenini ekleyerek veya değiştirirken, yeni
değerin uygulamalar tarafından çekilmek için aşağıdaki yaklaşımlardan birini kullanın:
net stop was /y ve ardından komut isteminden net start w3svc yürütün.
Sunucuyu yeniden başlatın.

macOS
MacOS için geçerli ortamın ayarlanması, uygulamayı çalıştırırken satır içinde gerçekleştirilebilir:

ASPNETCORE_ENVIRONMENT=Development dotnet run

Alternatif olarak, uygulamayı çalıştırmadan önce ortamı export ayarlayın:

export ASPNETCORE_ENVIRONMENT=Development

Makine düzeyinde ortam değişkenleri . bashrc veya . bash_profile dosyasında ayarlanır. Herhangi bir metin
düzenleyicisini kullanarak dosyayı düzenleyin. Aşağıdaki ifadeyi ekleyin:

export ASPNETCORE_ENVIRONMENT=Development

Linux
Linux distros için, oturum tabanlı değişken ayarları ve makine düzeyindeki ortam ayarları için bash_profile
dosyası için bir komut isteminde export komutunu kullanın.
Kodda ortam ayarlama
Konağı oluştururken UseEnvironment çağırın. Bkz. ASP.NET Core Web ana bilgisayarı.
Ortama göre yapılandırma
Yapılandırmayı ortama göre yüklemek için şunları yapmanızı öneririz:
appSettings dosyaları (appSettings. { Environment}. JSON ). Bkz. ASP.NET Core yapılandırma.
Ortam değişkenleri (uygulamanın barındırıldığı her bir sistemde ayarlanır). Bkz. ASP.NET Core Web
ana bilgisayarı ve ASP.NET Core sürümünde geliştirme sırasında uygulama gizli dizileri güvenli
depolama.
Gizli dizi Yöneticisi (yalnızca geliştirme ortamında). Bkz. ASP.NET Core sürümünde geliştirme sırasında
uygulama gizli dizileri güvenli depolama.

Ortam tabanlı başlangıç sınıfı ve yöntemleri


Başlangıç olarak ıhostingenvironment ekleme. yapılandırma
IHostingEnvironment Startup.Configure ekleme. Bu yaklaşım, uygulama yalnızca, ortam başına en az kod
farklılığı olan birkaç ortam için Startup.Configure yapılandırmayı gerektirdiğinde yararlıdır.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
// Development environment code
}
else
{
// Code for all other environments
}
}

Başlangıç sınıfına ıhostingenvironment ekleme


Startup oluşturucusuna IHostingEnvironment ekleyin ve hizmeti Startup sınıfı boyunca kullanmak üzere
bir alana atayın. Bu yaklaşım, uygulama her ortam için en az kod farklılığı olan birkaç ortam için başlatma
yapılandırması gerektirdiğinde faydalıdır.
Aşağıdaki örnekte:
Ortam _env alanında tutulur.
_env , ConfigureServices ve Configure uygulamanın ortamına göre başlangıç yapılandırmasını
uygulamak için kullanılır.
public class Startup
{
private readonly IHostingEnvironment _env;

public Startup(IHostingEnvironment env)


{
_env = env;
}

public void ConfigureServices(IServiceCollection services)


{
if (_env.IsDevelopment())
{
// Development environment code
}
else if (_env.IsStaging())
{
// Staging environment code
}
else
{
// Code for all other environments
}
}

public void Configure(IApplicationBuilder app)


{
if (_env.IsDevelopment())
{
// Development environment code
}
else
{
// Code for all other environments
}
}
}

Başlangıç sınıfı kuralları


ASP.NET Core bir uygulama başlatıldığında, Başlangıç sınıfı uygulamayı önyükleme. Uygulama farklı
ortamlar için ayrı Startup sınıfları tanımlayabilir (örneğin, StartupDevelopment ). Uygun Startup sınıfı
çalışma zamanında seçildi. Geçerli ortamla eşleşen ad sonekine sahip olan sınıf önceliklendirilir. Eşleşen bir
Startup{EnvironmentName} sınıfı bulunamazsa, Startup sınıfı kullanılır. Bu yaklaşım, uygulama başına çok
sayıda kod farklılığı olan birkaç ortam için başlangıç yapılandırması gerektirdiğinde yararlıdır.
Ortam tabanlı Startup sınıfları uygulamak için, kullanımdaki her ortam için bir Startup{EnvironmentName}
sınıfı ve bir geri dönüş Startup sınıfı oluşturun:
// Startup class to use in the Development environment
public class StartupDevelopment
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

// Startup class to use in the Production environment


public class StartupProduction
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

// Fallback Startup class


// Selected if the environment doesn't match a Startup{EnvironmentName} class
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
}
}

Derleme adını kabul eden Usestartup (ıwebhostbuilder, String) aşırı yüklemesini kullanın:

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;

return WebHost.CreateDefaultBuilder(args)
.UseStartup(assemblyName);
}

Başlangıç yöntemi kuralları


Yapılandırma ve ConfigureServices , form Configure<EnvironmentName> ve
Configure<EnvironmentName>Services ortama özgü sürümlerini destekler. Bu yaklaşım, uygulama başına çok
sayıda kod farklılığı olan birkaç ortam için başlangıç yapılandırması gerektirdiğinde yararlıdır.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
StartupConfigureServices(services);
}

public void ConfigureStagingServices(IServiceCollection services)


{
StartupConfigureServices(services);
}

private void StartupConfigureServices(IServiceCollection services)


{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))


{
app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();
app.UseMvc();
}

public void ConfigureStaging(IApplicationBuilder app, IHostingEnvironment env)


{
if (!env.IsStaging())
{
throw new Exception("Not staging.");
}

app.UseExceptionHandler("/Error");
app.UseStaticFiles();
app.UseMvc();
}
}

Ek kaynaklar
ASP.NET Core 'de uygulama başlatma
ASP.NET Core yapılandırma
.NET Core ve ASP.NET Core oturum açma
5.12.2019 • 52 minutes to read • Edit Online

Tom Dykstra ve Steve Smith tarafından


.NET Core, çeşitli yerleşik ve üçüncü taraf oturum açma sağlayıcılarıyla birlikte çalışarak bir günlüğe kaydetme API
'sini destekler. Bu makalede, yerleşik sağlayıcılarla günlüğe kaydetme API 'sinin nasıl kullanılacağı gösterilmektedir.
Bu makalede gösterilen kod örneklerinin çoğu ASP.NET Core uygulamalardan oluşur. Bu kod parçacıklarının
günlüğe kaydetmeye özgü bölümleri, genel ana bilgisayarıkullanan tüm .NET Core uygulamaları için geçerlidir.
Genel konağın Web 'de olmayan uygulamalarda kullanımı hakkında bilgi için bkz. barındırılan hizmetler.
Genel ana bilgisayarı olmayan uygulamalar için günlük kodu, sağlayıcıların Eklenme ve günlükçülerin
oluşturulmabiçiminde farklılık gösterir. Ana bilgisayar olmayan kod örnekleri, makalenin bu bölümlerinde
gösterilmiştir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Sağlayıcı Ekle
Günlük sağlayıcısı günlükleri görüntüler veya depolar. Örneğin, konsol sağlayıcısı günlükleri konsolunda görüntüler
ve Azure Application Insights sağlayıcısı bunları Azure Application Insights depolar. Birden çok sağlayıcı eklenerek
Günlükler birden çok hedefe gönderilebilir.
Genel ana bilgisayar kullanan bir uygulamaya sağlayıcı eklemek için, program.cs'de sağlayıcının
Add{provider name} uzantısı metodunu çağırın:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Konak olmayan bir konsol uygulamasında, bir LoggerFactory oluştururken sağlayıcının Add{provider name} uzantısı
metodunu çağırın:

var loggerFactory = LoggerFactory.Create(builder =>


{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

LoggerFactory ve AddConsole , Microsoft.Extensions.Logging için using bir ifade gerektirir.


Varsayılan ASP.NET Core proje şablonları, aşağıdaki günlük sağlayıcılarını ekleyen CreateDefaultBuilderçağırır:
Console
Hata ayıklama
EventSource
Olay günlüğü (yalnızca Windows üzerinde çalışırken)
Varsayılan sağlayıcıları kendi seçimlerinizle değiştirebilirsiniz. ClearProvidersçağırın ve istediğiniz sağlayıcıları
ekleyin.

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Bir sağlayıcı eklemek için sağlayıcının Add{provider name} uzantısı yöntemini program.csiçinde çağırın:

public static void Main(string[] args)


{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
// Requires `using Microsoft.Extensions.Logging;`
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
.UseStartup<Startup>()
.Build();

webHost.Run();
}

Yukarıdaki kod Microsoft.Extensions.Logging ve Microsoft.Extensions.Configuration başvuruları gerektirir.


Varsayılan proje şablonu, aşağıdaki günlük sağlayıcılarını ekleyen CreateDefaultBuilderçağırır:
Konsolu
Hata ayıklama
EventSource (ASP.NET Core 2,2 ' den başlayarak)
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();

CreateDefaultBuilder kullanıyorsanız, varsayılan sağlayıcıları kendi seçimlerinizle değiştirebilirsiniz.


ClearProvidersçağırın ve istediğiniz sağlayıcıları ekleyin.

public static void Main(string[] args)


{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});

Makalenin ilerleyen kısımlarında yerleşik günlük sağlayıcıları ve üçüncü taraf günlüğü sağlayıcıları hakkında daha
fazla bilgi edinin.

Günlükleri oluştur
Günlükler oluşturmak için bir ILogger<TCategoryName> nesnesi kullanın. Bir Web uygulamasında veya
barındırılan hizmette, bağımlılık ekleme (DI) ILogger alın. Konak dışı konsol uygulamalarında, bir ILogger
oluşturmak için LoggerFactory kullanın.
Aşağıdaki ASP.NET Core örnek kategori olarak TodoApiSample.Pages.AboutModel içeren bir günlükçü oluşturur.
Günlük kategorisi , her günlük ile ilişkili bir dizedir. Dı tarafından belirtilen ILogger<T> örneği, kategori olarak T
tam adı olan Günlükler oluşturur.

public class AboutModel : PageModel


{
private readonly ILogger _logger;

public AboutModel(ILogger<AboutModel> logger)


{
_logger = logger;
}

Aşağıdaki konak olmayan konsol uygulaması örneği, kategori olarak LoggingConsoleApp.Program olan bir günlükçü
oluşturur.
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

public class AboutModel : PageModel


{
private readonly ILogger _logger;

public AboutModel(ILogger<AboutModel> logger)


{
_logger = logger;
}

Aşağıdaki ASP.NET Core ve konsol uygulaması örneklerinde, günlükçü, düzeyi Information olan günlükleri
oluşturmak için kullanılır. Günlük düzeyi günlüğe kaydedilen etkinliğin önem derecesini gösterir.

public void OnGet()


{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation("Message displayed: {Message}", Message);
}

var loggerFactory = LoggerFactory.Create(builder =>


{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

public void OnGet()


{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation("Message displayed: {Message}", Message);
}

Düzeyler ve Kategoriler Bu makalenin ilerleyen kısımlarında daha ayrıntılı olarak açıklanmıştır.


Program sınıfında Günlükler oluşturma
ASP.NET Core uygulamasının Program sınıfında Günlükler yazmak için, konak oluşturulduktan sonra bir ILogger
örneği alın:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

IMyService myService = host.Services.GetRequiredService<IMyService>();


myService.WriteLog("Logged from MyService.");

host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Ana bilgisayar oluşturma sırasında günlüğe kaydetme doğrudan desteklenmez. Ancak, ayrı bir günlükçü
kullanılabilir. Aşağıdaki örnekte, CreateHostBuilder oturum açmak için bir Serilog günlükçü kullanılır. AddSerilog ,
Log.Logger belirtilen statik yapılandırmayı kullanır:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Program


{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args)


{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();

Log.Logger = new LoggerConfiguration()


.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();

try
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddRazorPages();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");

throw;
}
finally
{
Log.CloseAndFlush();
}
}
}

Başlangıç sınıfında Günlükler oluşturma


Bir ASP.NET Core uygulamasının Startup.Configure yönteminde Günlükler yazmak için, yöntem imzasına bir
ILogger parametresi ekleyin:
public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
logger.LogInformation("In Development environment");
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}

Startup.ConfigureServices yönteminde DI kapsayıcısı kurulumu tamamlanmadan önce Günlüklerin yazılması


desteklenmez:
Startup oluşturucusuna günlükçü ekleme desteklenmiyor.
Startup.ConfigureServices yöntemi imzasına günlükçü ekleme desteklenmiyor

Bu kısıtlamanın nedeni, günlük kaydının dı ve yapılandırmaya göre değişir ve bu da, ara ' ya bağlıdır. DI kapsayıcısı
ConfigureServices bitene kadar ayarlanamaz.

Web ana bilgisayarı için ayrı bir dı kapsayıcısı oluşturulduğundan, bir günlükçü Startup ' ye Oluşturucu Ekleme
ASP.NET Core önceki sürümlerinde çalışmaktadır. Genel ana bilgisayar için yalnızca bir kapsayıcı oluşturma
hakkında daha fazla bilgi için bkz. Son değişiklik duyurusu.
ILogger<T> bağımlı bir hizmet yapılandırmanız gerekiyorsa, bunu Oluşturucu ekleme veya bir fabrika yöntemi
sağlayarak de yapabilirsiniz. Fabrika yöntemi yaklaşımı yalnızca başka bir seçenek yoksa önerilir. Örneğin, bir
özelliği kaynağından bir hizmete doldurmanız gerektiğini varsayalım:

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers();
services.AddRazorPages();

services.AddSingleton<IMyService>((container) =>
{
var logger = container.GetRequiredService<ILogger<MyService>>();
return new MyService() { Logger = logger };
});

services.AddSingleton<ITodoRepository, TodoRepository>();
}

Önceki vurgulanan kod, DI kapsayıcısının bir MyService örneği oluşturmak için ilk kez çalışan bir Func . Kayıtlı
hizmetlerden herhangi birine bu şekilde erişebilirsiniz.
Başlangıçta günlük oluşturma
Startup sınıfında Günlükler yazmak için, Oluşturucu imzasına bir ILogger parametresi ekleyin:

public class Startup


{
private readonly ILogger _logger;

public Startup(IConfiguration configuration, ILogger<Startup> logger)


{
Configuration = configuration;
_logger = logger;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

// Add our repository type


services.AddSingleton<ITodoRepository, TodoRepository>();
_logger.LogInformation("Added TodoRepository to services");
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
_logger.LogInformation("In Development environment");
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc();
}
}

Program sınıfında Günlükler oluşturma


Program sınıfında Günlükler yazmak için, DI 'den bir ILogger örneği alın:
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});

Ana bilgisayar oluşturma sırasında günlüğe kaydetme doğrudan desteklenmez. Ancak, ayrı bir günlükçü
kullanılabilir. Aşağıdaki örnekte, CreateWebHostBuilder oturum açmak için bir Serilog günlükçü kullanılır. AddSerilog
, Log.Logger belirtilen statik yapılandırmayı kullanır:
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();

Log.Logger = new LoggerConfiguration()


.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();

try
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddMvc();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.UseStartup<Startup>();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");

throw;
}
finally
{
Log.CloseAndFlush();
}
}
}

Zaman uyumsuz günlükçü yöntemi yok


Günlüğe kaydetme, zaman uyumsuz kodun performans maliyetine değer olmaması kadar hızlı olmalıdır. Günlüğe
kaydetme veri depoluizin yavaşsa, doğrudan buna yazmayın. Başlangıç olarak günlük iletilerini hızlı bir mağazaya
yazmayı ve sonra yavaş depoya daha sonra taşımayı düşünün. Örneğin, SQL Server için günlük kaydı yapıyorsanız,
Log Yöntemler zaman uyumlu olduğundan bunu doğrudan bir Log yönteminde yapmak istemezsiniz. Bunun
yerine, günlük iletilerini bir bellek içi kuyruğa eşzamanlı olarak ekleyin ve bir arka plan çalışanı, SQL Server veri
gönderme zaman uyumsuz çalışmasını sağlamak için iletileri kuyruktan çekin. Daha fazla bilgi için Bu GitHub
sorununa bakın.
Yapılandırma
Günlüğe kaydetme sağlayıcısı yapılandırması bir veya daha fazla yapılandırma sağlayıcısı tarafından sağlanır:
Dosya biçimleri (ıNı, JSON ve XML ).
Komut satırı bağımsız değişkenleri.
Ortam değişkenleri.
Bellek içi .NET nesneleri.
Şifrelenmemiş gizli dizi Yöneticisi depolaması.
Azure Key Vaultgibi şifreli bir kullanıcı deposu.
Özel sağlayıcılar (yüklü veya oluşturulmuş).
Örneğin, günlük yapılandırma genellikle uygulama ayarları dosyalarının Logging bölümü tarafından sağlanır.
Aşağıdaki örnek tipik bir appSettings 'in içeriğini gösterir . Development. JSON dosyası:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console":
{
"IncludeScopes": true
}
}
}

Logging özelliği LogLevel ve günlük sağlayıcısı özelliklerine sahip olabilir (konsol gösterilir).
Logging altındaki LogLevel özelliği, Seçili kategoriler için günlüğe kaydedilecek minimum düzeyi belirtir. Örnekte,
System ve Microsoft kategorileri Information düzeyinde günlüğe kaydedilir ve diğerleri Debug düzeyinde
günlüğe kaydedilir.
Logging altındaki diğer özellikler günlük sağlayıcılarını belirtir. Örnek, konsol sağlayıcısına yöneliktir. Bir sağlayıcı,
günlük kapsamlarınıdestekliyorsa IncludeScopes etkinleştirilip etkinleştirilmeyeceğini gösterir. Bir sağlayıcı özelliği
(örneğin Console gibi), bir LogLevel özelliği de belirtebilir. sağlayıcı altında LogLevel , bu sağlayıcının günlüğe
kaydedilecek düzeyleri belirtir.
Logging.{providername}.LogLevel düzeyler belirtilirse, Logging.LogLevel ayarlanan her şeyi geçersiz kılar.
Günlüğe kaydetme API 'SI, bir uygulama çalışırken günlük düzeylerini değiştirme senaryosu içermez. Ancak, bazı
yapılandırma sağlayıcıları yapılandırmayı yeniden yükleme yeteneğine sahiptir ve bu, günlüğe kaydetme
yapılandırması üzerinde etkili bir şekilde gerçekleşir. Örneğin, ayar dosyalarını okumak için CreateDefaultBuilder
tarafından eklenen dosya yapılandırma sağlayıcısı, varsayılan olarak günlük yapılandırmasını yeniden yükler.
Uygulama çalışırken kodda yapılandırma değiştirilirse uygulama, uygulamanın günlük yapılandırmasını
güncelleştirmek için IController. Reload ' i çağırabilir.
Yapılandırma sağlayıcılarını uygulama hakkında daha fazla bilgi için bkz. ASP.NET Core yapılandırma.

Örnek günlüğe kaydetme çıkışı


Yukarıdaki bölümde gösterilen örnek kodla, uygulama komut satırından çalıştırıldığında Günlükler konsolunda
görüntülenir. Konsol çıkışının bir örneği aşağıda verilmiştir:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 84.26180000000001ms 307
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/api/todo/0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller action with
signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
info: TodoApiSample.Controllers.TodoController[1002]
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) -
ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 42.9286ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 148.889ms 404

Yukarıdaki Günlükler, http://localhost:5000/api/todo/0 konumundaki örnek uygulamaya HTTP GET isteği


yapılarak oluşturulmuştur.
Visual Studio 'da örnek uygulamayı çalıştırdığınızda hata ayıklama penceresinde göründükleri günlüklere yönelik
bir örnek aşağıda verilmiştir:

Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 GET


https://localhost:44328/api/todo/0
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint
'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action =
"GetById", controller = "Todo", page = ""}. Executing controller action with signature
Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
TodoApiSample.Controllers.TodoController: Information: Getting item 0
TodoApiSample.Controllers.TodoController: Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult: Information: Executing HttpStatusCodeResult, setting HTTP status
code 404
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action
TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in 34.167ms
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint
'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 98.41300000000001ms 404

Yukarıdaki bölümde gösterilen ILogger çağrıları tarafından oluşturulan Günlükler "TodoApiSample" ile başlar.
"Microsoft" kategorileri ile başlayan Günlükler ASP.NET Core Framework kodundan alınır. ASP.NET Core ve
uygulama kodu aynı günlük API 'sini ve sağlayıcılarını kullanıyor.

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET


http://localhost:53104/api/todo/0
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method
TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
TodoApi.Controllers.TodoController:Information: Getting item 0
TodoApi.Controllers.TodoController:Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult:Information: Executing HttpStatusCodeResult, setting HTTP status code
404
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action
TodoApi.Controllers.TodoController.GetById (TodoApi) in 152.5657ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 316.3195ms 404

Yukarıdaki bölümde gösterilen ILogger çağrıları tarafından oluşturulan Günlükler "TodoApi" ile başlar. "Microsoft"
kategorileri ile başlayan Günlükler ASP.NET Core Framework kodundan alınır. ASP.NET Core ve uygulama kodu
aynı günlük API 'sini ve sağlayıcılarını kullanıyor.
Bu makalenin geri kalanında günlüğe kaydetme için bazı ayrıntılar ve seçenekler açıklanmaktadır.

NuGet paketleri
ILogger ve ILoggerFactory arabirimleri Microsoft. Extensions. Logging. soyutlamalarve bunların varsayılan
uygulamaları Microsoft. Extensions. Logging' dir.

Günlük kategorisi
ILogger bir nesne oluşturulduğunda, için bir Kategori belirtilir. Bu kategori, bu ILogger örneği tarafından
oluşturulan her günlük iletisine dahildir. Kategori herhangi bir dize olabilir, ancak kural, "TodoApi. Controllers.
TodoController" gibi sınıf adını kullanmaktır.
Kategori olarak T tam nitelikli tür adını kullanan bir ILogger örneğini almak için ILogger<T> kullanın:

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}

Kategoriyi açıkça belirtmek için ILoggerFactory.CreateLogger çağırın:


public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
}

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
}

ILogger<T> , T tam nitelikli tür adıyla CreateLogger çağırma ile eşdeğerdir.

Günlük düzeyi
Her günlük bir LogLevel değerini belirtir. Günlük düzeyi önem derecesini veya önemini gösterir. Örneğin, bir
yöntem normal olarak sona erdiğinde bir Information günlüğü ve bir yöntem 404 bulunmayan bir durum kodu
döndürdüğünde bir Warning günlüğü yazabilirsiniz.
Aşağıdaki kod Information ve Warning günlüklerini oluşturur:

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

Önceki kodda, ilk parametredir oturum öğesini belirten Olay No. İkinci parametre, kalan Yöntem parametreleri
tarafından belirtilen bağımsız değişken değerleri için yer tutucuları olan bir ileti şablonudur. Yöntem parametreleri
bu makalenin ilerleyen kısımlarında bulunan ileti şablonu bölümünde açıklanmaktadır.
Yöntem adındaki düzeyi (örneğin, LogInformation ve LogWarning ) içeren günlük yöntemleri, ILogger için uzantı
yöntemleridir. Bu yöntemler bir LogLevel parametresi alan Log yöntemini çağırır. Bu uzantı yöntemlerinden biri
yerine doğrudan Log yöntemi çağırabilirsiniz, ancak söz dizimi görece karmaşıktır. Daha fazla bilgi için bkz.
ILogger ve günlükçü uzantıları kaynak kodu.
ASP.NET Core, en küçükten en yüksek öneme doğru sıralanan aşağıdaki günlük düzeylerini tanımlar.
İzleme = 0
Genellikle yalnızca hata ayıklama için değerli bilgiler için. Bu iletiler hassas uygulama verileri içerebilir, bu
nedenle bir üretim ortamında etkinleştirilmemelidir. Varsayılan olarak devre dışıdır.
Hata Ayıkla = 1
Geliştirme ve hata ayıklama konusunda yararlı olabilecek bilgiler için. Örnek:
Entering method Configure with flag set to true. en yüksek günlük hacimden dolayı yalnızca sorun
giderirken Debug düzeyi günlüklerini etkinleştirin.
Bilgi = 2
Uygulamanın genel akışını izlemek için. Bu günlüklerde genellikle uzun süreli bir değer vardır. Örnek:
Request received for path /api/todo

Uyarı = 3
Uygulama akışında anormal veya beklenmedik olaylar için. Bunlar, uygulamanın durmasına neden olmayan
ancak araştırılması gerekebilecek hataları veya diğer koşulları içerebilir. İşlenmiş özel durumlar Warning
günlük düzeyini kullanmak için yaygın bir yerdir. Örnek: FileNotFoundException for file quotes.txt.
Hata = 4
İşlenemeyen hatalar ve özel durumlar için. Bu iletiler, uygulama genelinde bir hata değil geçerli etkinlikte
veya işlemde (geçerli HTTP isteği gibi) bir hata olduğunu gösterir. Örnek günlük iletisi:
Cannot insert record due to duplicate key violation.

Kritik = 5
Anında ilgilenilmesi gereken hatalarda. Örnekler: veri kaybı senaryoları, disk alanı yetersiz.
Belirli bir depolama ortamında veya görüntüleme penceresinde ne kadar günlük çıkışının yazıldığını denetlemek
için günlük düzeyini kullanın. Örneğin:
Üretimde:
Trace Information düzeylerinde günlüğe kaydetme, yüksek hacimli ayrıntılı günlük iletileri oluşturur.
Maliyetleri denetlemek ve veri depolama sınırlarını aşmamak için, Information düzey iletileri kullanarak
Trace yüksek hacimli, düşük maliyetli bir veri deposuna günlüğe kaydedin.
Warning Critical düzeyler aracılığıyla günlüğe kaydetme işlemi genellikle daha az, daha küçük günlük
iletileri üretir. Bu nedenle, maliyetler ve depolama sınırları genellikle bir sorun değildir ve bu da veri
deposu seçiminden daha fazla esneklik elde etmez.
Geliştirme sırasında:
Konsola Critical iletileri aracılığıyla Warning .
Sorun giderirken Information iletileri aracılığıyla Trace ekleyin.
Bu makalede daha sonra bulunan günlük filtreleme bölümünde, bir sağlayıcının hangi günlük düzeylerinin işlediğini
nasıl denetleneceği açıklanmaktadır.
ASP.NET Core çerçeve olayları için günlükleri yazar. Bu makalede daha önce gelen günlük örnekleri Information
düzeyin altında tutulur, dolayısıyla hiçbir Debug veya Trace düzeyi günlüğü oluşturulmaz. Aşağıda, Debug
günlüklerini göstermek için yapılandırılmış örnek uygulama çalıştırılarak oluşturulan konsol günlüklerinin bir
örneği verilmiştir:

info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller action with
signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of authorization filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of resource filters (in the following order):
Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of action filters (in the following order):
Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter (Order: -2147483648),
Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of exception filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of result filters (in the following order):
Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[22]
Attempting to bind parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[44]
Attempting to bind parameter 'id' of type 'System.String' using the name 'id' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[45]
Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[23]
Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[26]
Attempting to validate the bound parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[27]
Done attempting to validate the bound parameter 'id' of type 'System.String'.
info: TodoApiSample.Controllers.TodoController[1002]
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in 32.690400000000004ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 176.9103ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:62555/api/todo/0
dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
Request successfully matched the route with name 'GetTodo' and template 'api/Todo/{id}'.
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Update (TodoApi)' with id '089d59b6-92ec-472d-b552-
cc613dfd625d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Delete (TodoApi)' with id 'f3476abe-4bd9-4ad3-9261-
3ead09607366' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action TodoApi.Controllers.TodoController.GetById (TodoApi)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) -
ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method TodoApi.Controllers.TodoController.GetById (TodoApi), returned result
Microsoft.AspNetCore.Mvc.NotFoundResult.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 0.8788ms
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
Connection id "0HL6L7NEFF2QD" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2.7286ms 404

Günlüğe olay KIMLIĞI


Her günlük belirtebilirsiniz bir öğesini belirten Olay No. Örnek uygulama bunu yerel olarak tanımlanmış bir
LoggingEvents sınıfını kullanarak yapar:

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public class LoggingEvents


{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;

public const int GetItemNotFound = 4000;


public const int UpdateItemNotFound = 4001;
}
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public class LoggingEvents


{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;

public const int GetItemNotFound = 4000;


public const int UpdateItemNotFound = 4001;
}

Olay KIMLIĞI bir olay kümesini ilişkilendirir. Örneğin, bir sayfadaki öğelerin listesini görüntülemek için ilgili tüm
Günlükler 1001 olabilir.
Günlüğe kaydetme sağlayıcısı, olay KIMLIĞINI günlüğe kaydetme iletisindeki kimlik alanında veya hiç değil, bir
kimlik alanında saklayabilir. Hata ayıklama sağlayıcısı olay kimliklerini göstermiyor. Konsol sağlayıcısı, etkinlik
kimliklerini kategoriden sonra parantez içinde gösterir:

info: TodoApi.Controllers.TodoController[1002]
Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
GetById(invalidid) NOT FOUND

Günlük iletisi şablonu


Her günlük bir ileti şablonunu belirtir. İleti şablonu, bağımsız değişkenlerin sağlandığı yer tutucuları içerebilir.
Sayılar değil, yer tutucular için adları kullanın.

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

Adlarının, değerlerinin sağlanması için hangi parametrelerin kullanılacağını belirleyen yer tutucular sırası. Aşağıdaki
kodda, parametre adlarının ileti şablonunda sıra dışı olduğuna dikkat edin:

string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);

Bu kod, sırasıyla parametre değerleriyle bir günlük iletisi oluşturur:

Parameter values: parm1, parm2

Günlüğe kaydetme altyapısı bu şekilde çalışarak, günlük sağlayıcılarının yapılandırılmış günlüğe yazma olarak da
bilinen anlamsal günlüğüuygulayabilmesini sağlayabilir. Bağımsız değişkenler yalnızca biçimli ileti şablonuna değil,
günlük sistemine geçirilir. Bu bilgiler, günlük sağlayıcılarının parametre değerlerini alan olarak depolamasına olanak
sağlar. Örneğin, günlükçü yönteminin şuna benzer şekilde göründüğünü varsayın:

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Günlükleri Azure Tablo depolama alanına gönderiyorsanız, her bir Azure Tablo varlığı ID ve RequestTime
özelliklerine sahip olabilir. Bu, günlük verilerinde sorguları basitleştirir. Bir sorgu, belirli bir RequestTime aralığındaki
tüm günlükleri, metin iletisinden zaman aşımına uğratmadan bulabilir.

Günlüğe kaydetme özel durumları


Günlükçü yöntemlerinin, aşağıdaki örnekte olduğu gibi bir özel durum iletmenizi sağlayan aşırı yüklemeleri vardır:

catch (Exception ex)


{
_logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);

catch (Exception ex)


{
_logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);

Özel durum bilgileri farklı yollarla farklı sağlayıcılarda işler. Yukarıda gösterilen koddan hata ayıklama sağlayıcısı
çıktısına bir örnek aşağıda verilmiştir.
TodoApiSample.Controllers.TodoController: Warning: GetById(55) NOT FOUND

System.Exception: Item not found exception.


at TodoApiSample.Controllers.TodoController.GetById(String id) in
C:\TodoApiSample\Controllers\TodoController.cs:line 226

Günlük filtreleme
Belirli bir sağlayıcı ve kategori için en az bir günlük düzeyi veya tüm sağlayıcılar ya da tüm kategoriler için
belirtebilirsiniz. Minimum düzeyin altındaki tüm Günlükler bu sağlayıcıya aktarılmaz, bu nedenle görüntülenmez
veya depolanmaz.
Tüm günlükleri gizlemek için en düşük günlük düzeyi olarak LogLevel.None belirtin. LogLevel.None tamsayı değeri
6 ' dır ve LogLevel.Critical (5) daha yüksektir.
Yapılandırmada filtre kuralları oluşturma
Proje şablonu kodu, konsol, hata ayıklama ve EventSource (ASP.NET Core 2,2 veya üzeri) sağlayıcılar için günlük
kaydı ayarlamak üzere CreateDefaultBuilder çağırır. CreateDefaultBuilder yöntemi, Bu makalenin önceki
kısımlarındaaçıklandığı gibi, Logging bir bölümünde yapılandırma aramak için günlüğe kaydetmeyi ayarlar.
Yapılandırma verileri aşağıdaki örnekte olduğu gibi sağlayıcıya ve kategoriye göre en düşük günlük düzeylerini
belirtir:

{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}

Bu JSON altı filtre kuralı oluşturur: biri hata ayıklama sağlayıcısı, konsol sağlayıcısı için dört ve diğeri tüm
sağlayıcılar için. ILogger bir nesne oluşturulduğunda her sağlayıcı için tek bir kural seçilir.
Koddaki filtre kuralları
Aşağıdaki örnek, koddaki filtre kurallarının nasıl kaydedileceği gösterilmektedir:

.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace))

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));

İkinci AddFilter , tür adını kullanarak hata ayıklama sağlayıcısını belirtir. İlk AddFilter bir sağlayıcı türü
belirtmediğinden, tüm sağlayıcılar için geçerlidir.
Filtreleme kuralları nasıl uygulanır
Yapılandırma verileri ve önceki örneklerde gösterilen AddFilter kodu, aşağıdaki tabloda gösterilen kuralları
oluşturur. İlk altı yapılandırma örneğinde ve son iki ise kod örneğinde gelir.

ŞUNUNLA BAŞLAYAN
SAYI SAĞLAYICI KATEGORILER... EN DÜŞÜK GÜNLÜK DÜZEYI

1. Hata ayıklama Tüm kategoriler Bilgisi

2 Konsolu Microsoft.AspNetCore.Mvc.R Uyarı


azor.Internal

3 Konsolu Microsoft.AspNetCore.Mvc.R Hata ayıklama


azor.Razor
ŞUNUNLA BAŞLAYAN
SAYI SAĞLAYICI KATEGORILER... EN DÜŞÜK GÜNLÜK DÜZEYI

4 Konsolu Microsoft.AspNetCore.Mvc.R Hata


azor

5 Konsolu Tüm kategoriler Bilgisi

6 Tüm sağlayıcılar Tüm kategoriler Hata ayıklama

7 Tüm sağlayıcılar Sistem Hata ayıklama

8 Hata ayıklama Microsoft İzleme

Bir ILogger nesnesi oluşturulduğunda, ILoggerFactory nesnesi, bu günlükçü için uygulanacak her sağlayıcı için tek
bir kural seçer. Bir ILogger örneği tarafından yazılan tüm iletiler, seçilen kurallara göre filtrelenmiştir. Her sağlayıcı
ve kategori çifti için mümkün olan en özel kural kullanılabilir kurallardan seçilir.
Belirli bir kategori için ILogger oluşturulduğunda, her sağlayıcı için aşağıdaki algoritma kullanılır:
Sağlayıcı veya diğer adıyla eşleşen tüm kuralları seçin. Hiçbir eşleşme bulunmazsa, boş bir sağlayıcıya sahip tüm
kurallar ' ı seçin.
Önceki adımın sonucunda, en uzun eşleşen kategori ön ekine sahip kurallar ' ı seçin. Eşleşme bulunmazsa,
kategori belirtmeyen tüm kuralları seçin.
Birden çok kural seçilirse, son olanı götürün.
Hiçbir kural seçilmezse MinimumLevel kullanın.
Yukarıdaki kurallar listesinde, "Microsoft. AspNetCore. Mvc. Razor. RazorViewEngine" kategorisi için bir ILogger
nesnesi oluşturduğunuzu varsayalım:
Hata ayıklama sağlayıcısı, kurallar 1, 6 ve 8 için geçerlidir. Kural 8 ' i en özeldir, yani seçili olanı seçilidir.
Konsol sağlayıcısı için, kurallar 3, 4, 5 ve 6 geçerlidir. Kural 3 en özeldir.
Elde edilen ILogger örneği, hata ayıklama sağlayıcısına Trace düzeyi ve üzeri Günlükler gönderir. Debug düzeyi
ve üzeri Günlükler konsol sağlayıcısına gönderilir.
Sağlayıcı diğer adları
Her sağlayıcı, tam nitelikli tür adı yerine yapılandırmada kullanılabilecek bir diğer ad tanımlar. Yerleşik sağlayıcılar
için aşağıdaki diğer adları kullanın:
Konsolu
Hata ayıklama
EventSource
EventLog
TraceSource
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Varsayılan en düşük düzey
Yalnızca belirli bir sağlayıcı ve kategori için yapılandırma veya koddan kural uygulanmaz geçerli olan en düşük
düzey ayar vardır. Aşağıdaki örnekte, en düşük düzeyin nasıl ayarlanacağı gösterilmektedir:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));

En düşük düzeyi açıkça ayarlamazsanız, varsayılan değer Information , bu da Trace ve Debug günlüklerinin
yoksayıldığı anlamına gelir.
Filtre işlevleri
Configuration veya Code tarafından kendisine atanmış kuralları olmayan tüm sağlayıcılar ve kategoriler için bir
filtre işlevi çağırılır. İşlevindeki kodun sağlayıcı türü, kategorisi ve günlük düzeyine erişimi vardır. Örneğin:

.ConfigureLogging(logBuilder =>
{
logBuilder.AddFilter((provider, category, logLevel) =>
{
if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
category == "TodoApiSample.Controllers.TodoController")
{
return false;
}
return true;
});
})

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logBuilder =>
{
logBuilder.AddFilter((provider, category, logLevel) =>
{
if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
category == "TodoApiSample.Controllers.TodoController")
{
return false;
}
return true;
});
});

Sistem kategorileri ve Düzeyler


ASP.NET Core ve Entity Framework Core tarafından kullanılan bazı kategoriler şunlardır ve bunlardan beklenen
Günlükler hakkında notlar bulunur:

KATEGORI NOTLAR

Microsoft.AspNetCore Genel ASP.NET Core tanılama.

Microsoft.AspNetCore.DataProtection Hangi anahtarların kabul edildiği, bulunduğu ve kullanıldığı.

Microsoft.AspNetCore.HostFiltering İzin verilen konaklar.


KATEGORI NOTLAR

Microsoft.AspNetCore.Hosting HTTP isteklerinin tamamlanması için geçen süre ve ne zaman


başladıkları. Hangi barındırma başlangıç derlemeleri yüklendi.

Microsoft.AspNetCore.Mvc MVC ve Razor tanılama. Model bağlama, filtre yürütme,


derlemeyi görüntüleme, eylem seçimi.

Microsoft.AspNetCore.Routing Eşleşen bilgileri yönlendirin.

Microsoft. AspNetCore. Server Bağlantı başlatın, durdurun ve canlı yanıtları koruyun. HTTPS
sertifika bilgileri.

Microsoft.AspNetCore.StaticFiles Sunulan dosyalar.

Microsoft. EntityFrameworkCore Genel Entity Framework Core tanılama. Veritabanı etkinliği ve


yapılandırması, değişiklik algılama, geçişler.

Günlük kapsamları
Kapsam bir mantıksal işlemler kümesini gruplandırabilir. Bu gruplandırma, kümenin bir parçası olarak oluşturulan
her günlüğe aynı verileri eklemek için kullanılabilir. Örneğin, bir işlemin işlenmesi kapsamında oluşturulan her
günlük işlem KIMLIĞI içerebilir.
Kapsam, BeginScope yöntemi tarafından döndürülen ve atılana kadar bir IDisposable türüdür. using bloğunda
günlükçü çağrılarını sarmalayarak kapsam kullanın:

public IActionResult GetById(string id)


{
TodoItem item;
using (_logger.BeginScope("Message attached to logs created in the using block"))
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
}
return new ObjectResult(item);
}

public IActionResult GetById(string id)


{
TodoItem item;
using (_logger.BeginScope("Message attached to logs created in the using block"))
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
}
return new ObjectResult(item);
}
Aşağıdaki kod konsol sağlayıcısı için kapsamları etkinleştirilir:
Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

.ConfigureLogging((hostingContext, logging) =>


{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})

NOTE
IncludeScopes konsolu günlükçüsü seçeneğini yapılandırmak, kapsam tabanlı günlüğe kaydetmeyi etkinleştirmek için
gereklidir.
Yapılandırma hakkında bilgi için yapılandırma bölümüne bakın.

Her günlük iletisi kapsamlı bilgiler içerir:

info: TodoApiSample.Controllers.TodoController[1002]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById
(TodoApi) => Message attached to logs created in the using block
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById
(TodoApi) => Message attached to logs created in the using block
GetById(0) NOT FOUND

Yerleşik günlük oluşturma sağlayıcıları


ASP.NET Core aşağıdaki sağlayıcıları sevk eder:
Console
Hata ayıklama
EventSource
EventLog
TraceSource
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
ASP.NET Core modülüyle stdout ve hata ayıklama günlüğü hakkında daha fazla bilgi için, bkz. Azure App Service
ve IIS 'de ASP.NET Core sorunlarını giderme ve ASP.NET Core Modülü.
Konsol sağlayıcısı
Microsoft. Extensions. Logging. Console sağlayıcı paketi, günlük çıktısını konsola gönderir.

logging.AddConsole();

Konsol günlüğü çıkışını görmek için proje klasöründe bir komut istemi açın ve aşağıdaki komutu çalıştırın:

dotnet run

Hata ayıklama sağlayıcısı


Microsoft. Extensions. Logging. Debug sağlayıcı paketi, System. Diagnostics. Debug sınıfını ( Debug.WriteLine
Yöntem çağrıları) kullanarak günlük çıktısını yazar.
Linux 'ta, bu sağlayıcı günlükleri /var/log/Messagedosyasına yazar.

logging.AddDebug();

Olay kaynak sağlayıcısı


Microsoft. Extensions. Logging. EventSource sağlayıcı paketi, Microsoft-Extensions-Logging adı Ile bir olay kaynağı
platformlar arası yazar. Windows 'da, sağlayıcı ETWkullanır.

logging.AddEventSourceLogger();

Konak oluşturmak için CreateDefaultBuilder çağrıldığında olay kaynak sağlayıcısı otomatik olarak eklenir.
DotNet izleme araçları
DotNet-Trace Aracı, çalışan bir Işlemin .NET Core izlemelerinin toplanmasını sağlayan platformlar arası CLI genel
aracıdır. Araç, bir LoggingEventSourcekullanarak Microsoft.Extensions.Logging.EventSource sağlayıcı verileri toplar.
DotNet Trace araçları komutunu aşağıdaki komutla birlikte yüklersiniz:

dotnet tool install --global dotnet-trace

Bir uygulamadan izleme toplamak için DotNet Trace araçları kullanın:


1. Uygulama ana bilgisayarı CreateDefaultBuilder oluşturmaz, olay kaynak sağlayıcısını uygulamanın günlük
yapılandırmasına ekleyin.
2. dotnet run komutuyla uygulamayı çalıştırın.
3. .NET Core uygulamasının işlem tanımlayıcısını (PID ) belirleme:
Windows 'ta aşağıdaki yaklaşımlardan birini kullanın:
Görev Yöneticisi (Ctrl + Alt + Del)
Tasklist komutu
Get-Process PowerShell komutu
Linux 'ta pidof komutunukullanın.
Uygulamanın derlemesi ile aynı ada sahip olan işlem için PID 'i bulun.
4. dotnet trace komutunu yürütün.
Genel komut sözdizimi:

dotnet trace collect -p {PID}


--providers Microsoft-Extensions-Logging:{Keyword}:{Event Level}
:FilterSpecs=\"
{Logger Category 1}:{Event Level 1};
{Logger Category 2}:{Event Level 2};
...
{Logger Category N}:{Event Level N}\"

PowerShell komut kabuğu kullanırken --providers değerini tek tırnak içine alın ( ' ):

dotnet trace collect -p {PID}


--providers 'Microsoft-Extensions-Logging:{Keyword}:{Event Level}
:FilterSpecs=\"
{Logger Category 1}:{Event Level 1};
{Logger Category 2}:{Event Level 2};
...
{Logger Category N}:{Event Level N}\"'

Windows dışı platformlarda, çıkış izleme dosyasının biçimini speedscope olarak değiştirmek için
-f speedscope seçeneğini ekleyin.

ANAHTAR SÖZCÜĞÜ AÇIKLAMA

1. LoggingEventSource ilgili meta olayları günlüğe kaydedin.


Olayları ILogger ) günlüğe kaydetmez.

2 ILogger.Log() çağrıldığında Message olayı açar.


Programlı (biçimlendirilmedi) bir şekilde bilgi sağlar.

4 ILogger.Log() çağrıldığında FormatMessage olayı açar. ,


Bilgilerin biçimlendirilen dize sürümünü sağlar.

8 ILogger.Log() çağrıldığında MessageJson olayı açar.


Bağımsız değişkenlerin JSON gösterimini sağlar.

OLAY DÜZEYI AÇIKLAMA

0 LogAlways

1. Critical

2 Error

3 Warning

4 Informational

5 Verbose

{Logger Category} ve {Event Level} için FilterSpecs girişleri ek günlük filtreleme koşullarını temsil eder.
FilterSpecs girdileri noktalı virgülle ayırın ( ; ).
Windows komut kabuğu ile örnek ( --providers değeri etrafında tek tırnakyoktur ):

dotnet trace collect -p {PID} --providers Microsoft-Extensions-


Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"

Yukarıdaki komut şunları etkinleştirir:


Hatalar için ( 2 ) biçimlendirilen dizeler ( 4 ) üretmek üzere olay kaynağı günlükçüsü.
günlüğe kaydetme Informational günlük düzeyinde ( 4 ) Microsoft.AspNetCore.Hosting .
5. ENTER tuşuna veya CTRL + C tuşlarına basarak DotNet izleme araçlarını durdurun.
İzleme, dotnet trace komutunun yürütüldüğü klasörde Trace. NetTrace adıyla kaydedilir.
6. Trace 'i PerfViewile açın. Trace. NetTrace dosyasını açın ve izleme olaylarını araştırın.
Daha fazla bilgi için bkz.
Performans Analizi yardımcı programı Için izleme (DotNet-Trace) (.NET Core belgeleri)
Performans Analizi yardımcı programı (DotNet-Trace) Için izleme (DotNet/Diagnostics GitHub deposu
belgeleri)
Loggingeventsource sınıfı (.NET API tarayıcısı)
EventLevel
Loggingeventsource başvuru kaynağı (3,0) – farklı bir sürüm için başvuru kaynağı elde etmek üzere, dalı
release/{Version} olarak değiştirin, burada {Version} istenen ASP.NET Core sürümüdür.
PerfView , olay kaynağı izlemelerini görüntülemek için kullanışlıdır –.
PerfView
Günlükleri toplamak ve görüntülemek için PerfView yardımcı programını kullanın. ETW günlüklerini
görüntülemeye yönelik başka araçlar da mevcuttur, ancak PerfView, ASP.NET Core tarafından yayınlanan ETW
olaylarıyla çalışmak için en iyi deneyimi sağlar.
Bu sağlayıcı tarafından günlüğe kaydedilen olayları toplamak için PerfView 'ı yapılandırmak için,
*Microsoft-Extensions-Logging dizeyi ek sağlayıcılar listesine ekleyin. ( Dizenin başlangıcında yıldız işaretini
kaçırmayın.)

Windows olay günlüğü sağlayıcısı


Microsoft. Extensions. Logging. EventLog sağlayıcı paketi, Windows olay günlüğüne günlük çıktısı gönderir.

logging.AddEventLog();

AddEventLog aşırı yüklemeler EventLogSettingsiletmenizi sağlar. null veya belirtilmemişse, aşağıdaki varsayılan
ayarlar kullanılır:
"uygulama" LogName –
SourceName – ".NET Runtime"
MachineName – yerel makine

TraceSource sağlayıcısı
Microsoft. Extensions. Logging. TraceSource sağlayıcı paketi TraceSource kitaplıklarını ve sağlayıcıları kullanır.

logging.AddTraceSource(sourceSwitchName);

Addtracesource aşırı yüklemeleri , bir kaynak anahtarı ve bir izleme dinleyicisi geçirmenize olanak sağlar.
Bu sağlayıcıyı kullanmak için, bir uygulamanın .NET Framework çalışması gerekir (.NET Core yerine). Sağlayıcı,
iletileri örnek uygulamada kullanılan TextWriterTraceListener gibi çeşitli dinleyicilerineyönlendirebilir.
Azure App Service sağlayıcı
Microsoft. Extensions. Logging. AzureAppServices sağlayıcı paketi, günlükleri bir Azure App Service uygulamasının
dosya sistemindeki metin dosyalarına ve bir Azure depolama hesabındaki BLOB depolama alanına yazar.

logging.AddAzureWebAppDiagnostics();

Sağlayıcı paketi, paylaşılan çerçeveye dahil değildir. Sağlayıcıyı kullanmak için sağlayıcı paketini projeye ekleyin.
Sağlayıcı paketi Microsoft. AspNetCore. app metapackage'e dahil değildir. .NET Framework veya
Microsoft.AspNetCore.App metapackage 'e başvuru yaparken, sağlayıcı paketini projeye ekleyin.

Sağlayıcı ayarlarını yapılandırmak için aşağıdaki örnekte gösterildiği gibi AzureFileLoggerOptions ve


AzureBlobLoggerOptionskullanın:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
})
)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Sağlayıcı ayarlarını yapılandırmak için aşağıdaki örnekte gösterildiği gibi AzureFileLoggerOptions ve


AzureBlobLoggerOptionskullanın:

public static void Main(string[] args)


{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
}))
.UseStartup<Startup>();
AddAzureWebAppDiagnostics aşırı yüklemesi AzureAppServicesDiagnosticsSettingsgeçirmenize olanak tanır.
Ayarlar nesnesi, günlük çıkış şablonu, blob adı ve dosya boyutu sınırı gibi varsayılan ayarları geçersiz kılabilir. (Çıktı
şablonu , bir ILogger yöntemi çağrısıyla sağlandığının yanı sıra tüm günlüklere uygulanan bir ileti şablonudur.)
App Service uygulamasına dağıtırken, uygulama, Azure portal App Service sayfasının App Service Günlükler
bölümündeki ayarları kabul eder. Aşağıdaki ayarlar güncelleştirilirken, değişiklikler uygulamanın yeniden
başlatılmasını veya yeniden dağıtımı gerekmeden hemen etkili olur.
Uygulama günlüğü (dosya sistemi)
Uygulama günlüğü (blob)
Günlük dosyaları için varsayılan konum D:\home\LogFiles\uygulama klasöründedir ve varsayılan dosya adı
Diagnostics-YYYYMMDD. txt' dir. Varsayılan dosya boyutu sınırı 10 MB 'tır ve tutulan varsayılan en fazla dosya
sayısı 2 ' dir. Varsayılan blob adı {app -name} {timestamp }/yyyy/mm/dd/ss/{Guid }-ApplicationLog.txt.
Sağlayıcı yalnızca proje Azure ortamında çalıştırıldığında çalışır. Proje yerel olarak çalıştırıldığında, yerel dosyalara
veya Bloblar için yerel geliştirme depolamasına yazmazsa—hiçbir etkisi yoktur.
Azure günlük akışı
Azure günlük akışı, günlük etkinliklerini gerçek zamanlı olarak görüntülemenize izin verir:
Uygulama sunucusu
Web sunucusu
Başarısız istek izleme
Azure günlük akışını yapılandırmak için:
Uygulamanızın Portal sayfasından App Service günlükleri sayfasına gidin.
Uygulama günlüğünü (FileSystem ) Açıkolarak ayarlayın.
Günlük düzeyiniseçin. Bu ayar, uygulamadaki diğer günlük sağlayıcılarını değil, yalnızca Azure günlük akışı için
geçerlidir.
Uygulama iletilerini görüntülemek için günlük akışı sayfasına gidin. Uygulama tarafından ILogger arabirimi
aracılığıyla günlüğe kaydedilir.
Azure Application Insights izleme günlüğü
Microsoft. Extensions. Logging. ApplicationInsights sağlayıcı paketi günlükleri Azure Application Insights yazar.
Application Insights, bir Web uygulamasını izleyen ve telemetri verilerini sorgulamak ve analiz etmek için araçlar
sağlayan bir hizmettir. Bu sağlayıcıyı kullanıyorsanız, Application Insights araçlarını kullanarak günlüklerinizi
sorgulayabilir ve analiz edebilirsiniz.
Günlüğe kaydetme sağlayıcısı, ASP.NET Core için tüm kullanılabilir telemetri sağlayan paket olan Microsoft.
ApplicationInsights. AspNetCore'un bağımlılığı olarak eklenmiştir. Bu paketi kullanırsanız, sağlayıcı paketini
yüklemek zorunda kalmazsınız.
ASP.NET 4. x için olan Microsoft. ApplicationInsights. Web paketini kullanmayın—.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
Application Insights genel bakış
ASP.NET Core uygulamalar için Application Insights -günlük kaydı ile birlikte Application Insights telemetrinin
tam aralığını uygulamak istiyorsanız buraya başlayın.
.NET Core ILogger günlükleri Için Applicationınsightsloggerprovider -günlük sağlayıcısını Application Insights
telemetri olmadan uygulamak istiyorsanız buraya başlayın.
Günlüğe kaydetme bağdaştırıcılarını Application Insights.
Microsoft Learn sitede Application Insights SDK-etkileşimli öğreticisini yükleyip başlatın .
Üçüncü taraf günlük oluşturma sağlayıcıları
ASP.NET Core ile birlikte çalışan üçüncü taraf günlük çerçeveleri:
ELMAH.io (GitHub deposu)
Gelf (GitHub deposu)
Jsnlog (GitHub deposu)
KissLog.net (GitHub deposu)
Log4Net (GitHub deposu)
Loggr (GitHub deposu)
NLog (GitHub deposu)
Sentry (GitHub deposu)
Serilog (GitHub deposu)
Stackdriver (GitHub deposu)
Bazı üçüncü taraf çerçeveler , yapılandırılmış günlük olarak da bilinen anlam günlüğe kaydetmeişlemini
gerçekleştirebilir.
Bir üçüncü taraf çerçevesinin kullanılması, yerleşik sağlayıcılardan birini kullanmaya benzer:
1. Projenize bir NuGet paketi ekleyin.
2. Günlüğe kaydetme çerçevesi tarafından sağlanmış bir ILoggerFactory Extension yöntemi çağırın.
Daha fazla bilgi için bkz. her sağlayıcının belgeleri. Üçüncü taraf günlüğü sağlayıcıları Microsoft tarafından
desteklenmez.

Ek kaynaklar
ASP.NET Core 'de LoggerMessage ile yüksek performanslı günlüğe kaydetme
ASP.NET Core yönlendirme
4.11.2019 • 141 minutes to read • Edit Online

Ryan şimdi ak, Steve Smithve Rick Anderson


Yönlendirme, istek URI 'Lerini uç noktalarla eşleştirmekten ve gelen istekleri bu uç noktalara gönderen
sorumludur. Yollar uygulamada tanımlanır ve uygulama başlatıldığında yapılandırılır. Yol, isteğe bağlı olarak
istekte bulunan URL 'den değerleri ayıklayabilir ve bu değerler, istek işleme için kullanılabilir. Uygulamadan
yönlendirme bilgilerini kullanarak, yönlendirme, uç noktalarıyla eşlenen URL 'Ler de oluşturabilir.

IMPORTANT
Bu belge, alt düzey ASP.NET Core yönlendirmeyi içerir. ASP.NET Core MVC yönlendirme hakkında daha fazla bilgi için
bkz. ASP.NET Core denetleyici eylemlerine yönlendirme. Razor Pages 'de yönlendirme kuralları hakkında bilgi için bkz.
ASP.NET Core Razor Pages yol ve uygulama kuralları.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Yönlendirme temelleri
Çoğu uygulama, URL 'Lerin okunabilir ve anlamlı olması için temel ve açıklayıcı bir yönlendirme şeması
seçmelidir. Varsayılan geleneksel yol {controller=Home}/{action=Index}/{id?} :
Temel ve açıklayıcı bir yönlendirme düzenini destekler.
, UI tabanlı uygulamalar için kullanışlı bir başlangıç noktasıdır.
Geliştiriciler, öznitelik yönlendirme veya adanmış geleneksel yollar kullanarak özel durumlarda (örneğin,
blog ve e-ticaret uç noktaları) bir uygulamanın yüksek trafik bölümlerine daha fazla terse yolu ekler.
Web API 'Leri, uygulamanın işlevselliğini HTTP fiilleri tarafından temsil edilen bir kaynak kümesi olarak
modellemek için öznitelik yönlendirmeyi kullanmalıdır. Bu, aynı mantıksal kaynaktaki birçok işlemin
(örneğin, GET, POST) aynı URL 'YI kullanacağı anlamına gelir. Öznitelik yönlendirme, bir API 'nin Genel uç
nokta yerleşimini dikkatle tasarlamak için gereken bir denetim düzeyi sağlar.
Razor Pages uygulamalar, bir uygulamanın Sayfalar klasöründe adlandırılmış kaynaklara hizmeti sağlamak
için varsayılan geleneksel yönlendirmeyi kullanır. Razor Pages yönlendirme davranışını özelleştirmenizi
sağlayan ek kurallar mevcuttur. Daha fazla bilgi için bkz. ASP.NET Core Razor Pages giriş ve ASP.NET Core
Razor Pages yol ve uygulama kuralları.
URL oluşturma desteği, uygulamanın, uygulamayı birbirine bağlamak için sabit kodlama URL 'Leri
olmadan geliştirilebilmesine izin verir. Bu destek, temel bir yönlendirme yapılandırmasıyla başlayıp
uygulamanın kaynak düzeni belirlendikten sonra yolların değiştirilmesini sağlar.
Yönlendirme, bir uygulamadaki mantıksal uç noktaları temsil etmek için uç noktaları ( Endpoint ) kullanır.
Bir uç nokta, istekleri işlemek için bir temsilci ve rastgele meta veri koleksiyonunu tanımlar. Meta veriler, her
uç noktaya eklenen ilkelere ve yapılandırmaya göre çapraz kesme sorunları uygulamak için kullanılır.
Yönlendirme sistemi aşağıdaki özelliklere sahiptir:
Yol şablonu sözdizimi, simgeleştirilmiş yol parametrelerine sahip yolları tanımlamak için kullanılır.
Geleneksel stil ve öznitelik stili uç nokta yapılandırmasına izin verilir.
IRouteConstraint, bir URL parametresinin belirli bir uç nokta kısıtlaması için geçerli bir değer içerip
içermediğini belirlemekte kullanılır.
MVC/Razor Pages gibi uygulama modelleri, yönlendirme senaryolarının öngörülebilir bir
uygulaması olan tüm uç noktalarını kaydeder.
Yönlendirme gerçekleştirme, yönlendirme kararlarını, ara yazılım ardışık düzeninde istediğiniz yere
getirir.
Bir yönlendirme ara yazılımı, belirli bir istek URI 'SI için yönlendirme ara yazılımı uç noktası
kararının sonucunu inceleyebilir.
Uygulamadaki tüm uç noktaları, ara yazılım ardışık düzeninde herhangi bir yerde listelemek
mümkündür.
Bir uygulama, uç nokta bilgilerine göre URL 'Ler oluşturmak için (örneğin, yeniden yönlendirme
veya bağlantılar için) yönlendirmeyi kullanabilir ve bu sayede bakım yapılmasına yardımcı olan sabit
kodlanmış URL 'Lerden kaçınabilirsiniz.
URL oluşturma, rastgele genişletilebilirliği destekleyen adreslere dayalıdır:
Bağlantı Oluşturucu API 'SI (LinkGenerator), bağımlılık ekleme (dı) kullanılarak URL 'ler
oluşturmak için her yerde çözülebilir.
Bağlantı Oluşturucu API 'sinin DI aracılığıyla kullanılamadığı durumlarda IUrlHelper URL 'Leri
derlemek için yöntemler sunar.

NOTE
Uç nokta bağlama, MVC/Razor Pages eylemleri ve sayfalarıyla sınırlıdır. Uç nokta bağlama yeteneklerinin
genişletmeleri, gelecek sürümlerde planlanmaktadır.

Yönlendirme, RouterMiddleware sınıfı tarafından, Ara yazılım ardışık düzenine bağlıdır. ASP.NET Core
MVC , yapılandırma kapsamında bir ara yazılım ardışık düzenine yönlendirme ekler ve MVC ve Razor
Pages uygulamalarında yönlendirmeyi işler. Tek başına bileşen olarak yönlendirmeyi nasıl kullanacağınızı
öğrenmek için yönlendirme ara yazılımı kullanma bölümüne bakın.
URL eşleştirme
URL eşleştirme, yönlendirmenin bir uç noktayagelen isteği gönderdiği işlemdir. Bu işlem, URL yolundaki
verileri temel alır, ancak istekteki verileri göz önünde bulundurmanız için genişletilebilir. Ayrı işleyicilere
istek gönderme özelliği, bir uygulamanın boyutunu ve karmaşıklığını ölçeklendirmeye yönelik anahtardır.
Bir yönlendirme ara yazılımı yürütüldüğünde, bir uç nokta ( Endpoint ) ayarlar ve değerleri HttpContextbir
özelliğe yönlendirir. Geçerli istek için:
Çağırma HttpContext.GetEndpoint bitiş noktasını alır.
HttpRequest.RouteValues yol değerlerinin koleksiyonunu alır.
Yönlendirme ara yazılımı ile çalışan ara yazılım, uç noktayı görebilir ve işlem yapabilir. Örneğin, bir
yetkilendirme ara yazılımı, bir yetkilendirme ilkesi için bitiş noktasının meta veri koleksiyonunu
sorgulanamıyor. İstek işleme ardışık düzeninde bulunan tüm ara yazılım yürütüldükten sonra, seçilen uç
noktanın temsilcisi çağrılır.
Uç nokta yönlendirmesinde yönlendirme sistemi tüm gönderme kararlarından sorumludur. Ara yazılım,
seçili uç noktaya göre ilkeler uyguladığı için, yönlendirme sisteminde güvenlik ilkelerinin dağıtımını
etkileyebilecek veya uygulamanın uygulanmasını etkileyebilecek herhangi bir kararın olması önemlidir.
Uç nokta temsilcisi yürütüldüğünde, Routecontext. RouteData özellikleri, bu nedenle yapılan istek işlemeye
bağlı olarak uygun değerlere ayarlanır.
RouteData. Values , rotada oluşturulan yol değerlerinin bir sözlüğüdür. Bu değerler genellikle URL 'YI
simgeleştirerek belirlenir ve Kullanıcı girişini kabul etmek ya da uygulama içinde daha fazla kararlar almak
için kullanılabilir.
RouteData. DataTokens , eşleşen rotayla ilgili ek verilerin bir özellik çantadır. DataTokens, uygulamanın
hangi yolun eşleştiğini temel alarak kararlar verebilmesi için durum verilerinin her bir rota ile
ilişkilendirilmesini desteklemek amacıyla sağlanır. Bu değerler, geliştirici tarafından tanımlanır ve
yönlendirme davranışını herhangi bir şekilde etkilemez. Ayrıca, RouteData. DataTokens içinde bulunan
değerler her türlü türden olabilir. Bu, veridizeleri arasında dönüştürülebilir olmalıdır.
RouteData. yönlendiriciler , isteği başarıyla eşleştirirken geçen yolların bir listesidir. Yollar bir diğerinin
içinde iç içe olabilir. Routers özelliği, bir eşleşme ile sonuçlanan yolların mantıksal ağacı aracılığıyla yolu
yansıtır. Genellikle, Routers ilk öğe yol koleksiyonudur ve URL oluşturma için kullanılmalıdır. Routers son
öğe, eşleşen yol işleyicisidir.
LinkGenerator ile URL oluşturma
URL oluşturma, yönlendirmenin bir yol değerleri kümesine göre bir URL yolu oluşturabileceği işlemdir. Bu,
uç noktalarınız ve bunlara erişen URL 'Ler arasında mantıksal bir ayrım sağlar.
Uç nokta yönlendirme bağlantı Oluşturucu API 'sini (LinkGenerator) içerir. LinkGenerator, DI 'dan
alınabilecek bir tek hizmettir. API, yürütülen bir istek bağlamı dışında kullanılabilir. MVC 'nin Etiket
Yardımcıları, HTML Yardımcıları ve eylem sonuçlarıgibi IUrlHelperkullanan IUrlHelper ve senaryoları,
bağlantı oluşturma yetenekleri sağlamak için bağlantı oluşturucuyu kullanır.
Bağlantı Oluşturucu, bir Adres ve Adres şemalarıkavramıyla desteklenir. Adres şeması, bağlantı oluşturma
için göz önünde bulundurmanız gereken uç noktaları belirlemenin bir yoludur. Örneğin, çok sayıda
kullanıcının yol adı ve yol değerleri senaryoları, MVC/Razor Pages tarafından tanıdık bir adres düzeni
olarak uygulanır.
Bağlantı Oluşturucu, aşağıdaki genişletme yöntemleri aracılığıyla MVC/Razor Pages eylemlerine ve
sayfalarına bağlanabilir:
GetPathByAction
GetUriByAction
GetPathByPage
GetUriByPage
Bu yöntemlerin aşırı yüklemesi HttpContext içeren bağımsız değişkenleri kabul eder. Bu yöntemler
Url.Action ve Url.Page işlevsel olarak eşdeğerdir ancak ek esneklik ve seçenekler sunar.

GetPath* yöntemleri, Url.Action ve Url.Page , mutlak bir yol içeren bir URI oluşturmak için en çok
benzerdir. GetUri* Yöntemler her zaman bir düzen ve konak içeren mutlak bir URI oluşturur. Bir
HttpContext kabul eden yöntemler, yürütülmekte olan istek bağlamında bir URI oluşturur.Ortam yolu
değerleri, URL taban yolu, şeması ve yürütülen istekten ana bilgisayar, geçersiz kılınmadıkça kullanılır.
LinkGenerator bir adresle çağrılır. URI oluşturma iki adımda gerçekleşir:
1. Adres, adresle eşleşen bir uç nokta listesine bağlanır.
2. Her uç noktanın RoutePattern , sağlanan değerlerle eşleşen bir rota deseninin bulunana kadar
değerlendirilir. Elde edilen çıktı, bağlantı oluşturucuya sağlanan diğer URI parçalarıyla birleştirilir ve
döndürülür.
LinkGenerator tarafından sunulan yöntemler, herhangi bir tür adresin standart bağlantı oluşturma
özelliklerini destekler. Bağlantı oluşturucuyu kullanmanın en kolay yolu, belirli bir adres türü için işlem
gerçekleştiren genişletme yöntemlerine yöneliktir.
GENIŞLETME YÖNTEMI AÇIKLAMA

GetPathByAddress Belirtilen değerleri temel alarak mutlak bir yola sahip bir
URI oluşturur.

GetUriByAddress Belirtilen değerleri temel alarak mutlak bir URI oluşturur.

WARNING
LinkGenerator yöntemlerinin çağrılmasının aşağıdaki etkilerine dikkat edin:
Gelen isteklerin Host üstbilgisini doğrulayan bir uygulama yapılandırmasında GetUri* uzantısı
yöntemlerini dikkatle kullanın. Gelen isteklerin Host üstbilgisi doğrulandıktan sonra, güvenilir olmayan istek
girişi, bir görünüm/sayfada URI 'Ler halinde istemciye geri gönderilebilir. Tüm üretim uygulamalarının, Host
üst bilgisini bilinen geçerli değerlere karşı doğrulamak için kendi sunucusunu yapılandırmasını öneririz.
Map veya MapWhen birlikte ara yazılım ile birlikte LinkGenerator kullanın. Map* , yürütülen isteğin temel
yolunu değiştirir ve bu da bağlantı oluşturma çıktısını etkiler. Tüm LinkGenerator API 'Leri temel yol
belirtmeye izin verir. Map* bağlantı oluşturmada etkilerini geri almak için her zaman boş bir temel yol belirtin.

Önceki yönlendirme sürümlerinden uç nokta yönlendirme farkları


ASP.NET Core 2,2 ' den önceki yönlendirmenin uç nokta yönlendirme ve sürümleri arasında birkaç fark
vardır:
Uç nokta yönlendirme sistemi, Routedevralma dahil IRoutertabanlı genişletilebilirliği desteklemez.
Uç nokta yönlendirme WebApiCompatShimdesteklemez. Uyumluluk Shim 'yi kullanmaya devam
etmek için 2,1 Uyumluluk sürümünü ( .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) )
kullanın.
Uç nokta yönlendirmesinde, geleneksel yollar kullanılırken oluşturulan URI 'lerin büyük küçük
harfleri için farklı davranış vardır.
Aşağıdaki varsayılan yol şablonunu göz önünde bulundurun:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Aşağıdaki rotayı kullanarak bir eyleme bağlantı oluşturduğunuzu varsayalım:

var link = Url.Action("ReadPost", "blog", new { id = 17, });

IRoutertabanlı yönlendirme ile bu kod, /blog/ReadPost/17 URI 'sini oluşturur ve bu da, belirtilen yol
değerinin büyük küçük harflerini üretir. ASP.NET Core 2,2 veya sonraki bir sürümde uç nokta
yönlendirme /Blog/ReadPost/17 ("blog" büyük harfli) oluşturur. Endpoint Routing, bu davranışı
küresel olarak özelleştirmek veya URL eşleme için farklı kurallar uygulamak üzere kullanılabilecek
IOutboundParameterTransformer arabirimini sağlar.

Daha fazla bilgi için bkz. Parameter transformatör başvurusu bölümü.


Standart yollarla MVC/Razor Pages tarafından kullanılan bağlantı oluşturma, mevcut olmayan bir
denetleyiciye/eyleme veya sayfaya bağlantı kurmaya çalışırken farklı şekilde davranır.
Aşağıdaki varsayılan yol şablonunu göz önünde bulundurun:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Aşağıdaki ile varsayılan şablonu kullanarak bir eyleme bağlantı oluşturduğunuzu varsayalım:

var link = Url.Action("ReadPost", "Blog", new { id = 17, });

IRouter tabanlı yönlendirme sayesinde, BlogController var olmasa veya bir ReadPost Action
yöntemine sahip olmasa bile sonuç daima /Blog/ReadPost/17 . Beklenen şekilde, işlem yöntemi varsa
ASP.NET Core 2,2 veya sonraki bir sürümde uç nokta yönlendirmesi /Blog/ReadPost/17 üretir.
Ancak, uç nokta yönlendirme, eylem yoksa boş bir dize oluşturur. Kavramsal olarak, uç nokta
yönlendirme, eylem mevcut değilse uç noktanın var olduğunu varsaymaz.
Bağlantı oluşturma çevresel değeri ınvalidation algoritması , uç nokta yönlendirme ile
kullanıldığında farklı davranır.
Çevresel değer ınvalidation , şu anda yürütülmekte olan isteğin (çevresel değerler) hangi rota
değerlerinin bağlantı oluşturma işlemlerinde kullanılabileceğini belirleyen algoritmadır. Geleneksel
yönlendirme, farklı bir eyleme bağlanılırken ek yol değerlerini her zaman geçersiz kıldı. ASP.NET
Core 2,2 sürümünden önce öznitelik yönlendirmesinde bu davranış yoktu. ASP.NET Core 'nin
önceki sürümlerinde, aynı yol parametresi adlarını kullanan başka bir eyleme bağlantılar, bağlantı
oluşturma hatalarıyla sonuçlandı. ASP.NET Core 2,2 veya sonraki sürümlerde, yönlendirme
biçimlerinin her ikisi de başka bir eyleme bağlanırken değerleri geçersiz kılar.
ASP.NET Core 2,1 veya önceki sürümlerde aşağıdaki örneği göz önünde bulundurun. Başka bir
eyleme (veya başka bir sayfaya) bağlanırken, yol değerleri istenmeyen yollarla yeniden kullanılabilir.
/Pages/Store/Product.exe:

@page "{id}"
@Url.Page("/Login")

/Pages/Login.exeiçinde:

@page "{id?}"

URI, ASP.NET Core 2,1 veya önceki sürümlerde /Store/Product/18 , @Url.Page("/Login") tarafından
Store/Info sayfasında oluşturulan bağlantı /Login/18 . 18 ' in id değeri, bağlantı hedefi
uygulamanın tamamen farklı bir parçası olsa bile yeniden kullanılır. /Login sayfasının bağlamındaki
id yol değeri büyük olasılıkla bir depolama ürün KIMLIĞI değeri değil, bir kullanıcı KIMLIĞI
değeridir.
ASP.NET Core 2,2 veya sonraki bir sürümü ile Endpoint Routing, sonuç /Login . Bağlantılı hedef
farklı bir eylem veya sayfa olduğunda çevresel değerler yeniden kullanılmaz.
Gidiş dönüşü yol parametresi sözdizimi: çift yıldız ( ** ) catch-all parametre sözdizimi kullanılırken
eğik çizgiler kodlanmaz.
Bağlantı oluşturma sırasında, yönlendirme sistemi, eğik çizgiler dışında bir çift yıldız ( ** ) catch-all
parametresinde (örneğin, {**myparametername} ) yakalanan değeri kodlar. Çift yıldız yakalama,
ASP.NET Core 2,2 veya sonraki sürümlerde IRouter tabanlı yönlendirme ile desteklenir.
ASP.NET Core ( {*myparametername} ) önceki sürümlerindeki tek yıldız catch-all parametre sözdizimi
desteklenmeye devam eder ve eğik çizgi kodlandı.

İLE OLUŞTURULAN BAĞLANTI


YOLU URL.ACTION(NEW { CATEGORY = "ADMIN/PRODUCTS" }) …

/search/{*page} /search/admin%2Fproducts (eğik çizgi kodlanmış)

/search/{**page} /search/admin/products

Ara yazılım örneği


Aşağıdaki örnekte, bir ara yazılım, mağaza ürünlerini listeleyen bir eylem yöntemine bağlantı oluşturmak
için LinkGenerator API 'sini kullanır. Ekleme tarafından bir sınıfa olan ve GenerateLink çağıran bağlantı
Oluşturucuyu kullanmak, bir uygulamadaki herhangi bir sınıfta kullanılabilir.

using Microsoft.AspNetCore.Routing;

public class ProductsLinkMiddleware


{
private readonly LinkGenerator _linkGenerator;

public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)


{
_linkGenerator = linkGenerator;
}

public async Task InvokeAsync(HttpContext httpContext)


{
var url = _linkGenerator.GetPathByAction("ListProducts", "Store");

httpContext.Response.ContentType = "text/plain";

await httpContext.Response.WriteAsync($"Go to {url} to see our products.");


}
}

Rotalar oluştur
Çoğu uygulama, IRouteBuildertanımlanan benzer uzantı yöntemlerinden birini veya MapRoute çağırarak
yollar oluşturur. IRouteBuilder uzantısı yöntemlerinden herhangi biri bir Route örneği oluşturur ve bunu yol
koleksiyonuna ekler.
MapRoute yol işleyicisi parametresini kabul etmez. MapRoute, yalnızca DefaultHandlertarafından işlenen
rotaları ekler. MVC 'de yönlendirme hakkında daha fazla bilgi için bkz. ASP.NET Core denetleyici
eylemlerine yönlendirme.
Aşağıdaki kod örneği, tipik bir ASP.NET Core MVC yol tanımı tarafından kullanılan MapRoute çağrısının
bir örneğidir:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Bu şablon bir URL yoluyla eşleşir ve yol değerlerini ayıklar. Örneğin, yol /Products/Details/17 şu yol
değerlerini üretir: { controller = Products, action = Details, id = 17 } .
Rota değerleri, URL yolunun kesimlere bölünüyor ve rota şablonundaki yol parametresi adı ile her bir
segmenti eşleştirerek belirlenir. Yol parametreleri olarak adlandırılır. Küme ayraçları içinde parametre adı
eklenerek tanımlanan parametreler { ... } .
Yukarıdaki şablon, URL yolu / de eşleştirebilir ve { controller = Home, action = Index } değerler
üretecektir. Bu, {controller} ve {action} yol parametrelerinin varsayılan değerleri olduğu ve id Route
parametresinin isteğe bağlı olduğu için oluşur. Eşittir işareti ( = ), yol parametresi adı parametre için
varsayılan bir değer tanımladıktan sonra bir değer izler. Yol parametre adından sonra bir soru işareti ( ? )
isteğe bağlı bir parametre tanımlar.
Yol parametreleri varsayılan değer ile her zaman rota değeri oluşturur. Karşılık gelen bir URL yol kesimi
yoksa isteğe bağlı parametreler yol değeri oluşturmaz. Yol şablonu senaryolarının ve sözdiziminin kapsamlı
bir açıklaması için yol şablonu başvurusu bölümüne bakın.
Aşağıdaki örnekte, yol parametresi tanımı {id:int} id Route parametresi için bir yol kısıtlaması
tanımlıyor:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id:int}");

Bu şablon /Products/Details/17 gibi bir URL yoluyla eşleşir ancak /Products/Details/Apples . Yol
kısıtlamaları IRouteConstraint uygular ve yol değerlerini inceleyerek onları doğrular. Bu örnekte, yol değeri
id bir tamsayıya dönüştürülebilir olmalıdır. Framework tarafından sunulan yol kısıtlamalarının açıklaması
için bkz. route-Constraint-Reference .
MapRoute ek aşırı yüklemeleri constraints , dataTokens ve defaults için değer kabul eder. Bu
parametrelerin tipik kullanımı, anonim türdeki özellik adlarının yol parametre adlarıyla eşleşen anonim
olarak yazılmış bir nesneyi geçirmektir.
Aşağıdaki MapRoute örnekleri eşdeğer yollar oluşturur:

routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
name: "default_route",
template: "{controller=Home}/{action=Index}/{id?}");

TIP
Kısıtlamaları ve Varsayılanları tanımlamaya yönelik satır içi sözdizimi basit yollar için kullanışlı olabilir. Ancak, satır içi
sözdizimi tarafından desteklenmeyen veri belirteçleri gibi senaryolar vardır.

Aşağıdaki örnek birkaç ek senaryoyu göstermektedir:

routes.MapRoute(
name: "blog",
template: "Blog/{**article}",
defaults: new { controller = "Blog", action = "ReadArticle" });

Önceki şablon /Blog/All-About-Routing/Introduction gibi bir URL yoluyla eşleşir ve


{ controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction } değerleri ayıklar.
controller ve action için varsayılan yol değerleri, şablonda karşılık gelen hiçbir yol parametresi olmasa
bile yol tarafından üretilir. Varsayılan değerler yol şablonunda belirtilebilir. article Route parametresi, yol
parametre adından önce bir çift yıldız işareti ( ** ) görünümüne göre catch-all olarak tanımlanır. Catch-all
yol parametreleri, URL yolunun kalanını yakalar ve boş dizeyle de aynı olabilir.
Aşağıdaki örnek yol kısıtlamalarını ve veri belirteçlerini ekler:

routes.MapRoute(
name: "us_english_products",
template: "en-US/Products/{id}",
defaults: new { controller = "Products", action = "Details" },
constraints: new { id = new IntRouteConstraint() },
dataTokens: new { locale = "en-US" });

Önceki şablon /en-US/Products/5 gibi bir URL yoluyla eşleşir ve


{ controller = Products, action = Details, id = 5 } ve veri belirteçleri { locale = en-US } değerleri
ayıklar.

Yol sınıfı URL 'SI oluşturma


Route sınıfı, yol değerlerini bir kümesini rota şablonuyla birleştirerek URL oluşturmayı da gerçekleştirebilir.
Bu, URL yolunu eşleştirmenin mantıksal bir işlemdir.

TIP
URL oluşturmayı daha iyi anlamak için, oluşturmak istediğiniz URL 'YI düşünün ve sonra bir yönlendirme şablonunun
bu URL ile nasıl eşleşeceğini düşünün. Hangi değerler üretilemidir? Bu, URL oluşturma 'nın Route sınıfında nasıl
çalıştığına ilişkin kaba bir eştir.

Aşağıdaki örnek genel ASP.NET Core MVC varsayılan yolunu kullanır:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Yol değerleri { controller = Products, action = List } , /Products/List URL 'SI oluşturulur. Yol değerleri,
URL yolunu biçimlendirmek için karşılık gelen yol parametrelerinin yerine kullanılır. id , isteğe bağlı bir yol
parametresi olduğundan, id için bir değer olmadan URL başarıyla oluşturulur.
Yol değerleri { controller = Home, action = Index } , / URL 'SI oluşturulur. Belirtilen yol değerleri
varsayılan değerlerle eşleşir ve varsayılan değerlere karşılık gelen segmentler güvenle atlanır.
Her iki URL de aşağıdaki yol tanımıyla ( /Home/Index ve / ) bir gidiş dönüş, URL oluşturmak için kullanılan
rota değerlerini oluşturur.

NOTE
ASP.NET Core MVC kullanan bir uygulama doğrudan yönlendirmeye çağırmak yerine URL oluşturmak için UrlHelper
kullanmalıdır.

URL oluşturma hakkında daha fazla bilgi için URL oluşturma başvurusu bölümüne bakın.

Yönlendirme ara yazılımı kullanma


Uygulamanın proje dosyasındaki Microsoft. AspNetCore. app metapackage öğesine başvurun.
Startup.ConfigureServices ' de hizmet kapsayıcısına yönlendirme ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddRouting();
}

Yolların Startup.Configure yönteminde yapılandırılması gerekir. Örnek uygulama aşağıdaki API 'Leri
kullanır:
RouteBuilder
MapGet – yalnızca HTTP GET istekleriyle eşleşir.
UseRouter

var trackPackageRouteHandler = new RouteHandler(context =>


{
var routeValues = context.GetRouteData().Values;
return context.Response.WriteAsync(
$"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
"Track Package Route",
"package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>


{
var name = context.GetRouteValue("name");
// The route handler when HTTP GET "hello/<anything>" matches
// To match HTTP GET "hello/<anything>/<anything>,
// use routeBuilder.MapGet("hello/{*name}"
return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();


app.UseRouter(routes);

Aşağıdaki tabloda verilen URI 'Ler ile ilgili yanıtlar gösterilmektedir.

URI YANITIYLA
URI YANITIYLA

/package/create/3 Herkese! Rota değerleri: [işlem, oluşturma], [kimlik, 3]

/package/track/-3 Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/-3/ Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/ İstek, eşleşme olmadan üzerinden yapılır.

GET /hello/Joe Merhaba, ali!

POST /hello/Joe İstek üzerinden geçer, yalnızca HTTP GET ile eşleşir.

GET /hello/Joe/Smith İstek, eşleşme olmadan üzerinden yapılır.

Çerçeve, yollar oluşturmak için bir genişletme yöntemleri kümesi sağlar


(RequestDelegateRouteBuilderExtensions):
MapDelete
MapGet
MapMiddlewareDelete
MapMiddlewareGet
MapMiddlewarePost
MapMiddlewarePut
MapMiddlewareRoute
MapMiddlewareVerb
MapPost
MapPut
MapRoute
MapVerb
Map[Verb] yöntemleri, yöntem adındaki HTTP fiili ile rotayı sınırlandırmak için kısıtlamaları kullanır.
Örneğin, bkz. MapGet ve MapVerb.

Rota şablonu başvurusu


Küme ayraçları içindeki belirteçler ( { ... } ), yol eşleştirildiği takdirde bağlanan Rota parametrelerini
tanımlar. Bir yol segmentinde birden fazla yol parametresi tanımlayabilirsiniz, ancak bunların bir değişmez
değer ile ayrılması gerekir. Örneğin, {controller} ve {action} arasında değişmez değer olmadığından
{controller=Home}{action=Index} geçerli bir yol değil. Bu rota parametrelerinin bir adı olmalı ve ek
öznitelikler belirtilmiş olabilir.
Yol parametreleri dışında (örneğin, {id} ) ve yol ayırıcı / URL içindeki metinle eşleşmesi gerekir. Metin
eşleştirme, büyük/küçük harfe duyarsızdır ve URL yolunun kodu çözülmüş gösterimine göre yapılır.
Değişmez değer yol parametresi sınırlayıcısından ( { veya } ) eşleştirmek için, karakteri ( {{ veya }} )
tekrarlayarak sınırlayıcıdan kaçış.
İsteğe bağlı bir dosya uzantısına sahip bir dosya adı yakalamaya deneyen URL desenlerinin ek konuları
vardır. Örneğin, files/{filename}.{ext?} şablonu düşünün. filename ve ext değerlerinin her ikisi de
varsa, her iki değer de doldurulur. URL 'de yalnızca filename için bir değer varsa, bitiş dönemi ( . ) isteğe
bağlı olduğundan yol eşleşir. Aşağıdaki URL 'Ler bu rota ile eşleşiyor:
/files/myFile.txt
/files/myFile

URI 'nin geri kalanına bağlamak için bir yol parametresinin öneki olarak bir yıldız işareti ( * ) veya çift yıldız
işareti ( ** ) kullanabilirsiniz. Bunlara catch-all parametreleri denir. Örneğin, blog/{**slug} /blog ile
başlayan ve ondan sonraki bir değere sahip olan slug yol değerine atanan tüm URI ile eşleşir. Catch-all
parametreleri boş dizeyle de aynı olabilir.
Yol ayırıcısı ( / ) karakterleri de dahil olmak üzere bir URL oluşturmak için bir yol kullanıldığında, catch-all
parametresi uygun karakterleri çıkar. Örneğin yol foo/{*path} rota değerleriyle { path = "my/path" }
foo/my%2Fpath üretir. Atlanan eğik çizgiye göz önünde edin. Yol ayırıcı karakterlerini geri döndürmek için
** Route parametresi önekini kullanın. { path = "my/path" } ile yol foo/{**path} foo/my/path üretir.

Yol parametrelerinin, parametre adından sonra varsayılan değer belirtilerek bir eşittir işareti ( = ) ile
ayrıldıktan sonra belirlenen varsayılan değerleri olabilir. Örneğin, Home controller için varsayılan değer
olarak {controller=Home} tanımlar. Parametresi için URL 'de hiçbir değer yoksa varsayılan değer kullanılır.
Yol parametreleri, id? gibi parametre adının sonuna bir soru işareti ( ? ) eklenerek isteğe bağlı olarak
yapılır. İsteğe bağlı değerler ve varsayılan yol parametreleri arasındaki fark, varsayılan değere sahip bir yol
parametresinin her zaman bir değer ürettiğinden—isteğe bağlı bir parametre yalnızca istek URL 'SI
tarafından bir değer sağlandığında bir değere sahip olur.
Rota parametrelerinin URL 'den bağlanan rota değeriyle eşleşmesi gereken kısıtlamaları olabilir. Yol
parametre adından sonra bir iki nokta üst üste ( : ) ve kısıtlama adının eklenmesi, bir yol parametresi
üzerinde bir satır içi kısıtlamayı belirtir. Kısıtlama bağımsız değişkenler gerektiriyorsa, kısıtlama adından
sonra parantez ( (...) ) içine alınır. Birden çok satır içi kısıtlama, başka bir iki nokta ( : ) ve kısıtlama adı
eklenerek belirtilebilir.
Kısıtlama adı ve bağımsız değişkenler, URL işlemede kullanılacak bir IRouteConstraint örneği oluşturmak
için IInlineConstraintResolver hizmetine geçirilir. Örneğin, yol şablonu blog/{article:minlength(10)} , 10
bağımsız değişkeniyle bir minlength kısıtlaması belirtir. Yol kısıtlamaları ve Framework tarafından sunulan
kısıtlamaların bir listesi hakkında daha fazla bilgi için, route kısıtlama başvurusu bölümüne bakın.
Yol parametrelerinde Ayrıca, bağlantı oluştururken ve URL 'Ler ile eşleşen eylemler ve sayfalar için bir
parametrenin değerini dönüştüren parametre dönüştürücüler bulunabilir. LIKE kısıtlamaları, yol parametre
adından sonra iki nokta üst üste ( : ) ve transformatör adı eklenerek, parametre dönüştürücüleri bir rota
parametresine eklenebilir. Örneğin, yol şablonu blog/{article:slugify} bir slugify transformatörü
belirtir. Parametre dönüştürücüler hakkında daha fazla bilgi için bkz. Parameter transformatör başvurusu
bölümü.
Aşağıdaki tabloda örnek yol şablonları ve bunların davranışları gösterilmektedir.

ROTA ŞABLONU ÖRNEK EŞLEŞEN URI İSTEK URI 'SI…

hello /hello Yalnızca /hello tek yol ile eşleşir.

{Page=Home} / Home``Page eşleşir ve ayarlar.

{Page=Home} /Contact Contact``Page eşleşir ve ayarlar.

{controller}/{action}/{id?} /Products/List Products denetleyicisi ve List


eylemiyle eşlenir.
ROTA ŞABLONU ÖRNEK EŞLEŞEN URI İSTEK URI 'SI…

{controller}/{action}/{id?} /Products/Details/123 Products denetleyicisi ve Details


eylemine eşlenir ( id 123 olarak
ayarlanır).

{controller=Home}/{action=Index}/{id?}
/ Home denetleyicisi ve Index
yöntemiyle eşlenir ( id yok sayılır).

Bir şablon kullanmak genellikle yönlendirmeye en basit yaklaşımdır. Kısıtlamalar ve varsayılanlar, yol
şablonu dışında da belirtilebilir.

TIP
Route, istekleri eşleştirme gibi yerleşik yönlendirme uygulamalarının nasıl yapıldığını görmek için günlük kaydını
etkinleştirin.

Ayrılmış yönlendirme adları


Aşağıdaki anahtar sözcükler ayrılmış isimlerdir ve yol adları veya parametreler olarak kullanılamaz:
action
area
controller
handler
page

Yol kısıtlama başvurusu


Yol kısıtlamaları, gelen URL 'de bir eşleşme meydana geldiğinde ve URL yolu yol değerlerinde
simgeleştirilir yürütülür. Rota kısıtlamaları genellikle yol şablonu aracılığıyla ilişkili rota değerini inceler ve
değerin kabul edilebilir olup olmadığı konusunda bir Evet/Hayır kararı getirir. Bazı rota kısıtlamaları, isteğin
yönlendirilip yönlendirilmeyeceğini göz önünde bulundurmanız için yol değeri dışındaki verileri kullanır.
Örneğin HttpMethodRouteConstraint, HTTP fiiline bağlı olarak bir isteği kabul edebilir veya reddedebilir.
Kısıtlamalar, yönlendirme isteklerinde ve bağlantı oluşturmada kullanılır.

WARNING
Giriş doğrulamasıiçin kısıtlamaları kullanmayın. Giriş doğrulamasıiçin kısıtlamalar kullanılıyorsa, doğru bir hata
iletisine sahip 400-Bad isteği yerine 404- olmayan bir Yanıt ile geçersiz giriş oluşur. Yol kısıtlamaları, belirli bir rota için
girdileri doğrulamak üzere değil, benzer yolların belirsizliğini ortadan kaldırmak için kullanılır.

Aşağıdaki tabloda örnek yol kısıtlamaları ve bunların beklenen davranışları gösterilmektedir.

KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

int {id:int} 123456789 , -123456789 Herhangi bir tamsayıyla


eşleşir

bool {active:bool} true , FALSE true veya false eşleşir


(büyük/küçük harfe
duyarsız)
KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

datetime {dob:datetime} 2016-12-31 , Geçerli bir DateTime


2016-12-31 7:32pm değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

decimal {price:decimal} 49.99 , -1,000.01 Geçerli bir decimal


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

double {weight:double} 1.234 , -1,001.01e8 Geçerli bir double


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

float {weight:float} 1.234 , -1,001.01e8 Geçerli bir float


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

guid {id:guid} CD2C1638-1638-72D5- Geçerli bir Guid değeriyle


1638-DEADBEEF1638 eşleşir
,
{CD2C1638-1638-72D5-
1638-DEADBEEF1638}

long {ticks:long} 123456789 , -123456789 Geçerli bir long değeriyle


eşleşir

minlength(value) {username:minlength(4)} Rick Dize en az 4 karakter


olmalıdır

maxlength(value) {filename:maxlength(8)} Richard Dize 8 karakterden uzun


olmamalıdır

length(length) {filename:length(12)} somefile.txt Dize tam olarak 12


karakter uzunluğunda
olmalıdır

length(min,max) {filename:length(8,16)} somefile.txt Dize en az 8 ve en fazla 16


karakter uzunluğunda
olmalıdır

min(value) {age:min(18)} 19 Tamsayı değeri en az 18


olmalıdır

max(value) {age:max(120)} 91 Tamsayı değeri 120 ' ten


fazla olmamalıdır

range(min,max) {age:range(18,120)} 91 Tamsayı değeri en az 18


olmalı ancak 120 ' ten
fazla olmamalıdır

alpha {name:alpha} Rick Dize bir veya daha fazla


alfabetik karakterden
oluşmalıdır ( a - z ,
büyük/küçük harfe
duyarsız)
KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

regex(expression) {ssn:regex(^\\d{{3}}- 123-45-6789 Dize, normal ifadeyle


\\d{{2}}-\\d{{4}}$)} eşleşmelidir (normal ifade
tanımlama hakkında
ipuçlarına bakın)

required {name:required} Rick URL oluşturma sırasında


parametre olmayan bir
değerin mevcut olduğunu
zorlamak için kullanılır

Birden çok, iki nokta üst üste sınırlı kısıtlama tek bir parametreye uygulanabilir. Örneğin, aşağıdaki
kısıtlama bir parametreyi 1 veya daha büyük bir tamsayı değeriyle kısıtlar:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

WARNING
URL 'YI doğrulayan ve bir CLR türüne ( int veya DateTime ) dönüştürülen yol kısıtlamaları her zaman sabit kültürü
kullanır. Bu kısıtlamalar, URL 'nin yerelleştirilemeyen olduğunu varsayar. Framework tarafından sunulan yol
kısıtlamaları, yol değerlerinde depolanan değerleri değiştirmez. URL 'den Ayrıştırılan tüm rota değerleri dizeler olarak
depolanır. Örneğin, float kısıtlaması yol değerini bir float öğesine dönüştürmeye çalışır, ancak dönüştürülen değer
yalnızca bir float öğesine dönüştürülebileceğini doğrulamak için kullanılır.

Normal ifadeler
ASP.NET Core Framework, normal ifade oluşturucusuna
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ekler. Bu üyelerin
açıklaması için bkz. RegexOptions.
Normal ifadeler, C# yönlendirme ve dil tarafından kullanılanlarla aynı sınırlayıcıları ve belirteçleri kullanır.
Normal ifade belirteçlerinin atlanmalıdır. ^\d{3}-\d{2}-\d{4}$ normal ifade ' i yönlendirmede kullanmak
için, ifadede, C# kaynak \ dosyadaki \\ (çift ters eğik çizgi) karakter olarak belirtilen \ (tek ters eğik
çizgi) karakterlere sahip olması gerekir. karakter (tam dize sabit değerlerikullanmadıkça). Yönlendirme
parametresi sınırlayıcı karakterlerini ( { , } , [ , ] ) atlamak için, ifadedeki karakterleri çift ( {{ , } , [[ ,
]] ). Aşağıdaki tabloda, bir normal ifade ve kaçan sürümü gösterilmektedir.

NORMAL IFADE KAÇAN NORMAL IFADE

^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$

^[a-z]{2}$ ^[[a-z]]{{2}}$

Yönlendirmelerde kullanılan normal ifadeler, genellikle şapka işareti ( ^ ) karakteriyle başlar ve dizenin
başlangıç konumuyla eşleşir. İfadeler genellikle dolar işareti ( $ ) karakteriyle biter ve dizenin sonuyla
eşleşir. ^ ve $ karakterler, normal ifadenin tüm yol parametresi değeri ile eşleştiğinden emin olun. ^ ve
$ karakterleri olmadan normal ifade, dize içindeki herhangi bir alt dizeden eşleşir ve bu genellikle
istenmeyen bir ifadedir. Aşağıdaki tabloda örnekler verilmektedir ve bunların eşleşmesinin neden
eşleşmediği veya eşleşmemesi açıklanmaktadır.
İFADE DIZE EŞLEŞTIRME YORUM

[a-z]{2} herkese Evet Alt dize eşleşmeleri

[a-z]{2} 123abc456 Evet Alt dize eşleşmeleri

[a-z]{2} MZ Evet Eşleşen ifadesi

[a-z]{2} MZ Evet Büyük/küçük harfe duyarlı


değil

^[a-z]{2}$ herkese Hayır Yukarıdaki ^ ve $ bakın

^[a-z]{2}$ 123abc456 Hayır Yukarıdaki ^ ve $ bakın

Normal ifade sözdizimi hakkında daha fazla bilgi için bkz. .NET Framework normal ifadeler.
Bir parametreyi bilinen olası değerler kümesiyle kısıtlamak için, normal bir ifade kullanın. Örneğin
{action:regex(^(list|get|create)$)} , yalnızca action Route değeri list , get veya create ile eşleşir.
Kısıtlama sözlüğüne geçirilirse dize ^(list|get|create)$ eşdeğerdir. Bilinen kısıtlamalardan biriyle
eşleşmeyen kısıtlama sözlüğüne (bir şablon içinde satır içi değil) geçirilen kısıtlamalar da normal ifadeler
olarak kabul edilir.

Özel yol kısıtlamaları


Yerleşik yol kısıtlamalarına ek olarak, IRouteConstraint arabirimi uygulayarak özel yol kısıtlamaları
oluşturulabilir. IRouteConstraint arabirimi, kısıtlama karşılandıysanız true döndüren Match tek bir yöntem
içerir ve aksi takdirde false .
Özel bir IRouteConstraintkullanmak için, yol kısıtlama türü uygulamanın hizmet kapsayıcısında
uygulamanın ConstraintMap kayıtlı olmalıdır. ConstraintMap, yol kısıtlama anahtarlarını bu kısıtlamaları
doğrulayan IRouteConstraint uygulamalarla eşleyen bir sözlüktür. Bir uygulamanın ConstraintMap, bir
hizmetin parçası olarak Startup.ConfigureServices güncelleştirilebilen olabilir . AddRouting çağrısı veya
RouteOptions doğrudan services.Configure<RouteOptions> ile yapılandırma. Örneğin:

services.AddRouting(options =>
{
options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Kısıtlama daha sonra, kısıtlama türü kaydedilirken belirtilen ad kullanılarak yollara her zamanki şekilde
uygulanabilir. Örneğin:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

Parametre transformatörü başvurusu


Parametre dönüştürücüler:
Routeiçin bağlantı oluştururken yürütün.
Microsoft.AspNetCore.Routing.IOutboundParameterTransformer uygulayın.
ConstraintMapkullanılarak yapılandırılır.
Parametrenin yol değerini alın ve yeni bir dize değerine dönüştürün.
Oluşturulan bağlantıda Dönüştürülmüş değerin kullanılmasına neden olacak.
Örneğin, Url.Action(new { article = "MyTestArticle" }) ile blog\{article:slugify} yol düzeninde özel
slugify parametresi transformatörü blog\my-test-article üretir.
Bir parametre transformatörü bir yol düzeninde kullanmak için, önce Startup.ConfigureServices
ConstraintMap kullanarak yapılandırın:

services.AddRouting(options =>
{
// Replace the type and the name used to refer to it with your own
// IOutboundParameterTransformer implementation
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

Parametre dönüştürücüler, bir uç noktanın çözümlediği URI 'yi dönüştürmek için çerçevesi tarafından
kullanılır. Örneğin, ASP.NET Core MVC, area , controller , action ve page eşleşecek şekilde kullanılan
rota değerini dönüştürmek için parametre dönüştürücüler kullanır.

routes.MapRoute(
name: "default",
template: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");

Önceki yol ile eylem SubscriptionManagementController.GetAll() , URI /subscription-management/get-all ile


eşleştirilir. Bir parametre transformatörü bir bağlantı oluşturmak için kullanılan rota değerlerini değiştirmez.
Örneğin, Url.Action("GetAll", "SubscriptionManagement") çıkışları /subscription-management/get-all .
ASP.NET Core, oluşturulan yollarla bir parametre dönüştürücüler kullanmak için API kuralları sağlar:
ASP.NET Core MVC 'nin Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention
API kuralı vardır. Bu kural, uygulamadaki tüm öznitelik yollarına belirtilen bir parametre transformatörü
uygular. Parametre transformatörü, öznitelik yol belirteçlerini değiştirildiklerinde dönüştürür. Daha fazla
bilgi için bkz. belirteç değişimini özelleştirmek için bir parametre transformatörü kullanma.
Razor Pages Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API kuralına
sahiptir. Bu kural, belirtilen bir parametre transformatörü otomatik olarak keşfedilen Razor Pages
uygular. Parametre transformatörü Razor Pages yolların klasör ve dosya adı segmentlerini dönüştürür.
Daha fazla bilgi için bkz. sayfa yollarını özelleştirmek için bir parametre transformatörü kullanma.

URL oluşturma başvurusu


Aşağıdaki örnek, yol değerlerinin bir sözlüğü ve bir RouteCollectioniçin bir yol bağlantısının nasıl
oluşturulacağını gösterir.
app.Run(async (context) =>
{
var dictionary = new RouteValueDictionary
{
{ "operation", "create" },
{ "id", 123}
};

var vpc = new VirtualPathContext(context, null, dictionary,


"Track Package Route");
var path = routes.GetVirtualPath(vpc).VirtualPath;

context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Menu<hr/>");
await context.Response.WriteAsync(
$"<a href='{path}'>Create Package 123</a><br/>");
});

Yukarıdaki örnek sonunda oluşturulan VirtualPath /package/create/123 . Sözlük, "paket yolunu Izle"
şablonunun package/{operation}/{id}``operation ve id yol değerlerini sağlar. Ayrıntılar için, yönlendirme
ara yazılımı kullanma bölümünde veya örnek uygulamadaörnek koda bakın.
VirtualPathContext oluşturucusunun ikinci parametresi bir ortam değerlerikoleksiyonudur. Ortam
değerleri, bir geliştiricinin bir istek bağlamı içinde belirtmesi gereken değer sayısını sınırlandırdığından
kullanım için uygundur. Geçerli isteğin geçerli yol değerleri, bağlantı oluşturma için çevresel değerler olarak
kabul edilir. ASP.NET Core MVC uygulamasının HomeController``About eyleminde,—ortam değeri Home
Index eyleme bağlamak için denetleyici yolu değerini belirtmeniz gerekmez.

Bir parametreyle eşleşmeyen çevresel değerler yok sayılır. Ayrıca, açıkça sağlanmış bir değer çevresel
değeri geçersiz kıldığında çevresel değerler de yoksayılır. Eşleştirme, URL 'de soldan sağa doğru gerçekleşir.
Açık olarak sağlanmış ancak yolun bir segmentiyle eşleşmeyen değerler sorgu dizesine eklenir. Aşağıdaki
tabloda {controller}/{action}/{id?} yol şablonu kullanılırken sonuç gösterilmektedir.

ÇEVRESEL DEĞERLER AÇIK DEĞERLER SONUÇ

denetleyici = "giriş" Action = "hakkında" /Home/About

denetleyici = "giriş" denetleyici = "Order", Action = /Order/About


"hakkında"

denetleyici = "giriş", renk = "kırmızı" Action = "hakkında" /Home/About

denetleyici = "giriş" Action = "hakkında", color = "Red" /Home/About?color=Red

Bir rotada bir parametreye karşılık gelen bir varsayılan değer varsa ve bu değer açıkça sağlanmışsa,
varsayılan değerle eşleşmelidir:

routes.MapRoute("blog_route", "blog/{*slug}",
defaults: new { controller = "Blog", action = "ReadPost" });

Bağlantı oluşturma yalnızca controller ve action için eşleşen değerler sağlandığında bu yol için bir
bağlantı oluşturur.

Karmaşık segmentler
Karmaşık segmentler (örneğin [Route("/x{token}y")] ), sabit değerli olmayan değişmez değerler ile sağdan
sola eşleştirilirken işlenir. Karmaşık segmentlerin nasıl eşleştirileceği hakkında ayrıntılı bir açıklama için bu
koda bakın. Kod örneği ASP.NET Core tarafından kullanılmaz, ancak karmaşık segmentler hakkında iyi bir
açıklama sağlar.

Uç nokta meta verilerini yapılandırma


Aşağıdaki bağlantılar, uç nokta meta verilerini yapılandırma hakkında bilgi sağlar:
Uç nokta yönlendirme ile CORS 'yi etkinleştirme
Özel bir [MinimumAgeAuthorize] özniteliği kullanan ıauthorizationpolicyprovider örneği
[Yetkilendir] özniteliğiyle test kimlik doğrulaması
RequireAuthorization
[Yetkilendir] özniteliğiyle düzeni seçme
[Yetkilendir] özniteliği kullanılarak ilkeler uygulanıyor
ASP.NET Core rol tabanlı yetkilendirme

RequireHost ile yollarla eşleşen ana bilgisayar


RequireHost , belirtilen Konağı gerektiren rotaya bir kısıtlama uygular. RequireHost veya [Host]
parametresi şu olabilir:
Ana bilgisayar: www.domain.com (herhangi bir bağlantı noktasıyla www.domain.com eşleşir)
Joker karakterle ana bilgisayar: *.domain.com (herhangi bir bağlantı noktasında www.domain.com ,
subdomain.domain.com veya www.subdomain.domain.com eşleşir )
Bağlantı noktası: *:5000 (herhangi bir konakla bağlantı noktası 5000 ile eşleşir)
Konak ve bağlantı noktası: www.domain.com:5000 , *.domain.com:5000 (ana bilgisayar ve bağlantı
noktasıyla eşleşir)
RequireHost veya [Host] kullanılarak birden çok parametre belirtilebilir. Kısıtlama, parametrelerden
herhangi biri için geçerli olan konaklara göre eşleşir. Örneğin, [Host("domain.com", "*.domain.com")]
domain.com , www.domain.com veya subdomain.domain.com eşleştirecektir.

Aşağıdaki kod, rotada belirtilen ana bilgisayarı gerektirmek için RequireHost kullanır:

public void Configure(IApplicationBuilder app)


{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", context => context.Response.WriteAsync("Hi Contoso!"))
.RequireHost("contoso.com");
endpoints.MapGet("/", context => context.Response.WriteAsync("Hi AdventureWorks!"))
.RequireHost("adventure-works.com");
endpoints.MapHealthChecks("/healthz").RequireHost("*:8080");
});
}

Aşağıdaki kod, denetleyicide belirtilen Konağı gerektirmek için [Host] özniteliğini kullanır:
[Host("contoso.com", "adventure-works.com")]
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)


{
_logger = logger;
}

public IActionResult Index()


{
return View();
}

[Host("example.com:8080")]
public IActionResult Privacy()
{
return View();
}

[Host] özniteliği hem denetleyici hem de eylem yöntemine uygulandığında:


Eylem üzerindeki özniteliği kullanılır.
Denetleyici özniteliği yok sayılır.
Yönlendirme, istek URI 'Lerini uç noktalarla eşleştirmekten ve gelen istekleri bu uç noktalara gönderen
sorumludur. Yollar uygulamada tanımlanır ve uygulama başlatıldığında yapılandırılır. Yol, isteğe bağlı olarak
istekte bulunan URL 'den değerleri ayıklayabilir ve bu değerler, istek işleme için kullanılabilir. Uygulamadan
yönlendirme bilgilerini kullanarak, yönlendirme, uç noktalarıyla eşlenen URL 'Ler de oluşturabilir.
ASP.NET Core 2,2 ' de en son yönlendirme senaryolarını kullanmak için Startup.ConfigureServices MVC
Hizmetleri kaydının Uyumluluk sürümünü belirtin:

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

EnableEndpointRouting seçeneği, yönlendirmenin, ASP.NET Core 2,1 veya önceki bir sürümünün uç nokta
tabanlı mantık veya IRoutertabanlı mantığını dahili olarak kullanması gerektiğini belirler. Uyumluluk
sürümü 2,2 veya üzeri bir değere ayarlandığında, varsayılan değer true olur. Önceki yönlendirme
mantığını kullanmak için değeri false olarak ayarlayın:

// Use the routing logic of ASP.NET Core 2.1 or earlier:


services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

IRoutertabanlı yönlendirme hakkında daha fazla bilgi için Bu konunun ASP.NET Core 2,1 sürümünebakın.

IMPORTANT
Bu belge, alt düzey ASP.NET Core yönlendirmeyi içerir. ASP.NET Core MVC yönlendirme hakkında daha fazla bilgi için
bkz. ASP.NET Core denetleyici eylemlerine yönlendirme. Razor Pages 'de yönlendirme kuralları hakkında bilgi için bkz.
ASP.NET Core Razor Pages yol ve uygulama kuralları.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)


Yönlendirme temelleri
Çoğu uygulama, URL 'Lerin okunabilir ve anlamlı olması için temel ve açıklayıcı bir yönlendirme şeması
seçmelidir. Varsayılan geleneksel yol {controller=Home}/{action=Index}/{id?} :
Temel ve açıklayıcı bir yönlendirme düzenini destekler.
, UI tabanlı uygulamalar için kullanışlı bir başlangıç noktasıdır.
Geliştiriciler, öznitelik yönlendirme veya adanmış geleneksel yollar kullanarak özel durumlarda (örneğin,
blog ve e-ticaret uç noktaları) bir uygulamanın yüksek trafik bölümlerine daha fazla terse yolu ekler.
Web API 'Leri, uygulamanın işlevselliğini HTTP fiilleri tarafından temsil edilen bir kaynak kümesi olarak
modellemek için öznitelik yönlendirmeyi kullanmalıdır. Bu, aynı mantıksal kaynaktaki birçok işlemin
(örneğin, GET, POST) aynı URL 'YI kullanacağı anlamına gelir. Öznitelik yönlendirme, bir API 'nin Genel uç
nokta yerleşimini dikkatle tasarlamak için gereken bir denetim düzeyi sağlar.
Razor Pages uygulamalar, bir uygulamanın Sayfalar klasöründe adlandırılmış kaynaklara hizmeti sağlamak
için varsayılan geleneksel yönlendirmeyi kullanır. Razor Pages yönlendirme davranışını özelleştirmenizi
sağlayan ek kurallar mevcuttur. Daha fazla bilgi için bkz. ASP.NET Core Razor Pages giriş ve ASP.NET Core
Razor Pages yol ve uygulama kuralları.
URL oluşturma desteği, uygulamanın, uygulamayı birbirine bağlamak için sabit kodlama URL 'Leri
olmadan geliştirilebilmesine izin verir. Bu destek, temel bir yönlendirme yapılandırmasıyla başlayıp
uygulamanın kaynak düzeni belirlendikten sonra yolların değiştirilmesini sağlar.
Yönlendirme, bir uygulamadaki mantıksal uç noktaları temsil etmek için uç noktaları ( Endpoint ) kullanır.
Bir uç nokta, istekleri işlemek için bir temsilci ve rastgele meta veri koleksiyonunu tanımlar. Meta veriler, her
bir uç noktaya eklenen ilkelere ve yapılandırmaya bağlı olarak çapraz kesme sorunları uygulamak için
kullanılır.
Yönlendirme sistemi aşağıdaki özelliklere sahiptir:
Yol şablonu sözdizimi, simgeleştirilmiş yol parametrelerine sahip yolları tanımlamak için kullanılır.
Geleneksel stil ve öznitelik stili uç nokta yapılandırmasına izin verilir.
IRouteConstraint, bir URL parametresinin belirli bir uç nokta kısıtlaması için geçerli bir değer içerip
içermediğini belirlemekte kullanılır.
MVC/Razor Pages gibi uygulama modelleri, yönlendirme senaryolarının öngörülebilir bir
uygulaması olan tüm uç noktalarını kaydeder.
Yönlendirme gerçekleştirme, yönlendirme kararlarını, ara yazılım ardışık düzeninde istediğiniz yere
getirir.
Bir yönlendirme ara yazılımı, belirli bir istek URI 'SI için yönlendirme ara yazılımı uç noktası
kararının sonucunu inceleyebilir.
Uygulamadaki tüm uç noktaları, ara yazılım ardışık düzeninde herhangi bir yerde listelemek
mümkündür.
Bir uygulama, uç nokta bilgilerine göre URL 'Ler oluşturmak için (örneğin, yeniden yönlendirme
veya bağlantılar için) yönlendirmeyi kullanabilir ve bu sayede bakım yapılmasına yardımcı olan sabit
kodlanmış URL 'Lerden kaçınabilirsiniz.
URL oluşturma, rastgele genişletilebilirliği destekleyen adreslere dayalıdır:
Bağlantı Oluşturucu API 'SI (LinkGenerator), bağımlılık ekleme (dı) kullanılarak URL 'ler
oluşturmak için her yerde çözülebilir.
Bağlantı Oluşturucu API 'sinin DI aracılığıyla kullanılamadığı durumlarda IUrlHelper URL 'Leri
derlemek için yöntemler sunar.

NOTE
ASP.NET Core 2,2 ' de uç nokta yönlendirme yayını ile, uç nokta bağlama MVC/Razor Pages eylemleri ve sayfaları ile
sınırlıdır. Uç nokta bağlama yeteneklerinin genişletmeleri, gelecek sürümlerde planlanmaktadır.

Yönlendirme, RouterMiddleware sınıfı tarafından, Ara yazılım ardışık düzenine bağlıdır. ASP.NET Core
MVC , yapılandırma kapsamında bir ara yazılım ardışık düzenine yönlendirme ekler ve MVC ve Razor
Pages uygulamalarında yönlendirmeyi işler. Tek başına bileşen olarak yönlendirmeyi nasıl kullanacağınızı
öğrenmek için yönlendirme ara yazılımı kullanma bölümüne bakın.
URL eşleştirme
URL eşleştirme, yönlendirmenin bir uç noktayagelen isteği gönderdiği işlemdir. Bu işlem, URL yolundaki
verileri temel alır, ancak istekteki verileri göz önünde bulundurmanız için genişletilebilir. Ayrı işleyicilere
istek gönderme özelliği, bir uygulamanın boyutunu ve karmaşıklığını ölçeklendirmeye yönelik anahtardır.
Uç nokta yönlendirmesinde yönlendirme sistemi tüm gönderme kararlarından sorumludur. Ara yazılım,
seçili uç noktaya göre ilkeler uyguladığı için, yönlendirme sisteminde güvenlik ilkelerinin dağıtımını
etkileyebilecek veya uygulamanın uygulanmasını etkileyebilecek herhangi bir kararın olması önemlidir.
Uç nokta temsilcisi yürütüldüğünde, Routecontext. RouteData özellikleri, bu nedenle yapılan istek işlemeye
bağlı olarak uygun değerlere ayarlanır.
RouteData. Values , rotada oluşturulan yol değerlerinin bir sözlüğüdür. Bu değerler genellikle URL 'YI
simgeleştirerek belirlenir ve Kullanıcı girişini kabul etmek ya da uygulama içinde daha fazla kararlar almak
için kullanılabilir.
RouteData. DataTokens , eşleşen rotayla ilgili ek verilerin bir özellik çantadır. DataTokens, uygulamanın
hangi yolun eşleştiğini temel alarak kararlar verebilmesi için durum verilerinin her bir rota ile
ilişkilendirilmesini desteklemek amacıyla sağlanır. Bu değerler, geliştirici tarafından tanımlanır ve
yönlendirme davranışını herhangi bir şekilde etkilemez. Ayrıca, RouteData. DataTokens içinde bulunan
değerler her türlü türden olabilir. Bu, veridizeleri arasında dönüştürülebilir olmalıdır.
RouteData. yönlendiriciler , isteği başarıyla eşleştirirken geçen yolların bir listesidir. Yollar bir diğerinin
içinde iç içe olabilir. Routers özelliği, bir eşleşme ile sonuçlanan yolların mantıksal ağacı aracılığıyla yolu
yansıtır. Genellikle, Routers ilk öğe yol koleksiyonudur ve URL oluşturma için kullanılmalıdır. Routers son
öğe, eşleşen yol işleyicisidir.
LinkGenerator ile URL oluşturma
URL oluşturma, yönlendirmenin bir yol değerleri kümesine göre bir URL yolu oluşturabileceği işlemdir. Bu,
uç noktalarınız ve bunlara erişen URL 'Ler arasında mantıksal bir ayrım sağlar.
Uç nokta yönlendirme bağlantı Oluşturucu API 'sini (LinkGenerator) içerir. LinkGenerator, DI 'dan
alınabilecek bir tek hizmettir. API, yürütülen bir istek bağlamı dışında kullanılabilir. MVC 'nin Etiket
Yardımcıları, HTML Yardımcıları ve eylem sonuçlarıgibi IUrlHelperkullanan IUrlHelper ve senaryoları,
bağlantı oluşturma yetenekleri sağlamak için bağlantı oluşturucuyu kullanır.
Bağlantı Oluşturucu, bir Adres ve Adres şemalarıkavramıyla desteklenir. Adres şeması, bağlantı oluşturma
için göz önünde bulundurmanız gereken uç noktaları belirlemenin bir yoludur. Örneğin, çok sayıda
kullanıcının yol adı ve yol değerleri senaryoları, MVC/Razor Pages tarafından tanıdık bir adres düzeni
olarak uygulanır.
Bağlantı Oluşturucu, aşağıdaki genişletme yöntemleri aracılığıyla MVC/Razor Pages eylemlerine ve
sayfalarına bağlanabilir:
GetPathByAction
GetUriByAction
GetPathByPage
GetUriByPage
Bu yöntemlerin aşırı yüklemesi HttpContext içeren bağımsız değişkenleri kabul eder. Bu yöntemler
Url.Action ve Url.Page işlevsel olarak eşdeğerdir ancak ek esneklik ve seçenekler sunar.

GetPath* yöntemleri, Url.Action ve Url.Page , mutlak bir yol içeren bir URI oluşturmak için en çok
benzerdir. GetUri* Yöntemler her zaman bir düzen ve konak içeren mutlak bir URI oluşturur. Bir
HttpContext kabul eden yöntemler, yürütülmekte olan istek bağlamında bir URI oluşturur.Ortam yolu
değerleri, URL taban yolu, şeması ve yürütülen istekten ana bilgisayar, geçersiz kılınmadıkça kullanılır.
LinkGenerator bir adresle çağrılır. URI oluşturma iki adımda gerçekleşir:
1. Adres, adresle eşleşen bir uç nokta listesine bağlanır.
2. Her uç noktanın RoutePattern , sağlanan değerlerle eşleşen bir rota deseninin bulunana kadar
değerlendirilir. Elde edilen çıktı, bağlantı oluşturucuya sağlanan diğer URI parçalarıyla birleştirilir ve
döndürülür.
LinkGenerator tarafından sunulan yöntemler, herhangi bir tür adresin standart bağlantı oluşturma
özelliklerini destekler. Bağlantı oluşturucuyu kullanmanın en kolay yolu, belirli bir adres türü için işlem
gerçekleştiren genişletme yöntemlerine yöneliktir.

GENIŞLETME YÖNTEMI AÇIKLAMA

GetPathByAddress Belirtilen değerleri temel alarak mutlak bir yola sahip bir
URI oluşturur.

GetUriByAddress Belirtilen değerleri temel alarak mutlak bir URI oluşturur.

WARNING
LinkGenerator yöntemlerinin çağrılmasının aşağıdaki etkilerine dikkat edin:
Gelen isteklerin Host üstbilgisini doğrulayan bir uygulama yapılandırmasında GetUri* uzantısı
yöntemlerini dikkatle kullanın. Gelen isteklerin Host üstbilgisi doğrulandıktan sonra, güvenilir olmayan istek
girişi, bir görünüm/sayfada URI 'Ler halinde istemciye geri gönderilebilir. Tüm üretim uygulamalarının, Host
üst bilgisini bilinen geçerli değerlere karşı doğrulamak için kendi sunucusunu yapılandırmasını öneririz.
Map veya MapWhen birlikte ara yazılım ile birlikte LinkGenerator kullanın. Map* , yürütülen isteğin temel
yolunu değiştirir ve bu da bağlantı oluşturma çıktısını etkiler. Tüm LinkGenerator API 'Leri temel yol
belirtmeye izin verir. Map* bağlantı oluşturmada etkilerini geri almak için her zaman boş bir temel yol belirtin.

Yönlendirmenin önceki sürümlerinden farklılıklar


ASP.NET Core 2,2 veya üzeri ve daha önceki yönlendirme sürümlerindeki ASP.NET Core uç nokta
yönlendirmesi arasında birkaç fark vardır:
Uç nokta yönlendirme sistemi, Routedevralma dahil IRoutertabanlı genişletilebilirliği desteklemez.
Uç nokta yönlendirme WebApiCompatShimdesteklemez. Uyumluluk Shim 'yi kullanmaya devam
etmek için 2,1 Uyumluluk sürümünü ( .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) )
kullanın.
Uç nokta yönlendirmesinde, geleneksel yollar kullanılırken oluşturulan URI 'lerin büyük küçük
harfleri için farklı davranış vardır.
Aşağıdaki varsayılan yol şablonunu göz önünde bulundurun:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Aşağıdaki rotayı kullanarak bir eyleme bağlantı oluşturduğunuzu varsayalım:

var link = Url.Action("ReadPost", "blog", new { id = 17, });

IRoutertabanlı yönlendirme ile bu kod, /blog/ReadPost/17 URI 'sini oluşturur ve bu da, belirtilen yol
değerinin büyük küçük harflerini üretir. ASP.NET Core 2,2 veya sonraki bir sürümde uç nokta
yönlendirme /Blog/ReadPost/17 ("blog" büyük harfli) oluşturur. Endpoint Routing, bu davranışı
küresel olarak özelleştirmek veya URL eşleme için farklı kurallar uygulamak üzere kullanılabilecek
IOutboundParameterTransformer arabirimini sağlar.

Daha fazla bilgi için bkz. Parameter transformatör başvurusu bölümü.


Standart yollarla MVC/Razor Pages tarafından kullanılan bağlantı oluşturma, mevcut olmayan bir
denetleyiciye/eyleme veya sayfaya bağlantı kurmaya çalışırken farklı şekilde davranır.
Aşağıdaki varsayılan yol şablonunu göz önünde bulundurun:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Aşağıdaki ile varsayılan şablonu kullanarak bir eyleme bağlantı oluşturduğunuzu varsayalım:

var link = Url.Action("ReadPost", "Blog", new { id = 17, });

IRouter tabanlı yönlendirme sayesinde, BlogController var olmasa veya bir ReadPost Action
yöntemine sahip olmasa bile sonuç daima /Blog/ReadPost/17 . Beklenen şekilde, işlem yöntemi varsa
ASP.NET Core 2,2 veya sonraki bir sürümde uç nokta yönlendirmesi /Blog/ReadPost/17 üretir.
Ancak, uç nokta yönlendirme, eylem yoksa boş bir dize oluşturur. Kavramsal olarak, uç nokta
yönlendirme, eylem mevcut değilse uç noktanın var olduğunu varsaymaz.
Bağlantı oluşturma çevresel değeri ınvalidation algoritması , uç nokta yönlendirme ile
kullanıldığında farklı davranır.
Çevresel değer ınvalidation , şu anda yürütülmekte olan isteğin (çevresel değerler) hangi rota
değerlerinin bağlantı oluşturma işlemlerinde kullanılabileceğini belirleyen algoritmadır. Geleneksel
yönlendirme, farklı bir eyleme bağlanılırken ek yol değerlerini her zaman geçersiz kıldı. ASP.NET
Core 2,2 sürümünden önce öznitelik yönlendirmesinde bu davranış yoktu. ASP.NET Core 'nin
önceki sürümlerinde, aynı yol parametresi adlarını kullanan başka bir eyleme bağlantılar, bağlantı
oluşturma hatalarıyla sonuçlandı. ASP.NET Core 2,2 veya sonraki sürümlerde, yönlendirme
biçimlerinin her ikisi de başka bir eyleme bağlanırken değerleri geçersiz kılar.
ASP.NET Core 2,1 veya önceki sürümlerde aşağıdaki örneği göz önünde bulundurun. Başka bir
eyleme (veya başka bir sayfaya) bağlanırken, yol değerleri istenmeyen yollarla yeniden kullanılabilir.
/Pages/Store/Product.exe:

@page "{id}"
@Url.Page("/Login")

/Pages/Login.exeiçinde:

@page "{id?}"

URI, ASP.NET Core 2,1 veya önceki sürümlerde /Store/Product/18 , @Url.Page("/Login") tarafından
Store/Info sayfasında oluşturulan bağlantı /Login/18 . 18 ' in id değeri, bağlantı hedefi
uygulamanın tamamen farklı bir parçası olsa bile yeniden kullanılır. /Login sayfasının bağlamındaki
id yol değeri büyük olasılıkla bir depolama ürün KIMLIĞI değeri değil, bir kullanıcı KIMLIĞI
değeridir.
ASP.NET Core 2,2 veya sonraki bir sürümü ile Endpoint Routing, sonuç /Login . Bağlantılı hedef
farklı bir eylem veya sayfa olduğunda çevresel değerler yeniden kullanılmaz.
Gidiş dönüşü yol parametresi sözdizimi: çift yıldız ( ** ) catch-all parametre sözdizimi kullanılırken
eğik çizgiler kodlanmaz.
Bağlantı oluşturma sırasında, yönlendirme sistemi, eğik çizgiler dışında bir çift yıldız ( ** ) catch-all
parametresinde (örneğin, {**myparametername} ) yakalanan değeri kodlar. Çift yıldız yakalama,
ASP.NET Core 2,2 veya sonraki sürümlerde IRouter tabanlı yönlendirme ile desteklenir.
ASP.NET Core ( {*myparametername} ) önceki sürümlerindeki tek yıldız catch-all parametre sözdizimi
desteklenmeye devam eder ve eğik çizgi kodlandı.

İLE OLUŞTURULAN BAĞLANTI


YOLU URL.ACTION(NEW { CATEGORY = "ADMIN/PRODUCTS" }) …

/search/{*page} /search/admin%2Fproducts (eğik çizgi kodlanmış)

/search/{**page} /search/admin/products

Ara yazılım örneği


Aşağıdaki örnekte, bir ara yazılım, mağaza ürünlerini listeleyen bir eylem yöntemine bağlantı oluşturmak
için LinkGenerator API 'sini kullanır. Ekleme tarafından bir sınıfa olan ve GenerateLink çağıran bağlantı
Oluşturucuyu kullanmak, bir uygulamadaki herhangi bir sınıfta kullanılabilir.
using Microsoft.AspNetCore.Routing;

public class ProductsLinkMiddleware


{
private readonly LinkGenerator _linkGenerator;

public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)


{
_linkGenerator = linkGenerator;
}

public async Task InvokeAsync(HttpContext httpContext)


{
var url = _linkGenerator.GetPathByAction("ListProducts", "Store");

httpContext.Response.ContentType = "text/plain";

await httpContext.Response.WriteAsync($"Go to {url} to see our products.");


}
}

Rotalar oluştur
Çoğu uygulama, IRouteBuildertanımlanan benzer uzantı yöntemlerinden birini veya MapRoute çağırarak
yollar oluşturur. IRouteBuilder uzantısı yöntemlerinden herhangi biri bir Route örneği oluşturur ve bunu yol
koleksiyonuna ekler.
MapRoute yol işleyicisi parametresini kabul etmez. MapRoute, yalnızca DefaultHandlertarafından işlenen
rotaları ekler. MVC 'de yönlendirme hakkında daha fazla bilgi için bkz. ASP.NET Core denetleyici
eylemlerine yönlendirme.
Aşağıdaki kod örneği, tipik bir ASP.NET Core MVC yol tanımı tarafından kullanılan MapRoute çağrısının
bir örneğidir:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Bu şablon bir URL yoluyla eşleşir ve yol değerlerini ayıklar. Örneğin, yol /Products/Details/17 şu yol
değerlerini üretir: { controller = Products, action = Details, id = 17 } .
Rota değerleri, URL yolunun kesimlere bölünüyor ve rota şablonundaki yol parametresi adı ile her bir
segmenti eşleştirerek belirlenir. Yol parametreleri olarak adlandırılır. Küme ayraçları içinde parametre adı
eklenerek tanımlanan parametreler { ... } .
Yukarıdaki şablon, URL yolu / de eşleştirebilir ve { controller = Home, action = Index } değerler
üretecektir. Bu, {controller} ve {action} yol parametrelerinin varsayılan değerleri olduğu ve id Route
parametresinin isteğe bağlı olduğu için oluşur. Eşittir işareti ( = ), yol parametresi adı parametre için
varsayılan bir değer tanımladıktan sonra bir değer izler. Yol parametre adından sonra bir soru işareti ( ? )
isteğe bağlı bir parametre tanımlar.
Yol parametreleri varsayılan değer ile her zaman rota değeri oluşturur. Karşılık gelen bir URL yol kesimi
yoksa isteğe bağlı parametreler yol değeri oluşturmaz. Yol şablonu senaryolarının ve sözdiziminin kapsamlı
bir açıklaması için yol şablonu başvurusu bölümüne bakın.
Aşağıdaki örnekte, yol parametresi tanımı {id:int} id Route parametresi için bir yol kısıtlaması
tanımlıyor:
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id:int}");

Bu şablon /Products/Details/17 gibi bir URL yoluyla eşleşir ancak /Products/Details/Apples . Yol
kısıtlamaları IRouteConstraint uygular ve yol değerlerini inceleyerek onları doğrular. Bu örnekte, yol değeri
id bir tamsayıya dönüştürülebilir olmalıdır. Framework tarafından sunulan yol kısıtlamalarının açıklaması
için bkz. route-Constraint-Reference .
MapRoute ek aşırı yüklemeleri constraints , dataTokens ve defaults için değer kabul eder. Bu
parametrelerin tipik kullanımı, anonim türdeki özellik adlarının yol parametre adlarıyla eşleşen anonim
olarak yazılmış bir nesneyi geçirmektir.
Aşağıdaki MapRoute örnekleri eşdeğer yollar oluşturur:

routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
name: "default_route",
template: "{controller=Home}/{action=Index}/{id?}");

TIP
Kısıtlamaları ve Varsayılanları tanımlamaya yönelik satır içi sözdizimi basit yollar için kullanışlı olabilir. Ancak, satır içi
sözdizimi tarafından desteklenmeyen veri belirteçleri gibi senaryolar vardır.

Aşağıdaki örnek birkaç ek senaryoyu göstermektedir:

routes.MapRoute(
name: "blog",
template: "Blog/{**article}",
defaults: new { controller = "Blog", action = "ReadArticle" });

Önceki şablon /Blog/All-About-Routing/Introduction gibi bir URL yoluyla eşleşir ve


{ controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction } değerleri ayıklar.
controller ve action için varsayılan yol değerleri, şablonda karşılık gelen hiçbir yol parametresi olmasa
bile yol tarafından üretilir. Varsayılan değerler yol şablonunda belirtilebilir. article Route parametresi, yol
parametre adından önce bir çift yıldız işareti ( ** ) görünümüne göre catch-all olarak tanımlanır. Catch-all
yol parametreleri, URL yolunun kalanını yakalar ve boş dizeyle de aynı olabilir.
Aşağıdaki örnek yol kısıtlamalarını ve veri belirteçlerini ekler:

routes.MapRoute(
name: "us_english_products",
template: "en-US/Products/{id}",
defaults: new { controller = "Products", action = "Details" },
constraints: new { id = new IntRouteConstraint() },
dataTokens: new { locale = "en-US" });

Önceki şablon /en-US/Products/5 gibi bir URL yoluyla eşleşir ve


{ controller = Products, action = Details, id = 5 } ve veri belirteçleri { locale = en-US } değerleri
ayıklar.

Yol sınıfı URL 'SI oluşturma


Route sınıfı, yol değerlerini bir kümesini rota şablonuyla birleştirerek URL oluşturmayı da gerçekleştirebilir.
Bu, URL yolunu eşleştirmenin mantıksal bir işlemdir.

TIP
URL oluşturmayı daha iyi anlamak için, oluşturmak istediğiniz URL 'YI düşünün ve sonra bir yönlendirme şablonunun
bu URL ile nasıl eşleşeceğini düşünün. Hangi değerler üretilemidir? Bu, URL oluşturma 'nın Route sınıfında nasıl
çalıştığına ilişkin kaba bir eştir.

Aşağıdaki örnek genel ASP.NET Core MVC varsayılan yolunu kullanır:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Yol değerleri { controller = Products, action = List } , /Products/List URL 'SI oluşturulur. Yol değerleri,
URL yolunu biçimlendirmek için karşılık gelen yol parametrelerinin yerine kullanılır. id , isteğe bağlı bir yol
parametresi olduğundan, id için bir değer olmadan URL başarıyla oluşturulur.
Yol değerleri { controller = Home, action = Index } , / URL 'SI oluşturulur. Belirtilen yol değerleri
varsayılan değerlerle eşleşir ve varsayılan değerlere karşılık gelen segmentler güvenle atlanır.
Her iki URL de aşağıdaki yol tanımıyla ( /Home/Index ve / ) bir gidiş dönüş, URL oluşturmak için kullanılan
rota değerlerini oluşturur.

NOTE
ASP.NET Core MVC kullanan bir uygulama doğrudan yönlendirmeye çağırmak yerine URL oluşturmak için UrlHelper
kullanmalıdır.

URL oluşturma hakkında daha fazla bilgi için URL oluşturma başvurusu bölümüne bakın.

Yönlendirme ara yazılımı kullanma


Uygulamanın proje dosyasındaki Microsoft. AspNetCore. app metapackage öğesine başvurun.
Startup.ConfigureServices ' de hizmet kapsayıcısına yönlendirme ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddRouting();
}

Yolların Startup.Configure yönteminde yapılandırılması gerekir. Örnek uygulama aşağıdaki API 'Leri
kullanır:
RouteBuilder
MapGet – yalnızca HTTP GET istekleriyle eşleşir.
UseRouter

var trackPackageRouteHandler = new RouteHandler(context =>


{
var routeValues = context.GetRouteData().Values;
return context.Response.WriteAsync(
$"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
"Track Package Route",
"package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>


{
var name = context.GetRouteValue("name");
// The route handler when HTTP GET "hello/<anything>" matches
// To match HTTP GET "hello/<anything>/<anything>,
// use routeBuilder.MapGet("hello/{*name}"
return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();


app.UseRouter(routes);

Aşağıdaki tabloda verilen URI 'Ler ile ilgili yanıtlar gösterilmektedir.

URI YANITIYLA

/package/create/3 Herkese! Rota değerleri: [işlem, oluşturma], [kimlik, 3]

/package/track/-3 Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/-3/ Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/ İstek, eşleşme olmadan üzerinden yapılır.

GET /hello/Joe Merhaba, ali!

POST /hello/Joe İstek üzerinden geçer, yalnızca HTTP GET ile eşleşir.

GET /hello/Joe/Smith İstek, eşleşme olmadan üzerinden yapılır.


Çerçeve, yollar oluşturmak için bir genişletme yöntemleri kümesi sağlar
(RequestDelegateRouteBuilderExtensions):
MapDelete
MapGet
MapMiddlewareDelete
MapMiddlewareGet
MapMiddlewarePost
MapMiddlewarePut
MapMiddlewareRoute
MapMiddlewareVerb
MapPost
MapPut
MapRoute
MapVerb
Map[Verb] yöntemleri, yöntem adındaki HTTP fiili ile rotayı sınırlandırmak için kısıtlamaları kullanır.
Örneğin, bkz. MapGet ve MapVerb.

Rota şablonu başvurusu


Küme ayraçları içindeki belirteçler ( { ... } ), yol eşleştirildiği takdirde bağlanan Rota parametrelerini
tanımlar. Bir yol segmentinde birden fazla yol parametresi tanımlayabilirsiniz, ancak bunların bir değişmez
değer ile ayrılması gerekir. Örneğin, {controller} ve {action} arasında değişmez değer olmadığından
{controller=Home}{action=Index} geçerli bir yol değil. Bu rota parametrelerinin bir adı olmalı ve ek
öznitelikler belirtilmiş olabilir.
Yol parametreleri dışında (örneğin, {id} ) ve yol ayırıcı / URL içindeki metinle eşleşmesi gerekir. Metin
eşleştirme, büyük/küçük harfe duyarsızdır ve URL yolunun kodu çözülmüş gösterimine göre yapılır.
Değişmez değer yol parametresi sınırlayıcısından ( { veya } ) eşleştirmek için, karakteri ( {{ veya }} )
tekrarlayarak sınırlayıcıdan kaçış.
İsteğe bağlı bir dosya uzantısına sahip bir dosya adı yakalamaya deneyen URL desenlerinin ek konuları
vardır. Örneğin, files/{filename}.{ext?} şablonu düşünün. filename ve ext değerlerinin her ikisi de
varsa, her iki değer de doldurulur. URL 'de yalnızca filename için bir değer varsa, bitiş dönemi ( . ) isteğe
bağlı olduğundan yol eşleşir. Aşağıdaki URL 'Ler bu rota ile eşleşiyor:
/files/myFile.txt
/files/myFile

URI 'nin geri kalanına bağlamak için bir yol parametresinin öneki olarak bir yıldız işareti ( * ) veya çift yıldız
işareti ( ** ) kullanabilirsiniz. Bunlara catch-all parametreleri denir. Örneğin, blog/{**slug} /blog ile
başlayan ve ondan sonraki bir değere sahip olan slug yol değerine atanan tüm URI ile eşleşir. Catch-all
parametreleri boş dizeyle de aynı olabilir.
Yol ayırıcısı ( / ) karakterleri de dahil olmak üzere bir URL oluşturmak için bir yol kullanıldığında, catch-all
parametresi uygun karakterleri çıkar. Örneğin yol foo/{*path} rota değerleriyle { path = "my/path" }
foo/my%2Fpath üretir. Atlanan eğik çizgiye göz önünde edin. Yol ayırıcı karakterlerini geri döndürmek için
** Route parametresi önekini kullanın. { path = "my/path" } ile yol foo/{**path} foo/my/path üretir.

Yol parametrelerinin, parametre adından sonra varsayılan değer belirtilerek bir eşittir işareti ( = ) ile
ayrıldıktan sonra belirlenen varsayılan değerleri olabilir. Örneğin, Home controller için varsayılan değer
olarak {controller=Home} tanımlar. Parametresi için URL 'de hiçbir değer yoksa varsayılan değer kullanılır.
Yol parametreleri, id? gibi parametre adının sonuna bir soru işareti ( ? ) eklenerek isteğe bağlı olarak
yapılır. İsteğe bağlı değerler ve varsayılan yol parametreleri arasındaki fark, varsayılan değere sahip bir yol
parametresinin her zaman bir değer ürettiğinden—isteğe bağlı bir parametre yalnızca istek URL 'SI
tarafından bir değer sağlandığında bir değere sahip olur.
Rota parametrelerinin URL 'den bağlanan rota değeriyle eşleşmesi gereken kısıtlamaları olabilir. Yol
parametre adından sonra bir iki nokta üst üste ( : ) ve kısıtlama adının eklenmesi, bir yol parametresi
üzerinde bir satır içi kısıtlamayı belirtir. Kısıtlama bağımsız değişkenler gerektiriyorsa, kısıtlama adından
sonra parantez ( (...) ) içine alınır. Birden çok satır içi kısıtlama, başka bir iki nokta ( : ) ve kısıtlama adı
eklenerek belirtilebilir.
Kısıtlama adı ve bağımsız değişkenler, URL işlemede kullanılacak bir IRouteConstraint örneği oluşturmak
için IInlineConstraintResolver hizmetine geçirilir. Örneğin, yol şablonu blog/{article:minlength(10)} , 10
bağımsız değişkeniyle bir minlength kısıtlaması belirtir. Yol kısıtlamaları ve Framework tarafından sunulan
kısıtlamaların bir listesi hakkında daha fazla bilgi için, route kısıtlama başvurusu bölümüne bakın.
Yol parametrelerinde Ayrıca, bağlantı oluştururken ve URL 'Ler ile eşleşen eylemler ve sayfalar için bir
parametrenin değerini dönüştüren parametre dönüştürücüler bulunabilir. LIKE kısıtlamaları, yol parametre
adından sonra iki nokta üst üste ( : ) ve transformatör adı eklenerek, parametre dönüştürücüleri bir rota
parametresine eklenebilir. Örneğin, yol şablonu blog/{article:slugify} bir slugify transformatörü
belirtir. Parametre dönüştürücüler hakkında daha fazla bilgi için bkz. Parameter transformatör başvurusu
bölümü.
Aşağıdaki tabloda örnek yol şablonları ve bunların davranışları gösterilmektedir.

ROTA ŞABLONU ÖRNEK EŞLEŞEN URI İSTEK URI 'SI…

hello /hello Yalnızca /hello tek yol ile eşleşir.

{Page=Home} / Home``Page eşleşir ve ayarlar.

{Page=Home} /Contact Contact``Page eşleşir ve ayarlar.

{controller}/{action}/{id?} /Products/List Products denetleyicisi ve List


eylemiyle eşlenir.

{controller}/{action}/{id?} /Products/Details/123 Products denetleyicisi ve Details


eylemine eşlenir ( id 123 olarak
ayarlanır).

{controller=Home}/{action=Index}/{id?}
/ Home denetleyicisi ve Index
yöntemiyle eşlenir ( id yok sayılır).

Bir şablon kullanmak genellikle yönlendirmeye en basit yaklaşımdır. Kısıtlamalar ve varsayılanlar, yol
şablonu dışında da belirtilebilir.

TIP
Route, istekleri eşleştirme gibi yerleşik yönlendirme uygulamalarının nasıl yapıldığını görmek için günlük kaydını
etkinleştirin.

Ayrılmış yönlendirme adları


Aşağıdaki anahtar sözcükler ayrılmış isimlerdir ve yol adları veya parametreler olarak kullanılamaz:
action
area
controller
handler
page

Yol kısıtlama başvurusu


Yol kısıtlamaları, gelen URL 'de bir eşleşme meydana geldiğinde ve URL yolu yol değerlerinde
simgeleştirilir yürütülür. Rota kısıtlamaları genellikle yol şablonu aracılığıyla ilişkili rota değerini inceler ve
değerin kabul edilebilir olup olmadığı konusunda bir Evet/Hayır kararı getirir. Bazı rota kısıtlamaları, isteğin
yönlendirilip yönlendirilmeyeceğini göz önünde bulundurmanız için yol değeri dışındaki verileri kullanır.
Örneğin HttpMethodRouteConstraint, HTTP fiiline bağlı olarak bir isteği kabul edebilir veya reddedebilir.
Kısıtlamalar, yönlendirme isteklerinde ve bağlantı oluşturmada kullanılır.

WARNING
Giriş doğrulamasıiçin kısıtlamaları kullanmayın. Giriş doğrulamasıiçin kısıtlamalar kullanılıyorsa, doğru bir hata
iletisine sahip 400-Bad isteği yerine 404- olmayan bir Yanıt ile geçersiz giriş oluşur. Yol kısıtlamaları, belirli bir rota için
girdileri doğrulamak üzere değil, benzer yolların belirsizliğini ortadan kaldırmak için kullanılır.

Aşağıdaki tabloda örnek yol kısıtlamaları ve bunların beklenen davranışları gösterilmektedir.

KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

int {id:int} 123456789 , -123456789 Herhangi bir tamsayıyla


eşleşir

bool {active:bool} true , FALSE true veya false eşleşir


(büyük/küçük harfe
duyarsız)

datetime {dob:datetime} 2016-12-31 , Geçerli bir DateTime


2016-12-31 7:32pm değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

decimal {price:decimal} 49.99 , -1,000.01 Geçerli bir decimal


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

double {weight:double} 1.234 , -1,001.01e8 Geçerli bir double


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

float {weight:float} 1.234 , -1,001.01e8 Geçerli bir float


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

guid {id:guid} CD2C1638-1638-72D5- Geçerli bir Guid değeriyle


1638-DEADBEEF1638 eşleşir
,
{CD2C1638-1638-72D5-
1638-DEADBEEF1638}
KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

long {ticks:long} 123456789 , -123456789 Geçerli bir long değeriyle


eşleşir

minlength(value) {username:minlength(4)} Rick Dize en az 4 karakter


olmalıdır

maxlength(value) {filename:maxlength(8)} Richard Dize 8 karakterden uzun


olmamalıdır

length(length) {filename:length(12)} somefile.txt Dize tam olarak 12


karakter uzunluğunda
olmalıdır

length(min,max) {filename:length(8,16)} somefile.txt Dize en az 8 ve en fazla 16


karakter uzunluğunda
olmalıdır

min(value) {age:min(18)} 19 Tamsayı değeri en az 18


olmalıdır

max(value) {age:max(120)} 91 Tamsayı değeri 120 ' ten


fazla olmamalıdır

range(min,max) {age:range(18,120)} 91 Tamsayı değeri en az 18


olmalı ancak 120 ' ten
fazla olmamalıdır

alpha {name:alpha} Rick Dize bir veya daha fazla


alfabetik karakterden
oluşmalıdır ( a - z ,
büyük/küçük harfe
duyarsız)

regex(expression) {ssn:regex(^\\d{{3}}- 123-45-6789 Dize, normal ifadeyle


\\d{{2}}-\\d{{4}}$)} eşleşmelidir (normal ifade
tanımlama hakkında
ipuçlarına bakın)

required {name:required} Rick URL oluşturma sırasında


parametre olmayan bir
değerin mevcut olduğunu
zorlamak için kullanılır

Birden çok, iki nokta üst üste sınırlı kısıtlama tek bir parametreye uygulanabilir. Örneğin, aşağıdaki
kısıtlama bir parametreyi 1 veya daha büyük bir tamsayı değeriyle kısıtlar:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
WARNING
URL 'YI doğrulayan ve bir CLR türüne ( int veya DateTime ) dönüştürülen yol kısıtlamaları her zaman sabit kültürü
kullanır. Bu kısıtlamalar, URL 'nin yerelleştirilemeyen olduğunu varsayar. Framework tarafından sunulan yol
kısıtlamaları, yol değerlerinde depolanan değerleri değiştirmez. URL 'den Ayrıştırılan tüm rota değerleri dizeler olarak
depolanır. Örneğin, float kısıtlaması yol değerini bir float öğesine dönüştürmeye çalışır, ancak dönüştürülen değer
yalnızca bir float öğesine dönüştürülebileceğini doğrulamak için kullanılır.

Normal ifadeler
ASP.NET Core Framework, normal ifade oluşturucusuna
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ekler. Bu üyelerin
açıklaması için bkz. RegexOptions.
Normal ifadeler, C# yönlendirme ve dil tarafından kullanılanlarla aynı sınırlayıcıları ve belirteçleri kullanır.
Normal ifade belirteçlerinin atlanmalıdır. ^\d{3}-\d{2}-\d{4}$ normal ifade ' i yönlendirmede kullanmak
için, ifadede, C# kaynak \ dosyadaki \\ (çift ters eğik çizgi) karakter olarak belirtilen \ (tek ters eğik
çizgi) karakterlere sahip olması gerekir. karakter (tam dize sabit değerlerikullanmadıkça). Yönlendirme
parametresi sınırlayıcı karakterlerini ( { , } , [ , ] ) atlamak için, ifadedeki karakterleri çift ( {{ , } , [[ ,
]] ). Aşağıdaki tabloda, bir normal ifade ve kaçan sürümü gösterilmektedir.

NORMAL IFADE KAÇAN NORMAL IFADE

^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$

^[a-z]{2}$ ^[[a-z]]{{2}}$

Yönlendirmelerde kullanılan normal ifadeler, genellikle şapka işareti ( ^ ) karakteriyle başlar ve dizenin
başlangıç konumuyla eşleşir. İfadeler genellikle dolar işareti ( $ ) karakteriyle biter ve dizenin sonuyla
eşleşir. ^ ve $ karakterler, normal ifadenin tüm yol parametresi değeri ile eşleştiğinden emin olun. ^ ve
$ karakterleri olmadan normal ifade, dize içindeki herhangi bir alt dizeden eşleşir ve bu genellikle
istenmeyen bir ifadedir. Aşağıdaki tabloda örnekler verilmektedir ve bunların eşleşmesinin neden
eşleşmediği veya eşleşmemesi açıklanmaktadır.

İFADE DIZE EŞLEŞTIRME YORUM

[a-z]{2} herkese Evet Alt dize eşleşmeleri

[a-z]{2} 123abc456 Evet Alt dize eşleşmeleri

[a-z]{2} MZ Evet Eşleşen ifadesi

[a-z]{2} MZ Evet Büyük/küçük harfe duyarlı


değil

^[a-z]{2}$ herkese Hayır Yukarıdaki ^ ve $ bakın

^[a-z]{2}$ 123abc456 Hayır Yukarıdaki ^ ve $ bakın

Normal ifade sözdizimi hakkında daha fazla bilgi için bkz. .NET Framework normal ifadeler.
Bir parametreyi bilinen olası değerler kümesiyle kısıtlamak için, normal bir ifade kullanın. Örneğin
{action:regex(^(list|get|create)$)} , yalnızca Route değeri list , get veya create ile eşleşir.
action
Kısıtlama sözlüğüne geçirilirse dize ^(list|get|create)$ eşdeğerdir. Bilinen kısıtlamalardan biriyle
eşleşmeyen kısıtlama sözlüğüne (bir şablon içinde satır içi değil) geçirilen kısıtlamalar da normal ifadeler
olarak kabul edilir.

Özel yol kısıtlamaları


Yerleşik yol kısıtlamalarına ek olarak, IRouteConstraint arabirimi uygulayarak özel yol kısıtlamaları
oluşturulabilir. IRouteConstraint arabirimi, kısıtlama karşılandıysanız true döndüren Match tek bir yöntem
içerir ve aksi takdirde false .
Özel bir IRouteConstraintkullanmak için, yol kısıtlama türü uygulamanın hizmet kapsayıcısında
uygulamanın ConstraintMap kayıtlı olmalıdır. ConstraintMap, yol kısıtlama anahtarlarını bu kısıtlamaları
doğrulayan IRouteConstraint uygulamalarla eşleyen bir sözlüktür. Bir uygulamanın ConstraintMap, bir
hizmetin parçası olarak Startup.ConfigureServices güncelleştirilebilen olabilir . AddRouting çağrısı veya
RouteOptions doğrudan services.Configure<RouteOptions> ile yapılandırma. Örneğin:

services.AddRouting(options =>
{
options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Kısıtlama daha sonra, kısıtlama türü kaydedilirken belirtilen ad kullanılarak yollara her zamanki şekilde
uygulanabilir. Örneğin:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

Parametre transformatörü başvurusu


Parametre dönüştürücüler:
Routeiçin bağlantı oluştururken yürütün.
Microsoft.AspNetCore.Routing.IOutboundParameterTransformer uygulayın.
ConstraintMapkullanılarak yapılandırılır.
Parametrenin yol değerini alın ve yeni bir dize değerine dönüştürün.
Oluşturulan bağlantıda Dönüştürülmüş değerin kullanılmasına neden olacak.
Örneğin, Url.Action(new { article = "MyTestArticle" }) ile blog\{article:slugify} yol düzeninde özel
slugify parametresi transformatörü blog\my-test-article üretir.
Bir parametre transformatörü bir yol düzeninde kullanmak için, önce Startup.ConfigureServices
ConstraintMap kullanarak yapılandırın:

services.AddRouting(options =>
{
// Replace the type and the name used to refer to it with your own
// IOutboundParameterTransformer implementation
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

Parametre dönüştürücüler, bir uç noktanın çözümlediği URI 'yi dönüştürmek için çerçevesi tarafından
kullanılır. Örneğin, ASP.NET Core MVC, area , controller , action ve page eşleşecek şekilde kullanılan
rota değerini dönüştürmek için parametre dönüştürücüler kullanır.
routes.MapRoute(
name: "default",
template: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");

Önceki yol ile eylem SubscriptionManagementController.GetAll() , URI /subscription-management/get-all ile


eşleştirilir. Bir parametre transformatörü bir bağlantı oluşturmak için kullanılan rota değerlerini değiştirmez.
Örneğin, Url.Action("GetAll", "SubscriptionManagement") çıkışları /subscription-management/get-all .
ASP.NET Core, oluşturulan yollarla bir parametre dönüştürücüler kullanmak için API kuralları sağlar:
ASP.NET Core MVC 'nin Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention
API kuralı vardır. Bu kural, uygulamadaki tüm öznitelik yollarına belirtilen bir parametre transformatörü
uygular. Parametre transformatörü, öznitelik yol belirteçlerini değiştirildiklerinde dönüştürür. Daha fazla
bilgi için bkz. belirteç değişimini özelleştirmek için bir parametre transformatörü kullanma.
Razor Pages Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API kuralına
sahiptir. Bu kural, belirtilen bir parametre transformatörü otomatik olarak keşfedilen Razor Pages
uygular. Parametre transformatörü Razor Pages yolların klasör ve dosya adı segmentlerini dönüştürür.
Daha fazla bilgi için bkz. sayfa yollarını özelleştirmek için bir parametre transformatörü kullanma.

URL oluşturma başvurusu


Aşağıdaki örnek, yol değerlerinin bir sözlüğü ve bir RouteCollectioniçin bir yol bağlantısının nasıl
oluşturulacağını gösterir.

app.Run(async (context) =>


{
var dictionary = new RouteValueDictionary
{
{ "operation", "create" },
{ "id", 123}
};

var vpc = new VirtualPathContext(context, null, dictionary,


"Track Package Route");
var path = routes.GetVirtualPath(vpc).VirtualPath;

context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Menu<hr/>");
await context.Response.WriteAsync(
$"<a href='{path}'>Create Package 123</a><br/>");
});

Yukarıdaki örnek sonunda oluşturulan VirtualPath /package/create/123 . Sözlük, "paket yolunu Izle"
şablonunun package/{operation}/{id}``operation ve id yol değerlerini sağlar. Ayrıntılar için, yönlendirme
ara yazılımı kullanma bölümünde veya örnek uygulamadaörnek koda bakın.
VirtualPathContext oluşturucusunun ikinci parametresi bir ortam değerlerikoleksiyonudur. Ortam
değerleri, bir geliştiricinin bir istek bağlamı içinde belirtmesi gereken değer sayısını sınırlandırdığından
kullanım için uygundur. Geçerli isteğin geçerli yol değerleri, bağlantı oluşturma için çevresel değerler olarak
kabul edilir. ASP.NET Core MVC uygulamasının HomeController``About eyleminde,—ortam değeri Home
Index eyleme bağlamak için denetleyici yolu değerini belirtmeniz gerekmez.

Bir parametreyle eşleşmeyen çevresel değerler yok sayılır. Ayrıca, açıkça sağlanmış bir değer çevresel
değeri geçersiz kıldığında çevresel değerler de yoksayılır. Eşleştirme, URL 'de soldan sağa doğru gerçekleşir.
Açık olarak sağlanmış ancak yolun bir segmentiyle eşleşmeyen değerler sorgu dizesine eklenir. Aşağıdaki
tabloda {controller}/{action}/{id?} yol şablonu kullanılırken sonuç gösterilmektedir.
ÇEVRESEL DEĞERLER AÇIK DEĞERLER SONUÇ

denetleyici = "giriş" Action = "hakkında" /Home/About

denetleyici = "giriş" denetleyici = "Order", Action = /Order/About


"hakkında"

denetleyici = "giriş", renk = "kırmızı" Action = "hakkında" /Home/About

denetleyici = "giriş" Action = "hakkında", color = "Red" /Home/About?color=Red

Bir rotada bir parametreye karşılık gelen bir varsayılan değer varsa ve bu değer açıkça sağlanmışsa,
varsayılan değerle eşleşmelidir:

routes.MapRoute("blog_route", "blog/{*slug}",
defaults: new { controller = "Blog", action = "ReadPost" });

Bağlantı oluşturma yalnızca controller ve action için eşleşen değerler sağlandığında bu yol için bir
bağlantı oluşturur.

Karmaşık segmentler
Karmaşık segmentler (örneğin [Route("/x{token}y")] ), sabit değerli olmayan değişmez değerler ile sağdan
sola eşleştirilirken işlenir. Karmaşık segmentlerin nasıl eşleştirileceği hakkında ayrıntılı bir açıklama için bu
koda bakın. Kod örneği ASP.NET Core tarafından kullanılmaz, ancak karmaşık segmentler hakkında iyi bir
açıklama sağlar.
Yönlendirme, istek URI 'Lerini rota işleyicileriyle eşleştirmekten ve gelen istekleri gönderen sorumludur.
Yollar uygulamada tanımlanır ve uygulama başlatıldığında yapılandırılır. Yol, isteğe bağlı olarak istekte
bulunan URL 'den değerleri ayıklayabilir ve bu değerler, istek işleme için kullanılabilir. Uygulamadan
yapılandırılan yollar kullanıldığında, yönlendirme, yol işleyicileriyle eşlenen URL 'Ler oluşturabilir.
ASP.NET Core 2,1 ' de en son yönlendirme senaryolarını kullanmak için Startup.ConfigureServices MVC
Hizmetleri kaydının Uyumluluk sürümünü belirtin:

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

IMPORTANT
Bu belge, alt düzey ASP.NET Core yönlendirmeyi içerir. ASP.NET Core MVC yönlendirme hakkında daha fazla bilgi için
bkz. ASP.NET Core denetleyici eylemlerine yönlendirme. Razor Pages 'de yönlendirme kuralları hakkında bilgi için bkz.
ASP.NET Core Razor Pages yol ve uygulama kuralları.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Yönlendirme temelleri
Çoğu uygulama, URL 'Lerin okunabilir ve anlamlı olması için temel ve açıklayıcı bir yönlendirme şeması
seçmelidir. Varsayılan geleneksel yol {controller=Home}/{action=Index}/{id?} :
Temel ve açıklayıcı bir yönlendirme düzenini destekler.
, UI tabanlı uygulamalar için kullanışlı bir başlangıç noktasıdır.
Geliştiriciler, öznitelik yönlendirme veya adanmış geleneksel yollar kullanarak özel durumlarda (örneğin,
blog ve e-ticaret uç noktaları) bir uygulamanın yüksek trafik bölümlerine daha fazla terse yolu ekler.
Web API 'Leri, uygulamanın işlevselliğini HTTP fiilleri tarafından temsil edilen bir kaynak kümesi olarak
modellemek için öznitelik yönlendirmeyi kullanmalıdır. Bu, aynı mantıksal kaynaktaki birçok işlemin
(örneğin, GET, POST) aynı URL 'YI kullanacağı anlamına gelir. Öznitelik yönlendirme, bir API 'nin Genel uç
nokta yerleşimini dikkatle tasarlamak için gereken bir denetim düzeyi sağlar.
Razor Pages uygulamalar, bir uygulamanın Sayfalar klasöründe adlandırılmış kaynaklara hizmeti sağlamak
için varsayılan geleneksel yönlendirmeyi kullanır. Razor Pages yönlendirme davranışını özelleştirmenizi
sağlayan ek kurallar mevcuttur. Daha fazla bilgi için bkz. ASP.NET Core Razor Pages giriş ve ASP.NET Core
Razor Pages yol ve uygulama kuralları.
URL oluşturma desteği, uygulamanın, uygulamayı birbirine bağlamak için sabit kodlama URL 'Leri
olmadan geliştirilebilmesine izin verir. Bu destek, temel bir yönlendirme yapılandırmasıyla başlayıp
uygulamanın kaynak düzeni belirlendikten sonra yolların değiştirilmesini sağlar.
Yönlendirme, yolları kullanır (IRouteruygulamalar):
Gelen istekleri Rota işleyicilerineeşleyin.
Yanıtlarda kullanılan URL 'Leri oluşturun.
Varsayılan olarak, bir uygulama tek bir yollar koleksiyonuna sahiptir. Bir istek geldiğinde koleksiyondaki
yollar, koleksiyonda var olan sırada işlenir. Çerçeve, koleksiyondaki her bir rotada RouteAsync yöntemini
çağırarak, gelen istek URL 'sini koleksiyondaki bir yola eşleştirmeye çalışır. Yanıt, yönlendirme bilgilerine
göre URL (örneğin, yeniden yönlendirme veya bağlantılar için) oluşturmak için yönlendirmeyi kullanabilir
ve bu sayede bakım yapılmasına yardımcı olan sabit kodlanmış URL 'Lerden kaçınabilirsiniz.
Yönlendirme sistemi aşağıdaki özelliklere sahiptir:
Yol şablonu sözdizimi, simgeleştirilmiş yol parametrelerine sahip yolları tanımlamak için kullanılır.
Geleneksel stil ve öznitelik stili uç nokta yapılandırmasına izin verilir.
IRouteConstraint, bir URL parametresinin belirli bir uç nokta kısıtlaması için geçerli bir değer içerip
içermediğini belirlemekte kullanılır.
MVC/Razor Pages gibi uygulama modelleri, yönlendirme senaryolarının öngörülebilir bir uygulaması
olan tüm yollarını kaydeder.
Yanıt, yönlendirme bilgilerine göre URL (örneğin, yeniden yönlendirme veya bağlantılar için)
oluşturmak için yönlendirmeyi kullanabilir ve bu sayede bakım yapılmasına yardımcı olan sabit
kodlanmış URL 'Lerden kaçınabilirsiniz.
URL oluşturma, rastgele genişletilebilirliği destekleyen yollara dayalıdır. IUrlHelper, URL 'Leri derlemek
için yöntemler sunar.
Yönlendirme, RouterMiddleware sınıfı tarafından, Ara yazılım ardışık düzenine bağlıdır. ASP.NET Core
MVC , yapılandırma kapsamında bir ara yazılım ardışık düzenine yönlendirme ekler ve MVC ve Razor
Pages uygulamalarında yönlendirmeyi işler. Tek başına bileşen olarak yönlendirmeyi nasıl kullanacağınızı
öğrenmek için yönlendirme ara yazılımı kullanma bölümüne bakın.
URL eşleştirme
URL eşleştirme, yönlendirmenin bir işleyiciyegelen istek gönderdiğine yönelik işlemdir. Bu işlem, URL
yolundaki verileri temel alır, ancak istekteki verileri göz önünde bulundurmanız için genişletilebilir. Ayrı
işleyicilere istek gönderme özelliği, bir uygulamanın boyutunu ve karmaşıklığını ölçeklendirmeye yönelik
anahtardır.
Gelen istekler, sırayla her bir rotada RouteAsync yöntemini çağıran RouterMiddlewaregirer. IRouter örneği,
Routecontext. Handler değerini null olmayan bir RequestDelegateayarlayarak isteğin işleneceğini belirler.
Bir yol istek için bir işleyici ayarlarsa, yol işleme duraklar ve işleyici isteği işlemek için çağrılır. İsteği işlemek
için yol işleyicisi bulunmazsa, ara yazılım istek ardışık düzeninde sonraki bir ara yazılım için isteği kapatır.
RouteAsync birincil giriş, geçerli istekle ilişkili Routecontext. HttpContext ' dir. Routecontext. Handler ve
Routecontext. RouteData , bir yol eşleştirdikten sonra çıkış olarak ayarlanır.
RouteAsync çağıran bir eşleşme de Routecontext. RouteData özelliklerinin özelliklerini, bu nedenle yapılan
istek işlemeye bağlı olarak uygun değerlere ayarlar.
RouteData. Values , rotada oluşturulan yol değerlerinin bir sözlüğüdür. Bu değerler genellikle URL 'YI
simgeleştirerek belirlenir ve Kullanıcı girişini kabul etmek ya da uygulama içinde daha fazla kararlar almak
için kullanılabilir.
RouteData. DataTokens , eşleşen rotayla ilgili ek verilerin bir özellik çantadır. DataTokens, uygulamanın
hangi yolun eşleştiğini temel alarak kararlar verebilmesi için durum verilerinin her bir rota ile
ilişkilendirilmesini desteklemek amacıyla sağlanır. Bu değerler, geliştirici tarafından tanımlanır ve
yönlendirme davranışını herhangi bir şekilde etkilemez. Ayrıca, RouteData. DataTokens içinde bulunan
değerler her türlü türden olabilir. Bu, veridizeleri arasında dönüştürülebilir olmalıdır.
RouteData. yönlendiriciler , isteği başarıyla eşleştirirken geçen yolların bir listesidir. Yollar bir diğerinin
içinde iç içe olabilir. Routers özelliği, bir eşleşme ile sonuçlanan yolların mantıksal ağacı aracılığıyla yolu
yansıtır. Genellikle, Routers ilk öğe yol koleksiyonudur ve URL oluşturma için kullanılmalıdır. Routers son
öğe, eşleşen yol işleyicisidir.
URL oluşturma
URL oluşturma, yönlendirmenin bir yol değerleri kümesine göre bir URL yolu oluşturabileceği işlemdir. Bu,
yönlendirme işleyicileri ve bunlara erişen URL 'Ler arasındaki mantıksal bir ayrım sağlar.
URL oluşturma benzer bir yinelemeli işlem izler, ancak yol koleksiyonunun GetVirtualPath metoduna
çağıran kullanıcı veya çerçeve kodu ile başlar. Her rotada null olmayan bir VirtualPathData döndürülene
kadar GetVirtualPath yöntemi sırayla çağırılır.
GetVirtualPath birincil girişleri şunlardır:
VirtualPathContext. HttpContext
VirtualPathContext. Values
VirtualPathContext. AmbientValues
Rotalar öncelikle Values ve AmbientValues tarafından sunulan yol değerlerini kullanarak bir URL oluşturma
ve hangi değerlerin dahil edileceğini belirleyin. AmbientValues, geçerli istekle eşleşmeden üretilmiş olan
rota değerleri kümesidir. Buna karşılık Values, geçerli işlem için istenen URL 'nin nasıl oluşturulacağını
belirten rota değerlerdir. HttpContext, bir yolun geçerli bağlamla ilişkili hizmetleri veya ek verileri alması
durumunda sağlanır.

TIP
Virtualpathcontext . Values öğesini Virtualpathcontext. AmbientValuesiçin bir geçersiz kılma kümesi olarak düşünün.
URL oluşturma, aynı rota veya yol değerlerini kullanan bağlantılar için URL 'Ler oluşturmak üzere geçerli istekten yol
değerlerini yeniden kullanmayı dener.

GetVirtualPath çıkışı bir VirtualPathData. VirtualPathData, RouteDataparaleldir. VirtualPathData, çıkış URL


'SI için VirtualPath ve yol tarafından ayarlanması gereken bazı ek özellikleri içerir.
VirtualPathData. VirtualPath özelliği, yol tarafından üretilen sanal yolu içerir. Gereksinimlerinize bağlı
olarak, yolu daha fazla işlem yapmanız gerekebilir. Oluşturulan URL 'YI HTML 'de işlemek istiyorsanız,
uygulamanın temel yolunu ekleyin.
VirtualPathData. Router , URL 'yi başarıyla oluşturmuş olan yola bir başvurudur.
VirtualPathData. DataTokens özellikleri, URL 'yi oluşturan rotayla ilgili ek verilerin bir sözlüğüdür. Bu,
RouteData. Datatoken'ların paraleldir.
Rotalar oluştur
Yönlendirme, IRouterstandart uygulama olarak Route sınıfını sağlar. Route, RouteAsync çağrıldığında URL
yoluyla eşleştirilecek desenleri tanımlamak için yol şablonu sözdizimini kullanır. Route, GetVirtualPath
çağrıldığında bir URL oluşturmak için aynı yol şablonunu kullanır.
Çoğu uygulama, IRouteBuildertanımlanan benzer uzantı yöntemlerinden birini veya MapRoute çağırarak
yollar oluşturur. IRouteBuilder uzantısı yöntemlerinden herhangi biri bir Route örneği oluşturur ve bunu yol
koleksiyonuna ekler.
MapRoute yol işleyicisi parametresini kabul etmez. MapRoute, yalnızca DefaultHandlertarafından işlenen
rotaları ekler. Varsayılan işleyici bir IRouter ve işleyici isteği işleyemeyebilir. Örneğin, ASP.NET Core MVC
genellikle yalnızca kullanılabilir bir denetleyici ve eylemle eşleşen istekleri işleyen varsayılan bir işleyici
olarak yapılandırılır. MVC 'de yönlendirme hakkında daha fazla bilgi için bkz. ASP.NET Core denetleyici
eylemlerine yönlendirme.
Aşağıdaki kod örneği, tipik bir ASP.NET Core MVC yol tanımı tarafından kullanılan MapRoute çağrısının
bir örneğidir:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Bu şablon bir URL yoluyla eşleşir ve yol değerlerini ayıklar. Örneğin, yol /Products/Details/17 şu yol
değerlerini üretir: { controller = Products, action = Details, id = 17 } .
Rota değerleri, URL yolunun kesimlere bölünüyor ve rota şablonundaki yol parametresi adı ile her bir
segmenti eşleştirerek belirlenir. Yol parametreleri olarak adlandırılır. Küme ayraçları içinde parametre adı
eklenerek tanımlanan parametreler { ... } .
Yukarıdaki şablon, URL yolu / de eşleştirebilir ve { controller = Home, action = Index } değerler
üretecektir. Bu, {controller} ve {action} yol parametrelerinin varsayılan değerleri olduğu ve id Route
parametresinin isteğe bağlı olduğu için oluşur. Eşittir işareti ( = ), yol parametresi adı parametre için
varsayılan bir değer tanımladıktan sonra bir değer izler. Yol parametre adından sonra bir soru işareti ( ? )
isteğe bağlı bir parametre tanımlar.
Yol parametreleri varsayılan değer ile her zaman rota değeri oluşturur. Karşılık gelen bir URL yol kesimi
yoksa isteğe bağlı parametreler yol değeri oluşturmaz. Yol şablonu senaryolarının ve sözdiziminin kapsamlı
bir açıklaması için yol şablonu başvurusu bölümüne bakın.
Aşağıdaki örnekte, yol parametresi tanımı {id:int} id Route parametresi için bir yol kısıtlaması
tanımlıyor:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id:int}");

Bu şablon /Products/Details/17 gibi bir URL yoluyla eşleşir ancak /Products/Details/Apples . Yol
kısıtlamaları IRouteConstraint uygular ve yol değerlerini inceleyerek onları doğrular. Bu örnekte, yol değeri
id bir tamsayıya dönüştürülebilir olmalıdır. Framework tarafından sunulan yol kısıtlamalarının açıklaması
için bkz. route-Constraint-Reference .
MapRoute ek aşırı yüklemeleri constraints , dataTokens ve defaults için değer kabul eder. Bu
parametrelerin tipik kullanımı, anonim türdeki özellik adlarının yol parametre adlarıyla eşleşen anonim
olarak yazılmış bir nesneyi geçirmektir.
Aşağıdaki MapRoute örnekleri eşdeğer yollar oluşturur:

routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
name: "default_route",
template: "{controller=Home}/{action=Index}/{id?}");

TIP
Kısıtlamaları ve Varsayılanları tanımlamaya yönelik satır içi sözdizimi basit yollar için kullanışlı olabilir. Ancak, satır içi
sözdizimi tarafından desteklenmeyen veri belirteçleri gibi senaryolar vardır.

Aşağıdaki örnek birkaç ek senaryoyu göstermektedir:

routes.MapRoute(
name: "blog",
template: "Blog/{*article}",
defaults: new { controller = "Blog", action = "ReadArticle" });

Önceki şablon /Blog/All-About-Routing/Introduction gibi bir URL yoluyla eşleşir ve


{ controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction } değerleri ayıklar.
controller ve action için varsayılan yol değerleri, şablonda karşılık gelen hiçbir yol parametresi olmasa
bile yol tarafından üretilir. Varsayılan değerler yol şablonunda belirtilebilir. article Route parametresi, yol
parametre adından önce bir yıldız işareti ( * ) görünümüne göre catch-all olarak tanımlanır. Catch-all yol
parametreleri, URL yolunun kalanını yakalar ve boş dizeyle de aynı olabilir.
Aşağıdaki örnek yol kısıtlamalarını ve veri belirteçlerini ekler:

routes.MapRoute(
name: "us_english_products",
template: "en-US/Products/{id}",
defaults: new { controller = "Products", action = "Details" },
constraints: new { id = new IntRouteConstraint() },
dataTokens: new { locale = "en-US" });

Önceki şablon /en-US/Products/5 gibi bir URL yoluyla eşleşir ve


{ controller = Products, action = Details, id = 5 } ve veri belirteçleri { locale = en-US } değerleri
ayıklar.
Yol sınıfı URL 'SI oluşturma
Route sınıfı, yol değerlerini bir kümesini rota şablonuyla birleştirerek URL oluşturmayı da gerçekleştirebilir.
Bu, URL yolunu eşleştirmenin mantıksal bir işlemdir.

TIP
URL oluşturmayı daha iyi anlamak için, oluşturmak istediğiniz URL 'YI düşünün ve sonra bir yönlendirme şablonunun
bu URL ile nasıl eşleşeceğini düşünün. Hangi değerler üretilemidir? Bu, URL oluşturma 'nın Route sınıfında nasıl
çalıştığına ilişkin kaba bir eştir.

Aşağıdaki örnek genel ASP.NET Core MVC varsayılan yolunu kullanır:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

Yol değerleri { controller = Products, action = List } , /Products/List URL 'SI oluşturulur. Yol değerleri,
URL yolunu biçimlendirmek için karşılık gelen yol parametrelerinin yerine kullanılır. id , isteğe bağlı bir yol
parametresi olduğundan, id için bir değer olmadan URL başarıyla oluşturulur.
Yol değerleri { controller = Home, action = Index } , / URL 'SI oluşturulur. Belirtilen yol değerleri
varsayılan değerlerle eşleşir ve varsayılan değerlere karşılık gelen segmentler güvenle atlanır.
Her iki URL de aşağıdaki yol tanımıyla ( /Home/Index ve / ) bir gidiş dönüş, URL oluşturmak için kullanılan
rota değerlerini oluşturur.

NOTE
ASP.NET Core MVC kullanan bir uygulama doğrudan yönlendirmeye çağırmak yerine URL oluşturmak için UrlHelper
kullanmalıdır.

URL oluşturma hakkında daha fazla bilgi için URL oluşturma başvurusu bölümüne bakın.

Yönlendirme ara yazılımı kullanma


Uygulamanın proje dosyasındaki Microsoft. AspNetCore. app metapackage öğesine başvurun.
Startup.ConfigureServices ' de hizmet kapsayıcısına yönlendirme ekleyin:
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}

Yolların Startup.Configure yönteminde yapılandırılması gerekir. Örnek uygulama aşağıdaki API 'Leri
kullanır:
RouteBuilder
MapGet – yalnızca HTTP GET istekleriyle eşleşir.
UseRouter

var trackPackageRouteHandler = new RouteHandler(context =>


{
var routeValues = context.GetRouteData().Values;
return context.Response.WriteAsync(
$"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
"Track Package Route",
"package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>


{
var name = context.GetRouteValue("name");
// The route handler when HTTP GET "hello/<anything>" matches
// To match HTTP GET "hello/<anything>/<anything>,
// use routeBuilder.MapGet("hello/{*name}"
return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();


app.UseRouter(routes);

Aşağıdaki tabloda verilen URI 'Ler ile ilgili yanıtlar gösterilmektedir.

URI YANITIYLA

/package/create/3 Herkese! Rota değerleri: [işlem, oluşturma], [kimlik, 3]

/package/track/-3 Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/-3/ Herkese! Rota değerleri: [işlem, izleme], [kimlik,-3]

/package/track/ İstek, eşleşme olmadan üzerinden yapılır.

GET /hello/Joe Merhaba, ali!

POST /hello/Joe İstek üzerinden geçer, yalnızca HTTP GET ile eşleşir.

GET /hello/Joe/Smith İstek, eşleşme olmadan üzerinden yapılır.

Tek bir yol yapılandırıyorsanız, bir IRouter örneğinde geçen UseRouter çağırın. RouteBuilderkullanmanız
gerekmez.
Çerçeve, yollar oluşturmak için bir genişletme yöntemleri kümesi sağlar
(RequestDelegateRouteBuilderExtensions):
MapDelete
MapGet
MapMiddlewareDelete
MapMiddlewareGet
MapMiddlewarePost
MapMiddlewarePut
MapMiddlewareRoute
MapMiddlewareVerb
MapPost
MapPut
MapRoute
MapVerb
MapGetgibi listelenen yöntemlerin bazıları RequestDelegategerektirir. Yol eşleştiğinde yol işleyicisi olarak
RequestDelegate kullanılır. Bu ailedeki diğer yöntemler, yönlendirme işleyicisi olarak kullanılmak üzere bir
ara yazılım ardışık düzeni yapılandırmaya olanak tanır. Map* yöntemi MapRoutegibi bir işleyiciyi kabul
etmez DefaultHandlerkullanır.
Map[Verb] yöntemleri, yöntem adındaki HTTP fiili ile rotayı sınırlandırmak için kısıtlamaları kullanır.
Örneğin, bkz. MapGet ve MapVerb.

Rota şablonu başvurusu


Küme ayraçları içindeki belirteçler ( { ... } ), yol eşleştirildiği takdirde bağlanan Rota parametrelerini
tanımlar. Bir yol segmentinde birden fazla yol parametresi tanımlayabilirsiniz, ancak bunların bir değişmez
değer ile ayrılması gerekir. Örneğin, {controller} ve {action} arasında değişmez değer olmadığından
{controller=Home}{action=Index} geçerli bir yol değil. Bu rota parametrelerinin bir adı olmalı ve ek
öznitelikler belirtilmiş olabilir.
Yol parametreleri dışında (örneğin, {id} ) ve yol ayırıcı / URL içindeki metinle eşleşmesi gerekir. Metin
eşleştirme, büyük/küçük harfe duyarsızdır ve URL yolunun kodu çözülmüş gösterimine göre yapılır.
Değişmez değer yol parametresi sınırlayıcısından ( { veya } ) eşleştirmek için, karakteri ( {{ veya }} )
tekrarlayarak sınırlayıcıdan kaçış.
İsteğe bağlı bir dosya uzantısına sahip bir dosya adı yakalamaya deneyen URL desenlerinin ek konuları
vardır. Örneğin, files/{filename}.{ext?} şablonu düşünün. filename ve ext değerlerinin her ikisi de
varsa, her iki değer de doldurulur. URL 'de yalnızca filename için bir değer varsa, bitiş dönemi ( . ) isteğe
bağlı olduğundan yol eşleşir. Aşağıdaki URL 'Ler bu rota ile eşleşiyor:
/files/myFile.txt
/files/myFile

Yıldız işaretini ( * ) URI 'nin geri kalanına bağlamak için bir yol parametresinin öneki olarak
kullanabilirsiniz. Buna catch-all parametresi denir. Örneğin, blog/{*slug} /blog ile başlayan ve ondan
sonraki bir değere sahip olan slug yol değerine atanan tüm URI ile eşleşir. Catch-all parametreleri boş
dizeyle de aynı olabilir.
Yol ayırıcısı ( / ) karakterleri de dahil olmak üzere bir URL oluşturmak için bir yol kullanıldığında, catch-all
parametresi uygun karakterleri çıkar. Örneğin yol foo/{*path} rota değerleriyle { path = "my/path" }
foo/my%2Fpath üretir. Atlanan eğik çizgiye göz önünde edin.
Yol parametrelerinin, parametre adından sonra varsayılan değer belirtilerek bir eşittir işareti ( = ) ile
ayrıldıktan sonra belirlenen varsayılan değerleri olabilir. Örneğin, Home controller için varsayılan değer
olarak {controller=Home} tanımlar. Parametresi için URL 'de hiçbir değer yoksa varsayılan değer kullanılır.
Yol parametreleri, id? gibi parametre adının sonuna bir soru işareti ( ? ) eklenerek isteğe bağlı olarak
yapılır. İsteğe bağlı değerler ve varsayılan yol parametreleri arasındaki fark, varsayılan değere sahip bir yol
parametresinin her zaman bir değer ürettiğinden—isteğe bağlı bir parametre yalnızca istek URL 'SI
tarafından bir değer sağlandığında bir değere sahip olur.
Rota parametrelerinin URL 'den bağlanan rota değeriyle eşleşmesi gereken kısıtlamaları olabilir. Yol
parametre adından sonra bir iki nokta üst üste ( : ) ve kısıtlama adının eklenmesi, bir yol parametresi
üzerinde bir satır içi kısıtlamayı belirtir. Kısıtlama bağımsız değişkenler gerektiriyorsa, kısıtlama adından
sonra parantez ( (...) ) içine alınır. Birden çok satır içi kısıtlama, başka bir iki nokta ( : ) ve kısıtlama adı
eklenerek belirtilebilir.
Kısıtlama adı ve bağımsız değişkenler, URL işlemede kullanılacak bir IRouteConstraint örneği oluşturmak
için IInlineConstraintResolver hizmetine geçirilir. Örneğin, yol şablonu blog/{article:minlength(10)} , 10
bağımsız değişkeniyle bir minlength kısıtlaması belirtir. Yol kısıtlamaları ve Framework tarafından sunulan
kısıtlamaların bir listesi hakkında daha fazla bilgi için, route kısıtlama başvurusu bölümüne bakın.
Aşağıdaki tabloda örnek yol şablonları ve bunların davranışları gösterilmektedir.

ROTA ŞABLONU ÖRNEK EŞLEŞEN URI İSTEK URI 'SI…

hello /hello Yalnızca /hello tek yol ile eşleşir.

{Page=Home} / Home``Page eşleşir ve ayarlar.

{Page=Home} /Contact Contact``Page eşleşir ve ayarlar.

{controller}/{action}/{id?} /Products/List Products denetleyicisi ve List


eylemiyle eşlenir.

{controller}/{action}/{id?} /Products/Details/123 Products denetleyicisi ve Details


eylemine eşlenir ( id 123 olarak
ayarlanır).

{controller=Home}/{action=Index}/{id?}
/ Home denetleyicisi ve Index
yöntemiyle eşlenir ( id yok sayılır).

Bir şablon kullanmak genellikle yönlendirmeye en basit yaklaşımdır. Kısıtlamalar ve varsayılanlar, yol
şablonu dışında da belirtilebilir.

TIP
Route, istekleri eşleştirme gibi yerleşik yönlendirme uygulamalarının nasıl yapıldığını görmek için günlük kaydını
etkinleştirin.

Ayrılmış yönlendirme adları


Aşağıdaki anahtar sözcükler ayrılmış isimlerdir ve yol adları veya parametreler olarak kullanılamaz:
action
area
controller
handler
page

Yol kısıtlama başvurusu


Yol kısıtlamaları, gelen URL 'de bir eşleşme meydana geldiğinde ve URL yolu yol değerlerinde
simgeleştirilir yürütülür. Rota kısıtlamaları genellikle yol şablonu aracılığıyla ilişkili rota değerini inceler ve
değerin kabul edilebilir olup olmadığı konusunda bir Evet/Hayır kararı getirir. Bazı rota kısıtlamaları, isteğin
yönlendirilip yönlendirilmeyeceğini göz önünde bulundurmanız için yol değeri dışındaki verileri kullanır.
Örneğin HttpMethodRouteConstraint, HTTP fiiline bağlı olarak bir isteği kabul edebilir veya reddedebilir.
Kısıtlamalar, yönlendirme isteklerinde ve bağlantı oluşturmada kullanılır.

WARNING
Giriş doğrulamasıiçin kısıtlamaları kullanmayın. Giriş doğrulamasıiçin kısıtlamalar kullanılıyorsa, doğru bir hata
iletisine sahip 400-Bad isteği yerine 404- olmayan bir Yanıt ile geçersiz giriş oluşur. Yol kısıtlamaları, belirli bir rota için
girdileri doğrulamak üzere değil, benzer yolların belirsizliğini ortadan kaldırmak için kullanılır.

Aşağıdaki tabloda örnek yol kısıtlamaları ve bunların beklenen davranışları gösterilmektedir.

KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

int {id:int} 123456789 , -123456789 Herhangi bir tamsayıyla


eşleşir

bool {active:bool} true , FALSE true veya false eşleşir


(büyük/küçük harfe
duyarsız)

datetime {dob:datetime} 2016-12-31 , Geçerli bir DateTime


2016-12-31 7:32pm değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

decimal {price:decimal} 49.99 , -1,000.01 Geçerli bir decimal


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

double {weight:double} 1.234 , -1,001.01e8 Geçerli bir double


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

float {weight:float} 1.234 , -1,001.01e8 Geçerli bir float


değeriyle eşleşir (Sabit
kültür içinde, bkz. uyarı)

guid {id:guid} CD2C1638-1638-72D5- Geçerli bir Guid değeriyle


1638-DEADBEEF1638
eşleşir
,
{CD2C1638-1638-72D5-
1638-DEADBEEF1638}

long {ticks:long} 123456789 , -123456789 Geçerli bir long değeriyle


eşleşir
KISITLAMA ÖRNEK ÖRNEK EŞLEŞMELER NOTLAR

minlength(value) {username:minlength(4)} Rick Dize en az 4 karakter


olmalıdır

maxlength(value) {filename:maxlength(8)} Richard Dize 8 karakterden uzun


olmamalıdır

length(length) {filename:length(12)} somefile.txt Dize tam olarak 12


karakter uzunluğunda
olmalıdır

length(min,max) {filename:length(8,16)} somefile.txt Dize en az 8 ve en fazla 16


karakter uzunluğunda
olmalıdır

min(value) {age:min(18)} 19 Tamsayı değeri en az 18


olmalıdır

max(value) {age:max(120)} 91 Tamsayı değeri 120 ' ten


fazla olmamalıdır

range(min,max) {age:range(18,120)} 91 Tamsayı değeri en az 18


olmalı ancak 120 ' ten
fazla olmamalıdır

alpha {name:alpha} Rick Dize bir veya daha fazla


alfabetik karakterden
oluşmalıdır ( a - z ,
büyük/küçük harfe
duyarsız)

regex(expression) {ssn:regex(^\\d{{3}}- 123-45-6789 Dize, normal ifadeyle


\\d{{2}}-\\d{{4}}$)} eşleşmelidir (normal ifade
tanımlama hakkında
ipuçlarına bakın)

required {name:required} Rick URL oluşturma sırasında


parametre olmayan bir
değerin mevcut olduğunu
zorlamak için kullanılır

Birden çok, iki nokta üst üste sınırlı kısıtlama tek bir parametreye uygulanabilir. Örneğin, aşağıdaki
kısıtlama bir parametreyi 1 veya daha büyük bir tamsayı değeriyle kısıtlar:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

WARNING
URL 'YI doğrulayan ve bir CLR türüne ( int veya DateTime ) dönüştürülen yol kısıtlamaları her zaman sabit kültürü
kullanır. Bu kısıtlamalar, URL 'nin yerelleştirilemeyen olduğunu varsayar. Framework tarafından sunulan yol
kısıtlamaları, yol değerlerinde depolanan değerleri değiştirmez. URL 'den Ayrıştırılan tüm rota değerleri dizeler olarak
depolanır. Örneğin, float kısıtlaması yol değerini bir float öğesine dönüştürmeye çalışır, ancak dönüştürülen değer
yalnızca bir float öğesine dönüştürülebileceğini doğrulamak için kullanılır.
Normal ifadeler
ASP.NET Core Framework, normal ifade oluşturucusuna
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ekler. Bu üyelerin
açıklaması için bkz. RegexOptions.
Normal ifadeler, C# yönlendirme ve dil tarafından kullanılanlarla aynı sınırlayıcıları ve belirteçleri kullanır.
Normal ifade belirteçlerinin atlanmalıdır. ^\d{3}-\d{2}-\d{4}$ normal ifade ' i yönlendirmede kullanmak
için, ifadede, C# kaynak \ dosyadaki \\ (çift ters eğik çizgi) karakter olarak belirtilen \ (tek ters eğik
çizgi) karakterlere sahip olması gerekir. karakter (tam dize sabit değerlerikullanmadıkça). Yönlendirme
parametresi sınırlayıcı karakterlerini ( { , } , [ , ] ) atlamak için, ifadedeki karakterleri çift ( {{ , } , [[ ,
]] ). Aşağıdaki tabloda, bir normal ifade ve kaçan sürümü gösterilmektedir.

NORMAL IFADE KAÇAN NORMAL IFADE

^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$

^[a-z]{2}$ ^[[a-z]]{{2}}$

Yönlendirmelerde kullanılan normal ifadeler, genellikle şapka işareti ( ^ ) karakteriyle başlar ve dizenin
başlangıç konumuyla eşleşir. İfadeler genellikle dolar işareti ( $ ) karakteriyle biter ve dizenin sonuyla
eşleşir. ^ ve $ karakterler, normal ifadenin tüm yol parametresi değeri ile eşleştiğinden emin olun. ^ ve
$ karakterleri olmadan normal ifade, dize içindeki herhangi bir alt dizeden eşleşir ve bu genellikle
istenmeyen bir ifadedir. Aşağıdaki tabloda örnekler verilmektedir ve bunların eşleşmesinin neden
eşleşmediği veya eşleşmemesi açıklanmaktadır.

İFADE DIZE EŞLEŞTIRME YORUM

[a-z]{2} herkese Evet Alt dize eşleşmeleri

[a-z]{2} 123abc456 Evet Alt dize eşleşmeleri

[a-z]{2} MZ Evet Eşleşen ifadesi

[a-z]{2} MZ Evet Büyük/küçük harfe duyarlı


değil

^[a-z]{2}$ herkese Hayır Yukarıdaki ^ ve $ bakın

^[a-z]{2}$ 123abc456 Hayır Yukarıdaki ^ ve $ bakın

Normal ifade sözdizimi hakkında daha fazla bilgi için bkz. .NET Framework normal ifadeler.
Bir parametreyi bilinen olası değerler kümesiyle kısıtlamak için, normal bir ifade kullanın. Örneğin
{action:regex(^(list|get|create)$)} , yalnızca action Route değeri list , get veya create ile eşleşir.
Kısıtlama sözlüğüne geçirilirse dize ^(list|get|create)$ eşdeğerdir. Bilinen kısıtlamalardan biriyle
eşleşmeyen kısıtlama sözlüğüne (bir şablon içinde satır içi değil) geçirilen kısıtlamalar da normal ifadeler
olarak kabul edilir.

Özel yol kısıtlamaları


Yerleşik yol kısıtlamalarına ek olarak, IRouteConstraint arabirimi uygulayarak özel yol kısıtlamaları
oluşturulabilir. IRouteConstraint arabirimi, kısıtlama karşılandıysanız true döndüren Match tek bir yöntem
içerir ve aksi takdirde false .
Özel bir IRouteConstraintkullanmak için, yol kısıtlama türü uygulamanın hizmet kapsayıcısında
uygulamanın ConstraintMap kayıtlı olmalıdır. ConstraintMap, yol kısıtlama anahtarlarını bu kısıtlamaları
doğrulayan IRouteConstraint uygulamalarla eşleyen bir sözlüktür. Bir uygulamanın ConstraintMap, bir
hizmetin parçası olarak Startup.ConfigureServices güncelleştirilebilen olabilir . AddRouting çağrısı veya
RouteOptions doğrudan services.Configure<RouteOptions> ile yapılandırma. Örneğin:

services.AddRouting(options =>
{
options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Kısıtlama daha sonra, kısıtlama türü kaydedilirken belirtilen ad kullanılarak yollara her zamanki şekilde
uygulanabilir. Örneğin:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

URL oluşturma başvurusu


Aşağıdaki örnek, yol değerlerinin bir sözlüğü ve bir RouteCollectioniçin bir yol bağlantısının nasıl
oluşturulacağını gösterir.

app.Run(async (context) =>


{
var dictionary = new RouteValueDictionary
{
{ "operation", "create" },
{ "id", 123}
};

var vpc = new VirtualPathContext(context, null, dictionary,


"Track Package Route");
var path = routes.GetVirtualPath(vpc).VirtualPath;

context.Response.ContentType = "text/html";
await context.Response.WriteAsync("Menu<hr/>");
await context.Response.WriteAsync(
$"<a href='{path}'>Create Package 123</a><br/>");
});

Yukarıdaki örnek sonunda oluşturulan VirtualPath /package/create/123 . Sözlük, "paket yolunu Izle"
şablonunun package/{operation}/{id}``operation ve id yol değerlerini sağlar. Ayrıntılar için, yönlendirme
ara yazılımı kullanma bölümünde veya örnek uygulamadaörnek koda bakın.
VirtualPathContext oluşturucusunun ikinci parametresi bir ortam değerlerikoleksiyonudur. Ortam
değerleri, bir geliştiricinin bir istek bağlamı içinde belirtmesi gereken değer sayısını sınırlandırdığından
kullanım için uygundur. Geçerli isteğin geçerli yol değerleri, bağlantı oluşturma için çevresel değerler olarak
kabul edilir. ASP.NET Core MVC uygulamasının HomeController``About eyleminde,—ortam değeri Home
Index eyleme bağlamak için denetleyici yolu değerini belirtmeniz gerekmez.

Bir parametreyle eşleşmeyen çevresel değerler yok sayılır. Ayrıca, açıkça sağlanmış bir değer çevresel
değeri geçersiz kıldığında çevresel değerler de yoksayılır. Eşleştirme, URL 'de soldan sağa doğru gerçekleşir.
Açık olarak sağlanmış ancak yolun bir segmentiyle eşleşmeyen değerler sorgu dizesine eklenir. Aşağıdaki
tabloda {controller}/{action}/{id?} yol şablonu kullanılırken sonuç gösterilmektedir.
ÇEVRESEL DEĞERLER AÇIK DEĞERLER SONUÇ

denetleyici = "giriş" Action = "hakkında" /Home/About

denetleyici = "giriş" denetleyici = "Order", Action = /Order/About


"hakkında"

denetleyici = "giriş", renk = "kırmızı" Action = "hakkında" /Home/About

denetleyici = "giriş" Action = "hakkında", color = "Red" /Home/About?color=Red

Bir rotada bir parametreye karşılık gelen bir varsayılan değer varsa ve bu değer açıkça sağlanmışsa,
varsayılan değerle eşleşmelidir:

routes.MapRoute("blog_route", "blog/{*slug}",
defaults: new { controller = "Blog", action = "ReadPost" });

Bağlantı oluşturma yalnızca controller ve action için eşleşen değerler sağlandığında bu yol için bir
bağlantı oluşturur.

Karmaşık segmentler
Karmaşık segmentler (örneğin [Route("/x{token}y")] ), sabit değerli olmayan değişmez değerler ile sağdan
sola eşleştirilirken işlenir. Karmaşık segmentlerin nasıl eşleştirileceği hakkında ayrıntılı bir açıklama için bu
koda bakın. Kod örneği ASP.NET Core tarafından kullanılmaz, ancak karmaşık segmentler hakkında iyi bir
açıklama sağlar.
ASP.NET Core hataları işleme
6.12.2019 • 14 minutes to read • Edit Online

Tom Dykstra, Luke Lathamve Steve Smith tarafından


Bu makalede ASP.NET Core Web Apps 'teki hataları işlemeye yönelik yaygın yaklaşımlar ele alınmaktadır.
Bkz. Web API 'Leri için ASP.NET Core Web API 'Lerinde hataları işleme.
Görüntüleme veya indirme örnek kodu. (Nasıl indirilir.) Makale, farklı senaryoları etkinleştirmek için örnek
uygulamada Önişlemci yönergelerinin ( #if , #endif , #define ) nasıl ayarlanacağı hakkında yönergeler içerir.

Geliştirici özel durum sayfası


Geliştirici özel durum sayfası , istek özel durumları hakkında ayrıntılı bilgileri görüntüler. Sayfa, Microsoft.
aspnetcore. app metapackageiçindeki Microsoft. Aspnetcore. Diagnostics paketi tarafından kullanılabilir hale
getirilir. Uygulama geliştirme ortamındaçalışırken sayfayı etkinleştirmek için Startup.Configure yöntemine
kod ekleyin:

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

Özel durumları yakalamak istediğiniz herhangi bir ara yazılımın önüne UseDeveloperExceptionPage çağrısı
koyun.

WARNING
Geliştirici özel durum sayfasını yalnızca uygulama geliştirme ortamında çalışırkenetkinleştirin. Uygulama üretimde
çalıştırıldığında ayrıntılı özel durum bilgilerini herkese açık bir şekilde paylaşmak istemezsiniz. Ortamları yapılandırma
hakkında daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları kullanma.

Sayfa, özel durum ve istek hakkında şu bilgileri içerir:


Yığın izleme
Sorgu dizesi parametreleri (varsa)
Tanımlama bilgileri (varsa)
Üstbilgiler
Örnek uygulamadageliştirici özel durum sayfasını görmek için, DevEnvironment Önişlemci yönergesini
kullanın ve giriş sayfasında özel durum Tetikle ' yi seçin.

Özel durum işleyici sayfası


Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için özel durum Işleme ara yazılımını kullanın.
Ara yazılım:
Özel durumları yakalar ve günlüğe kaydeder.
İsteği, belirtilen sayfa veya denetleyici için alternatif bir ardışık düzende yeniden yürütür. Yanıt başlatılmışsa
istek yeniden yürütülmez.
Aşağıdaki örnekte UseExceptionHandler, özel durum Işleme ara yazılımını geliştirme olmayan ortamlara
ekler:

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

Razor Pages App Template, Sayfalar klasöründe bir hata sayfası ( . cshtml) ve PageModel sınıfı ( ErrorModel )
sağlar. MVC uygulaması için, proje şablonu bir hata eylemi yöntemi ve bir hata görünümü içerir. Eylem
yöntemi aşağıda verilmiştir:

[AllowAnonymous]
public IActionResult Error()
{
return View(new ErrorViewModel
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

Hata işleyicisi eylem yöntemini, HttpGet gibi HTTP yöntemi öznitelikleriyle işaretlemeyin. Açık fiiller bazı
isteklerin yönteme ulaşmasını önler. Kimliği doğrulanmamış kullanıcıların hata görünümünü alabilmesi için
metoda anonim erişime izin verin.
Özel duruma erişin
Hata işleyicisi denetleyicisi veya sayfasındaki özel duruma ve özgün istek yoluna erişmek için
IExceptionHandlerPathFeature kullanın:

var exceptionHandlerPathFeature =
HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
ExceptionMessage = "File error thrown";
}
if (exceptionHandlerPathFeature?.Path == "/index")
{
ExceptionMessage += " from home page";
}

WARNING
İstemcilere hassas hata bilgileri sunma. Hatalara hizmet vermek bir güvenlik riskidir.

Örnek uygulamadakiözel durum işleme sayfasını görmek için ProdEnvironment ve ErrorHandlerPage


önişlemci yönergelerini kullanın ve giriş sayfasında bir özel durum Tetikle ' yi seçin.

Özel durum işleyici lambda


Özel bir özel durum işleyici sayfasına bir alternatif, UseExceptionHandlerlambda sağlamaktır. Lambda
kullanılması, yanıtı döndürmeden önce hataya erişim sağlar.
Özel durum işleme için lambda kullanmanın bir örneği aşağıda verilmiştir:

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500;
context.Response.ContentType = "text/html";

await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");


await context.Response.WriteAsync("ERROR!<br><br>\r\n");

var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();

// Use exceptionHandlerPathFeature to process the exception (for example,


// logging), but do NOT expose sensitive error information directly to
// the client.

if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync("File error thrown!<br><br>\r\n");
}

await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");


await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512)); // IE padding
});
});
app.UseHsts();
}

WARNING
IExceptionHandlerFeature veya IExceptionHandlerPathFeature istemcilere duyarlı hata bilgileri sunma. Hatalara hizmet
vermek bir güvenlik riskidir.

Örnek uygulamadalambda işleme 'nin sonucunu görmek için, ProdEnvironment ve ErrorHandlerLambda


önişlemci yönergelerini kullanın ve giriş sayfasında bir özel durum Tetikle ' yi seçin.

UseStatusCodePages
Varsayılan olarak, bir ASP.NET Core uygulama HTTP durum kodları için 404 -bulunamadıgibi bir durum
kodu sayfası sağlamaz. Uygulama bir durum kodu ve boş bir yanıt gövdesi döndürür. Durum kodu sayfaları
sağlamak için durum kodu sayfaları ara yazılımını kullanın.
Ara yazılım, Microsoft. aspnetcore. app metapackageiçindeki Microsoft. Aspnetcore. Diagnostics paketi
tarafından kullanılabilir hale gelir.
Ortak hata durum kodları için varsayılan salt metin işleyicilerini etkinleştirmek üzere Startup.Configure
yönteminde UseStatusCodePages çağırın:
app.UseStatusCodePages();

İstek işleme ara yazılımı (örneğin, statik dosya ara yazılımı ve MVC ara yazılımı) için önce UseStatusCodePages
çağırın.
Varsayılan işleyiciler tarafından görüntülenbir metin örneği aşağıda verilmiştir:

Status Code: 404; Not Found

Örnek uygulamadakiçeşitli durum kodu sayfası biçimlerinden birini görmek için StatusCodePages ile başlayan
Önişlemci yönergelerinden birini kullanın ve giriş sayfasında 404 tetikleme ' yı seçin.

Biçim dizesiyle UseStatusCodePages


Yanıt içerik türünü ve metnini özelleştirmek için, içerik türü ve biçim dizesi alan UseStatusCodePages aşırı
yüklemesini kullanın:

app.UseStatusCodePages(
"text/plain", "Status code page, status code: {0}");

Lambda ile UseStatusCodePages


Özel hata işleme ve yanıt yazma kodu belirtmek için, lambda ifadesi alan UseStatusCodePages aşırı
yüklemesini kullanın:

app.UseStatusCodePages(async context =>


{
context.HttpContext.Response.ContentType = "text/plain";

await context.HttpContext.Response.WriteAsync(
"Status code page, status code: " +
context.HttpContext.Response.StatusCode);
});

Usestatuscodepageswithyönlendirmeler
UseStatusCodePagesWithRedirects uzantısı yöntemi:
İstemciye 302 tarafından bulunan bir durum kodu gönderir.
İstemciyi, URL şablonunda belirtilen konuma yönlendirir.

app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");

URL şablonu, örnekte gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu bir tilde (~)
ile başlıyorsa, tilde uygulamanın PathBase alır. Uygulamanın içindeki bir uç noktayı işaret ederseniz, uç nokta
için bir MVC görünümü veya Razor sayfası oluşturun. Razor Pages bir örnek için bkz. örnek uygulamadaki
Pages/StatusCode. cshtml .
Bu yöntem genellikle uygulama şu şekilde kullanılır:
, Genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya
yönlendirmelidir. Web Apps için, istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
İlk yeniden yönlendirme yanıtıyla birlikte özgün durum kodunu korumamalıdır ve döndürmemelidir.

UseStatusCodePagesWithReExecute
UseStatusCodePagesWithReExecute uzantısı yöntemi:
İstemciye özgün durum kodunu döndürür.
Alternatif bir yol kullanarak istek ardışık düzenini yeniden yürüterek yanıt gövdesini oluşturur.

app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");

Uygulamanın içindeki bir uç noktayı işaret ederseniz, uç nokta için bir MVC görünümü veya Razor sayfası
oluşturun. Razor Pages bir örnek için bkz. örnek uygulamadaki Pages/StatusCode. cshtml .
Bu yöntem genellikle uygulama şunları yaparken kullanılır:
Farklı bir uç noktaya yönlendirmeye gerek kalmadan isteği işleyin. Web Apps için, istemcinin tarayıcı adres
çubuğu, ilk olarak istenen uç noktayı yansıtır.
Yanıt ile orijinal durum kodunu koruyun ve geri döndürün.
URL ve sorgu dizesi şablonları durum kodu için bir yer tutucu ( {0} ) içerebilir. URL şablonu eğik çizgiyle ( / )
başlamalıdır. Yolda bir yer tutucu kullanırken, uç noktanın (sayfa veya denetleyicinin) yol kesimini işleyediğini
doğrulayın. Örneğin, bir Razor sayfası, @page yönergesi ile isteğe bağlı yol segmenti değerini kabul etmelidir:

@page "{code?}"

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi, hatayı oluşturan özgün URL 'YI alabilir:

var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();


if (statusCodeReExecuteFeature != null)
{
OriginalURL =
statusCodeReExecuteFeature.OriginalPathBase
+ statusCodeReExecuteFeature.OriginalPath
+ statusCodeReExecuteFeature.OriginalQueryString;
}

Durum kodu sayfalarını devre dışı bırak


MVC denetleyicisi veya eylem yöntemi için durum kodu sayfalarını devre dışı bırakmak için
[SkipStatusCodePages] özniteliğini kullanın.

Razor Pages işleyici yöntemindeki veya bir MVC denetleyicisindeki belirli istekler için durum kodu sayfalarını
devre dışı bırakmak için IStatusCodePagesFeaturekullanın:

var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}

Özel durum işleme kodu


Özel durum işleme sayfalarındaki kod özel durumlar oluşturabilir. Üretim hatası sayfalarının tamamen statik
içerikten oluşması genellikle iyi bir fikirdir.
Yanıt üst bilgileri
Yanıt üstbilgileri gönderildikten sonra:
Uygulama, yanıtın durum kodunu değiştiremiyor.
Tüm özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı iptal edilmiş
olmalıdır.

Sunucu özel durum işleme


Uygulamanızın özel durum işleme mantığına ek olarak, http sunucusu uygulaması bazı özel durumları
işleyebilir. Sunucu yanıt üstbilgileri gönderilmeden önce bir özel durum yakalarsa, sunucu yanıt gövdesi
olmadan 500 -Iç sunucu hatası yanıtı gönderir. Yanıt üstbilgileri gönderildikten sonra sunucu bir özel durum
yakalar, sunucu bağlantıyı kapatır. Uygulamanız tarafından işlenmeyen istekler sunucu tarafından işlenir.
Sunucu isteği gerçekleştirirken oluşan tüm özel durumlar sunucunun özel durum işleme tarafından işlenir.
Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Başlatma özel durum işleme


Uygulama başlangıcında gerçekleşen özel durumları yalnızca barındırma katmanı işleyebilir. Konak, Başlangıç
hatalarını yakalamak ve ayrıntılı hataları yakalamakiçin yapılandırılabilir.
Barındırma katmanı, yalnızca hatanın ana bilgisayar adresi/bağlantı noktası bağlamalarından sonra oluşması
durumunda yakalanan başlatma hatası için bir hata sayfası gösterebilir. Bağlama başarısız olursa:
Barındırma katmanı, kritik bir özel durumu günlüğe kaydeder.
DotNet işlemi kilitleniyor.
HTTP sunucusu Kestrelolduğunda hata sayfası gösterilmez.
IIS 'de (veya Azure App Service) veya IIS Expressçalışırken, işlem başlatılamazsa ASP.NET Core modülü
tarafından 502,5 işlem hatası döndürülür. Daha fazla bilgi için bkz. Azure App Service ve IIS 'de ASP.NET
Core sorunlarını giderme.

Veritabanı hata sayfası


Veritabanı hata sayfası ara yazılımı, Entity Framework geçişleri kullanılarak çözümleneyolabilecek
veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar gerçekleştiğinde, sorunu çözmeye yönelik olası
eylemlerin ayrıntılarını içeren bir HTML yanıtı oluşturulur. Bu sayfa yalnızca geliştirme ortamında
etkinleştirilmelidir. Startup.Configure kod ekleyerek sayfayı etkinleştirin:

if (env.IsDevelopment())
{
app.UseDatabaseErrorPage();
}

Özel durum filtreleri


MVC uygulamalarında özel durum filtreleri, genel olarak veya denetleyicide veya eylem temelinde
yapılandırılabilir. Razor Pages uygulamalarda, genel olarak veya sayfa modeli başına yapılandırılabilirler. Bu
filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmemiş özel
durumları işler. Daha fazla bilgi için bkz. ASP.NET Core filtreler.
TIP
Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için yararlıdır, ancak özel durum Işleme ara
yazılımı kadar esnek değildir. Ara yazılımı kullanmanızı öneririz. Yalnızca hangi MVC eyleminin seçilmesinden ayrı olarak
hata işleme yapmanız gereken durumlarda filtreleri kullanın.

Model durumu hataları


Model durumu hatalarını işleme hakkında daha fazla bilgi için bkz. model bağlama ve model doğrulaması.

Ek kaynaklar
Azure App Service ve IIS 'de ASP.NET Core sorunlarını giderme
ASP.NET Core ile Azure App Service ve IIS için ortak hatalar başvurusu
ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP
istekleri yapın
4.12.2019 • 70 minutes to read • Edit Online

Glenn CONDRON, Ryan şimdi ak, Steve Gordon, Rick Andersonve Kirk larkabağı
Bir IHttpClientFactory, bir uygulamadaki HttpClient örnekleri yapılandırmak ve oluşturmak için kaydedilebilir ve
kullanılabilir. IHttpClientFactory aşağıdaki avantajları sunar:
, Mantıksal HttpClient örneklerinin adlandırılması ve yapılandırılması için merkezi bir konum sağlar.
Örneğin, GitHub adlı bir Istemci, GitHub'a erişmek için kaydedilebilir ve yapılandırılabilir. Varsayılan istemci,
genel erişim için kaydedilebilir.
HttpClient , işleyiciler için temsilci atama yoluyla giden ara yazılım kavramını daha da artırır. HttpClient ' de
işleyiciler temsilci seçme avantajlarından faydalanmak için, Polya tabanlı bir ara yazılım için uzantılar sağlar.
Temel alınan HttpClientMessageHandler örneklerinin biriktirmesini ve ömrünü yönetir. Otomatik yönetim,
HttpClient yaşam sürelerini el ile yönetirken oluşan ortak DNS (etki alanı adı sistemi) sorunlarını önler.
Fabrika tarafından oluşturulan istemcilerle gönderilen tüm istekler için yapılandırılabilir bir günlük deneyimi (
ILogger aracılığıyla) ekler.

Örnek kodu görüntüleyin veya indirin (nasıl indirilir).


Bu konu sürümündeki örnek kod, HTTP yanıtlarında döndürülen JSON içeriğinin serisini kaldırmak için
System.Text.Json kullanır. Json.NET ve ReadAsAsync<T> kullanan örnekler için, bu konunun 2. x sürümünü seçmek
üzere sürüm seçiciyi kullanın.

Tüketim desenleri
Bir uygulamada IHttpClientFactory çeşitli yollar vardır:
Temel kullanım
Adlandırılmış istemciler
Yazılan istemciler
Oluşturulan istemciler
En iyi yaklaşım, uygulamanın gereksinimlerine bağlı olarak değişir.
Temel kullanım
IHttpClientFactory , AddHttpClient çağırarak kaydedilebilir:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient();
// Remaining code deleted for brevity.

IHttpClientFactory , bağımlılık ekleme (dı)kullanılarak istenebilir. Aşağıdaki kod, bir HttpClient örneği
oluşturmak için IHttpClientFactory kullanır:

public class BasicUsageModel : PageModel


{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubBranch> Branches { get; private set; }

public bool GetBranchesError { get; private set; }

public BasicUsageModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

var client = _clientFactory.CreateClient();

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
Branches = await JsonSerializer.DeserializeAsync
<IEnumerable<GitHubBranch>>(responseStream);
}
else
{
GetBranchesError = true;
Branches = Array.Empty<GitHubBranch>();
}
}
}

Yukarıdaki örnekte olduğu gibi IHttpClientFactory kullanmak, mevcut bir uygulamayı yeniden düzenleme için
iyi bir yoldur. HttpClient kullanılma şekli üzerinde hiçbir etkisi yoktur. Mevcut bir uygulamada HttpClient
örneklerinin oluşturulduğu yerlerde, bu oluşumları CreateClientçağrılarıyla değiştirin.
Adlandırılmış istemciler
Adlandırılmış istemciler şu durumlarda iyi bir seçimdir:
Uygulama birçok farklı HttpClient kullanımı gerektirir.
Birçok HttpClient farklı yapılandırmaya sahiptir.

Adlandırılmış bir HttpClient yapılandırması, Startup.ConfigureServices kayıt sırasında belirtilebilir:

services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
// Github API versioning
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
// Github requires a user-agent
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

İstemcinin yapılandırıldığı önceki kodda:


Temel adres https://api.github.com/ .
GitHub API 'SI ile çalışmak için iki üst bilgi gereklidir.
CreateClient
CreateClient her çağrıldığında:
Yeni bir HttpClient örneği oluşturulur.
Yapılandırma eylemi çağrılır.
Adlandırılmış bir istemci oluşturmak için adını CreateClient geçirin:
public class NamedClientModel : PageModel
{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

public bool GetPullRequestsError { get; private set; }

public bool HasPullRequests => PullRequests.Any();

public NamedClientModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"repos/aspnet/AspNetCore.Docs/pulls");

var client = _clientFactory.CreateClient("github");

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
PullRequests = await JsonSerializer.DeserializeAsync
<IEnumerable<GitHubPullRequest>>(responseStream);
}
else
{
GetPullRequestsError = true;
PullRequests = Array.Empty<GitHubPullRequest>();
}
}
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez. İstemci için yapılandırılan taban adresi
kullanıldığından, kod yalnızca yolu geçirebilir.
Yazılan istemciler
Yazılan istemciler:
Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.
İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.
Yapılandırmak ve belirli bir HttpClient etkileşimde bulunmak için tek bir konum sağlayın. Örneğin, tek bir
türü belirtilmiş istemci kullanılabilir:
Tek bir arka uç uç noktası için.
Uç nokta ile ilgili tüm mantığı kapsüllemek için.
DI ile birlikte çalışın ve uygulamada gerektiğinde eklenebilir.
Türü belirtilmiş istemci, oluşturucusunda bir HttpClient parametresi kabul eder:
public class GitHubService
{
public HttpClient Client { get; }

public GitHubService(HttpClient client)


{
client.BaseAddress = new Uri("https://api.github.com/");
// GitHub API versioning
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
// GitHub requires a user-agent
client.DefaultRequestHeaders.Add("User-Agent",
"HttpClientFactory-Sample");

Client = client;
}

public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()


{
var response = await Client.GetAsync(
"/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

response.EnsureSuccessStatusCode();

using var responseStream = await response.Content.ReadAsStreamAsync();


return await JsonSerializer.DeserializeAsync
<IEnumerable<GitHubIssue>>(responseStream);
}
}

Önceki kodda:
Yapılandırma, yazılan istemciye taşınır.
HttpClient nesnesi ortak bir özellik olarak sunulur.

HttpClient işlevselliği ortaya çıkaran API 'ye özgü Yöntemler oluşturulabilir. Örneğin, GetAspNetDocsIssues
yöntemi açık sorunları almak için kodu kapsüller.
Aşağıdaki kod, bir tür istemci sınıfını kaydetmek için Startup.ConfigureServices AddHttpClient çağırır:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir. Yazılan istemci doğrudan eklenebilir ve tüketilebilir:
public class TypedClientModel : PageModel
{
private readonly GitHubService _gitHubService;

public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

public bool HasIssue => LatestIssues.Any();

public bool GetIssuesError { get; private set; }

public TypedClientModel(GitHubService gitHubService)


{
_gitHubService = gitHubService;
}

public async Task OnGet()


{
try
{
LatestIssues = await _gitHubService.GetAspNetDocsIssues();
}
catch(HttpRequestException)
{
GetIssuesError = true;
LatestIssues = Array.Empty<GitHubIssue>();
}
}
}

Türü belirlenmiş bir istemcinin yapılandırması, türü belirlenmiş istemcinin Oluşturucusu yerine
Startup.ConfigureServices kayıt sırasında belirtilebilir:

services.AddHttpClient<RepoService>(c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

HttpClient , türü belirlenmiş bir istemci içinde kapsüllenebilir. Bunu bir özellik olarak göstermek yerine,
HttpClient örneğini dahili olarak çağıran bir yöntem tanımlayın:
public class RepoService
{
// _httpClient isn't exposed publicly
private readonly HttpClient _httpClient;

public RepoService(HttpClient client)


{
_httpClient = client;
}

public async Task<IEnumerable<string>> GetRepos()


{
var response = await _httpClient.GetAsync("aspnet/repos");

response.EnsureSuccessStatusCode();

using var responseStream = await response.Content.ReadAsStreamAsync();


return await JsonSerializer.DeserializeAsync
<IEnumerable<string>>(responseStream);
}
}

Yukarıdaki kodda HttpClient bir özel alanda depolanır. HttpClient erişim, genel GetRepos yöntemine göre
yapılır.
Oluşturulan istemciler
IHttpClientFactory , yeniden sığdırmagibi üçüncü taraf kitaplıklarla birlikte kullanılabilir. Yeniden sığdırma, .NET
için bir REST kitaplığıdır. REST API 'Leri canlı arabirimlere dönüştürür. Bir arabirimin uygulanması, dış HTTP
çağrılarını yapmak için HttpClient kullanılarak RestService tarafından dinamik olarak oluşturulur.
Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:

public interface IHelloClient


{
[Get("/helloworld")]
Task<Reply> GetMessageAsync();
}

public class Reply


{
public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient("hello", c =>
{
c.BaseAddress = new Uri("http://localhost:5000");
})
.AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

services.AddControllers();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHelloClient _client;

public ValuesController(IHelloClient client)


{
_client = client;
}

[HttpGet("/")]
public async Task<ActionResult<Reply>> Index()
{
return await _client.GetMessageAsync();
}
}

Giden istek ara yazılımı


HttpClient , giden HTTP istekleri için bir araya bağlanabilen işleyicileri temsilci seçme kavramıdır.
IHttpClientFactory :
Her bir adlandırılmış istemci için uygulanacak işleyiciler tanımlamayı basitleştirir.
Bir giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydedilmesini ve zincirleme
kullanımını destekler. Bu işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir. Bu model:
ASP.NET Core gelen ara yazılım ardışık düzenine benzerdir.
, HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar, örneğin:
önbelleğe alma
hata işleme
serileştirme
günlük kaydı
Temsilci seçme işleyicisi oluşturmak için:
DelegatingHandlertüret.
SendAsyncgeçersiz kıl. İsteği ardışık düzen içindeki bir sonraki işleyiciye geçirmeden önce kodu yürütün:

public class ValidateHeaderHandler : DelegatingHandler


{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("X-API-KEY"))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"You must supply an API key header called X-API-KEY")
};
}

return await base.SendAsync(request, cancellationToken);


}
}
Yukarıdaki kod, X-API-KEY üst bilgisinin istekte olup olmadığını denetler. X-API-KEY eksikse, BadRequest
döndürülür.
Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.AddHttpMessageHandlerbir HttpClient
yapılandırmaya birden fazla işleyici eklenebilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddTransient<ValidateHeaderHandler>();

services.AddHttpClient("externalservice", c =>
{
// Assume this is an "external" service which requires an API KEY
c.BaseAddress = new Uri("https://localhost:5001/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();

// Remaining code deleted for brevity.

Yukarıdaki kodda ValidateHeaderHandler DI ile kaydedilir. IHttpClientFactory her işleyici için ayrı bir dı kapsamı
oluşturur. İşleyiciler herhangi bir kapsamın hizmetlerine bağlı olabilir. İşleyicilerin bağımlı olduğu hizmetler,
işleyicinin elden çıkarılmasıyla kaldırılır.
Kaydedildikten sonra, işleyicinin türü olarak AddHttpMessageHandler çağrılabilir.
Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir. Her işleyici, son HttpClientHandler isteği
çalıştırana kadar sonraki işleyiciyi sarmalar:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
// This handler is on the outside and called first during the
// request, last during the response.
.AddHttpMessageHandler<SecureRequestHandler>()
// This handler is on the inside, closest to the request being
// sent.
.AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:
HttpRequestMessage. Propertieskullanarak işleyicide veri geçirin.
Geçerli isteğe erişmek için IHttpContextAccessor kullanın.
Verileri geçirmek için özel bir AsyncLocal<T> depolama nesnesi oluşturun.

Polly tabanlı işleyiciler kullanın


IHttpClientFactory , üçüncü taraf kitaplığı Pollyile tümleşir. Polly, .NET için kapsamlı bir esnekliği ve geçici hata
işleme kitaplığıdır. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş yalıtımı, akıcı ve iş
parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.
Uzantı yöntemleri, yapılandırılmış HttpClient örnekleri ile Polly ilkelerin kullanımını etkinleştirmek için sağlanır.
Polly uzantıları, istemcilere Polly tabanlı işleyiciler eklemeyi destekler. Polly, Microsoft. Extensions. http. Polly
NuGet paketini gerektirir.
Geçici hataları işle
Hatalar genellikle dış HTTP çağrıları geçici olduğunda oluşur. AddTransientHttpErrorPolicy, geçici hataları
işlemek için bir ilkenin tanımlanmasını sağlar. AddTransientHttpErrorPolicy ile yapılandırılan ilkeler aşağıdaki
yanıtları işleyecek şekilde yapılandırılır:
HttpRequestException
HTTP 5xx
HTTP 408
AddTransientHttpErrorPolicy , olası bir geçici hatayı temsil eden hataları işlemek için yapılandırılmış bir
PolicyBuilder nesnesine erişim sağlar:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient<UnreliableEndpointCallerService>()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

// Remaining code deleted for brevity.

Yukarıdaki kodda WaitAndRetryAsync bir ilke tanımlanmıştır. Başarısız istekler, denemeler arasındaki 600 MS
gecikmeyle en fazla üç kez yeniden denenir.
Dinamik olarak ilke seçme
Uzantı yöntemleri, örneğin AddPolicyHandler, Polly tabanlı işleyiciler eklemek için sağlanır. Aşağıdaki
AddPolicyHandler aşırı yüklemesi hangi ilkenin uygulanacağını belirlemek için isteği inceler:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(


TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
.AddPolicyHandler(request =>
request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır. Diğer HTTP yöntemleri
için, 30 saniyelik bir zaman aşımı kullanılır.
Birden çok Polly işleyici ekleme
Polly ilkeleri iç içe almak yaygın bir şekilde yapılır:

services.AddHttpClient("multiplepolicies")
.AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
.AddTransientHttpErrorPolicy(
p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte:
İki işleyici eklenir.
İlk işleyici, yeniden deneme ilkesi eklemek için AddTransientHttpErrorPolicy kullanır. Başarısız istekler en fazla
üç kez yeniden denenir.
İkinci AddTransientHttpErrorPolicy çağrısı bir devre kesici ilkesi ekler. 5 başarısız girişim sıralı olarak
gerçekleşirse, daha fazla dış istek 30 saniye boyunca engellenir. Devre kesici ilkeleri durum bilgisi vardır. Bu
istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu paylaşır.
Polly kayıt defterinden ilke ekleme
Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlamak ve bir
PolicyRegistry kaydetmektir.
Aşağıdaki kodda:
"Normal" ve "uzun" ilkeler eklenmiştir.
AddPolicyHandlerFromRegistry, kayıt defterinden "normal" ve "uzun" ilkeleri ekler.

public void ConfigureServices(IServiceCollection services)


{
var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(30));

var registry = services.AddPolicyRegistry();

registry.Add("regular", timeout);
registry.Add("long", longTimeout);

services.AddHttpClient("regularTimeoutHandler")
.AddPolicyHandlerFromRegistry("regular");

services.AddHttpClient("longTimeoutHandler")
.AddPolicyHandlerFromRegistry("long");

// Remaining code deleted for brevity.

IHttpClientFactory ve Polly tümleştirmeler hakkında daha fazla bilgi için bkz. Polly wiki.

HttpClient ve ömür yönetimi


IHttpClientFactory``CreateClienther çağrıldığında yeni bir HttpClient örneği döndürülür. Adlandırılmış
istemci başına bir HttpMessageHandler oluşturulur. Fabrika HttpMessageHandler örneklerinin yaşam sürelerini
yönetir.
kaynak tüketimini azaltmak için fabrika tarafından oluşturulan HttpMessageHandler örnekleri IHttpClientFactory
havuzlar. HttpMessageHandler bir örnek, süresi dolmamışsa yeni bir HttpClient örneği oluşturulurken havuzdan
yeniden kullanılabilir.
Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.
Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir. Ayrıca, bazı
işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS (etki alanı adı sistemi) değişikliklerine
yeniden davranmasını engelleyebilir.
Varsayılan işleyici ömrü iki dakikadır. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient("extendedhandlerlifetime")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

// Remaining code deleted for brevity.

HttpClient örnekleri genellikle aktiften çıkarma gerektirmeyen .NET nesneleri olarak kabul edilebilir.
Aktiften çıkarma giden istekleri iptal eder ve Disposeçağrıldıktan sonra verilen HttpClient örneğinin
kullanılamaz olmasını sağlar. IHttpClientFactory , HttpClient örnekleri tarafından kullanılan kaynakları izler ve
ortadan kaldırır.
Tek bir HttpClient örneğinin uzun süre canlı tutulması, IHttpClientFactory önünde kullanılmadan önce
kullanılan ortak bir modeldir. Bu kalıp IHttpClientFactory geçtikten sonra gereksiz hale gelir.
Ihttpclientfactory alternatifleri
Dı özellikli bir uygulamada IHttpClientFactory kullanmak şunları önler:
HttpMessageHandler örnekleri havuza alarak kaynak tükenmesi sorunları.
Düzenli aralıklarla HttpMessageHandler örnekleri arasında geçiş yaparak eski DNS sorunları.
Uzun süreli SocketsHttpHandler örneği kullanarak önceki sorunları çözmenin alternatif yolları vardır.
Uygulama başlatıldığında SocketsHttpHandler örneğini oluşturun ve uygulamanın ömrü boyunca kullanın.
PooledConnectionLifetime DNS yenileme zamanına göre uygun bir değere yapılandırın.
Gerektiğinde new HttpClient(handler, dispostHandler: false) kullanarak HttpClient örnekleri oluşturun.

Yukarıdaki yaklaşımlar IHttpClientFactory benzer bir şekilde çözdüğü kaynak yönetimi sorunlarını çözer.
SocketsHttpHandler , HttpClient örnekleri arasında bağlantıları paylaşır. Bu paylaşım, yuva azalmasına engel
olur.
SocketsHttpHandler , eski DNS sorunlarından kaçınmak için bağlantıları PooledConnectionLifetime göre
döngüler.
Özgü
Havuza alınmış HttpMessageHandler örnekleri, CookieContainer nesneleri paylaşılmasına neden olur.
Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır. Tanımlama bilgileri gerektiren
uygulamalar için şunlardan birini göz önünde bulundurun:
Otomatik tanımlama bilgisi işlemeyi devre dışı bırakma
IHttpClientFactory önleme

Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmak için ConfigurePrimaryHttpMessageHandler çağırın:

services.AddHttpClient("configured-disable-automatic-cookies")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
UseCookies = false,
};
});

Günlüğe Kaydetme
Tüm istekler için IHttpClientFactory kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler. Varsayılan günlük
iletilerini görmek için günlük yapılandırmasında uygun bilgi düzeyini etkinleştirin. İstek üst bilgilerinin günlüğe
kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.
Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir. Örneğin, Mynamedclientadlı bir istemci,
"System .net. http. HttpClient" kategorisine sahip iletileri günlüğe kaydeder. Mynamedclient. LogicalHandler ".
Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur. İstekte, işlem hattındaki diğer
işleyiciler işlenmeden önce iletiler günlüğe kaydedilir. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan
sonra iletiler günlüğe kaydedilir.
Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir. Mynamedclient örneğinde, bu Iletiler
"System .net. http. HttpClient" günlük kategorisiyle günlüğe kaydedilir. Mynamedclient. ClientHandler ". İstek
için bu, tüm diğer işleyiciler çalıştırıldıktan sonra ve istek gönderilmeden hemen önce gerçekleşir. Yanıtta, bu
günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.
İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından
yapılan değişikliklerin incelemesini etkinleştirir. Bu, istek üst bilgilerinde veya yanıt durum kodunda yapılan
değişiklikleri içerebilir.
İstemcinin adını log kategorisinde da içermek, belirli adlandırılmış istemciler için günlük filtrelemeyi sunar.

HttpMessageHandler 'ı yapılandırma


İstemci tarafından kullanılan iç HttpMessageHandler yapılandırmasını denetlemek gerekli olabilir.
Adlandırılmış veya yazılan istemciler eklenirken bir IHttpClientBuilder döndürülür.
ConfigurePrimaryHttpMessageHandler uzantısı yöntemi bir temsilciyi tanımlamak için kullanılabilir. Temsilci, bu
istemci tarafından kullanılan birincil HttpMessageHandler oluşturmak ve yapılandırmak için kullanılır:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient("configured-inner-handler")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});

// Remaining code deleted for brevity.

Konsol uygulamasında ıhttpclientfactory kullanma


Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:
Microsoft. Extensions. Hosting
Microsoft. Extensions. http
Aşağıdaki örnekte:
IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.
MyService , hizmetten bir HttpClient oluşturmak için kullanılan bir istemci fabrikası örneği oluşturur.
HttpClient , bir Web sayfasını almak için kullanılır.
Main , hizmetin GetPage yöntemini yürütmek için bir kapsam oluşturur ve Web sayfası içeriğinin ilk 500
karakterini konsola yazar.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
static async Task<int> Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient();
services.AddTransient<IMyService, MyService>();
}).UseConsoleLifetime();
var host = builder.Build();

using (var serviceScope = host.Services.CreateScope())


{
var services = serviceScope.ServiceProvider;

try
{
var myService = services.GetRequiredService<IMyService>();
var pageContent = await myService.GetPage();

Console.WriteLine(pageContent.Substring(0, 500));
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();

logger.LogError(ex, "An error occurred.");


}
}

return 0;
}

public interface IMyService


{
Task<string> GetPage();
}

public class MyService : IMyService


{
private readonly IHttpClientFactory _clientFactory;

public MyService(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task<string> GetPage()


{
// Content from BBC One: Dr. Who website (©BBC)
var request = new HttpRequestMessage(HttpMethod.Get,
"https://www.bbc.co.uk/programmes/b006q2x0");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return $"StatusCode: {response.StatusCode}";
}
}
}
}

Ek kaynaklar
Dayanıklı HTTP isteklerini uygulamak için HttpClientFactory kullanma
HttpClientFactory ve Polly ilkeleriyle üstel geri alma ile HTTP çağrı yeniden denemeleri uygulayın
Devre Kesici desenini uygulama
, Glenn CONDRON, Ryan şimdi eve Steve Gordon
Bir IHttpClientFactory, bir uygulamadaki HttpClient örnekleri yapılandırmak ve oluşturmak için kaydedilebilir ve
kullanılabilir. Aşağıdaki avantajları sunar:
, Mantıksal HttpClient örneklerinin adlandırılması ve yapılandırılması için merkezi bir konum sağlar.
Örneğin, GitHub istemcisi kayıtlı ve GitHub'a erişebilecek şekilde yapılandırılabilir. Varsayılan istemci, diğer
amaçlar için kaydedilebilir.
HttpClient ' de işleyiciler temsilci seçme yoluyla giden ara yazılım kavramını daha da artırır ve bundan
faydalanmak için, Polya tabanlı ara yazılım için uzantılar sağlar.
HttpClient yaşam sürelerini el ile yönetirken gerçekleşen yaygın DNS sorunlarından kaçınmak için temel
HttpClientMessageHandler örneklerinin biriktirmesini ve ömrünü yönetir.
Fabrika tarafından oluşturulan istemcilerle gönderilen tüm istekler için yapılandırılabilir bir günlük deneyimi (
ILogger aracılığıyla) ekler.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Tüketim desenleri
Bir uygulamada IHttpClientFactory çeşitli yollar vardır:
Temel kullanım
Adlandırılmış istemciler
Yazılan istemciler
Oluşturulan istemciler
Hiçbiri diğerinden tamamen üst değildir. En iyi yaklaşım, uygulamanın kısıtlamalarına bağlıdır.
Temel kullanım
IHttpClientFactory, Startup.ConfigureServices yönteminin içindeki IServiceCollection``AddHttpClient
genişletme yöntemi çağırarak kaydedilebilir.

services.AddHttpClient();

Kaydedildikten sonra kod, bağımlılık ekleme (dı)ile her yerden IHttpClientFactory kabul edebilir.
IHttpClientFactory , bir HttpClient örneği oluşturmak için kullanılabilir:
public class BasicUsageModel : PageModel
{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubBranch> Branches { get; private set; }

public bool GetBranchesError { get; private set; }

public BasicUsageModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

var client = _clientFactory.CreateClient();

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
Branches = await response.Content
.ReadAsAsync<IEnumerable<GitHubBranch>>();
}
else
{
GetBranchesError = true;
Branches = Array.Empty<GitHubBranch>();
}
}
}

Bu biçimde IHttpClientFactory kullanmak, mevcut bir uygulamayı yeniden düzenleme için iyi bir yoldur.
HttpClient kullanılma şekli üzerinde hiçbir etkisi yoktur. HttpClient örneklerinin Şu anda oluşturulduğu
yerlerde, bu oluşumların CreateClientçağrısı ile değiştirin.
Adlandırılmış istemciler
Bir uygulama, her biri farklı bir yapılandırmaya sahip HttpClient birçok farklı kullanım gerektiriyorsa,
adlandırılmış istemcilerkullanılır. Adlandırılmış bir HttpClient yapılandırması, Startup.ConfigureServices
kayıt sırasında belirtilebilir.

services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
// Github API versioning
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
// Github requires a user-agent
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Yukarıdaki kodda AddHttpClient , GitHubadlı adı sağlar. Bu istemci, GitHub API 'SI ile çalışmak için gerekli olan
temel adres ve iki üst bilgiyle—uygulanmış olan bazı varsayılan yapılandırmaları içerir.
CreateClient her çağrıldığında, yeni bir HttpClient örneği oluşturulur ve yapılandırma eylemi çağrılır.
Adlandırılmış bir istemciyi kullanmak için, CreateClient bir dize parametresi geçirilebilir. Oluşturulacak
istemcinin adını belirtin:
public class NamedClientModel : PageModel
{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

public bool GetPullRequestsError { get; private set; }

public bool HasPullRequests => PullRequests.Any();

public NamedClientModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"repos/aspnet/AspNetCore.Docs/pulls");

var client = _clientFactory.CreateClient("github");

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
PullRequests = await response.Content
.ReadAsAsync<IEnumerable<GitHubPullRequest>>();
}
else
{
GetPullRequestsError = true;
PullRequests = Array.Empty<GitHubPullRequest>();
}
}
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez. İstemci için yapılandırılan taban adresi
kullanıldığından, bu yalnızca yolu geçirebilir.
Yazılan istemciler
Yazılan istemciler:
Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.
İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.
Yapılandırmak ve belirli bir HttpClient etkileşimde bulunmak için tek bir konum sağlayın. Örneğin, tek bir
arka uç uç noktası için tek bir adet yazılmış istemci kullanılabilir ve bu uç nokta ile ilgili tüm mantığı
kapsüllenebilir.
DI ile birlikte çalışın ve uygulamanızda gerektiğinde eklenebilir.
Türü belirtilmiş istemci, oluşturucusunda bir HttpClient parametresi kabul eder:
public class GitHubService
{
public HttpClient Client { get; }

public GitHubService(HttpClient client)


{
client.BaseAddress = new Uri("https://api.github.com/");
// GitHub API versioning
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
// GitHub requires a user-agent
client.DefaultRequestHeaders.Add("User-Agent",
"HttpClientFactory-Sample");

Client = client;
}

public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()


{
var response = await Client.GetAsync(
"/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

response.EnsureSuccessStatusCode();

var result = await response.Content


.ReadAsAsync<IEnumerable<GitHubIssue>>();

return result;
}
}

Önceki kodda, yapılandırma yazılan istemciye taşınır. HttpClient nesnesi ortak bir özellik olarak sunulur.
HttpClient işlevselliği ortaya çıkaran API 'ye özel yöntemler tanımlamak mümkündür. GetAspNetDocsIssues
yöntemi, GitHub deposundan en son açık sorunları sorgulamak ve ayrıştırmak için gereken kodu kapsüller.
Türü belirtilmiş bir istemciyi kaydetmek için genel AddHttpClient uzantısı yöntemi, türü belirlenmiş istemci
sınıfını belirterek Startup.ConfigureServices içinde kullanılabilir:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir. Yazılan istemci doğrudan eklenebilir ve tüketilebilir:
public class TypedClientModel : PageModel
{
private readonly GitHubService _gitHubService;

public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

public bool HasIssue => LatestIssues.Any();

public bool GetIssuesError { get; private set; }

public TypedClientModel(GitHubService gitHubService)


{
_gitHubService = gitHubService;
}

public async Task OnGet()


{
try
{
LatestIssues = await _gitHubService.GetAspNetDocsIssues();
}
catch(HttpRequestException)
{
GetIssuesError = true;
LatestIssues = Array.Empty<GitHubIssue>();
}
}
}

Tercih edilirse, yazılan istemcinin yapılandırması, türü belirlenmiş istemcinin Oluşturucusu yerine
Startup.ConfigureServices kayıt sırasında belirtilebilir:

services.AddHttpClient<RepoService>(c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Türü belirlenmiş bir istemci içinde tamamen kapsül HttpClient lemek mümkündür. Bunu bir özellik olarak
göstermek yerine, HttpClient örneğini dahili olarak çağıran ortak Yöntemler sunulabilir.
public class RepoService
{
// _httpClient isn't exposed publicly
private readonly HttpClient _httpClient;

public RepoService(HttpClient client)


{
_httpClient = client;
}

public async Task<IEnumerable<string>> GetRepos()


{
var response = await _httpClient.GetAsync("aspnet/repos");

response.EnsureSuccessStatusCode();

var result = await response.Content


.ReadAsAsync<IEnumerable<string>>();

return result;
}
}

Yukarıdaki kodda HttpClient bir özel alan olarak depolanır. Dış çağrıları yapmak için tüm erişim GetRepos
yönteminden geçer.
Oluşturulan istemciler
IHttpClientFactory , yeniden sığdırmagibi diğer üçüncü taraf kitaplıklarla birlikte kullanılabilir. Yeniden sığdırma,
.NET için bir REST kitaplığıdır. REST API 'Leri canlı arabirimlere dönüştürür. Bir arabirimin uygulanması, dış
HTTP çağrılarını yapmak için HttpClient kullanılarak RestService tarafından dinamik olarak oluşturulur.
Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:

public interface IHelloClient


{
[Get("/helloworld")]
Task<Reply> GetMessageAsync();
}

public class Reply


{
public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient("hello", c =>
{
c.BaseAddress = new Uri("https://localhost:5001");
})
.AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

services.AddMvc();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHelloClient _client;

public ValuesController(IHelloClient client)


{
_client = client;
}

[HttpGet("/")]
public async Task<ActionResult<Reply>> Index()
{
return await _client.GetMessageAsync();
}
}

Giden istek ara yazılımı


HttpClient , giden HTTP istekleri için bir araya bağlanabilen işleyicileri temsilci seçme kavramıdır.
IHttpClientFactory , her bir adlandırılmış istemci için uygulanacak işleyicileri tanımlamanızı kolaylaştırır. Bir
giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydını ve zincirlemeyi destekler. Bu
işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir. Bu düzen, ASP.NET Core gelen ara yazılım
ardışık düzenine benzer. Bu model, önbelleğe alma, hata işleme, serileştirme ve günlüğe kaydetme dahil olmak
üzere HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar.
Bir işleyici oluşturmak için DelegatingHandlertüretilen bir sınıf tanımlayın. İsteği ardışık düzen içindeki bir
sonraki işleyiciye geçirmeden önce kodu yürütmek için SendAsync yöntemini geçersiz kılın:

public class ValidateHeaderHandler : DelegatingHandler


{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("X-API-KEY"))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"You must supply an API key header called X-API-KEY")
};
}

return await base.SendAsync(request, cancellationToken);


}
}

Yukarıdaki kod, temel bir işleyiciyi tanımlar. İsteğe bağlı bir X-API-KEY üst bilgisi olup olmadığını denetler. Üst
bilgi eksikse, HTTP çağrısından kaçınabilir ve uygun bir yanıt döndürebilir.
Kayıt sırasında, bir HttpClient yapılandırmasına bir veya daha fazla işleyici eklenebilir. Bu görev
IHttpClientBuilderuzantı yöntemleri aracılığıyla gerçekleştirilir.
services.AddTransient<ValidateHeaderHandler>();

services.AddHttpClient("externalservice", c =>
{
// Assume this is an "external" service which requires an API KEY
c.BaseAddress = new Uri("https://localhost:5000/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();

Yukarıdaki kodda ValidateHeaderHandler DI ile kaydedilir. IHttpClientFactory her işleyici için ayrı bir dı kapsamı
oluşturur. İşleyiciler herhangi bir kapsamın hizmetlerine bağlı olarak ücretsizdir. İşleyicilerin bağımlı olduğu
hizmetler, işleyicinin elden çıkarılmasıyla kaldırılır.
Kaydedildikten sonra, işleyicinin türü olarak AddHttpMessageHandler çağrılabilir.
Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir. Her işleyici, son HttpClientHandler isteği
çalıştırana kadar sonraki işleyiciyi sarmalar:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
// This handler is on the outside and called first during the
// request, last during the response.
.AddHttpMessageHandler<SecureRequestHandler>()
// This handler is on the inside, closest to the request being
// sent.
.AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:
HttpRequestMessage.Properties kullanarak işleyicide veri geçirin.
Geçerli isteğe erişmek için IHttpContextAccessor kullanın.
Verileri geçirmek için özel bir AsyncLocal depolama nesnesi oluşturun.

Polly tabanlı işleyiciler kullanın


IHttpClientFactory , Pollyadlı popüler bir üçüncü taraf kitaplıkla tümleştirilir. Polly, .NET için kapsamlı bir
esnekliği ve geçici hata işleme kitaplığıdır. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş
yalıtımı, akıcı ve iş parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.
Uzantı yöntemleri, yapılandırılmış HttpClient örnekleri ile Polly ilkelerin kullanımını etkinleştirmek için sağlanır.
Polly uzantıları:
İstemcilere Polly tabanlı işleyiciler eklemeyi destekler.
, Microsoft. Extensions. http. Polly NuGet paketini yükledikten sonra kullanılabilir. Paket, ASP.NET Core
paylaşılan çerçevesine dahil değildir.
Geçici hataları işle
Yaygın hatalar, dış HTTP çağrıları geçici olduğunda oluşur. AddTransientHttpErrorPolicy adlı, bir ilkenin geçici
hataları işleyecek şekilde tanımlanmasını sağlayan uygun bir genişletme yöntemi vardır. Bu uzantı yöntemiyle
yapılandırılan ilkeler HttpRequestException , HTTP 5xx yanıtları ve HTTP 408 yanıtları.
AddTransientHttpErrorPolicy uzantısı Startup.ConfigureServices içinde kullanılabilir. Uzantı, olası bir geçici
hatayı temsil eden hataları işlemek için yapılandırılmış bir PolicyBuilder nesnesine erişim sağlar:
services.AddHttpClient<UnreliableEndpointCallerService>()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

Yukarıdaki kodda WaitAndRetryAsync bir ilke tanımlanmıştır. Başarısız istekler, denemeler arasındaki 600 MS
gecikmeyle en fazla üç kez yeniden denenir.
Dinamik olarak ilke seçme
Polly tabanlı işleyiciler eklemek için kullanılabilecek ek uzantı yöntemleri vardır. Bu tür bir uzantı birden çok aşırı
yüklemesi olan AddPolicyHandler . Bir aşırı yükleme, hangi ilkenin uygulanacağını tanımlarken isteğin
incelenebilirliğini sağlar:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(


TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
.AddPolicyHandler(request =>
request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır. Diğer HTTP yöntemleri
için, 30 saniyelik bir zaman aşımı kullanılır.
Birden çok Polly işleyici ekleme
Gelişmiş işlevsellik sağlamak için çok fazla ilke iç içe geçmiş bir yaygın hale gelir:

services.AddHttpClient("multiplepolicies")
.AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
.AddTransientHttpErrorPolicy(
p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte, iki işleyici eklenmiştir. İlki, yeniden deneme ilkesi eklemek için AddTransientHttpErrorPolicy
uzantısını kullanır. Başarısız istekler en fazla üç kez yeniden denenir. AddTransientHttpErrorPolicy ikinci çağrısı,
devre kesici ilkesi ekler. Beş başarısız girişim sırayla gerçekleşiyorsa, daha fazla dış istek 30 saniye için engellenir.
Devre kesici ilkeleri durum bilgisi vardır. Bu istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu
paylaşır.
Polly kayıt defterinden ilke ekleme
Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlamak ve bir
PolicyRegistry kaydetmektir. Kayıt defterinden bir ilke kullanılarak bir işleyicinin eklenmesine izin veren bir
genişletme yöntemi sağlanır:

var registry = services.AddPolicyRegistry();

registry.Add("regular", timeout);
registry.Add("long", longTimeout);

services.AddHttpClient("regulartimeouthandler")
.AddPolicyHandlerFromRegistry("regular");

Yukarıdaki kodda, PolicyRegistry ServiceCollection eklendiğinde iki ilke kaydedilir. Kayıt defterinden bir ilke
kullanmak için AddPolicyHandlerFromRegistry yöntemi kullanılır ve uygulanacak ilke adı geçer.
IHttpClientFactory ve Polly tümleştirmeler hakkında daha fazla bilgi, Polly wikiüzerinde bulunabilir.

HttpClient ve ömür yönetimi


IHttpClientFactory``CreateClienther çağrıldığında yeni bir HttpClient örneği döndürülür. Adlandırılmış
istemci başına bir HttpMessageHandler vardır. Fabrika HttpMessageHandler örneklerinin yaşam sürelerini yönetir.
kaynak tüketimini azaltmak için fabrika tarafından oluşturulan HttpMessageHandler örnekleri IHttpClientFactory
havuzlar. HttpMessageHandler bir örnek, süresi dolmamışsa yeni bir HttpClient örneği oluşturulurken havuzdan
yeniden kullanılabilir.
Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.
Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir. Ayrıca, bazı
işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS değişikliklerine yeniden davranmasını
engelleyebilir.
Varsayılan işleyici ömrü iki dakikadır. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir.Bunu
geçersiz kılmak için, istemci oluştururken döndürülen IHttpClientBuilder SetHandlerLifetime çağırın:

services.AddHttpClient("extendedhandlerlifetime")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

İstemcinin çıkarılması gerekli değildir. Aktiften çıkarma giden istekleri iptal eder ve Disposeçağrıldıktan sonra
verilen HttpClient örneğinin kullanılamaz olmasını sağlar. IHttpClientFactory , HttpClient örnekleri tarafından
kullanılan kaynakları izler ve ortadan kaldırır. HttpClient örnekleri genellikle aktiften çıkarma gerektirmeyen
.NET nesneleri olarak kabul edilebilir.
Tek bir HttpClient örneğinin uzun süre canlı tutulması, IHttpClientFactory önünde kullanılmadan önce
kullanılan ortak bir modeldir. Bu kalıp IHttpClientFactory geçtikten sonra gereksiz hale gelir.
Ihttpclientfactory alternatifleri
Dı özellikli bir uygulamada IHttpClientFactory kullanmak şunları önler:
HttpMessageHandler örnekleri havuza alarak kaynak tükenmesi sorunları.
Düzenli aralıklarla HttpMessageHandler örnekleri arasında geçiş yaparak eski DNS sorunları.
Uzun süreli SocketsHttpHandler örneği kullanarak önceki sorunları çözmenin alternatif yolları vardır.
Uygulama başlatıldığında SocketsHttpHandler örneğini oluşturun ve uygulamanın ömrü boyunca kullanın.
PooledConnectionLifetime DNS yenileme zamanına göre uygun bir değere yapılandırın.
Gerektiğinde new HttpClient(handler, dispostHandler: false) kullanarak HttpClient örnekleri oluşturun.
Yukarıdaki yaklaşımlar IHttpClientFactory benzer bir şekilde çözdüğü kaynak yönetimi sorunlarını çözer.
SocketsHttpHandler , HttpClient örnekleri arasında bağlantıları paylaşır. Bu paylaşım, yuva azalmasına engel
olur.
SocketsHttpHandler , eski DNS sorunlarından kaçınmak için bağlantıları PooledConnectionLifetime göre
döngüler.
Özgü
Havuza alınmış HttpMessageHandler örnekleri, CookieContainer nesneleri paylaşılmasına neden olur.
Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır. Tanımlama bilgileri gerektiren
uygulamalar için şunlardan birini göz önünde bulundurun:
Otomatik tanımlama bilgisi işlemeyi devre dışı bırakma
IHttpClientFactory önleme
Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmak için ConfigurePrimaryHttpMessageHandler çağırın:

services.AddHttpClient("configured-disable-automatic-cookies")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
UseCookies = false,
};
});

Günlüğe Kaydetme
Tüm istekler için IHttpClientFactory kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler. Varsayılan günlük
iletilerini görmek için günlük yapılandırmanızda uygun bilgi düzeyini etkinleştirin. İstek üst bilgilerinin günlüğe
kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.
Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir. Örneğin, Mynamedclientadlı bir istemci,
iletileri bir System.Net.Http.HttpClient.MyNamedClient.LogicalHandler kategorisi ile günlüğe kaydeder.
Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur. İstekte, işlem hattındaki diğer
işleyiciler işlenmeden önce iletiler günlüğe kaydedilir. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan
sonra iletiler günlüğe kaydedilir.
Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir. Mynamedclient örneğinde, bu iletiler
System.Net.Http.HttpClient.MyNamedClient.ClientHandler günlük kategorisine göre günlüğe kaydedilir. İstek için
bu, tüm diğer işleyiciler çalıştıktan sonra ve istek ağda gönderilmeden hemen önce gerçekleşir. Yanıtta, bu
günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.
İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından
yapılan değişikliklerin incelemesini etkinleştirir. Bu, örneğin veya yanıt durum kodunda istek başlıklarındaki
değişiklikleri içerebilir.
İstemci adı ' nı log kategorisinde da içermek, gerektiğinde belirli adlandırılmış istemciler için günlük filtrelemeyi
sunar.

HttpMessageHandler 'ı yapılandırma


İstemci tarafından kullanılan iç HttpMessageHandler yapılandırmasını denetlemek gerekli olabilir.
Adlandırılmış veya yazılan istemciler eklenirken bir IHttpClientBuilder döndürülür.
ConfigurePrimaryHttpMessageHandler uzantısı yöntemi bir temsilciyi tanımlamak için kullanılabilir. Temsilci, bu
istemci tarafından kullanılan birincil HttpMessageHandler oluşturmak ve yapılandırmak için kullanılır:

services.AddHttpClient("configured-inner-handler")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});

Konsol uygulamasında ıhttpclientfactory kullanma


Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:
Microsoft. Extensions. Hosting
Microsoft. Extensions. http
Aşağıdaki örnekte:
IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.
MyService , hizmetten bir HttpClient oluşturmak için kullanılan bir istemci fabrikası örneği oluşturur.
HttpClient , bir Web sayfasını almak için kullanılır.
Main , hizmetin GetPage yöntemini yürütmek için bir kapsam oluşturur ve Web sayfası içeriğinin ilk 500
karakterini konsola yazar.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
static async Task<int> Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient();
services.AddTransient<IMyService, MyService>();
}).UseConsoleLifetime();

var host = builder.Build();

using (var serviceScope = host.Services.CreateScope())


{
var services = serviceScope.ServiceProvider;

try
{
var myService = services.GetRequiredService<IMyService>();
var pageContent = await myService.GetPage();

Console.WriteLine(pageContent.Substring(0, 500));
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();

logger.LogError(ex, "An error occurred.");


}
}

return 0;
}

public interface IMyService


{
Task<string> GetPage();
}

public class MyService : IMyService


{
private readonly IHttpClientFactory _clientFactory;

public MyService(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
_clientFactory = clientFactory;
}

public async Task<string> GetPage()


{
// Content from BBC One: Dr. Who website (©BBC)
var request = new HttpRequestMessage(HttpMethod.Get,
"https://www.bbc.co.uk/programmes/b006q2x0");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return $"StatusCode: {response.StatusCode}";
}
}
}
}

Ek kaynaklar
Dayanıklı HTTP isteklerini uygulamak için HttpClientFactory kullanma
HttpClientFactory ve Polly ilkeleriyle üstel geri alma ile HTTP çağrı yeniden denemeleri uygulayın
Devre Kesici desenini uygulama
, Glenn CONDRON, Ryan şimdi eve Steve Gordon
Bir IHttpClientFactory, bir uygulamadaki HttpClient örnekleri yapılandırmak ve oluşturmak için kaydedilebilir ve
kullanılabilir. Aşağıdaki avantajları sunar:
, Mantıksal HttpClient örneklerinin adlandırılması ve yapılandırılması için merkezi bir konum sağlar.
Örneğin, GitHub istemcisi kayıtlı ve GitHub'a erişebilecek şekilde yapılandırılabilir. Varsayılan istemci, diğer
amaçlar için kaydedilebilir.
HttpClient ' de işleyiciler temsilci seçme yoluyla giden ara yazılım kavramını daha da artırır ve bundan
faydalanmak için, Polya tabanlı ara yazılım için uzantılar sağlar.
HttpClient yaşam sürelerini el ile yönetirken gerçekleşen yaygın DNS sorunlarından kaçınmak için temel
HttpClientMessageHandler örneklerinin biriktirmesini ve ömrünü yönetir.
Fabrika tarafından oluşturulan istemcilerle gönderilen tüm istekler için yapılandırılabilir bir günlük deneyimi (
ILogger aracılığıyla) ekler.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Prerequisites
.NET Framework hedefleyen projeler Microsoft. Extensions. http NuGet paketinin yüklenmesini gerektirir. .NET
Core ile hedeflenen ve Microsoft. AspNetCore. app metapackage 'e başvuran projeler zaten
Microsoft.Extensions.Http paketini içerir.

Tüketim desenleri
Bir uygulamada IHttpClientFactory çeşitli yollar vardır:
Temel kullanım
Adlandırılmış istemciler
Yazılan istemciler
Oluşturulan istemciler
Hiçbiri diğerinden tamamen üst değildir. En iyi yaklaşım, uygulamanın kısıtlamalarına bağlıdır.
Temel kullanım
IHttpClientFactory, Startup.ConfigureServices yönteminin içindeki IServiceCollection``AddHttpClient
genişletme yöntemi çağırarak kaydedilebilir.

services.AddHttpClient();

Kaydedildikten sonra kod, bağımlılık ekleme (dı)ile her yerden IHttpClientFactory kabul edebilir.
IHttpClientFactory , bir HttpClient örneği oluşturmak için kullanılabilir:

public class BasicUsageModel : PageModel


{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubBranch> Branches { get; private set; }

public bool GetBranchesError { get; private set; }

public BasicUsageModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

var client = _clientFactory.CreateClient();

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
Branches = await response.Content
.ReadAsAsync<IEnumerable<GitHubBranch>>();
}
else
{
GetBranchesError = true;
Branches = Array.Empty<GitHubBranch>();
}
}
}

Bu biçimde IHttpClientFactory kullanmak, mevcut bir uygulamayı yeniden düzenleme için iyi bir yoldur.
HttpClient kullanılma şekli üzerinde hiçbir etkisi yoktur. HttpClient örneklerinin Şu anda oluşturulduğu
yerlerde, bu oluşumların CreateClientçağrısı ile değiştirin.
Adlandırılmış istemciler
Bir uygulama, her biri farklı bir yapılandırmaya sahip HttpClient birçok farklı kullanım gerektiriyorsa,
adlandırılmış istemcilerkullanılır. Adlandırılmış bir HttpClient yapılandırması, Startup.ConfigureServices
kayıt sırasında belirtilebilir.
services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
// Github API versioning
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
// Github requires a user-agent
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Yukarıdaki kodda AddHttpClient , GitHubadlı adı sağlar. Bu istemci, GitHub API 'SI ile çalışmak için gerekli olan
temel adres ve iki üst bilgiyle—uygulanmış olan bazı varsayılan yapılandırmaları içerir.
CreateClient her çağrıldığında, yeni bir HttpClient örneği oluşturulur ve yapılandırma eylemi çağrılır.
Adlandırılmış bir istemciyi kullanmak için, CreateClient bir dize parametresi geçirilebilir. Oluşturulacak
istemcinin adını belirtin:

public class NamedClientModel : PageModel


{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

public bool GetPullRequestsError { get; private set; }

public bool HasPullRequests => PullRequests.Any();

public NamedClientModel(IHttpClientFactory clientFactory)


{
_clientFactory = clientFactory;
}

public async Task OnGet()


{
var request = new HttpRequestMessage(HttpMethod.Get,
"repos/aspnet/AspNetCore.Docs/pulls");

var client = _clientFactory.CreateClient("github");

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
PullRequests = await response.Content
.ReadAsAsync<IEnumerable<GitHubPullRequest>>();
}
else
{
GetPullRequestsError = true;
PullRequests = Array.Empty<GitHubPullRequest>();
}
}
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez. İstemci için yapılandırılan taban adresi
kullanıldığından, bu yalnızca yolu geçirebilir.
Yazılan istemciler
Yazılan istemciler:
Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.
İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.
Yapılandırmak ve belirli bir HttpClient etkileşimde bulunmak için tek bir konum sağlayın. Örneğin, tek bir
arka uç uç noktası için tek bir adet yazılmış istemci kullanılabilir ve bu uç nokta ile ilgili tüm mantığı
kapsüllenebilir.
DI ile birlikte çalışın ve uygulamanızda gerektiğinde eklenebilir.
Türü belirtilmiş istemci, oluşturucusunda bir HttpClient parametresi kabul eder:

public class GitHubService


{
public HttpClient Client { get; }

public GitHubService(HttpClient client)


{
client.BaseAddress = new Uri("https://api.github.com/");
// GitHub API versioning
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
// GitHub requires a user-agent
client.DefaultRequestHeaders.Add("User-Agent",
"HttpClientFactory-Sample");

Client = client;
}

public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()


{
var response = await Client.GetAsync(
"/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

response.EnsureSuccessStatusCode();

var result = await response.Content


.ReadAsAsync<IEnumerable<GitHubIssue>>();

return result;
}
}

Önceki kodda, yapılandırma yazılan istemciye taşınır. HttpClient nesnesi ortak bir özellik olarak sunulur.
HttpClient işlevselliği ortaya çıkaran API 'ye özel yöntemler tanımlamak mümkündür. GetAspNetDocsIssues
yöntemi, GitHub deposundan en son açık sorunları sorgulamak ve ayrıştırmak için gereken kodu kapsüller.
Türü belirtilmiş bir istemciyi kaydetmek için genel AddHttpClient uzantısı yöntemi, türü belirlenmiş istemci
sınıfını belirterek Startup.ConfigureServices içinde kullanılabilir:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir. Yazılan istemci doğrudan eklenebilir ve tüketilebilir:
public class TypedClientModel : PageModel
{
private readonly GitHubService _gitHubService;

public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

public bool HasIssue => LatestIssues.Any();

public bool GetIssuesError { get; private set; }

public TypedClientModel(GitHubService gitHubService)


{
_gitHubService = gitHubService;
}

public async Task OnGet()


{
try
{
LatestIssues = await _gitHubService.GetAspNetDocsIssues();
}
catch(HttpRequestException)
{
GetIssuesError = true;
LatestIssues = Array.Empty<GitHubIssue>();
}
}
}

Tercih edilirse, yazılan istemcinin yapılandırması, türü belirlenmiş istemcinin Oluşturucusu yerine
Startup.ConfigureServices kayıt sırasında belirtilebilir:

services.AddHttpClient<RepoService>(c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Türü belirlenmiş bir istemci içinde tamamen kapsül HttpClient lemek mümkündür. Bunu bir özellik olarak
göstermek yerine, HttpClient örneğini dahili olarak çağıran ortak Yöntemler sunulabilir.
public class RepoService
{
// _httpClient isn't exposed publicly
private readonly HttpClient _httpClient;

public RepoService(HttpClient client)


{
_httpClient = client;
}

public async Task<IEnumerable<string>> GetRepos()


{
var response = await _httpClient.GetAsync("aspnet/repos");

response.EnsureSuccessStatusCode();

var result = await response.Content


.ReadAsAsync<IEnumerable<string>>();

return result;
}
}

Yukarıdaki kodda HttpClient bir özel alan olarak depolanır. Dış çağrıları yapmak için tüm erişim GetRepos
yönteminden geçer.
Oluşturulan istemciler
IHttpClientFactory , yeniden sığdırmagibi diğer üçüncü taraf kitaplıklarla birlikte kullanılabilir. Yeniden sığdırma,
.NET için bir REST kitaplığıdır. REST API 'Leri canlı arabirimlere dönüştürür. Bir arabirimin uygulanması, dış
HTTP çağrılarını yapmak için HttpClient kullanılarak RestService tarafından dinamik olarak oluşturulur.
Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:

public interface IHelloClient


{
[Get("/helloworld")]
Task<Reply> GetMessageAsync();
}

public class Reply


{
public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddHttpClient("hello", c =>
{
c.BaseAddress = new Uri("http://localhost:5000");
})
.AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

services.AddMvc();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHelloClient _client;

public ValuesController(IHelloClient client)


{
_client = client;
}

[HttpGet("/")]
public async Task<ActionResult<Reply>> Index()
{
return await _client.GetMessageAsync();
}
}

Giden istek ara yazılımı


HttpClient , giden HTTP istekleri için bir araya bağlanabilen işleyicileri temsilci seçme kavramıdır.
IHttpClientFactory , her bir adlandırılmış istemci için uygulanacak işleyicileri tanımlamanızı kolaylaştırır. Bir
giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydını ve zincirlemeyi destekler. Bu
işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir. Bu düzen, ASP.NET Core gelen ara yazılım
ardışık düzenine benzer. Bu model, önbelleğe alma, hata işleme, serileştirme ve günlüğe kaydetme dahil olmak
üzere HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar.
Bir işleyici oluşturmak için DelegatingHandlertüretilen bir sınıf tanımlayın. İsteği ardışık düzen içindeki bir
sonraki işleyiciye geçirmeden önce kodu yürütmek için SendAsync yöntemini geçersiz kılın:

public class ValidateHeaderHandler : DelegatingHandler


{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("X-API-KEY"))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"You must supply an API key header called X-API-KEY")
};
}

return await base.SendAsync(request, cancellationToken);


}
}

Yukarıdaki kod, temel bir işleyiciyi tanımlar. İsteğe bağlı bir X-API-KEY üst bilgisi olup olmadığını denetler. Üst
bilgi eksikse, HTTP çağrısından kaçınabilir ve uygun bir yanıt döndürebilir.
Kayıt sırasında, bir HttpClient yapılandırmasına bir veya daha fazla işleyici eklenebilir. Bu görev
IHttpClientBuilderuzantı yöntemleri aracılığıyla gerçekleştirilir.
services.AddTransient<ValidateHeaderHandler>();

services.AddHttpClient("externalservice", c =>
{
// Assume this is an "external" service which requires an API KEY
c.BaseAddress = new Uri("https://localhost:5000/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();

Yukarıdaki kodda ValidateHeaderHandler DI ile kaydedilir. İşleyicinin, bir geçici hizmet olarak dı 'ye kayıtlı olması
gerekir , hiçbir koşulda kapsamı yoktur. İşleyici kapsamlı bir hizmet olarak kayıtlıysa ve işleyicinin bağımlı
olduğu tüm hizmetler atılabilir olur:
İşleyici kapsam dışına geçmeden önce işleyicinin Hizmetleri atılamaz.
Atılmış işleyici Hizmetleri işleyicinin başarısız olmasına neden olur.
Kaydedildikten sonra, AddHttpMessageHandler, işleyici türünü geçirerek çağrılabilir.
Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir. Her işleyici, son HttpClientHandler isteği
çalıştırana kadar sonraki işleyiciyi sarmalar:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
// This handler is on the outside and called first during the
// request, last during the response.
.AddHttpMessageHandler<SecureRequestHandler>()
// This handler is on the inside, closest to the request being
// sent.
.AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:
HttpRequestMessage.Properties kullanarak işleyicide veri geçirin.
Geçerli isteğe erişmek için IHttpContextAccessor kullanın.
Verileri geçirmek için özel bir AsyncLocal depolama nesnesi oluşturun.

Polly tabanlı işleyiciler kullanın


IHttpClientFactory , Pollyadlı popüler bir üçüncü taraf kitaplıkla tümleştirilir. Polly, .NET için kapsamlı bir
esnekliği ve geçici hata işleme kitaplığıdır. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş
yalıtımı, akıcı ve iş parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.
Uzantı yöntemleri, yapılandırılmış HttpClient örnekleri ile Polly ilkelerin kullanımını etkinleştirmek için sağlanır.
Polly uzantıları:
İstemcilere Polly tabanlı işleyiciler eklemeyi destekler.
, Microsoft. Extensions. http. Polly NuGet paketini yükledikten sonra kullanılabilir. Paket, ASP.NET Core
paylaşılan çerçevesine dahil değildir.
Geçici hataları işle
Yaygın hatalar, dış HTTP çağrıları geçici olduğunda oluşur. AddTransientHttpErrorPolicy adlı, bir ilkenin geçici
hataları işleyecek şekilde tanımlanmasını sağlayan uygun bir genişletme yöntemi vardır. Bu uzantı yöntemiyle
yapılandırılan ilkeler HttpRequestException , HTTP 5xx yanıtları ve HTTP 408 yanıtları.
AddTransientHttpErrorPolicy uzantısı Startup.ConfigureServices içinde kullanılabilir. Uzantı, olası bir geçici
hatayı temsil eden hataları işlemek için yapılandırılmış bir PolicyBuilder nesnesine erişim sağlar:

services.AddHttpClient<UnreliableEndpointCallerService>()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

Yukarıdaki kodda WaitAndRetryAsync bir ilke tanımlanmıştır. Başarısız istekler, denemeler arasındaki 600 MS
gecikmeyle en fazla üç kez yeniden denenir.
Dinamik olarak ilke seçme
Polly tabanlı işleyiciler eklemek için kullanılabilecek ek uzantı yöntemleri vardır. Bu tür bir uzantı birden çok aşırı
yüklemesi olan AddPolicyHandler . Bir aşırı yükleme, hangi ilkenin uygulanacağını tanımlarken isteğin
incelenebilirliğini sağlar:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(


TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
.AddPolicyHandler(request =>
request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır. Diğer HTTP yöntemleri
için, 30 saniyelik bir zaman aşımı kullanılır.
Birden çok Polly işleyici ekleme
Gelişmiş işlevsellik sağlamak için çok fazla ilke iç içe geçmiş bir yaygın hale gelir:

services.AddHttpClient("multiplepolicies")
.AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
.AddTransientHttpErrorPolicy(
p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte, iki işleyici eklenmiştir. İlki, yeniden deneme ilkesi eklemek için AddTransientHttpErrorPolicy
uzantısını kullanır. Başarısız istekler en fazla üç kez yeniden denenir. AddTransientHttpErrorPolicy ikinci çağrısı,
devre kesici ilkesi ekler. Beş başarısız girişim sırayla gerçekleşiyorsa, daha fazla dış istek 30 saniye için engellenir.
Devre kesici ilkeleri durum bilgisi vardır. Bu istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu
paylaşır.
Polly kayıt defterinden ilke ekleme
Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlamak ve bir
PolicyRegistry kaydetmektir. Kayıt defterinden bir ilke kullanılarak bir işleyicinin eklenmesine izin veren bir
genişletme yöntemi sağlanır:

var registry = services.AddPolicyRegistry();

registry.Add("regular", timeout);
registry.Add("long", longTimeout);

services.AddHttpClient("regulartimeouthandler")
.AddPolicyHandlerFromRegistry("regular");

Yukarıdaki kodda, PolicyRegistry ServiceCollection eklendiğinde iki ilke kaydedilir. Kayıt defterinden bir ilke
kullanmak için AddPolicyHandlerFromRegistry yöntemi kullanılır ve uygulanacak ilke adı geçer.
IHttpClientFactory ve Polly tümleştirmeler hakkında daha fazla bilgi, Polly wikiüzerinde bulunabilir.

HttpClient ve ömür yönetimi


IHttpClientFactory``CreateClient her çağrıldığında yeni bir HttpClient örneği döndürülür. Adlandırılmış
istemci başına bir HttpMessageHandler vardır. Fabrika HttpMessageHandler örneklerinin yaşam sürelerini yönetir.
kaynak tüketimini azaltmak için fabrika tarafından oluşturulan HttpMessageHandler örnekleri IHttpClientFactory
havuzlar. HttpMessageHandler bir örnek, süresi dolmamışsa yeni bir HttpClient örneği oluşturulurken havuzdan
yeniden kullanılabilir.
Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.
Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir. Ayrıca, bazı
işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS değişikliklerine yeniden davranmasını
engelleyebilir.
Varsayılan işleyici ömrü iki dakikadır. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir.Bunu
geçersiz kılmak için, istemci oluştururken döndürülen IHttpClientBuilder SetHandlerLifetime çağırın:

services.AddHttpClient("extendedhandlerlifetime")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

İstemcinin çıkarılması gerekli değildir. Aktiften çıkarma giden istekleri iptal eder ve Disposeçağrıldıktan sonra
verilen HttpClient örneğinin kullanılamaz olmasını sağlar. IHttpClientFactory , HttpClient örnekleri tarafından
kullanılan kaynakları izler ve ortadan kaldırır. HttpClient örnekleri genellikle aktiften çıkarma gerektirmeyen
.NET nesneleri olarak kabul edilebilir.
Tek bir HttpClient örneğinin uzun süre canlı tutulması, IHttpClientFactory önünde kullanılmadan önce
kullanılan ortak bir modeldir. Bu kalıp IHttpClientFactory geçtikten sonra gereksiz hale gelir.
Ihttpclientfactory alternatifleri
Dı özellikli bir uygulamada IHttpClientFactory kullanmak şunları önler:
HttpMessageHandler örnekleri havuza alarak kaynak tükenmesi sorunları.
Düzenli aralıklarla HttpMessageHandler örnekleri arasında geçiş yaparak eski DNS sorunları.
Uzun süreli SocketsHttpHandler örneği kullanarak önceki sorunları çözmenin alternatif yolları vardır.
Uygulama başlatıldığında SocketsHttpHandler örneğini oluşturun ve uygulamanın ömrü boyunca kullanın.
PooledConnectionLifetime DNS yenileme zamanına göre uygun bir değere yapılandırın.
Gerektiğinde new HttpClient(handler, dispostHandler: false) kullanarak HttpClient örnekleri oluşturun.
Yukarıdaki yaklaşımlar IHttpClientFactory benzer bir şekilde çözdüğü kaynak yönetimi sorunlarını çözer.
SocketsHttpHandler , HttpClient örnekleri arasında bağlantıları paylaşır. Bu paylaşım, yuva azalmasına engel
olur.
SocketsHttpHandler , eski DNS sorunlarından kaçınmak için bağlantıları PooledConnectionLifetime göre
döngüler.
Özgü
Havuza alınmış HttpMessageHandler örnekleri, CookieContainer nesneleri paylaşılmasına neden olur.
Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır. Tanımlama bilgileri gerektiren
uygulamalar için şunlardan birini göz önünde bulundurun:
Otomatik tanımlama bilgisi işlemeyi devre dışı bırakma
IHttpClientFactory önleme

Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmak için ConfigurePrimaryHttpMessageHandler çağırın:

services.AddHttpClient("configured-disable-automatic-cookies")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
UseCookies = false,
};
});

Günlüğe Kaydetme
Tüm istekler için IHttpClientFactory kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler. Varsayılan günlük
iletilerini görmek için günlük yapılandırmanızda uygun bilgi düzeyini etkinleştirin. İstek üst bilgilerinin günlüğe
kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.
Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir. Örneğin, Mynamedclientadlı bir istemci,
iletileri bir System.Net.Http.HttpClient.MyNamedClient.LogicalHandler kategorisi ile günlüğe kaydeder.
Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur. İstekte, işlem hattındaki diğer
işleyiciler işlenmeden önce iletiler günlüğe kaydedilir. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan
sonra iletiler günlüğe kaydedilir.
Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir. Mynamedclient örneğinde, bu iletiler
System.Net.Http.HttpClient.MyNamedClient.ClientHandler günlük kategorisine göre günlüğe kaydedilir. İstek için
bu, tüm diğer işleyiciler çalıştıktan sonra ve istek ağda gönderilmeden hemen önce gerçekleşir. Yanıtta, bu
günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.
İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından
yapılan değişikliklerin incelemesini etkinleştirir. Bu, örneğin veya yanıt durum kodunda istek başlıklarındaki
değişiklikleri içerebilir.
İstemci adı ' nı log kategorisinde da içermek, gerektiğinde belirli adlandırılmış istemciler için günlük filtrelemeyi
sunar.

HttpMessageHandler 'ı yapılandırma


İstemci tarafından kullanılan iç HttpMessageHandler yapılandırmasını denetlemek gerekli olabilir.
Adlandırılmış veya yazılan istemciler eklenirken bir IHttpClientBuilder döndürülür.
ConfigurePrimaryHttpMessageHandler uzantısı yöntemi bir temsilciyi tanımlamak için kullanılabilir. Temsilci, bu
istemci tarafından kullanılan birincil HttpMessageHandler oluşturmak ve yapılandırmak için kullanılır:

services.AddHttpClient("configured-inner-handler")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});
Konsol uygulamasında ıhttpclientfactory kullanma
Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:
Microsoft. Extensions. Hosting
Microsoft. Extensions. http
Aşağıdaki örnekte:
IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.
MyService , hizmetten bir HttpClient oluşturmak için kullanılan bir istemci fabrikası örneği oluşturur.
HttpClient , bir Web sayfasını almak için kullanılır.
Main , hizmetin GetPage yöntemini yürütmek için bir kapsam oluşturur ve Web sayfası içeriğinin ilk 500
karakterini konsola yazar.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
static async Task<int> Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient();
services.AddTransient<IMyService, MyService>();
}).UseConsoleLifetime();

var host = builder.Build();

using (var serviceScope = host.Services.CreateScope())


{
var services = serviceScope.ServiceProvider;

try
{
var myService = services.GetRequiredService<IMyService>();
var pageContent = await myService.GetPage();

Console.WriteLine(pageContent.Substring(0, 500));
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();

logger.LogError(ex, "An error occurred.");


}
}

return 0;
}

public interface IMyService


{
Task<string> GetPage();
}

public class MyService : IMyService


{
private readonly IHttpClientFactory _clientFactory;
public MyService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}

public async Task<string> GetPage()


{
// Content from BBC One: Dr. Who website (©BBC)
var request = new HttpRequestMessage(HttpMethod.Get,
"https://www.bbc.co.uk/programmes/b006q2x0");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return $"StatusCode: {response.StatusCode}";
}
}
}
}

Ek kaynaklar
Dayanıklı HTTP isteklerini uygulamak için HttpClientFactory kullanma
HttpClientFactory ve Polly ilkeleriyle üstel geri alma ile HTTP çağrı yeniden denemeleri uygulayın
Devre Kesici desenini uygulama
ASP.NET Core statik dosyalar
3.12.2019 • 14 minutes to read • Edit Online

By Rick Anderson ve Scott Ade


HTML, CSS, resim ve JavaScript gibi statik dosyalar, ASP.NET Core bir uygulamanın doğrudan istemcilere
hizmet verdiği varlıklardır. Bu dosyalara hizmet sunma özelliğini etkinleştirmek için bazı yapılandırmalar
gerekir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Statik dosyaları sunma


Statik dosyalar projenin Web kök dizininde depolanır. Varsayılan dizin {Content root}/Wwwroot, ancak
usewebroot yöntemi aracılığıyla değiştirilebilir. Daha fazla bilgi için bkz. içerik kökü ve Web kök .
Uygulamanın Web ana bilgisayarı, içerik kök dizininden haberdar olmalıdır.
WebHost.CreateDefaultBuilder yöntemi, içerik kökünü geçerli dizine ayarlar:

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

Program.Main içinde Usecontentroot 'yi çağırarak içerik kökünü geçerli dizine ayarlayın:

public class Program


{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();

host.Run();
}
}

Statik dosyalara, Web kökünegöre bir yol aracılığıyla erişilebilir. Örneğin, Web uygulaması proje şablonu
Wwwroot klasörü içinde birkaç klasör içerir:
Wwwroot
Self
yansımasını
JS
Görüntüler alt klasöründeki bir dosyaya erışmek için URI biçimi, http://<server_address
>/images/<image_file_name > . Örneğin, http://localhost:9189/images/banner3.svg .
.NET Framework hedefliyorsanız, Microsoft. AspNetCore. StaticFiles paketini projeye ekleyin. .NET Core
hedefleniyorsa, Microsoft. AspNetCore. app metapackage bu paketi içerir.
.NET Framework hedefliyorsanız, Microsoft. AspNetCore. StaticFiles paketini projeye ekleyin. .NET Core
hedefleniyorsa, Microsoft. AspNetCore. All metapackage bu paketi içerir.
Projeye Microsoft. AspNetCore. StaticFiles paketini ekleyin.
Statik dosyaları sunmaya izin veren ara yazılımı yapılandırın.
Web kökünün içindeki dosyaları sunma
Startup.Configure içinde Usestaticfiles metodunu çağırın:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles();
}

Parametresiz UseStaticFiles yöntemi aşırı yüklemesi, Web kökündeki dosyaları servable olarak işaretler.
Aşağıdaki biçimlendirme Wwwroot/Images/banner1. SVGöğesine başvuruyor:

<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

Yukarıdaki kodda, tilde karakteri Web köküneişaret eder ~/ .


Dosyaları Web kökünün dışında sunma
Sunulacak statik dosyaların Web kökünündışında yer aldığı bir dizin hiyerarşisini göz önünde bulundurun:
Wwwroot
Self
yansımasını
JS
MyStaticFiles
yansımasını
banner1. SVG
Bir istek statik dosya ara yazılımını aşağıdaki şekilde yapılandırarak banner1. SVG dosyasına erişebilir:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles(); // For the wwwroot folder

app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
}
Yukarıdaki kodda, mystaticfiles dizin hiyerarşisi, staticfiles URI segmenti aracılığıyla herkese açıktır.
Http://<server_address >/StaticFiles/images/banner1.SVG için bir istek banner1. SVG dosyasına hizmet
verir.
Aşağıdaki biçimlendirme Mystaticfiles/Images/banner1. SVG' ye başvurur:

<img src="~/StaticFiles/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

HTTP yanıt üstbilgilerini ayarla


Staticfileoptions NESNESI, http yanıt üst bilgilerini ayarlamak için kullanılabilir. Web kökündenstatik dosya
sunma yapılandırmasına ek olarak, aşağıdaki kod Cache-Control üst bilgisini ayarlar:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
var cachePeriod = env.IsDevelopment() ? "600" : "604800";
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
// Requires the following import:
// using Microsoft.AspNetCore.Http;
ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={cachePeriod}");
}
});
}

Headerdictionaryextensions. Append yöntemi, Microsoft. Aspnetcore. http paketinde bulunur.


Dosyalar, geliştirme ortamında 10 dakika (600 saniye) için genel olarak önbelleklenebilir hale getirilir:

Statik dosya yetkilendirmesi


Statik dosya ara yazılımı yetkilendirme denetimleri sağlamıyor. Wwwrootaltındakiler de dahil olmak üzere
hizmet tarafından sunulan tüm dosyalar herkese açık olarak erişilebilir. Dosyalara yetkilendirme temelinde
hizmeti sağlamak için:
Onları Wwwroot dışında ve statik dosya ara yazılımı tarafından erişilebilen herhangi bir dizinle
saklayın.
Yetkilendirmeyi uygulanan bir eylem yöntemi aracılığıyla onlara sunar. Bir FileResult nesnesi
döndürür:

[Authorize]
public IActionResult BannerImage()
{
var file = Path.Combine(Directory.GetCurrentDirectory(),
"MyStaticFiles", "images", "banner1.svg");

return PhysicalFile(file, "image/svg+xml");


}
Dizin taramayı etkinleştir
Dizin tarama, Web uygulamanızın kullanıcılarına belirtilen bir dizin içindeki bir dizin listesini ve dosyalarını
görmesini sağlar. Dizin tarama, güvenlik nedenleriyle varsayılan olarak devre dışıdır (bkz. hususlar).
Startup.Configure içinde Usedirectorybrowser metodunu çağırarak dizin taramayı etkinleştirin:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles(); // For the wwwroot folder

app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});
}

Startup.ConfigureServices adresinden Adddirectorybrowser yöntemini çağırarak gerekli hizmetleri ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddDirectoryBrowser();
}

Yukarıdaki kod, her bir dosya ve klasörün bağlantılarıyla birlikte http://<server_address >/myImagesURL
'sini kullanarak Wwwroot/görüntüler klasöründe Dizin taramasına izin verir:

Göz atmayı etkinleştirirken güvenlik riskleri hakkındaki noktalara göz atın.


Aşağıdaki örnekte iki UseStaticFiles çağrısı olduğunu aklınızda edin. İlk çağrı Wwwroot klasöründeki statik
dosyaları sunmaya izin veriyor. İkinci çağrı, http://<server_address >/myImagesURL 'sini kullanarak
Wwwroot/görüntüler klasöründe dizin taramayı mümkün bir şekilde sunar:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(); // For the wwwroot folder

app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});
}

Varsayılan bir belge sunar


Varsayılan ana sayfanın ayarlanması, ziyaretçi sitenizi ziyaret ederken mantıksal bir başlangıç noktası sağlar.
Kullanıcı URI 'yi tamamen nitelemeden varsayılan bir sayfaya hizmeti sağlamak için Startup.Configure ' den
Usedefaultfiles metodunu çağırın:

public void Configure(IApplicationBuilder app)


{
app.UseDefaultFiles();
app.UseStaticFiles();
}

IMPORTANT
Varsayılan dosyayı kullanabilmek için UseStaticFiles önce UseDefaultFiles çağrılmalıdır. UseDefaultFiles ,
dosyayı gerçekten sunan bir URL yeniden yazar. Dosyayı çalıştırmak için UseStaticFiles aracılığıyla statik dosya ara
yazılımı etkinleştirin.

UseDefaultFiles , bir klasör için arama istekleri:


default. htm
default. html
index. htm
index. html
Listedeki ilk dosya, istek tam URI olmasına rağmen olarak sunulur. Tarayıcı URL 'SI, istenen URI 'yi
yansıtacak şekilde devam ediyor.
Aşağıdaki kod varsayılan dosya adını mydefault. htmlolarak değiştirir:
public void Configure(IApplicationBuilder app)
{
// Serve my app-specific default file, if present.
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
}

Usedosya sunucusu
UseFileServer, UseStaticFiles , UseDefaultFiles ve isteğe bağlı olarak UseDirectoryBrowser işlevlerini
birleştirir.
Aşağıdaki kod, statik dosyaların ve varsayılan dosyanın kullanılmasına izin veriyor. Dizin tarama etkin değil.

app.UseFileServer();

Aşağıdaki kod, dizin taramayı etkinleştirerek Parametresiz aşırı yüklemeden sonra oluşturulur:

app.UseFileServer(enableDirectoryBrowsing: true);

Aşağıdaki dizin hiyerarşisini göz önünde bulundurun:


Wwwroot
Self
yansımasını
JS
MyStaticFiles
yansımasını
banner1. SVG
default. html
Aşağıdaki kod, MyStaticFiles statik dosyaları, varsayılan dosyaları ve dizin taramayı mümkün bir şekilde
sunar:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles(); // For the wwwroot folder

app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
}

AddDirectoryBrowser , EnableDirectoryBrowsing Özellik değeri true olduğunda çağrılmalıdır:


public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}

Dosya hiyerarşisini ve önceki kodu kullanarak, URL 'Ler aşağıdaki şekilde çözümlenir:

{1>URI<1} YANITIYLA

http://<server_address >/StaticFiles/images/banner1.svg MyStaticFiles/Images/banner1. SVG

http://<server_address >/StaticFiles MyStaticFiles/default.html

Mystaticfiles dizininde varsayılan adlı dosya yoksa, http://<server_address >/staticfiles , tıklanabilir


bağlantılarla dizin listesini döndürür:

NOTE
UseDefaultFiles ve UseDirectoryBrowser http://{SERVER ADDRESS}/StaticFiles (sondaki eğik çizgi olmadan)
( )
http://{SERVER ADDRESS}/StaticFiles/ için sondaki eğik çizgiyle istemci tarafı yeniden yönlendirmesi
gerçekleştirin. Staticfiles dizinindeki göreli URL 'ler, sondaki eğik çizgi olmadan geçersizdir.

FileExtensionContentTypeProvider
Fileextensioncontenttypeprovider sınıfı, MIME içerik türlerine dosya uzantılarının eşlemesi olarak hizmet
veren bir Mappings özelliği içerir. Aşağıdaki örnekte, bazı dosya uzantıları bilinen MIME türlerine kaydedilir. .
Rtf uzantısı değiştirilmiştir ve . mp4 kaldırılır.
public void Configure(IApplicationBuilder app)
{
// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
// Remove MP4 videos.
provider.Mappings.Remove(".mp4");

app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages",
ContentTypeProvider = provider
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/MyImages"
});
}

Bkz. MIME içerik türleri.

Standart olmayan içerik türleri


Statik dosya ara yazılımı, neredeyse 400 bilinen dosya içerik türlerini anlamıştır. Kullanıcı bilinmeyen bir
dosya türüne sahip bir dosya isterse, statik dosya ara yazılımı isteği ardışık düzendeki bir sonraki ara
yazılıma geçirir. Bir ara yazılım, isteği işlediğinde, bir 404 bulunamadı yanıtı döndürülür. Dizin tarama
etkinse, bir dizin listesinde dosyaya bir bağlantı görüntülenir.
Aşağıdaki kod, bilinmeyen türlere hizmet olarak bilinmeyen türler sunar ve bilinmeyen dosyayı görüntü
olarak işler:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
}

Yukarıdaki kodla, bilinmeyen içerik türüne sahip bir dosya isteği görüntü olarak döndürülür.

WARNING
ServeUnknownFileTypes etkinleştirme bir güvenlik riskidir. Varsayılan olarak devre dışıdır ve kullanımı önerilmez.
Fileextensioncontenttypeprovider standart olmayan uzantılara sahip dosyalara hizmet vermeye yönelik daha güvenli
bir alternatif sağlar.

Birden çok konumdan dosyaları sunma


UseStaticFiles ve UseFileServer , Wwwroot' a işaret eden dosya sağlayıcısına varsayılan olarak sahiptir.
Diğer konumlardan dosya sunmak için diğer dosya sağlayıcılarıyla UseStaticFiles ve UseFileServer ek
örnekleri sağlayabilirsiniz. Daha fazla bilgi için Bu GitHub sorununabakın.
Dikkat Edilecekler

WARNING
UseDirectoryBrowser ve UseStaticFiles gizli dizileri sızıntısına neden olabilir. Üretimde dizin taramayı devre dışı
bırakmak önemle önerilir. Hangi dizinlerin UseStaticFiles veya UseDirectoryBrowser aracılığıyla etkinleştirildiğini
dikkatle gözden geçirin. Tüm dizin ve alt dizinleri herkese açık şekilde erişilebilir hale gelir. <content_root
>/Wwwrootgibi özel bir dizinde herkese sunma için uygun dosyaları depolayın. Bu dosyaları MVC görünümlerinden
ayırın, Razor Pages (yalnızca 2. x), yapılandırma dosyaları vb.

UseDirectoryBrowserve UseStaticFiles birlikte sunulan içerik URL 'Leri, temel dosya sisteminin
büyük/küçük harf duyarlılığı ve karakter kısıtlamalarına tabidir. Örneğin, Windows büyük/küçük harfe
duyarsız—macOS ve Linux değildir.
IIS 'de barındırılan ASP.NET Core uygulamalar, statik dosya istekleri de dahil olmak üzere tüm
istekleri uygulamaya iletmek için ASP.NET Core modülünü kullanır. IIS statik dosya işleyicisi
kullanılmıyor. Modül tarafından işlenmek üzere istekleri işleme şansı yoktur.
Sunucu veya Web sitesi düzeyinde IIS statik dosya işleyicisini kaldırmak için IIS Yöneticisi ' nde
aşağıdaki adımları uygulayın:
1. Modüller özelliğine gidin.
2. Listeden StaticFileModule ' ü seçin.
3. Eylemler kenar çubuğunda Kaldır ' a tıklayın.

WARNING
IIS statik dosya işleyicisi etkinse ve ASP.NET Core modülü yanlış yapılandırılmışsa, statik dosyalar sunulur. Bu, örneğin,
Web. config dosyası dağıtılmamışsa oluşur.

Kod dosyalarını ( . cs ve . cshtmldahil) uygulama projesinin Web kökünündışına yerleştirin. Bu nedenle,


uygulamanın istemci tarafı içeriği ile sunucu tabanlı kod arasında bir mantıksal ayrım oluşturulur. Bu,
sunucu tarafı kodun sızmasını önler.

Ek kaynaklar
Ara Yazılım
ASP.NET Core giriş
ASP.NET Core Razor Pages giriş
6.12.2019 • 66 minutes to read • Edit Online

By Rick Anderson ve Ryan şimdi ak


Razor Pages, kodlama sayfasına odaklanmış senaryolar denetleyicileri ve görünümleri kullanmaktan
daha kolay ve daha üretken hale getirebilirsiniz.
Model-View -Controller yaklaşımını kullanan bir öğretici arıyorsanız, bkz. ASP.NET Core MVC ile
çalışmaya başlama.
Bu belge Razor Pages bir giriş sağlar. Adım adım öğretici değildir. Bölümlerden bazılarını çok
gelişmiş bir şekilde bulursanız, bkz. Razor Pages kullanmaya başlama. ASP.NET Core genel bir bakış
için bkz. ASP.NET Core giriş.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Razor Pages projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Razor Pages projesi oluşturma hakkında ayrıntılı yönergeler için bkz. Razor Pages kullanmaya
başlama .

Razor Pages
Razor Pages, Startup.cs'de etkinleştirilmiştir:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}

Temel bir sayfa düşünün:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

Yukarıdaki kod, denetleyiciler ve görünümlerle ASP.NET Core bir uygulamada kullanılan Razor
görünüm dosyası gibi bir çok şey arar. Bu, farklı kılan @page yönergedir. @page , dosyayı bir
denetleyiciye geçmeden doğrudan istekleri işlediği anlamına gelen bir MVC eylemine sahip olur.
@page sayfadaki ilk Razor yönergesi olmalıdır. @page diğer Razor yapıları davranışını etkiler. Razor
Pages dosya adlarında . cshtml soneki vardır.
PageModel sınıfı kullanan benzer bir sayfa aşağıdaki iki dosyada gösterilmiştir. Pages/Index2. cshtml
dosyası:
@page
@using RazorPagesIntro.Pages
@model Index2Model

<h2>Separate page model</h2>


<p>
@Model.Message
</p>

Pages/Index2. cshtml. cs sayfa modeli:

using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;

namespace RazorPagesIntro.Pages
{
public class Index2Model : PageModel
{
public string Message { get; private set; } = "PageModel in C#";

public void OnGet()


{
Message += $" Server time is { DateTime.Now }";
}
}
}

Kurala göre PageModel sınıf dosyası, . cs eklenmiş Razor sayfası dosyasıyla aynı ada sahiptir. Örneğin,
önceki Razor sayfası Pages/Index2. cshtml' dir. PageModel sınıfını içeren dosya sayfa/Index2. cshtml.
csolarak adlandırılır.
URL yollarının sayfalara olan ilişkilendirmeleri, sayfanın dosya sistemindeki konumuna göre
belirlenir. Aşağıdaki tabloda bir Razor sayfa yolu ve eşleşen URL gösterilmektedir:

DOSYA ADI VE YOLU EŞLEŞEN URL

/Pages/Index.cshtml / veya /Index

/Pages/Contact.exe /Contact

/Pages/Store/Contact.exe /Store/Contact

/Pages/Store/Index.cshtml /Store veya /Store/Index

Notlar:
Çalışma zamanı, Sayfalar klasöründeki Razor Pages dosyaları varsayılan olarak arar.
Index , URL bir sayfa içermiyorsa varsayılan sayfasıdır.

Temel form yazma


Razor Pages, Web tarayıcıları ile kullanılan ortak desenleri bir uygulama oluştururken kolayca
uygulanması için tasarlanmıştır. Model bağlama, ETIKET yardımcılarıve HTML Yardımcıları hepsi,
Razor sayfası sınıfında tanımlanan özelliklerle çalışır . Contact modeli için temel bir "bize başvurun"
formu uygulayan bir sayfa düşünün:
Bu belgedeki örnekler için DbContext , Startup.cs dosyasında başlatılır.

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<CustomerDbContext>(options =>
options.UseInMemoryDatabase("name"));
services.AddRazorPages();
}

Veri modeli:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }

[Required, StringLength(10)]
public string Name { get; set; }
}
}

DB bağlamı:

using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Models;

namespace RazorPagesContacts.Data
{
public class CustomerDbContext : DbContext
{
public CustomerDbContext(DbContextOptions options)
: base(options)
{
}

public DbSet<Customer> Customers { get; set; }


}
}

Pages/Create. cshtml görünüm dosyası:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

Pages/Create. cshtml. cs sayfa modeli:


using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
using RazorPagesContacts.Models;
using System.Threading.Tasks;

namespace RazorPagesContacts.Pages.Customers
{
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;

public CreateModel(CustomerDbContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customers.Add(Customer);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}
}

Kurala göre PageModel sınıfı <PageName>Model olarak adlandırılır ve sayfayla aynı ad alanında yer
alan.
PageModel sınıfı, bir sayfa mantığının sunumundaki ayırmayı sağlar. Sayfaya gönderilen istekler için
sayfa işleyicilerini ve sayfayı işlemek için kullanılan verileri tanımlar. Bu ayrım şunları sağlar:
Bağımlılık eklemeyoluyla sayfa bağımlılıklarını yönetme.
Birim testi
Sayfada, POST isteklerinde çalışan bir OnPostAsync işleyicisi yöntemivardır (bir Kullanıcı formu
gönderdiğinde). Herhangi bir HTTP fiili için işleyici metotları eklenebilir. En yaygın işleyiciler
şunlardır:
Sayfanın başlatılması için gereken durum OnGet . Yukarıdaki kodda OnGet yöntemi CreateModel.
cshtml Razor sayfasını görüntüler.
form gönderilerini işlemek için OnPost .

Async adlandırma son eki isteğe bağlıdır, ancak genellikle zaman uyumsuz işlevler için kural
tarafından kullanılır. Yukarıdaki kod Razor Pages için tipik bir davranıştır.
Denetleyicileri ve görünümleri kullanarak ASP.NET uygulamaları hakkında bilginiz varsa:
Yukarıdaki örnekteki OnPostAsync kodu, tipik denetleyici koduna benzer şekilde görünür.
Model bağlama, doğrulamave eylem sonuçları gibi mvc temel elemanlarının çoğu denetleyiciler
ve Razor Pages aynı şekilde çalışır.
Önceki OnPostAsync yöntemi:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customers.Add(Customer);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

OnPostAsync temel akışı:


Doğrulama hatalarını kontrol edin.
Hata yoksa, verileri kaydedin ve yeniden yönlendirin.
Hatalar varsa, doğrulama iletileriyle sayfayı yeniden görüntüleyin. Çoğu durumda, doğrulama
hataları istemci üzerinde algılanır ve sunucuya hiçbir zaman gönderilmez.
Pages/Create. cshtml görünüm dosyası:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

Sayfalardan işlenmiş HTML /Create. cshtml:

<p>Enter a customer name:</p>

<form method="post">
Name:
<input type="text" data-val="true"
data-val-length="The field Name must be a string with a maximum length of 10."
data-val-length-max="10" data-val-required="The Name field is required."
id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
<input type="submit" />
<input name="__RequestVerificationToken" type="hidden"
value="<Antiforgery token here>" />
</form>

Önceki kodda, formu deftere nakletme:


Geçerli verilerle:
OnPostAsync Handler yöntemi RedirectToPage yardımcı yöntemini çağırır.
RedirectToPage , bir RedirectToPageResult örneği döndürür. RedirectToPage :
Bir eylem sonucudur.
RedirectToAction veya RedirectToRoute benzerdir (denetleyiciler ve görünümlerde
kullanılır).
Sayfalar için özelleştirilir. Önceki örnekte, kök dizin sayfasına ( /Index ) yeniden
yönlendirir. RedirectToPage , Sayfalar Için URL oluşturma bölümünde ayrıntılı olarak
açıklanmıştır.
Sunucuya geçirilen doğrulama hatalarıyla birlikte:
OnPostAsync Handler yöntemi Page yardımcı yöntemini çağırır. Page , bir PageResult
örneği döndürür. Page döndürmek, denetleyicilerde eylemlerin View nasıl dönüşlerine
benzer. PageResult , bir işleyici yöntemi için varsayılan dönüş türüdür. void döndüren bir
işleyici yöntemi sayfayı işler.
Yukarıdaki örnekte, formun hiçbir değer olmadan nakledilmesi ModelState ile sonuçlanır.
IsValid yanlış döndürüyor. Bu örnekte, istemcide hiçbir doğrulama hatası gösterilmezler.
Doğrulama hatası teslim etme bu belgenin ilerleyen bölümlerinde ele alınmıştır.

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customers.Add(Customer);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

İstemci tarafı doğrulaması tarafından algılanan doğrulama hatalarıyla birlikte:


Veriler sunucuya nakledilmedi.
İstemci tarafı doğrulaması bu belgenin ilerleyen kısımlarında açıklanmıştır.
Customer özelliği, model bağlamasını kabul etmek için [BindProperty] özniteliğini kullanır:
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;

public CreateModel(CustomerDbContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customers.Add(Customer);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}

, istemci tarafından değiştirilmemesi gereken özellikler içeren modellerde


[BindProperty]
kullanılmamalıdır. Daha fazla bilgi için bkz. fazla nakil.
Razor Pages, varsayılan olarak, özellikleri yalnızca GET olmayan fiiller ile bağlayın. Özelliklere
bağlama, HTTP verilerini model türüne dönüştürmek için kod yazma ihtiyacını ortadan kaldırır.
Bağlama, form alanlarını işlemek için aynı özelliği kullanarak kodu azaltır (
<input asp-for="Customer.Name"> ) ve girişi kabul eder.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir.
Özelliklerle eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine
veya rota değerlerine dayanan senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true
olarak ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Sayfalar/oluşturma. cshtml görünüm dosyası gözden geçiriliyor:


@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

Yukarıdaki kodda, giriş etiketi yardımcısı <input asp-for="Customer.Name" /> HTML <input>
öğesini Customer.Name model ifadesine bağlar.
@addTagHelper etiket yardımcılarını kullanılabilir hale getirir.

Giriş sayfası
Index. cshtml giriş sayfasıdır:

@page
@model RazorPagesContacts.Pages.Customers.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Contacts home page</h1>


<form method="post">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Customer)
{
<tr>
<td> @contact.Id </td>
<td>@contact.Name</td>
<td>
<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
<button type="submit" asp-page-handler="delete"
asp-route-id="@contact.Id">delete
</button>
</td>
</tr>
}
</tbody>
</table>
<a asp-page="Create">Create New</a>
</form>

İlişkili PageModel sınıfı (Index.cshtml.cs):


public class IndexModel : PageModel
{
private readonly CustomerDbContext _context;

public IndexModel(CustomerDbContext context)


{
_context = context;
}

public IList<Customer> Customer { get; set; }

public async Task OnGetAsync()


{
Customer = await _context.Customers.ToListAsync();
}

public async Task<IActionResult> OnPostDeleteAsync(int id)


{
var contact = await _context.Customers.FindAsync(id);

if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}

return RedirectToPage();
}
}

Index. cshtml dosyası aşağıdaki biçimlendirmeyi içerir:

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |

<a /a> tutturucu etiketi Yardımcısı , düzenleme sayfasına bir bağlantı oluşturmak için
asp-route-{value} özniteliğini kullandı. Bağlantı, iletişim KIMLIĞINE sahip rota verileri içerir.
Örneğin: https://localhost:5001/Edit/1 . Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin
oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştir.
Index. cshtml dosyası her müşteri için bir silme düğmesi oluşturmak için biçimlendirme içerir:

<button type="submit" asp-page-handler="delete"


asp-route-id="@contact.Id">delete

İşlenmiş HTML:

<button type="submit" formaction="/Customers?id=1&amp;handler=delete">delete</button>

Sil düğmesi HTML 'de işlendiğinde, bu nesnenin biçimlendirme parametreleri içerir:


asp-route-id özniteliğiyle belirtilen müşteri iletişim KIMLIĞI.
asp-page-handler özniteliğiyle belirtilen handler .

Düğme seçildiğinde, sunucuya bir form POST isteği gönderilir. Kurala göre, işleyici yönteminin adı,
düzen OnPost[handler]Async göre handler parametresinin değerine göre seçilir.
Bu örnekte handler delete olduğundan, OnPostDeleteAsync Handler yöntemi POST isteğini
işlemek için kullanılır. asp-page-handler , remove gibi farklı bir değere ayarlandıysa
OnPostRemoveAsync ada sahip bir işleyici yöntemi seçilidir.

public async Task<IActionResult> OnPostDeleteAsync(int id)


{
var contact = await _context.Customers.FindAsync(id);

if (contact != null)
{
_context.Customers.Remove(contact);
await _context.SaveChangesAsync();
}

return RedirectToPage();
}

OnPostDeleteAsync Yöntemi:
Sorgu dizesinden id alır.
FindAsync ile müşteri iletişim için veritabanını sorgular.
Müşteri ilgili kişisi bulunursa, kaldırılır ve veritabanı güncelleştirilir.
Kök dizin sayfasına yeniden yönlendirmek için RedirectToPage çağırır ( /Index ).
Edit. cshtml dosyası

@page "{id:int}"
@model RazorPagesContacts.Pages.Customers.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Edit Customer - @Model.Customer.Id</h1>


<form method="post">
<div asp-validation-summary="All"></div>
<input asp-for="Customer.Id" type="hidden" />
<div>
<label asp-for="Customer.Name"></label>
<div>
<input asp-for="Customer.Name" />
<span asp-validation-for="Customer.Name"></span>
</div>
</div>

<div>
<button type="submit">Save</button>
</div>
</form>

İlk satır @page "{id:int}" yönergesini içerir. Yönlendirme kısıtlaması "{id:int}" , sayfaya istekleri
int yönlendirme verileri içeren sayfaya kabul etmesini söyler. Sayfaya yapılan bir istek bir int
dönüştürülebildiği rota verileri içermiyorsa, çalışma zamanı bir HTTP 404 (bulunamadı) hatası
döndürür. KIMLIĞI isteğe bağlı yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

Edit.cshtml.cs dosyası:
public class EditModel : PageModel
{
private readonly CustomerDbContext _context;

public EditModel(CustomerDbContext context)


{
_context = context;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnGetAsync(int id)


{
Customer = await _context.Customers.FindAsync(id);

if (Customer == null)
{
return RedirectToPage("./Index");
}

return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Customer).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw new Exception($"Customer {Customer.Id} not found!");
}

return RedirectToPage("./Index");
}

Doğrulama
Doğrulama kuralları:
Model sınıfında bildirimli olarak belirtilir.
Uygulamada her yerde zorlanır.
System.ComponentModel.DataAnnotations ad alanı, bir sınıfa veya özelliğe bildirimli olarak
uygulanan bir yerleşik doğrulama öznitelikleri kümesi sağlar. Veri açıklamaları, biçimlendirme ile
yardım eden [DataType] gibi biçimlendirme özniteliklerini de içerir ve herhangi bir doğrulama
sağlamaz.
Customer modelini göz önünde bulundurun:
using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
public class Customer
{
public int Id { get; set; }

[Required, StringLength(10)]
public string Name { get; set; }
}
}

Aşağıdaki Create. cshtml görünüm dosyasını kullanarak:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Validation: customer name:</p>

<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

Yukarıdaki kod:
JQuery ve jQuery doğrulama betikleri içerir.
Etkinleştirmek için <div /> ve <span /> etiketi yardımcıları kullanır:
İstemci tarafı doğrulama.
Doğrulama hatası işleme.
Aşağıdaki HTML 'yi oluşturur:

<p>Enter a customer name:</p>

<form method="post">
Name:
<input type="text" data-val="true"
data-val-length="The field Name must be a string with a maximum length of 10."
data-val-length-max="10" data-val-required="The Name field is required."
id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
<input type="submit" />
<input name="__RequestVerificationToken" type="hidden"
value="<Antiforgery token here>" />
</form>

<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

Create formunu ad değeri olmadan göndermek "ad alanı gereklidir" hata iletisini görüntüler.
formunda. İstemcide JavaScript etkinse tarayıcı, sunucuya göndermeden hatayı görüntüler.
[StringLength(10)] özniteliği işlenmiş HTML üzerinde data-val-length-max="10" oluşturur.
data-val-length-max , tarayıcıların belirtilen uzunluk üst sınırından daha fazlasını girmesini engeller.
Gönderiyi düzenlemek ve yeniden oynatmak için Fiddler gibi bir araç kullanılıyorsa:
, Adı 10 ' dan daha uzun.
"Alan adı, en fazla 10 uzunluğunda bir dize olmalıdır" hata iletisi. döndürülür.
Aşağıdaki Movie modelini göz önünde bulundurun:

public class Movie


{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}

Doğrulama öznitelikleri, uygulanan model özellikleri üzerinde zorlamak için davranışı belirtir:
Required ve MinimumLength öznitelikleri bir özelliğin bir değere sahip olması gerektiğini
belirtir, ancak hiçbir şey, kullanıcının bu doğrulamayı karşılamak için boşluk girmesini engeller.
RegularExpression özniteliği, hangi karakterlerin giriş yapabileceğini sınırlamak için kullanılır.
Yukarıdaki kodda, "tarz":
Yalnızca harfler kullanılmalıdır.
İlk harfin büyük harfle olması gerekir. Boşluk, sayı ve özel karakterlere izin verilmez.
RegularExpression "derecelendirmesi":

İlk karakterin büyük harf olmasını gerektirir.


Sonraki boşlukların içindeki özel karakter ve sayılara izin verir. "PG -13" bir derecelendirme
için geçerlidir, ancak bir "tarz" için başarısız olur.
Range özniteliği, bir değeri belirtilen bir aralık içinde kısıtlar.

StringLengthözniteliği, bir dize özelliğinin en büyük uzunluğunu ve isteğe bağlı olarak en


düşük uzunluğunu ayarlar.
Değer türleri (örneğin decimal , int , float , DateTime ), doğal olarak gereklidir ve
[Required] özniteliğine gerek kalmaz.
Movie modeli için Oluştur sayfasında, geçersiz değerlere sahip hatalar görüntülenir:

Daha fazla bilgi için bkz.


Film uygulamasına doğrulama ekleme
ASP.NET Core 'de model doğrulaması.

OnGet işleyicisi geri dönüşü ile tanıtıcı HEAD istekleri


HEAD istekleri belirli bir kaynağın üst bilgilerini almaya izin verir. GET isteklerinin aksine HEAD
istekleri bir yanıt gövdesi döndürmez.
Normalde, HEAD istekleri için OnHead işleyicisi oluşturulur ve çağırılır:

public void OnHead()


{
HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}

Razor Pages, OnHead işleyicisi tanımlanmamışsa OnGet işleyicisini çağırmaya geri döner.

XSRF/CSRF ve Razor Pages


Razor Pages, Antiforgery doğrulamasıtarafından korunur. Formtaghelper , antiforgery belirteçlerini
HTML form öğelerine çıkartır.

Razor Pages ile düzenleri, partileri, şablonları ve etiket


yardımcılarını kullanma
Sayfalar, Razor görünüm altyapısının tüm özellikleri ile çalışır. Düzenler, partıals, şablonlar, etiket
yardımcıları, _ViewStart. cshtmlve _ViewImports. cshtml geleneksel Razor görünümlerinde oldukları
gibi çalışır.
Bu özelliklerden bazılarının avantajlarından yararlanarak bu sayfayı declutter edelim.
Sayfa/paylaşılan/_Layout. cshtml'ye bir Düzen sayfası ekleyin:

<!DOCTYPE html>
<html>
<head>
<title>RP Sample</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
<a asp-page="/Index">Home</a>
<a asp-page="/Customers/Create">Create</a>
<a asp-page="/Customers/Index">Customers</a> <br />

@RenderBody()
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</body>
</html>

Düzen:
Her sayfanın yerleşimini denetler (sayfa düzen dışında değilse).
JavaScript ve stil sayfaları gibi HTML yapılarını içeri aktarır.
Razor sayfasının içerikleri @RenderBody() her çağrıldığında işlenir.
Daha fazla bilgi için bkz. Düzen sayfası.
Layout özelliği Pages/_ViewStart. cshtml' de ayarlanır:

@{
Layout = "_Layout";
}

Düzen Sayfalar/paylaşılan klasöründedir. Sayfalar, geçerli sayfayla aynı klasörden başlayarak diğer
görünümleri (düzenler, şablonlar, parals) hiyerarşik olarak arar. Sayfalar/paylaşılan klasördeki bir
düzen, Sayfalar klasörü altındaki herhangi bir Razor sayfasından kullanılabilir.
Düzen dosyası Sayfalar/paylaşılan klasörüne gitmelidir.
Düzen dosyasını Görünümler/paylaşılan klasöre yerleştirmenizi öneririz . Görünümler/paylaşılan
bir MVC görünümleri modelidir. Razor Pages, yol kurallarını değil klasör hiyerarşisine güvenmektir.
Bir Razor sayfasından arama görüntüleme, Sayfalar klasörünü içerir. MVC denetleyicileri ve
geleneksel Razor görünümleriyle kullanılan düzenler, şablonlar ve partilar yalnızca çalışır.
Bir Pages/_ViewImports. cshtml dosyası ekleyin:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@namespace öğreticide daha sonra açıklanmaktadır. @addTagHelper yönergesi, yerleşik etiket


yardımcılarını Sayfalar klasöründeki tüm sayfalara getirir.
Bir sayfada @namespace yönerge kümesi:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
@Model.Message
</p>

@namespace yönergesi sayfanın ad alanını ayarlar. @model yönergesinin ad alanını içermesi


gerekmez.
@namespace yönergesi _ViewImports. cshtmliçinde yer aldığında, belirtilen ad alanı @namespace
yönergesini Içeri aktaran sayfada oluşturulan ad alanı için ön ek sağlar. Oluşturulan ad alanı (sonek
bölümü) geri kalanı, _ViewImports. cshtml içeren klasör ve sayfayı içeren klasör arasındaki noktayla
ayrılmış göreli yoldur.
Örneğin, PageModel Class Pages/Customers/Edit. cshtml. cs , ad alanını açıkça ayarlar:

namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;

public EditModel(AppDbContext db)


{
_db = db;
}

// Code removed for brevity.

Pages/_ViewImports. cshtml dosyası aşağıdaki ad alanını ayarlar:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Pages/Customers/Edit. cshtml Razor sayfasının oluşturulan ad alanı PageModel sınıfıyla aynıdır.


@namespace Ayrıca geleneksel Razor görünümleriyle birlikte kullanılabilir.
Pages/Create. cshtml görünüm dosyasını göz önünde bulundurun:
@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Validation: customer name:</p>

<form method="post">
<div asp-validation-summary="ModelOnly"></div>
<span asp-validation-for="Customer.Name"></span>
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

Güncelleştirilmiş sayfalar/oluşturma. cshtml görünüm dosyası _ViewImports. cshtml ve önceki düzen


dosyası:

@page
@model CreateModel

<p>Enter a customer name:</p>

<form method="post">
Name:
<input asp-for="Customer.Name" />
<input type="submit" />
</form>

Yukarıdaki kodda _ViewImports. cshtml ad alanı ve etiket yardımcıları içeri aktardı. Düzen dosyası
JavaScript dosyalarını içeri aktardı.
Razor Pages Starter projesi , istemci tarafı doğrulamayı bağlayan sayfaları/_ValidationScriptsPartial.
cshtml'yi içerir.
Kısmi görünümler hakkında daha fazla bilgi için bkz. ASP.NET Core kısmi görünümler.

Sayfalar için URL oluşturma


Daha önce gösterilen Create sayfası RedirectToPage kullanır:
public class CreateModel : PageModel
{
private readonly CustomerDbContext _context;

public CreateModel(CustomerDbContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customers.Add(Customer);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}

Uygulama aşağıdaki dosya/klasör yapısına sahiptir:


/Pages
Index.cshtml
Gizlilik. cshtml
/Customers
. Cshtml oluştur
Edit.cshtml
Index.cshtml
Pages/Customers/Create. cshtml ve Pages/Customers/Edit. cshtml sayfaları, başarılı olduktan sonra
sayfaları/müşterileri/Index. cshtml 'ye yeniden yönlendirir. Dize ./Index , önceki sayfaya erişmek için
kullanılan göreli bir sayfa adıdır. Pages/Customers/Index. cshtml sayfasının URL 'leri oluşturmak için
kullanılır. Örneğin:
Url.Page("./Index", ...)
<a asp-page="./Index">Customers Index Page</a>
RedirectToPage("./Index")

/Index mutlak sayfa adı, Sayfalar/Index. cshtml sayfasına URL 'ler oluşturmak için kullanılır.
Örneğin:
Url.Page("/Index", ...)
<a asp-page="/Index">Home Index Page</a>
RedirectToPage("/Index")
Sayfa adı, kök /Pages klasöründeki, önde gelen / (örneğin, /Index ) içeren sayfanın yoludur. Önceki
URL oluşturma örnekleri, bir URL 'YI sabit kodlamadan gelişmiş seçenekler ve işlevsel yetenekler
sunar. URL oluşturma yönlendirme kullanır ve yolun hedef yolda nasıl tanımlandığınıza göre
parametreleri oluşturabilir ve kodlayabilir.
Sayfalar için URL oluşturma göreli adları destekler. Aşağıdaki tabloda, sayfalarda/müşteriler/Create.
cshtml'de farklı RedirectToPage parametreleri kullanılarak hangi dizin sayfasının seçildiği
gösterilmektedir.

REDIRECTTOPAGE (X) SAYFA

RedirectToPage ("/Index") Sayfa/dizin

RedirectToPage ("./Index"); Sayfalar/müşteriler/Dizin

RedirectToPage (".. /İndex ") Sayfa/dizin

RedirectToPage ("Dizin") Sayfalar/müşteriler/Dizin

RedirectToPage("Index") , RedirectToPage("./Index") ve RedirectToPage("../Index") göreli adlardır.


RedirectToPage parametresi, hedef sayfanın adını hesaplamak için geçerli sayfanın yoluyla birleştirilir
.
Karmaşık bir yapıya sahip siteler oluştururken göreli ad bağlama yararlı olur. Bir klasördeki sayfalar
arasında bağlantı için göreli adlar kullanıldığında:
Bir klasörü yeniden adlandırmak, göreli bağlantıları bozmaz.
Klasör adını içermediği için bağlantılar kopuk değildir.
Farklı bir alandakibir sayfaya yeniden yönlendirmek için alanını belirtin:

RedirectToPage("/Index", new { area = "Services" });

Daha fazla bilgi için bkz. ASP.NET Core bölgeler ve ASP.NET Core Razor Pages yol ve uygulama
kuralları.

ViewData özniteliği
Veriler, ViewDataAttributebir sayfaya geçirilebilir. [ViewData] özniteliğiyle birlikte bulunan özellikler,
ViewDataDictionarydeğerlerinin depolandığı ve yüklendiği değerlerdir.
Aşağıdaki örnekte AboutModel , Title özelliğine [ViewData] özniteliğini uygular:

public class AboutModel : PageModel


{
[ViewData]
public string Title { get; } = "About";

public void OnGet()


{
}
}

Hakkında sayfasında, Title özelliğine model özelliği olarak erişin:


<h1>@Model.Title</h1>

Mizanpajda, başlık ViewData sözlüğünden okundu:

<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...

TempData
ASP.NET Core TempDatakullanıma sunar. Bu özellik, okunana kadar verileri depolar. Keep ve Peek
yöntemleri silinmeden verileri incelemek için kullanılabilir. TempData , bir tek istekten daha fazla veri
gerektiğinde yeniden yönlendirme için kullanışlıdır.
Aşağıdaki kod, TempData kullanarak Message değerini ayarlar:

public class CreateDotModel : PageModel


{
private readonly AppDbContext _db;

public CreateDotModel(AppDbContext db)


{
_db = db;
}

[TempData]
public string Message { get; set; }

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./Index");
}
}

Pages/Customers/Index. cshtml dosyasında aşağıdaki biçimlendirme TempData kullanarak Message


değerini görüntüler.

<h3>Msg: @Model.Message</h3>

Pages/Customers/Index. cshtml. cs sayfa modeli, [TempData] özniteliğini Message özelliğine uygular.

[TempData]
public string Message { get; set; }
Daha fazla bilgi için bkz. TempData.

Sayfa başına birden çok işleyici


Aşağıdaki sayfa asp-page-handler etiketi Yardımcısını kullanarak iki işleyici için biçimlendirme
oluşturur:

@page
@model CreateFATHModel

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>

Yukarıdaki örnekteki formda, her biri farklı bir URL 'ye göndermek için FormActionTagHelper
kullanan iki gönderme düğmesi vardır. asp-page-handler özniteliği asp-page bir yardımcı olur.
asp-page-handler , bir sayfa tarafından tanımlanan her bir işleyici yöntemini gönderen URL 'Ler
oluşturur. örnek geçerli sayfaya bağlandığından asp-page belirtilmedi.
Sayfa modeli:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;

namespace RazorPagesContacts.Pages.Customers
{
public class CreateFATHModel : PageModel
{
private readonly AppDbContext _db;

public CreateFATHModel(AppDbContext db)


{
_db = db;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostJoinListAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}

public async Task<IActionResult> OnPostJoinListUCAsync()


{
if (!ModelState.IsValid)
{
return Page();
}
Customer.Name = Customer.Name?.ToUpper();
return await OnPostJoinListAsync();
}
}
}

Yukarıdaki kod, adlandırılmış işleyici yöntemlerinikullanır. Adlandırılmış işleyici yöntemleri,


On<HTTP Verb> sonra ve Async önce (varsa), ad içindeki metin alınarak oluşturulur. Yukarıdaki
örnekte, Page metotları OnPostJoinlistAsync ve onpostJoinlıstucAsync ' dir. Onpost Ile zaman
uyumsuz olarak kaldırıldığında, işleyici adları JoinList ve JoinListUC .

<input type="submit" asp-page-handler="JoinList" value="Join" />


<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

Yukarıdaki kodu kullanarak, ' a gönderen URL yolu


OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH?handler=JoinList . OnPostJoinListUCAsync ' a gönderen
URL yolu https://localhost:5001/Customers/CreateFATH?handler=JoinListUC .

Özel yollar
@page yönergesini kullanarak şunları yapın:
Sayfaya özel bir yol belirtin. Örneğin, hakkında sayfasına olan yol
@page "/Some/Other/Path"``/Some/Other/Path olarak ayarlanabilir.
Kesimleri bir sayfanın varsayılan yoluna ekleyin. Örneğin, bir "öğe" segmenti sayfanın varsayılan
yoluna @page "item" eklenebilir.
Bir sayfanın varsayılan yoluna parametreleri ekleyin. Örneğin, @page "{id}" bir sayfa için id bir
ID parametresi gerekebilir.
Yolun başındaki bir tilde ( ~ ) tarafından atanan kök göreli bir yol desteklenir. Örneğin,
@page "~/Some/Other/Path" @page "/Some/Other/Path" aynıdır.

Yol şablonu @page "{handler?}" belirterek /JoinList URL 'sindeki ?handler=JoinList sorgu dizesini
bir rota kesimine değiştirebilirsiniz.
Sorgu dizesini URL 'de ?handler=JoinList beğenmezseniz, işleyicinin yol bölümüne işleyici adını
koymak için yolu değiştirebilirsiniz. Yolu, @page yönergesinden sonra çift tırnak içine alınmış bir rota
şablonu ekleyerek özelleştirebilirsiniz.

@page "{handler?}"
@model CreateRouteModel

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>

Yukarıdaki kodu kullanarak, ' a gönderen URL yolu


OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH/JoinList . OnPostJoinListUCAsync ' a gönderen URL
yolu https://localhost:5001/Customers/CreateFATH/JoinListUC .
Aşağıdaki handler ? yol parametresinin isteğe bağlı olduğu anlamına gelir.

Gelişmiş yapılandırma ve ayarlar


Aşağıdaki bölümlerdeki yapılandırma ve ayarlar çoğu uygulama için gerekli değildir.
Gelişmiş seçenekleri yapılandırmak için AddRazorPagesOptionsgenişletme yöntemini kullanın:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
}

Sayfaların kök dizinini ayarlamak için RazorPagesOptions kullanın veya sayfalar için uygulama
modeli kuralları ekleyin. Kurallar hakkında daha fazla bilgi için bkz. Razor Pages yetkilendirme
kuralları.
Görünümleri önceden derlemek için bkz. Razor görünüm derlemesi.
Razor Pages içerik kökünde olduğunu belirtin
Varsayılan olarak, Razor Pages /Pages dizininde kök olarak depolanır. Razor Pages uygulamanın
(ContentRootPath) içerik kökünde olduğunu belirtmek için WithRazorPagesAtContentRoot ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesAtContentRoot();
}

Razor Pages özel kök dizinde olduğunu belirtin


Razor Pages uygulamada bir özel kök dizinde olduğunu belirtmek için WithRazorPagesRoot ekleyin
(göreli bir yol sağlayın):

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/MyPages/Admin");
})
.WithRazorPagesRoot("/path/to/razor/pages");
}

Ek kaynaklar
Bkz. Razor Pages kullanmaya başlama, bu giriş hakkında derleme
Örnek kodu indirme veya görüntüleme
ASP.NET Core’a Giriş
ASP.NET Core Razor söz dizimi başvurusu
ASP.NET Core bölgeler
Öğretici: ASP.NET Core Razor Pages ile çalışmaya başlama
ASP.NET Core Razor Pages yetkilendirme kuralları
ASP.NET Core Razor Pages yol ve uygulama kuralları
ASP.NET Core birim testlerini Razor Pages
ASP.NET Core kısmi görünümler
By Rick Anderson ve Ryan şimdi ak
Razor Pages, kod odaklı senaryoları daha kolay ve daha üretken hale getiren ASP.NET Core MVC
'nin yeni bir yönüdür.
Model-View -Controller yaklaşımını kullanan bir öğretici arıyorsanız, bkz. ASP.NET Core MVC ile
çalışmaya başlama.
Bu belge Razor Pages bir giriş sağlar. Adım adım öğretici değildir. Bölümlerden bazılarını çok
gelişmiş bir şekilde bulursanız, bkz. Razor Pages kullanmaya başlama. ASP.NET Core genel bir bakış
için bkz. ASP.NET Core giriş.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK
sürümleri hakkında bilgi için.

Razor Pages projesi oluşturma


Visual Studio
Mac için Visual Studio
Visual Studio Code
Razor Pages projesi oluşturma hakkında ayrıntılı yönergeler için bkz. Razor Pages kullanmaya
başlama .

Razor Pages
Razor Pages, Startup.cs'de etkinleştirilmiştir:

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
// Includes support for Razor Pages and controllers.
services.AddMvc();
}

public void Configure(IApplicationBuilder app)


{
app.UseMvc();
}
}

Temel bir sayfa düşünün:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

Yukarıdaki kod, denetleyiciler ve görünümlerle ASP.NET Core bir uygulamada kullanılan Razor
görünüm dosyası gibi bir çok şey arar. Bu, farklı kılan @page yönergedir. @page , dosyayı bir
denetleyiciye geçmeden doğrudan istekleri işlediği anlamına gelen bir MVC eylemine sahip olur.
@page sayfadaki ilk Razor yönergesi olmalıdır. @page diğer Razor yapıları davranışını etkiler.

PageModel sınıfı kullanan benzer bir sayfa aşağıdaki iki dosyada gösterilmiştir. Pages/Index2. cshtml
dosyası:
@page
@using RazorPagesIntro.Pages
@model IndexModel2

<h2>Separate page model</h2>


<p>
@Model.Message
</p>

Pages/Index2. cshtml. cs sayfa modeli:

using Microsoft.AspNetCore.Mvc.RazorPages;
using System;

namespace RazorPagesIntro.Pages
{
public class IndexModel2 : PageModel
{
public string Message { get; private set; } = "PageModel in C#";

public void OnGet()


{
Message += $" Server time is { DateTime.Now }";
}
}
}

Kurala göre PageModel sınıf dosyası, . cs eklenmiş Razor sayfası dosyasıyla aynı ada sahiptir. Örneğin,
önceki Razor sayfası Pages/Index2. cshtml' dir. PageModel sınıfını içeren dosya sayfa/Index2. cshtml.
csolarak adlandırılır.
URL yollarının sayfalara olan ilişkilendirmeleri, sayfanın dosya sistemindeki konumuna göre
belirlenir. Aşağıdaki tabloda bir Razor sayfa yolu ve eşleşen URL gösterilmektedir:

DOSYA ADI VE YOLU EŞLEŞEN URL

/Pages/Index.cshtml / veya /Index

/Pages/Contact.exe /Contact

/Pages/Store/Contact.exe /Store/Contact

/Pages/Store/Index.cshtml /Store veya /Store/Index

Notlar:
Çalışma zamanı, Sayfalar klasöründeki Razor Pages dosyaları varsayılan olarak arar.
Index , URL bir sayfa içermiyorsa varsayılan sayfasıdır.

Temel form yazma


Razor Pages, Web tarayıcıları ile kullanılan ortak desenleri bir uygulama oluştururken kolayca
uygulanması için tasarlanmıştır. Model bağlama, ETIKET yardımcılarıve HTML Yardımcıları hepsi,
Razor sayfası sınıfında tanımlanan özelliklerle çalışır . Contact modeli için temel bir "bize başvurun"
formu uygulayan bir sayfa düşünün:
Bu belgedeki örnekler için DbContext , Startup.cs dosyasında başlatılır.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesContacts.Data;

namespace RazorPagesContacts
{
public class Startup
{
public IHostingEnvironment HostingEnvironment { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("name"));
services.AddMvc();
}

public void Configure(IApplicationBuilder app)


{
app.UseMvc();
}
}
}

Veri modeli:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Data
{
public class Customer
{
public int Id { get; set; }

[Required, StringLength(100)]
public string Name { get; set; }
}
}

DB bağlamı:

using Microsoft.EntityFrameworkCore;

namespace RazorPagesContacts.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options)
: base(options)
{
}

public DbSet<Customer> Customers { get; set; }


}
}

Pages/Create. cshtml görünüm dosyası:


@page
@model RazorPagesContacts.Pages.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>

Pages/Create. cshtml. cs sayfa modeli:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;

namespace RazorPagesContacts.Pages
{
public class CreateModel : PageModel
{
private readonly AppDbContext _db;

public CreateModel(AppDbContext db)


{
_db = db;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
}
}

Kurala göre PageModel sınıfı <PageName>Model olarak adlandırılır ve sayfayla aynı ad alanında yer
alan.
PageModel sınıfı, bir sayfa mantığının sunumundaki ayırmayı sağlar. Sayfaya gönderilen istekler için
sayfa işleyicilerini ve sayfayı işlemek için kullanılan verileri tanımlar. Bu ayrım şunları sağlar:
Bağımlılık eklemeyoluyla sayfa bağımlılıklarını yönetme.
Sayfaların birim testi .
Sayfada, POST isteklerinde çalışan bir OnPostAsync işleyicisi yöntemivardır (bir Kullanıcı formu
gönderdiğinde). Herhangi bir HTTP fiili için işleyici yöntemleri ekleyebilirsiniz. En yaygın işleyiciler
şunlardır:
Sayfanın başlatılması için gereken durum OnGet . OnGet örneği.
form gönderilerini işlemek için OnPost .
Async adlandırma son eki isteğe bağlıdır, ancak genellikle zaman uyumsuz işlevler için kural
tarafından kullanılır. Yukarıdaki kod Razor Pages için tipik bir davranıştır.
Denetleyicileri ve görünümleri kullanarak ASP.NET uygulamaları hakkında bilginiz varsa:
Yukarıdaki örnekteki OnPostAsync kodu, tipik denetleyici koduna benzer şekilde görünür.
Model bağlama, doğrulama, doğrulamave eylem sonuçları gibi mvc temel elemanlarının çoğu
paylaşılır.
Önceki OnPostAsync yöntemi:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}

OnPostAsync temel akışı:


Doğrulama hatalarını kontrol edin.
Hata yoksa, verileri kaydedin ve yeniden yönlendirin.
Hatalar varsa, doğrulama iletileriyle sayfayı yeniden görüntüleyin. İstemci tarafı doğrulaması
geleneksel ASP.NET Core MVC uygulamalarıyla aynıdır. Çoğu durumda, doğrulama hataları
istemci üzerinde algılanır ve sunucuya hiçbir zaman gönderilmez.
Veriler başarıyla girildiğinde, OnPostAsync Handler yöntemi bir RedirectToPageResult örneğini
döndürmek için RedirectToPage yardımcı yöntemini çağırır. RedirectToPage , RedirectToAction veya
RedirectToRoute benzer ancak sayfalar için özelleştirilen yeni bir eylem sonucudur. Önceki örnekte,
kök dizin sayfasına ( /Index ) yeniden yönlendirir. RedirectToPage , Sayfalar Için URL oluşturma
bölümünde ayrıntılı olarak açıklanmıştır.
Gönderilen formda doğrulama hataları olduğunda (sunucuya geçirilen) OnPostAsync işleyicisi
yöntemi Page yardımcı yöntemini çağırır. Page , bir PageResult örneği döndürür. Page döndürmek,
denetleyicilerde eylemlerin View nasıl dönüşlerine benzer. PageResult , bir işleyici yöntemi için
varsayılan dönüş türüdür. void döndüren bir işleyici yöntemi sayfayı işler.
Customer özelliği, model bağlamasını kabul etmek için [BindProperty] özniteliğini kullanır.
public class CreateModel : PageModel
{
private readonly AppDbContext _db;

public CreateModel(AppDbContext db)


{
_db = db;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
}

Razor Pages, varsayılan olarak, özellikleri yalnızca GET olmayan fiiller ile bağlayın. Özelliklere
bağlamak, yazmanız gereken kod miktarını azaltabilir. Bağlama, form alanlarını işlemek için aynı
özelliği kullanarak kodu azaltır ( <input asp-for="Customer.Name"> ) ve girişi kabul eder.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir.
Özelliklerle eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine
veya rota değerlerine dayanan senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true
olarak ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Giriş sayfası (Index. cshtml):


@page
@model RazorPagesContacts.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Contacts</h1>
<form method="post">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Customers)
{
<tr>
<td>@contact.Id</td>
<td>@contact.Name</td>
<td>
<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>
<button type="submit" asp-page-handler="delete"
asp-route-id="@contact.Id">delete</button>
</td>
</tr>
}
</tbody>
</table>

<a asp-page="./Create">Create</a>
</form>

İlişkili PageModel sınıfı (Index.cshtml.cs):


using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace RazorPagesContacts.Pages
{
public class IndexModel : PageModel
{
private readonly AppDbContext _db;

public IndexModel(AppDbContext db)


{
_db = db;
}

public IList<Customer> Customers { get; private set; }

public async Task OnGetAsync()


{
Customers = await _db.Customers.AsNoTracking().ToListAsync();
}

public async Task<IActionResult> OnPostDeleteAsync(int id)


{
var contact = await _db.Customers.FindAsync(id);

if (contact != null)
{
_db.Customers.Remove(contact);
await _db.SaveChangesAsync();
}

return RedirectToPage();
}
}
}

Index. cshtml dosyası her kişi için bir düzenleme bağlantısı oluşturmak üzere aşağıdaki
biçimlendirmeyi içerir:

<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> tutturucu etiketi Yardımcısı , düzenleme


sayfasına bir bağlantı oluşturmak için asp-route-{value} özniteliğini kullandı. Bağlantı, iletişim
KIMLIĞINE sahip rota verileri içerir. Örneğin: https://localhost:5001/Edit/1 . Etiket Yardımcıları,
Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Etiket Yardımcıları @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
tarafından etkinleştirilir
Pages/Edit. cshtml dosyası:
@page "{id:int}"
@model RazorPagesContacts.Pages.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
ViewData["Title"] = "Edit Customer";
}

<h1>Edit Customer - @Model.Customer.Id</h1>


<form method="post">
<div asp-validation-summary="All"></div>
<input asp-for="Customer.Id" type="hidden" />
<div>
<label asp-for="Customer.Name"></label>
<div>
<input asp-for="Customer.Name" />
<span asp-validation-for="Customer.Name" ></span>
</div>
</div>

<div>
<button type="submit">Save</button>
</div>
</form>

İlk satır @page "{id:int}" yönergesini içerir. Yönlendirme kısıtlaması "{id:int}" , sayfaya istekleri
int yönlendirme verileri içeren sayfaya kabul etmesini söyler. Sayfaya yapılan bir istek bir int
dönüştürülebildiği rota verileri içermiyorsa, çalışma zamanı bir HTTP 404 (bulunamadı) hatası
döndürür. KIMLIĞI isteğe bağlı yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

Pages/Edit. cshtml. cs dosyası:


using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;

namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;

public EditModel(AppDbContext db)


{
_db = db;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnGetAsync(int id)


{
Customer = await _db.Customers.FindAsync(id);

if (Customer == null)
{
return RedirectToPage("/Index");
}

return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Attach(Customer).State = EntityState.Modified;

try
{
await _db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw new Exception($"Customer {Customer.Id} not found!");
}

return RedirectToPage("/Index");
}
}
}

Index. cshtml dosyası, her müşteri kişisi için bir silme düğmesi oluşturmak için de biçimlendirme
içerir:

<button type="submit" asp-page-handler="delete"


asp-route-id="@contact.Id">delete</button>

Sil düğmesi HTML 'de işlendiğinde, formaction şunlar için parametreler içerir:
asp-route-id özniteliği tarafından belirtilen müşteri iletişim KIMLIĞI.
asp-page-handler özniteliği tarafından belirtilen handler .

Müşteri irtibat KIMLIĞI 1 olan işlenmiş silme düğmesine bir örnek aşağıda verilmiştir:

<button type="submit" formaction="/?id=1&amp;handler=delete">delete</button>

Düğme seçildiğinde, sunucuya bir form POST isteği gönderilir. Kurala göre, işleyici yönteminin adı,
düzen OnPost[handler]Async göre handler parametresinin değerine göre seçilir.
Bu örnekte handler delete olduğundan, OnPostDeleteAsync Handler yöntemi POST isteğini
işlemek için kullanılır. asp-page-handler , remove gibi farklı bir değere ayarlandıysa
OnPostRemoveAsync ada sahip bir işleyici yöntemi seçilidir. Aşağıdaki kod OnPostDeleteAsync
işleyicisini gösterir:

public async Task<IActionResult> OnPostDeleteAsync(int id)


{
var contact = await _db.Customers.FindAsync(id);

if (contact != null)
{
_db.Customers.Remove(contact);
await _db.SaveChangesAsync();
}

return RedirectToPage();
}

OnPostDeleteAsync Yöntemi:
Sorgu dizesinden id kabul eder. Index. cshtml sayfa yönergesi yönlendirme kısıtlaması
"{id:int?}" içeriyorsa, id rota verilerinden gelir. id için rota verileri, URI 'de
https://localhost:5001/Customers/2 gibi belirtilir.
FindAsync ile müşteri iletişim için veritabanını sorgular.
Müşteri ilgili kişisi bulunursa, bunlar müşteri kişileri listesinden kaldırılır. Veritabanı
güncelleştirildi.
Kök dizin sayfasına yeniden yönlendirmek için RedirectToPage çağırır ( /Index ).

Sayfa özelliklerini gerektiği gibi işaretle


PageModel Özellikler gerekli öznitelikle işaretlenebilir:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}

[BindProperty]
[Required(ErrorMessage = "Color is required")]
public string Color { get; set; }

public IActionResult OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

// Process color.

return RedirectToPage("./Index");
}
}
}

Daha fazla bilgi için bkz. model doğrulaması.

OnGet işleyicisi geri dönüşü ile tanıtıcı HEAD istekleri


HEAD istekleri belirli bir kaynak için üst bilgileri almanızı sağlar. GET isteklerinin aksine HEAD
istekleri bir yanıt gövdesi döndürmez.
Normalde, HEAD istekleri için OnHead işleyicisi oluşturulur ve çağırılır:

public void OnHead()


{
HttpContext.Response.Headers.Add("HandledBy", "Handled by OnHead!");
}

ASP.NET Core 2,1 veya sonraki sürümlerde Razor Pages, OnHead işleyici tanımlanmadığında OnGet
işleyicisini çağırmaya geri döner. Bu davranış, Startup.ConfigureServices Setcompatibilityversion
çağrısıyla etkinleştirilir:

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Varsayılan Şablonlar, ASP.NET Core 2,1 ve 2,2 ' de SetCompatibilityVersion çağrısını üretir.
SetCompatibilityVersion AllowMappingHeadRequestsToGetHandler Razor Pages seçeneğini true için
etkin şekilde ayarlar.
SetCompatibilityVersion tüm davranışlardan çıkmak yerine, açıkça belirli davranışları kabul
edebilirsiniz. Aşağıdaki kod, HEAD isteklerinin OnGet işleyicisine eşlenmesine izin vermek için ' de
kullanılır:
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.AllowMappingHeadRequestsToGetHandler = true;
});

XSRF/CSRF ve Razor Pages


Antiforgery doğrulamasıiçin herhangi bir kod yazmanız gerekmez. Antiforgery belirteci oluşturma ve
doğrulama, Razor Pages otomatik olarak eklenir.

Razor Pages ile düzenleri, partileri, şablonları ve etiket


yardımcılarını kullanma
Sayfalar, Razor görünüm altyapısının tüm özellikleri ile çalışır. Düzenler, partıals, şablonlar, etiket
yardımcıları, _ViewStart. cshtml, _ViewImports. cshtml geleneksel Razor görünümlerinde oldukları
gibi çalışır.
Bu özelliklerden bazılarının avantajlarından yararlanarak bu sayfayı declutter edelim.
Sayfa/paylaşılan/_Layout. cshtml'ye bir Düzen sayfası ekleyin:

<!DOCTYPE html>
<html>
<head>
<title>Razor Pages Sample</title>
</head>
<body>
<a asp-page="/Index">Home</a>
@RenderBody()
<a asp-page="/Customers/Create">Create</a> <br />
</body>
</html>

Düzen:
Her sayfanın yerleşimini denetler (sayfa düzen dışında değilse).
JavaScript ve stil sayfaları gibi HTML yapılarını içeri aktarır.
Daha fazla bilgi için bkz. Düzen sayfası .
Layout özelliği Pages/_ViewStart. cshtml' de ayarlanır:

@{
Layout = "_Layout";
}

Düzen Sayfalar/paylaşılan klasöründedir. Sayfalar, geçerli sayfayla aynı klasörden başlayarak diğer
görünümleri (düzenler, şablonlar, parals) hiyerarşik olarak arar. Sayfalar/paylaşılan klasördeki bir
düzen, Sayfalar klasörü altındaki herhangi bir Razor sayfasından kullanılabilir.
Düzen dosyası Sayfalar/paylaşılan klasörüne gitmelidir.
Düzen dosyasını Görünümler/paylaşılan klasöre yerleştirmenizi öneririz . Görünümler/paylaşılan
bir MVC görünümleri modelidir. Razor Pages, yol kurallarını değil klasör hiyerarşisine güvenmektir.
Bir Razor sayfasından arama görüntüleme, Sayfalar klasörünü içerir. MVC denetleyicileri ve
geleneksel Razor görünümleriyle kullandığınız düzenler, şablonlar ve parals işlemleri yalnızca çalışır.
Bir Pages/_ViewImports. cshtml dosyası ekleyin:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@namespace öğreticide daha sonra açıklanmaktadır. @addTagHelper yönergesi, yerleşik etiket


yardımcılarını Sayfalar klasöründeki tüm sayfalara getirir.
@namespace yönergesi açıkça bir sayfada kullanıldığında:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
@Model.Message
</p>

Yönergesi sayfanın ad alanını ayarlar. @model yönergesinin ad alanını içermesi gerekmez.


@namespace yönergesi _ViewImports. cshtmliçinde yer aldığında, belirtilen ad alanı @namespace
yönergesini Içeri aktaran sayfada oluşturulan ad alanı için ön ek sağlar. Oluşturulan ad alanı (sonek
bölümü) geri kalanı, _ViewImports. cshtml içeren klasör ve sayfayı içeren klasör arasındaki noktayla
ayrılmış göreli yoldur.
Örneğin, PageModel Class Pages/Customers/Edit. cshtml. cs , ad alanını açıkça ayarlar:

namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;

public EditModel(AppDbContext db)


{
_db = db;
}

// Code removed for brevity.

Pages/_ViewImports. cshtml dosyası aşağıdaki ad alanını ayarlar:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Pages/Customers/Edit. cshtml Razor sayfasının oluşturulan ad alanı PageModel sınıfıyla aynıdır.


@namespace Ayrıca geleneksel Razor görünümleriyle birlikte kullanılabilir.
Özgün Sayfalar/Create. cshtml görünüm dosyası:
@page
@model RazorPagesContacts.Pages.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>

Güncelleştirilmiş Sayfalar/Create. cshtml görünüm dosyası:

@page
@model CreateModel

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>

Razor Pages Starter projesi , istemci tarafı doğrulamayı bağlayan sayfaları/_ValidationScriptsPartial.


cshtml'yi içerir.
Kısmi görünümler hakkında daha fazla bilgi için bkz. ASP.NET Core kısmi görünümler.

Sayfalar için URL oluşturma


Daha önce gösterilen Create sayfası RedirectToPage kullanır:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}

Uygulama aşağıdaki dosya/klasör yapısına sahiptir:


/Pages
Index.cshtml
/Customers
. Cshtml oluştur
Edit.cshtml
Index.cshtml
Pages/Customers/Create. cshtml ve Pages/Customers/Edit. cshtml sayfaları, başarılı olduktan sonra
Pages/Index. cshtml dosyasına yönlendirilir. /Index dize, önceki sayfaya erişmek için URI 'nin bir
parçasıdır. /Index dize /Index. cshtml sayfasına URI oluşturmak için kullanılır. Örneğin:
Url.Page("/Index", ...)
<a asp-page="/Index">My Index Page</a>
RedirectToPage("/Index")

Sayfa adı, kök /Pages klasöründeki, önde gelen / (örneğin, /Index ) içeren sayfanın yoludur. Önceki
URL oluşturma örnekleri bir URL 'YI kodlamadan gelişmiş seçenekler ve işlevsel yetenekler sunar.
URL oluşturma yönlendirme kullanır ve yolun hedef yolda nasıl tanımlandığınıza göre parametreleri
oluşturabilir ve kodlayabilir.
Sayfalar için URL oluşturma göreli adları destekler. Aşağıdaki tabloda, sayfa/müşteri/oluşturma.
cshtml'den farklı RedirectToPage parametrelerle hangi dizin sayfasının seçildiği gösterilmektedir:

REDIRECTTOPAGE (X) SAYFA

RedirectToPage ("/Index") Sayfa/dizin

RedirectToPage ("./Index"); Sayfalar/müşteriler/Dizin

RedirectToPage (".. /İndex ") Sayfa/dizin

RedirectToPage ("Dizin") Sayfalar/müşteriler/Dizin

RedirectToPage("Index") , RedirectToPage("./Index") ve RedirectToPage("../Index") , göreli adlardır.


RedirectToPage parametresi, hedef sayfanın adını hesaplamak için geçerli sayfanın yoluyla birleştirilir
.
Karmaşık bir yapıya sahip siteler oluştururken göreli ad bağlama yararlı olur. Bir klasördeki sayfalar
arasında bağlantı sağlamak için göreli adlar kullanırsanız, bu klasörü yeniden adlandırabilirsiniz. Tüm
bağlantılar hala çalışır (klasör adını içermediği için).
Farklı bir alandakibir sayfaya yeniden yönlendirmek için alanını belirtin:

RedirectToPage("/Index", new { area = "Services" });

Daha fazla bilgi için bkz. ASP.NET Core bölgeler.

ViewData özniteliği
Veri, Viewdataattributeiçeren bir sayfaya geçirilebilir. [ViewData] özniteliği olan denetleyicilerde veya
Razor sayfa modellerinde bulunan özelliklerin değerleri, ViewDataDictionary'den depolanır ve
yüklenir.
Aşağıdaki örnekte AboutModel , [ViewData] ile işaretlenmiş bir Title özelliği içerir. Title özelliği,
hakkında sayfasının başlığına ayarlanır:
public class AboutModel : PageModel
{
[ViewData]
public string Title { get; } = "About";

public void OnGet()


{
}
}

Hakkında sayfasında, Title özelliğine model özelliği olarak erişin:

<h1>@Model.Title</h1>

Mizanpajda, başlık ViewData sözlüğünden okundu:

<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...

TempData
ASP.NET Core bir denetleyicide TempData özelliğini kullanıma sunar. Bu özellik, okunana kadar
verileri depolar. Keep ve Peek yöntemleri silinmeden verileri incelemek için kullanılabilir. TempData ,
bir tek istekten daha fazla veri gerektiğinde yeniden yönlendirme için kullanışlıdır.
Aşağıdaki kod, TempData kullanarak Message değerini ayarlar:

public class CreateDotModel : PageModel


{
private readonly AppDbContext _db;

public CreateDotModel(AppDbContext db)


{
_db = db;
}

[TempData]
public string Message { get; set; }

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./Index");
}
}
Pages/Customers/Index. cshtml dosyasında aşağıdaki biçimlendirme TempData kullanarak Message
değerini görüntüler.

<h3>Msg: @Model.Message</h3>

Pages/Customers/Index. cshtml. cs sayfa modeli, [TempData] özniteliğini Message özelliğine uygular.

[TempData]
public string Message { get; set; }

Daha fazla bilgi için bkz. TempData .

Sayfa başına birden çok işleyici


Aşağıdaki sayfa asp-page-handler etiketi Yardımcısını kullanarak iki işleyici için biçimlendirme
oluşturur:

@page
@model CreateFATHModel

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>

Yukarıdaki örnekteki formda, her biri farklı bir URL 'ye göndermek için FormActionTagHelper
kullanan iki gönderme düğmesi vardır. asp-page-handler özniteliği asp-page bir yardımcı olur.
asp-page-handler , bir sayfa tarafından tanımlanan her bir işleyici yöntemini gönderen URL 'Ler
oluşturur. örnek geçerli sayfaya bağlandığından asp-page belirtilmedi.
Sayfa modeli:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;

namespace RazorPagesContacts.Pages.Customers
{
public class CreateFATHModel : PageModel
{
private readonly AppDbContext _db;

public CreateFATHModel(AppDbContext db)


{
_db = db;
}

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostJoinListAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}

public async Task<IActionResult> OnPostJoinListUCAsync()


{
if (!ModelState.IsValid)
{
return Page();
}
Customer.Name = Customer.Name?.ToUpper();
return await OnPostJoinListAsync();
}
}
}

Yukarıdaki kod, adlandırılmış işleyici yöntemlerinikullanır. Adlandırılmış işleyici yöntemleri,


On<HTTP Verb> sonra ve Async önce (varsa), ad içindeki metin alınarak oluşturulur. Yukarıdaki
örnekte, Page metotları OnPostJoinlistAsync ve onpostJoinlıstucAsync ' dir. Onpost Ile zaman
uyumsuz olarak kaldırıldığında, işleyici adları JoinList ve JoinListUC .

<input type="submit" asp-page-handler="JoinList" value="Join" />


<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

Yukarıdaki kodu kullanarak, ' a gönderen URL yolu


OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH?handler=JoinList . OnPostJoinListUCAsync ' a gönderen
URL yolu https://localhost:5001/Customers/CreateFATH?handler=JoinListUC .

Özel yollar
@page yönergesini kullanarak şunları yapın:
Sayfaya özel bir yol belirtin. Örneğin, hakkında sayfasına olan yol
@page "/Some/Other/Path"``/Some/Other/Path olarak ayarlanabilir.
Kesimleri bir sayfanın varsayılan yoluna ekleyin. Örneğin, bir "öğe" segmenti sayfanın varsayılan
yoluna @page "item" eklenebilir.
Bir sayfanın varsayılan yoluna parametreleri ekleyin. Örneğin, @page "{id}" bir sayfa için id bir
ID parametresi gerekebilir.
Yolun başındaki bir tilde ( ~ ) tarafından atanan kök göreli bir yol desteklenir. Örneğin,
@page "~/Some/Other/Path" @page "/Some/Other/Path" aynıdır.

Yol şablonu @page "{handler?}" belirterek /JoinList URL 'sindeki ?handler=JoinList sorgu dizesini
bir rota kesimine değiştirebilirsiniz.
Sorgu dizesini URL 'de ?handler=JoinList beğenmezseniz, işleyicinin yol bölümüne işleyici adını
koymak için yolu değiştirebilirsiniz. Yolu, @page yönergesinden sonra çift tırnak içine alınmış bir rota
şablonu ekleyerek özelleştirebilirsiniz.

@page "{handler?}"
@model CreateRouteModel

<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>

Yukarıdaki kodu kullanarak, ' a gönderen URL yolu


OnPostJoinListAsync
https://localhost:5001/Customers/CreateFATH/JoinList . OnPostJoinListUCAsync ' a gönderen URL
yolu https://localhost:5001/Customers/CreateFATH/JoinListUC .
Aşağıdaki handler ? yol parametresinin isteğe bağlı olduğu anlamına gelir.

Yapılandırma ve ayarlar
Gelişmiş seçenekleri yapılandırmak için, MVC Oluşturucu 'da AddRazorPagesOptions genişletme
yöntemini kullanın:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
}

Şu anda, sayfalar için kök dizini ayarlamak veya sayfalar için uygulama modeli kuralları eklemek
üzere RazorPagesOptions kullanabilirsiniz. Gelecekte bu şekilde daha fazla genişletilebilirlik
etkinleştireceğiz.
Görünümleri önceden derlemek için bkz. Razor görünüm derlemesi .
Örnek kodu indirin veya görüntüleyin.
Bu giriş hakkında bilgi için bkz. Razor Pages kullanmaya başlama.
Razor Pages içerik kökünde olduğunu belirtin
Varsayılan olarak, Razor Pages /Pages dizininde kök olarak depolanır. Razor Pages, uygulamanın
içerik kökünde (contentrootpath) olduğunu belirtmek Için addmvc 'ye
WithRazorPagesAtContentRoot ekleyin:

services.AddMvc()
.AddRazorPagesOptions(options =>
{
...
})
.WithRazorPagesAtContentRoot();

Razor Pages özel kök dizinde olduğunu belirtin


Razor Pages uygulamadaki özel bir kök dizinde olduğunu belirtmek için Addmvc 'ye
WithRazorPagesRoot ekleyin (göreli bir yol sağlayın):

services.AddMvc()
.AddRazorPagesOptions(options =>
{
...
})
.WithRazorPagesRoot("/path/to/razor/pages");

Ek kaynaklar
ASP.NET Core’a Giriş
ASP.NET Core Razor söz dizimi başvurusu
ASP.NET Core bölgeler
Öğretici: ASP.NET Core Razor Pages ile çalışmaya başlama
ASP.NET Core Razor Pages yetkilendirme kuralları
ASP.NET Core Razor Pages yol ve uygulama kuralları
ASP.NET Core birim testlerini Razor Pages
ASP.NET Core kısmi görünümler
Öğretici: ASP.NET Core ile Razor Pages Web
uygulaması oluşturma
1.10.2019 • 2 minutes to read • Edit Online

Bu öğretici dizisinde Razor Pages Web uygulaması oluşturma temelleri açıklanmaktadır.


Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz. tanıtım
Razor Pages.
Bu seri aşağıdaki öğreticileri içerir:
1. Razor Sayfaları web uygulaması oluşturma
2. Razor Pages uygulamasına model ekleme
3. Yapı iskelesi (oluşturma) Razor sayfaları
4. Bir veritabanıyla çalışma
5. Razor sayfalarını güncelleştirme
6. Arama ekleme
7. Yeni alan ekleme
8. Doğrulama ekleme
Son olarak, bir film veritabanını görüntüleyebilen ve yönetebileceğini bir uygulamanıza sahip olacaksınız.
Öğretici: ASP.NET Core Razor Pages ile
çalışmaya başlama
10.12.2019 • 19 minutes to read • Edit Online

Tarafından Rick Anderson


Bu, bir serinin ASP.NET Core Razor Pages Web uygulaması oluşturma hakkında temel bilgileri öğretir.
Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz.
tanıtım Razor Pages.
Serinin sonunda, bir film veritabanını yöneten bir uygulamanız olacaktır.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu öğreticide şunları yaptınız:
Razor Pages bir Web uygulaması oluşturun.
Uygulamayı çalıştırın.
Proje dosyalarını inceleyin.
Bu öğreticinin sonunda, daha sonraki öğreticilerde oluşturacağınız çalışan bir Razor Pages Web
uygulamasına sahipsiniz.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019 16,4 veya üzeri
.NET Core 3,1 SDK veya üzeri
Razor Pages Web uygulaması oluşturma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun ve İleri ' yiseçin. Yeni ASP.NET Core Web
uygulaması

Projeyi RazorPagesMovieolarak adlandırın. Kodu kopyaladığınızda ve yapıştırdığınızda ad


alanlarının eşleşmesi için Project RazorPagesMovie olarak adı vermek önemlidir. Yeni ASP.NET
Core Web uygulaması

Açılan Web uygulamasındaki ASP.NET Core 3,1 ' i seçin ve ardından Oluştur' u seçin.
Aşağıdaki Başlatıcı proje oluşturulur:

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.
Aşağıdaki iletişim kutusu görüntülenir:

Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.


Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve
example.com gibi bir şey görüntülenir. Bunun nedeni, localhost yerel bilgisayar için Standart
ana bilgisayar adıdır. Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual
Studio bir Web projesi oluşturduğunda, Web sunucusu için rastgele bir bağlantı noktası kullanılır.

Proje dosyalarını inceleyin


Aşağıda, daha sonraki öğreticilerde birlikte çalışacağımız ana proje klasörlerine ve dosyalarına genel bir
bakış sunulmaktadır.
Sayfalar klasörü
Razor sayfaları ve destekleyici dosyalar içerir. Her Razor sayfası bir dosya çiftidir:
Razor söz dizimi kullanarak C# kodla HTML işaretlemesi içeren bir . cshtml dosyası.
Sayfa olaylarını işleyen kodu içeren C# bir . cshtml.cs dosyası.
Destekleyici dosyalar bir alt çizgiyle başlayan adlara sahiptir. Örneğin, _Layout. cshtml dosyası tüm
sayfalarda ortak kullanıcı arabirimi öğelerini yapılandırır. Bu dosya sayfanın en üstündeki gezinti
menüsünü ve sayfanın alt kısmındaki telif hakkı bildirimini ayarlar. Daha fazla bilgi için bkz. ASP.NET
Core düzen.
Wwwroot klasörü
HTML dosyaları, JavaScript dosyaları ve CSS dosyaları gibi statik dosyaları içerir. Daha fazla bilgi için
bkz. ASP.NET Core statik dosyalar.
appSettings. JSON
Bağlantı dizeleri gibi yapılandırma verilerini içerir. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Program.cs
Programın giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs
Uygulama davranışını yapılandıran kodu içerir. Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama
başlatma.

Sonraki adımlar
Serideki bir sonraki öğreticiye ilerleyin:

M ODEL
EKLEM E

Bu, bir serinin ilk öğreticisidir. Seriler , bir ASP.NET Core Razor pages Web uygulaması oluşturma
hakkında temel bilgileri öğretir.
Denetleyiciler ve görünümler hakkında bilgi sahibi olan geliştiricilere daha gelişmiş bir giriş için bkz.
tanıtım Razor Pages.
Serinin sonunda, bir film veritabanını yöneten bir uygulamanız olacaktır.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu öğreticide şunları yaptınız:
Razor Pages bir Web uygulaması oluşturun.
Uygulamayı çalıştırın.
Proje dosyalarını inceleyin.
Bu öğreticinin sonunda, daha sonraki öğreticilerde oluşturacağınız çalışan bir Razor Pages Web
uygulamasına sahipsiniz.
Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK
sürümleri hakkında bilgi için.

Razor Pages Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun ve İleri ' yiseçin.
Projeyi RazorPagesMovieolarak adlandırın. Kodu kopyaladığınızda ve yapıştırdığınızda ad
alanlarının eşleşmesi için Project RazorPagesMovie olarak adı vermek önemlidir.

Açılan Web uygulamasındaki ASP.NET Core 2,2 ' i seçin ve ardından Oluştur' u seçin.
Aşağıdaki Başlatıcı proje oluşturulur:

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.
Aşağıdaki iletişim kutusu görüntülenir:

Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.


Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğu example.com gibi değil
localhost:port# gösterir. Bunun nedeni, localhost yerel bilgisayar için Standart ana bilgisayar
adıdır. Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual Studio bir web
projesi oluşturduğunda, web sunucusu için rastgele bir bağlantı noktası kullanılır.
Uygulamanın giriş sayfasında, izlemeye izin vermek için kabul et ' i seçin.
Bu uygulama kişisel bilgileri izlemez, ancak proje şablonu, Avrupa Birliği 'nin genel veri koruma
yönetmeliği (GDPR )ile uyumlu olması için ihtiyaç duymanız durumunda izin özelliğini içerir.
Aşağıdaki görüntüde, izlemeye onay verdikten sonra uygulama gösterilmektedir:

Proje dosyalarını inceleyin


Aşağıda, daha sonraki öğreticilerde birlikte çalışacağımız ana proje klasörlerine ve dosyalarına genel bir
bakış sunulmaktadır.
Sayfalar klasörü
Razor sayfaları ve destekleyici dosyalar içerir. Her Razor sayfası bir dosya çiftidir:
Razor söz dizimi kullanarak C# kodla HTML işaretlemesi içeren bir . cshtml dosyası.
Sayfa olaylarını işleyen kodu içeren C# bir . cshtml.cs dosyası.
Destekleyici dosyalar bir alt çizgiyle başlayan adlara sahiptir. Örneğin, _Layout. cshtml dosyası tüm
sayfalarda ortak kullanıcı arabirimi öğelerini yapılandırır. Bu dosya sayfanın en üstündeki gezinti
menüsünü ve sayfanın alt kısmındaki telif hakkı bildirimini ayarlar. Daha fazla bilgi için bkz. ASP.NET
Core düzen.
Wwwroot klasörü
HTML dosyaları, JavaScript dosyaları ve CSS dosyaları gibi statik dosyaları içerir. Daha fazla bilgi için
bkz. ASP.NET Core statik dosyalar.
appSettings. JSON
Bağlantı dizeleri gibi yapılandırma verilerini içerir. Daha fazla bilgi için bkz. ASP.NET Core yapılandırma.
Program.cs
Programın giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs
Tanımlama bilgilerinin onayını gerektirip gerektirmediğini belirten uygulama davranışını yapılandıran
kodu içerir. Daha fazla bilgi için bkz. ASP.NET Core 'de uygulama başlatma.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Sonraki adımlar
Serideki bir sonraki öğreticiye ilerleyin:

M ODEL
EKLEM E
Bir ASP.NET Core Razor sayfaları uygulama için
model ekleme
10.12.2019 • 40 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, platformlar arası bir SQLite veritabanındafilm yönetimi için sınıflar eklenir. Bir ASP.NET Core
şablondan oluşturulan uygulamalar bir SQLite veritabanı kullanır. Uygulamanın model sınıfları, veritabanıyla
çalışmak için Entity Framework Core (EF Core) (SQLite EF Core veritabanı sağlayıcısı) ile kullanılır. EF Core,
veri erişimini kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
EF Core üzerinde herhangi bir bağımlılığı olmadığından model sınıfları ("düz eski CLR nesnelerden") POCO
sınıfları olarak bilinir. Bunlar, veritabanında depolanan verilerin özelliklerini tanımlayın.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Bir veri modeli ekleme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Sağ RazorPagesMovie Proje > Ekle > yeni klasör. Klasör adı modelleri.
Sağ tıklayın modelleri klasör. Seçin ekleme > sınıfı. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfına ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı şunları içerir:


ID alanı birincil anahtar için veritabanı gerektirir.
[DataType(DataType.Date)] : DataType özniteliği verilerin türünü belirtir (Tarih). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.
Derleme hata doğrulamak için projeyi derleyin.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Oluşturma bir sayfaları/filmler klasörü:
Yeni > klasör eklemek > Sayfalar klasörüne sağ tıklayın.
Klasör adı filmler
Sayfalar/filmler klasörüne sağ tıklayın > > yeni yapı Iskelesi öğesi ekleyin .

Yapı Iskelesi Ekle iletişim kutusunda Razor Pages Entity Framework (crud) > Ekle' yi seçin.
Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:
İçinde Model sınıfı seçin, açılan menü film (RazorPagesMovie.Models) .
Veri bağlamı sınıfı satırında + (artı) işaretini seçin ve oluşturulan adı RazorPagesMovie ' dan değiştirin.
Modeller. RazorPagesMovieContext to RazorPagesMovie. Veri. RazorPagesMovieContext. Bu değişiklik
gerekli değildir. Doğru ad alanıyla veritabanı bağlamı sınıfını oluşturur.
Add (Ekle) seçeneğini belirleyin.

Appsettings.json dosya yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi ile güncelleştirilir.
Oluşturulan dosyalar
Visual Studio
Visual Studio Code/Mac için Visual Studio
İskele işlem oluşturur ve aşağıdaki dosyaları güncelleştirir:
Sayfa/filmler: oluşturma, silme, Ayrıntılar, düzenleme ve dizin.
Data/RazorPagesMovieContext.cs
Güncelleştirme tarihi
Startup.cs
Oluşturulan ve güncelleştirilen dosyalar, sonraki bölümde açıklanmıştır.

İlk geçiş
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bu bölümde, Paket Yöneticisi Konsolu (PMC'yi) için kullanılır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.

PMC'de aşağıdaki komutları girin:

Add-Migration InitialCreate
Update-Database

Yukarıdaki komutlar şu uyarıyı oluşturur: "' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür
belirtilmedi. Bu, varsayılan duyarlık ve ölçeğe uygun olmadıkları takdirde değerlerin sessizce kesilmesine
neden olur. ' Hasccolumntype () ' kullanarak tüm değerleri barındırabilecek SQL Server sütun türünü açık
olarak belirtin. "
Bu uyarıyı yoksayabilirsiniz, daha sonraki bir öğreticide düzeltilecektir.
Geçişler komutu, ilk veritabanı şemasını oluşturmak için kod üretir. Şema, DbContext belirtilen modeli temel
alır. InitialCreate Bağımsız değişkeni, geçişlerin adlandırmak için kullanılır. Herhangi bir ad kullanılabilir,
ancak bir adı seçili kural gereği, geçiş açıklar.
update komutu uygulanmamış geçişlerde Up yöntemini çalıştırır. Bu durumda update , veritabanını
oluşturan geçiş/<zaman damgası > _InitialCreate. cs dosyasında Up yöntemini çalıştırır.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı), uygulama
başlatma sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren
bileşenler bu hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu
kodu öğreticinin ilerleyen bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme kapsayıcısını ile
kayıtlı.
İnceleme Startup.ConfigureServices yöntemi. Vurgulanan satırı iskele kurucu tarafından eklendi:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

RazorPagesMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları
Movie modeli. Veri bağlamı ( RazorPagesMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext.
Veri bağlamı, hangi varlıkları veri modelinde yer alan belirtir.

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
public class RazorPagesMovieContext : DbContext
{
public RazorPagesMovieContext (DbContextOptions<RazorPagesMovieContext> options)
: base(options)
{
}

public DbSet<RazorPagesMovie.Models.Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir
varlık kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Hatası alırsanız:

SqlException: Cannot open database "RazorPagesMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül
İngilizce olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer
gerekir. Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Sonraki öğreticiye yapı iskelesi tarafından oluşturulan dosyaları açıklar.

Ek kaynaklar

Ö N C E K I: S O N R A K I: R A Z O R S A Y F A L A R I IÇ IN IS K E L E
BA ŞL A M A KURULM UŞ

Bu bölümde, platformlar arası bir SQLite veritabanındafilm yönetimi için sınıflar eklenir. Bir ASP.NET Core
şablondan oluşturulan uygulamalar bir SQLite veritabanı kullanır. Uygulamanın model sınıfları, veritabanıyla
çalışmak için Entity Framework Core (EF Core) (SQLite EF Core veritabanı sağlayıcısı) ile kullanılır. EF Core,
veri erişimini kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
EF Core üzerinde herhangi bir bağımlılığı olmadığından model sınıfları ("düz eski CLR nesnelerden") POCO
sınıfları olarak bilinir. Bunlar, veritabanında depolanan verilerin özelliklerini tanımlayın.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Bir veri modeli ekleme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Sağ RazorPagesMovie Proje > Ekle > yeni klasör. Klasör adı modelleri.
Sağ tıklayın modelleri klasör. Seçin ekleme > sınıfı. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfına ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı şunları içerir:


ID alanı birincil anahtar için veritabanı gerektirir.
[DataType(DataType.Date)] : DataType özniteliği verilerin türünü belirtir (Tarih). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.
Derleme hata doğrulamak için projeyi derleyin.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Oluşturma bir sayfaları/filmler klasörü:
Yeni > klasör eklemek > Sayfalar klasörüne sağ tıklayın.
Klasör adı filmler
Sayfalar/filmler klasörüne sağ tıklayın > > yeni yapı Iskelesi öğesi ekleyin .

Yapı Iskelesi Ekle iletişim kutusunda Razor Pages Entity Framework (crud) > Ekle' yi seçin.

Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:


İçinde Model sınıfı seçin, açılan menü film (RazorPagesMovie.Models) .
İçinde veri bağlamı sınıfının satır, select + (artı) oturum açın ve oluşturulan adı kabul
RazorPagesMovie.Models.RazorPagesMovieContext.
Add (Ekle) seçeneğini belirleyin.

Appsettings.json dosya yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi ile güncelleştirilir.
İskele işlem oluşturur ve aşağıdaki dosyaları güncelleştirir:
Oluşturulan dosyalar
Sayfa/filmler: oluşturma, silme, Ayrıntılar, düzenleme ve dizin.
Data/RazorPagesMovieContext.cs
Dosya güncelleştirildi
Startup.cs
Oluşturulan ve güncelleştirilen dosyalar, sonraki bölümde açıklanmıştır.

İlk geçiş
Visual Studio
Visual Studio Code
Mac için Visual Studio
Bu bölümde, Paket Yöneticisi Konsolu (PMC'yi) için kullanılır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.
PMC'de aşağıdaki komutları girin:

Add-Migration Initial
Update-Database

Add-Migration Komut, ilk veritabanı şeması oluşturmak için kod oluşturur. Şema, DbContext belirtilen modele
dayalıdır ( RazorPagesMovieContext.cs dosyasında). InitialCreate bağımsız değişkeni, geçişi adlandırmak
için kullanılır. Herhangi bir ad kullanılabilir, ancak kurala göre geçiş tanımlayan bir ad kullanılır.Daha fazla bilgi
için bkz. Öğretici: EF Core ile geçiş özelliğini kullanma-ASP.NET MVC.
Update-Database Komutu çalıştırmaları Up yönteminde geçişleri /<zaman damgası > _InitialCreate.cs dosya.
Up Yöntemi veritabanı oluşturur.

NOTE
Yukarıdaki komutlar şu uyarıyı oluşturur: " ' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür belirtilmedi. Bu,
varsayılan duyarlık ve ölçeğe uygun olmadıkları takdirde değerlerin sessizce kesilmesine neden olur. '
Hasccolumntype () ' kullanarak tüm değerleri barındırabilecek SQL Server sütun türünü açık olarak belirtin. " Bu
uyarıyı yoksayabilirsiniz, daha sonraki bir öğreticide düzeltilecektir.

Visual Studio
Visual Studio Code
Mac için Visual Studio
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı), uygulama
başlatma sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren
bileşenler bu hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu
kodu öğreticinin ilerleyen bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme kapsayıcısını ile
kayıtlı.
İnceleme Startup.ConfigureServices yöntemi. Vurgulanan satırı iskele kurucu tarafından eklendi:
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
// needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("RazorPagesMovieContext")));
}

RazorPagesMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları
Movie modeli. Veri bağlamı ( RazorPagesMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext.
Veri bağlamı, hangi varlıkları veri modelinde yer alan belirtir.

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
public class RazorPagesMovieContext : DbContext
{
public RazorPagesMovieContext (DbContextOptions<RazorPagesMovieContext> options)
: base(options)
{
}

public DbSet<RazorPagesMovie.Models.Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir
varlık kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Hatası alırsanız:

SqlException: Cannot open database "RazorPagesMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı.
NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül
İngilizce olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer
gerekir. Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Sonraki öğreticiye yapı iskelesi tarafından oluşturulan dosyaları açıklar.

Ek kaynaklar

Ö N C E K I: S O N R A K I: R A Z O R S A Y F A L A R I IÇ IN IS K E L E
BA ŞL A M A KURULM UŞ
ASP.NET Core Razor Pages scafkatlama
23.11.2019 • 25 minutes to read • Edit Online

Tarafından Rick Anderson


Bu öğreticide, önceki öğreticidescafkatlama tarafından oluşturulan Razor Pages incelenir.
Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).

Oluşturma, silme, Ayrıntılar ve düzenleme sayfaları


Pages/filmler/Index. cshtml. cs sayfa modelini inceleyin:

// Unused usings removed.


using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get;set; }

public async Task OnGetAsync()


{
Movie = await _context.Movie.ToListAsync();
}
}
}

Razor Pages PageModel türetilir. Kurala göre PageModel türetilmiş sınıf <PageName>Model olarak adlandırılır.
Oluşturucu, RazorPagesMovieContext sayfaya eklemek için bağımlılık ekleme işlemini kullanır. Tüm yapı iskelesi
sayfaları bu düzene uyar. Entity Framework zaman uyumsuz programlama hakkında daha fazla bilgi için bkz.
zaman uyumsuz kod .
Sayfa için bir istek yapıldığında OnGetAsync yöntemi, Razor sayfasına bir film listesi döndürür. OnGetAsync
veya OnGet , sayfanın durumunu başlatmak için çağırılır. Bu durumda, OnGetAsync film listesini alır ve
görüntüler.
OnGet void döndürdüğünde veya OnGetAsync``Task döndürürse, hiçbir dönüş açıklaması kullanılmaz. Dönüş
türü IActionResult veya Task<IActionResult> olduğunda, return ifadesinin sağlanması gerekir. Örneğin,
Pages/filmler/Create. cshtml. cs OnPostAsync yöntemi:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}

Pages/filmler/Index. cshtml Razor sayfasını inceleyin:


@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Razor, HTML 'den C# ya da Razor 'e özgü biçimlendirmeye geçiş yapabilir. Bir @ sembol sonrasında Razor
ayrılmış bir anahtar sözcükolduğunda, bu, ' a geçiş yapar C#.
@page yönergesi
@page Razor yönergesi, dosyayı bir MVC eylemi yapar, bu da istekleri işleyebileceği anlamına gelir. @page
sayfadaki ilk Razor yönergesi olmalıdır. @page , Razor 'e özgü biçimlendirmeye geçme örneğidir. Daha fazla
bilgi için bkz. Razor söz dizimi .
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movie[0].Title)

DisplayNameFor HTML Yardımcısı, görünen adı belirlemede lambda ifadesinde başvurulan Title özelliğini
inceler. Lambda ifadesi değerlendirilmek yerine incelenir. Bu, model , model.Movie veya model.Movie[0] null
veya boş olduğunda herhangi bir erişim ihlali olmadığı anlamına gelir. Lambda ifadesi değerlendirildiğinde
(örneğin, @Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.
@model yönergesi

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@model yönergesi, Razor sayfasına geçirilen modelin türünü belirtir. Yukarıdaki örnekte @model satırı,
PageModel türetilmiş sınıfı Razor sayfası için kullanılabilir hale getirir. Model, @Html.DisplayNameFor ve
sayfadaki HTML yardımcılarını @Html.DisplayFor kullanılır.
Düzen sayfası
Menü bağlantılarını (RazorPagesMovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir.
Menü düzeni sayfa/paylaşılan/_Layout. cshtml dosyasında uygulanır. Pages/Shared/_Layout. cshtml dosyasını
açın.
Düzen ŞABLONLARı, HTML kapsayıcı düzeninin şu şekilde olmasını sağlar:
Tek bir yerde belirtildi.
Sitede birden çok sayfada uygulandı.
@RenderBody() satırını bulun. RenderBody , tüm sayfaya özgü görünümlerin, Düzen sayfasında kaydırılan bir
yer tutucudur. Örneğin, Gizlilik bağlantısını seçin ve Sayfalar/gizlilik. cshtml görünümü RenderBody yöntemi
içinde işlenir.
ViewData ve Layout
Pages/filmler/Index. cshtml dosyasından aşağıdaki biçimlendirmeyi göz önünde bulundurun:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

Önceki vurgulanan biçimlendirme, Razor geçişi örneği olan bir örnektir C#. { ve } karakterler bir C# kod
bloğunu kapsar.
PageModel temel sınıfı, verileri bir görünüme geçirmek için kullanılabilen bir ViewData Dictionary özelliği içerir.
Nesneler, anahtar/değer düzeniyle ViewData sözlüğüne eklenir. Yukarıdaki örnekte, "Title" özelliği ViewData
sözlüğüne eklenir.
"Title" özelliği sayfa/paylaşılan/_Layout. cshtml dosyasında kullanılır. Aşağıdaki biçimlendirme _Layout.
cshtml dosyasının ilk birkaç satırını gösterir.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>

@*Markup removed for brevity.*@

Satır @*Markup removed for brevity.*@ bir Razor açıklamadır. HTML yorumlarının ( <!-- --> ) aksine, Razor
açıklamaları istemciye gönderilmez.
Düzeni güncelleştirme
Pages/Shared/_Layout. cshtml dosyasındaki <title> öğesini RazorPagesMovieyerine filmi görüntüleyecek
şekilde değiştirin.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie</title>

Sayfa/paylaşılan/_Layout. cshtml dosyasında aşağıdaki tutturucu öğeyi bulun.

<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>

Önceki öğeyi aşağıdaki biçimlendirmeyle değiştirin:

<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>

Önceki tutturucu öğesi bir etiket yardımcıdır. Bu durumda, bağlantı etiketi yardımcısınınolması gerekir.
asp-page="/Movies/Index" Tag Helper özniteliği ve değeri, /Movies/Index Razor sayfasına bir bağlantı
oluşturur. asp-area öznitelik değeri boş olduğundan, alan bağlantıda kullanılmaz. Daha fazla bilgi için bkz.
alanlara bakın.
Değişikliklerinizi kaydedin ve Rpmovie bağlantısına tıklayarak uygulamayı test edin. Herhangi bir sorununuz
varsa GitHub 'daki _Layout. cshtml dosyasına bakın.
Diğer bağlantıları test edin (giriş, rpmovie, oluşturma, düzenlemeve silme). Her sayfada, tarayıcı
sekmesinde görebileceğiniz başlık ayarlanır. Bir sayfada yer işareti eklediğinizde başlık, yer işareti için kullanılır.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih
biçimleri için virgül (",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı
globalize için adımlar uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .

Layout özelliği Pages/_ViewStart. cshtml dosyasında ayarlanır:

@{
Layout = "_Layout";
}
Yukarıdaki biçimlendirme düzen dosyasını Sayfalar klasörü altındaki tüm Razor dosyaları için
Sayfalar/paylaşılan/_Layout. cshtml olarak ayarlar. Daha fazla bilgi için bkz. Düzen .
Sayfa oluştur modeli
Pages/filmler/Create. cshtml. cs sayfa modelini inceleyin:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}
}

OnGet yöntemi, sayfa için gereken tüm durumları başlatır. Oluşturma sayfasında başlatılacak durum yok, bu
nedenle Page döndürülür. Öğreticide daha sonra, OnGet başlatma durumuna bir örnek gösterilir. Page
yöntemi Create. cshtml sayfasını işleyen bir PageResult nesnesi oluşturur.
Movie özelliği, model bağlamayıkabul etmek için [BindProperty] özniteliğini kullanır. Oluşturma formu form
değerlerini gönderirse, ASP.NET Core çalışma zamanı, postalanan değerleri Movie modeline bağlar.
OnPostAsync yöntemi, sayfa form verileri gönderdiğinde çalıştırılır:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

Herhangi bir model hatası varsa, form, gönderilen tüm form verileriyle birlikte yeniden görüntülenir. Form
gönderilmeden önce çoğu model hatası istemci tarafında yakalanabilir. Bir model hatasına bir örnek, Date alanı
için bir tarihe dönüştürülemeyen bir değer gönderme. İstemci tarafı doğrulama ve model doğrulaması
Öğreticinin ilerleyen kısımlarında ele alınmıştır.
Model hatası yoksa, veriler kaydedilir ve tarayıcı dizin sayfasına yönlendirilir.
Razor Oluştur sayfası
Pages/filmler/Create. cshtml Razor sayfa dosyasını inceleyin:
@page
@model RazorPagesMovie.Pages.Movies.CreateModel

@{
ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio, etiket yardımcıları için kullanılan farklı kalın yazı tipiyle aşağıdaki etiketleri görüntüler:
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post"> öğesi bir form etiketi yardımcıdır. Form etiketi Yardımcısı, bir antiforgery
belirteciniotomatik olarak içerir.
Yapı iskelesi altyapısı, modeldeki her alan için (KIMLIK hariç), aşağıdakine benzer Razor biçimlendirmesi
oluşturur:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>


<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Doğrulama etiketi yardımcıları ( <div asp-validation-summary ve <span asp-validation-for ) doğrulama


hatalarını görüntüler. Doğrulama, bu serinin ilerleyen kısımlarında daha ayrıntılı bir şekilde ele alınmıştır.
Etiket etiketi Yardımcısı ( <label asp-for="Movie.Title" class="control-label"></label> ), Title özelliği için
etiket başlığını ve for özniteliğini oluşturur.
Giriş etiketi Yardımcısı ( <input asp-for="Movie.Title" class="form-control"> ), dataaçıklamaların özniteliklerini
kullanır ve istemci tarafında jQuery doğrulaması için gerekli HTML özniteliklerini üretir.
<form method="post"> gibi etiket yardımcıları hakkında daha fazla bilgi için bkz. ASP.NET Core etiket
yardımcıları.

Ek kaynaklar

Ö N C E K I: B IR M O D E L SON RA KI :
EKLEM E V E R IT A B A N I
Tarafından Rick Anderson
Bu öğreticide, önceki öğreticidescafkatlama tarafından oluşturulan Razor Pages incelenir.
Görüntüleme veya indirme örnek.

Oluşturma, silme, Ayrıntılar ve düzenleme sayfaları


Pages/filmler/Index. cshtml. cs sayfa modelini inceleyin:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;

namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get;set; }

public async Task OnGetAsync()


{
Movie = await _context.Movie.ToListAsync();
}
}
}

Razor Pages PageModel türetilir. Kurala göre PageModel türetilmiş sınıf <PageName>Model olarak adlandırılır.
Oluşturucu, RazorPagesMovieContext sayfaya eklemek için bağımlılık ekleme işlemini kullanır. Tüm yapı iskelesi
sayfaları bu düzene uyar. Entity Framework zaman uyumsuz programlama hakkında daha fazla bilgi için bkz.
zaman uyumsuz kod .
Sayfa için bir istek yapıldığında OnGetAsync yöntemi, Razor sayfasına bir film listesi döndürür. OnGetAsync
veya OnGet bir Razor sayfasında, sayfanın durumunu başlatmak için çağrılır. Bu durumda, OnGetAsync film
listesini alır ve görüntüler.
OnGet döndürdüğünde veya OnGetAsync``Task döndürürse, hiçbir dönüş yöntemi kullanılmaz. Dönüş
void
türü IActionResult veya Task<IActionResult> olduğunda, return ifadesinin sağlanması gerekir. Örneğin,
Pages/filmler/Create. cshtml. cs OnPostAsync yöntemi:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}

Pages/filmler/Index. cshtml Razor sayfasını inceleyin:


@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Razor, HTML 'den C# ya da Razor 'e özgü biçimlendirmeye geçiş yapabilir. Bir @ sembol sonrasında Razor
ayrılmış bir anahtar sözcükolduğunda, bu, ' a geçiş yapar C#.
@page Razor yönergesi, dosyayı bir MVC eylemine dönüştürür, bu da istekleri işleyebileceği anlamına gelir.
@page sayfadaki ilk Razor yönergesi olmalıdır. @page , Razor 'e özgü biçimlendirmeye geçme örneğidir. Daha
fazla bilgi için bkz. Razor söz dizimi .
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movie[0].Title)

DisplayNameFor HTML Yardımcısı, görünen adı belirlemede lambda ifadesinde başvurulan Title özelliğini
inceler. Lambda ifadesi değerlendirilmek yerine incelenir. Bu, model , model.Movie veya model.Movie[0] null
veya boş olduğunda herhangi bir erişim ihlali olmadığı anlamına gelir. Lambda ifadesi değerlendirildiğinde
(örneğin, @Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.
@model yönergesi

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@model yönergesi, Razor sayfasına geçirilen modelin türünü belirtir. Yukarıdaki örnekte @model satırı,
PageModel türetilmiş sınıfı Razor sayfası için kullanılabilir hale getirir. Model, @Html.DisplayNameFor ve
sayfadaki HTML yardımcılarını @Html.DisplayFor kullanılır.
Düzen sayfası
Menü bağlantılarını (RazorPagesMovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir.
Menü düzeni sayfa/paylaşılan/_Layout. cshtml dosyasında uygulanır. Pages/Shared/_Layout. cshtml dosyasını
açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden
çok sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm sayfaya
özgü görünümlerin, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını seçerseniz,
Sayfa/Gizlilik. cshtml görünümü RenderBody yöntemi içinde işlenir.
ViewData ve Layout
Pages/filmler/Index. cshtml dosyasından aşağıdaki kodu göz önünde bulundurun:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

Önceki vurgulanan kod, Razor geçişi örneği olan bir örnektir C#. { ve } karakterler bir C# kod bloğunu
kapsar.
PageModel temel sınıfında, bir görünüme geçirmek istediğiniz verileri eklemek için kullanılabilecek bir
ViewData Dictionary özelliği vardır. Bir anahtar/değer düzeniyle ViewData sözlüğüne nesne eklersiniz.
Yukarıdaki örnekte, "title" özelliği ViewData sözlüğüne eklenir.
"Title" özelliği sayfa/paylaşılan/_Layout. cshtml dosyasında kullanılır. Aşağıdaki biçimlendirme _Layout. cshtml
dosyasının ilk birkaç satırını gösterir.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>

@*Markup removed for brevity.*@


Satır @*Markup removed for brevity.*@ , düzen dosyanızda görünmeyen bir Razor açıklamadır. HTML
yorumlarının ( <!-- --> ) aksine, Razor açıklamaları istemciye gönderilmez.
Düzeni güncelleştirme
Pages/Shared/_Layout. cshtml dosyasındaki <title> öğesini RazorPagesMovieyerine filmi görüntüleyecek
şekilde değiştirin.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie</title>

Sayfa/paylaşılan/_Layout. cshtml dosyasında aşağıdaki tutturucu öğeyi bulun.

<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>

Önceki öğeyi aşağıdaki biçimlendirme ile değiştirin.

<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>

Önceki tutturucu öğesi bir etiket yardımcıdır. Bu durumda, bağlantı etiketi yardımcısınınolması gerekir.
asp-page="/Movies/Index" Tag Helper özniteliği ve değeri, /Movies/Index Razor sayfasına bir bağlantı
oluşturur. asp-area öznitelik değeri boş olduğundan, alan bağlantıda kullanılmaz. Daha fazla bilgi için bkz.
alanlara bakın.
Değişikliklerinizi kaydedin ve Rpmovie bağlantısına tıklayarak uygulamayı test edin. Herhangi bir sorununuz
varsa GitHub 'daki _Layout. cshtml dosyasına bakın.
Diğer bağlantıları test edin (giriş, rpmovie, oluşturma, düzenlemeve silme). Her sayfada, tarayıcı
sekmesinde görebileceğiniz başlık ayarlanır. Bir sayfada yer işareti eklediğinizde başlık, yer işareti için kullanılır.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih
biçimleri için virgül (",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı
globalize için adımlar uygulamanız gerekir. Bu GitHub, ondalık virgülden ekleme hakkında yönergeler için 4076 sorun .

Layout özelliği Pages/_ViewStart. cshtml dosyasında ayarlanır:

@{
Layout = "_Layout";
}

Yukarıdaki biçimlendirme düzen dosyasını Sayfalar klasörü altındaki tüm Razor dosyaları için
Sayfalar/paylaşılan/_Layout. cshtml olarak ayarlar. Daha fazla bilgi için bkz. Düzen .
Sayfa oluştur modeli
Pages/filmler/Create. cshtml. cs sayfa modelini inceleyin:
// Unused usings removed.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public CreateModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
}
}

OnGet yöntemi, sayfa için gereken tüm durumları başlatır. Oluşturma sayfasında başlatılacak durum yok, bu
nedenle Page döndürülür. Öğreticide daha sonra OnGet yöntemi başlatma durumunu görürsünüz. Page
yöntemi Create. cshtml sayfasını işleyen bir PageResult nesnesi oluşturur.
Movie özelliği, model bağlamayıkabul etmek için [BindProperty] özniteliğini kullanır. Oluşturma formu form
değerlerini gönderirse, ASP.NET Core çalışma zamanı, postalanan değerleri Movie modeline bağlar.
OnPostAsync yöntemi, sayfa form verileri gönderdiğinde çalıştırılır:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Movie.Add(Movie);
await _context.SaveChangesAsync();

return RedirectToPage("./Index");
}
Herhangi bir model hatası varsa, form, gönderilen tüm form verileriyle birlikte yeniden görüntülenir. Form
gönderilmeden önce çoğu model hatası istemci tarafında yakalanabilir. Bir model hatasına bir örnek, Date alanı
için bir tarihe dönüştürülemeyen bir değer gönderme. İstemci tarafı doğrulama ve model doğrulaması
Öğreticinin ilerleyen kısımlarında ele alınmıştır.
Model hatası yoksa, veriler kaydedilir ve tarayıcı dizin sayfasına yönlendirilir.
Razor Oluştur sayfası
Pages/filmler/Create. cshtml Razor sayfa dosyasını inceleyin:

@page
@model RazorPagesMovie.Pages.Movies.CreateModel

@{
ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-page="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio, etiket yardımcıları için kullanılan farklı kalın yazı tipiyle <form method="post"> etiketini
görüntüler:

<form method="post"> öğesi bir form etiketi yardımcıdır. Form etiketi Yardımcısı, bir antiforgery
belirteciniotomatik olarak içerir.
Yapı iskelesi altyapısı, modeldeki her alan için (KIMLIK hariç), aşağıdakine benzer Razor biçimlendirmesi
oluşturur:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>


<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Doğrulama etiketi yardımcıları ( <div asp-validation-summary ve <span asp-validation-for ) doğrulama


hatalarını görüntüler. Doğrulama, bu serinin ilerleyen kısımlarında daha ayrıntılı bir şekilde ele alınmıştır.
Etiket etiketi Yardımcısı ( <label asp-for="Movie.Title" class="control-label"></label> ), Title özelliği için
etiket başlığını ve for özniteliğini oluşturur.
Giriş etiketi Yardımcısı ( <input asp-for="Movie.Title" class="form-control"> ), dataaçıklamaların özniteliklerini
kullanır ve istemci tarafında jQuery doğrulaması için gerekli HTML özniteliklerini üretir.
Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: B IR M O D E L SON RA KI :
EKLEM E V E R IT A B A N I
Veritabanı ve ASP.NET Core çalışma
23.11.2019 • 20 minutes to read • Edit Online

Tarafından Rick Anderson ve ALi Audette


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
RazorPagesMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme
görevini işler. Veritabanı bağlamı, Startup.csiçindeki ConfigureServices yönteminde bağımlılık ekleme
kapsayıcısına kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages();

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON
dosyasından bağlantı dizesini alır.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Veritabanı ( Database={Database name} ) için ad değeri, oluşturulan kodunuz için farklı olacaktır. Ad değeri
rastgele.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-
bc;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini gerçek bir veritabanı sunucusuna
ayarlamak için bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio
SQL Server Express LocalDB
LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür.
LocalDB, isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan
olarak, LocalDB veritabanı C:\Users\<user>\ dizininde *.mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.

Movie tabloya sağ tıklayıp Görünüm Tasarımcısı' nı seçin:


ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar için ID adlı bir özellik
oluşturur.
Movie tabloya sağ tıklayın ve verileri görüntüle' yi seçin:

Veritabanının çekirdeğini oluşturma


Modeller klasöründe aşağıdaki kodla SeedData adlı yeni bir sınıf oluşturun:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
using System;
using System.Linq;

namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Temel yöntemi çağırın ve bu yönteme geçerek bağlamı geçer.
Çekirdek yöntemi tamamlandığında bağlamı atın.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;

namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Update-Database çalıştırılmayan aşağıdaki özel durum oluşur:

SqlException: Cannot open database "RazorPagesMovieContext-" requested by the login. The login failed.
Login failed for user 'user name'.
Uygulamayı test etme
Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya Ssox 'ten silme bağlantılarıyla
yapabilirsiniz
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri
çağırın). Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur' a
dokunun:

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5


tuşuna basın.
Ile hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Sonraki öğreticide, verilerin sunumu gelişmeyecektir.

Ek kaynaklar

Ö N C E K I: Y A P I IS K E L E S I R A Z O R IL E R I: S A Y F A L A R I
PAGES G Ü N C E L L E Ş T IR M E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
RazorPagesMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme
görevini işler. Veritabanı bağlamı, Startup.csiçindeki ConfigureServices yönteminde bağımlılık ekleme
kapsayıcısına kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
// needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("RazorPagesMovieContext")));
}

ConfigureServices ' de kullanılan yöntemler hakkında daha fazla bilgi için bkz.:
CookiePolicyOptionsiçin ASP.NET Core ab genel veri koruma yönetmeliği (GDPR ) desteği .
SetCompatibilityVersion
ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON
dosyasından bağlantı dizesini alır.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Veritabanı ( Database={Database name} ) için ad değeri, oluşturulan kodunuz için farklı olacaktır. Ad değeri
rastgele.

{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-
1234;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini gerçek bir veritabanı sunucusuna
ayarlamak için bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code
Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür.
LocalDB, isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan
olarak, LocalDB veritabanı C:/Users/<user/> dizininde *.mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.

Movie tabloya sağ tıklayıp Görünüm Tasarımcısı' nı seçin:


ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar için ID adlı bir özellik
oluşturur.
Movie tabloya sağ tıklayın ve verileri görüntüle' yi seçin:

Veritabanının çekirdeğini oluşturma


Modeller klasöründe aşağıdaki kodla SeedData adlı yeni bir sınıf oluşturun:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Temel yöntemi çağırın ve bu yönteme geçerek bağlamı geçer.
Çekirdek yöntemi tamamlandığında bağlamı atın.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;
using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context=services.
GetRequiredService<RazorPagesMovieContext>();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

Bir üretim uygulaması Database.Migrate çağırmaz. Update-Database çalıştırılmadığından aşağıdaki özel


durumu engellemek için yukarıdaki koda eklenir:
SqlException: oturum açma tarafından istenen "RazorPagesMovieContext-21" veritabanı açılamıyor. Oturum
açılamadı. ' Kullanıcı adı ' kullanıcısı için oturum açma başarısız.
Uygulamayı test etme
Visual Studio
Visual Studio Code
Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya Ssox 'ten silme bağlantılarıyla
yapabilirsiniz
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri
çağırın). Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur' a
dokunun:

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5


tuşuna basın.
Ile hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir:

Sonraki öğretici, verilerin sunumunu temizler.


Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: Y A P I IS K E L E S I R A Z O R IL E R I: S A Y F A L A R I
PAGES G Ü N C E L L E Ş T IR M E
ASP.NET Core uygulamasında oluşturulan sayfaları
güncelleştirme
23.11.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate Yayın tarihi
(iki sözcük) olmalıdır.

Oluşturulan kodu Güncelleştir


Modeller/film. cs dosyasını açın ve aşağıdaki kodda gösterilen vurgulanmış satırları ekleyin:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

[Column(TypeName = "decimal(18, 2)")] veri ek açıklaması, Entity Framework Core veritabanında Price para
birimine doğru şekilde eşlemesine olanak sağlar. Daha fazla bilgi için bkz. veri türleri.
Veri açıklamaları sonraki öğreticide ele alınmıştır. Display özniteliği bir alanın adı için (Bu durumda
"ReleaseDate" yerine "Yayın tarihi") görüntüleneceğini belirtir. DataType özniteliği verilerin türünü belirtir
(Tarih), bu nedenle alanda depolanan zaman bilgileri gösterilmez.
Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/filmler/Index. cshtml dosyasındaki tutturucu etiketi Yardımcısı
tarafından oluşturulur.
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper , Razor sayfasından (yol göreli), asp-page ve yol
kimliği ( asp-route-id ) HTML href öznitelik değerini dinamik olarak oluşturur. Daha fazla bilgi için bkz.
Sayfalar Için URL oluşturma .
Oluşturulan biçimlendirmeyi incelemek için sık kullandığınız tarayıcıdan Görünüm kaynağını kullanın.
Oluşturulan HTML 'nin bir bölümü aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>

Dinamik olarak oluşturulan bağlantılar, film KIMLIĞINI bir sorgu dizesiyle (örneğin,
https://localhost:5001/Movies/Details?id=1``?id=1 ) iletir.

Rota şablonu Ekle


"{İd: int}" yol şablonunu kullanmak için Düzenle, Ayrıntılar ve Sil Razor Pages güncelleştirin. Bu sayfaların her
biri için Page yönergesini @page "{id:int}"``@page değiştirin. Uygulamayı çalıştırın ve kaynağı görüntüleyin.
Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI ekler:

<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>

Tamsayıyı içermeyen " {id: int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404 (bulunamadı) hatası
döndürüyor. Örneğin, http://localhost:5000/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı
yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"
@page "{id:int?}" davranışını test etmek için:
Pages/filmler/details. cshtml içindeki page yönergesini @page "{id:int?}" olarak ayarlayın.
public async Task<IActionResult> OnGetAsync(int? id) ( sayfalarda/filmlerde/details. cshtml. cs) bir kesme
noktası ayarlayın.
https://test-cors.org sayfasına gidin.
@page "{id:int}" yönergesi ile, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404
döndürür. @page "{id:int?}" kullanarak OnGetAsync yöntemi NotFound ( HTTP 404 ) döndürür.

Eşzamanlılık özel durum işlemeyi gözden geçirme


Pages/filmler/Edit. cshtml. cs dosyasındaki OnPostAsync yöntemini gözden geçirin:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Önceki kod, bir istemci filmi sildiği ve diğer istemci filmle değişiklik yaptığı zaman eşzamanlılık özel
durumlarını algılar.
catch bloğunu test etmek için:
catch (DbUpdateConcurrencyException) kesme noktası ayarlama
Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
Önceki tarayıcı penceresinde filmdeki değişiklikleri gönderin.
Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. eşzamanlılık
çakışmalarını işleme .
Gönderme ve bağlama incelemesi
Pages/filmler/Edit. cshtml. cs dosyasını inceleyin:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);

if (Movie == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Filmler/düzenleme sayfasına HTTP GET isteği yapıldığında (örneğin, http://localhost:5000/Movies/Edit/2 ):


OnGetAsync yöntemi, filmi veritabanından getirir ve Page yöntemini döndürür.
Page yöntemi, Pages/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası, film
modelinin sayfada kullanılabilir olmasını sağlayan model yönergesini (
@model RazorPagesMovie.Pages.Movies.EditModel ) içerir.
Düzenleme formu filmdeki değerlerle birlikte görüntülenir.
Filmler/Düzenle sayfası gönderildiğinde:
Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty] özniteliği model
bağlamayımümkün.

[BindProperty]
public Movie Movie { get; set; }

Model durumunda hatalar varsa (örneğin, ReleaseDate bir tarihe dönüştürülemiyorsa), form gönderilen
değerlerle yeniden görüntülenir.
Model hatası yoksa, film kaydedilir.
Razor sayfalarında Dizin, oluşturma ve silme gibi HTTP GET yöntemleri benzer bir düzende yer alır. Razor
Oluştur sayfasındaki HTTP POST OnPostAsync yöntemi, Razor düzenleme sayfasındaki OnPostAsync
yöntemine benzer bir düzen izler.

Ek kaynaklar

Ö N C E K I: B IR V E R IT A B A N IY L A IL E R I: A R A M A
Ç A L IŞ M A EKLE

Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate Yayın tarihi
(iki sözcük) olmalıdır.

Oluşturulan kodu Güncelleştir


Modeller/film. cs dosyasını açın ve aşağıdaki kodda gösterilen vurgulanmış satırları ekleyin:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

[Column(TypeName = "decimal(18, 2)")] veri ek açıklaması, Entity Framework Core veritabanında Price para
birimine doğru şekilde eşlemesine olanak sağlar. Daha fazla bilgi için bkz. veri türleri.
Veri açıklamaları sonraki öğreticide ele alınmıştır. Display özniteliği bir alanın adı için (Bu durumda
"ReleaseDate" yerine "Yayın tarihi") görüntüleneceğini belirtir. DataType özniteliği verilerin türünü belirtir
(Tarih), bu nedenle alanda depolanan zaman bilgileri gösterilmez.
Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/filmler/Index. cshtml dosyasındaki tutturucu etiketi Yardımcısı
tarafından oluşturulur.
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper , Razor sayfasından (yol göreli), asp-page ve yol
kimliği ( asp-route-id ) HTML href öznitelik değerini dinamik olarak oluşturur. Daha fazla bilgi için bkz.
Sayfalar Için URL oluşturma .
Oluşturulan biçimlendirmeyi incelemek için sık kullandığınız tarayıcıdan Görünüm kaynağını kullanın.
Oluşturulan HTML 'nin bir bölümü aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>

Dinamik olarak oluşturulan bağlantılar, film KIMLIĞINI bir sorgu dizesiyle (örneğin,
https://localhost:5001/Movies/Details?id=1``?id=1 ) iletir.

"{İd: int}" yol şablonunu kullanmak için Düzenle, Ayrıntılar ve Sil Razor Pages güncelleştirin. Bu sayfaların her
biri için Page yönergesini @page "{id:int}"``@page değiştirin. Uygulamayı çalıştırın ve kaynağı görüntüleyin.
Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI ekler:

<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>

Tamsayıyı içermeyen " {id: int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404 (bulunamadı) hatası
döndürüyor. Örneğin, http://localhost:5000/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı
yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

@page "{id:int?}" davranışını test etmek için:


Pages/filmler/details. cshtml içindeki page yönergesini @page "{id:int?}" olarak ayarlayın.
public async Task<IActionResult> OnGetAsync(int? id) ( sayfalarda/filmlerde/details. cshtml. cs) bir kesme
noktası ayarlayın.
https://test-cors.org sayfasına gidin.
@page "{id:int}" yönergesi ile, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404
döndürür. @page "{id:int?}" kullanarak OnGetAsync yöntemi NotFound ( HTTP 404 ) döndürür.

Eşzamanlılık özel durum işlemeyi gözden geçirme


Pages/filmler/Edit. cshtml. cs dosyasındaki OnPostAsync yöntemini gözden geçirin:

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}

private bool MovieExists(int id)


{
return _context.Movie.Any(e => e.ID == id);
}

Önceki kod, bir istemci filmi sildiği ve diğer istemci filmle değişiklik yaptığı zaman eşzamanlılık özel
durumlarını algılar.
catch bloğunu test etmek için:
catch (DbUpdateConcurrencyException) kesme noktası ayarlama
Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
Önceki tarayıcı penceresinde filmdeki değişiklikleri gönderin.
Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. eşzamanlılık
çakışmalarını işleme .
Gönderme ve bağlama incelemesi
Pages/filmler/Edit. cshtml. cs dosyasını inceleyin:
public class EditModel : PageModel
{
private readonly RazorPagesMovieContext _context;

public EditModel(RazorPagesMovieContext context)


{
_context = context;
}

[BindProperty]
public Movie Movie { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);

if (Movie == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Attach(Movie).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Movie.Any(e => e.ID == Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}

return RedirectToPage("./Index");
}
}

Filmler/düzenleme sayfasına HTTP GET isteği yapıldığında (örneğin, http://localhost:5000/Movies/Edit/2 ):


OnGetAsync yöntemi, filmi veritabanından getirir ve Page yöntemini döndürür.
Page yöntemi, Pages/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası, film
modelinin sayfada kullanılabilir olmasını sağlayan model yönergesini (
@model RazorPagesMovie.Pages.Movies.EditModel ) içerir.
Düzenleme formu filmdeki değerlerle birlikte görüntülenir.
Filmler/Düzenle sayfası gönderildiğinde:
Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty] özniteliği model
bağlamayımümkün.

[BindProperty]
public Movie Movie { get; set; }

Model durumunda hatalar varsa (örneğin, ReleaseDate bir tarihe dönüştürülemiyorsa), form gönderilen
değerlerle birlikte görüntülenir.
Model hatası yoksa, film kaydedilir.
Razor sayfalarında Dizin, oluşturma ve silme gibi HTTP GET yöntemleri benzer bir düzende yer alır. Razor
Oluştur sayfasındaki HTTP POST OnPostAsync yöntemi, Razor düzenleme sayfasındaki OnPostAsync
yöntemine benzer bir düzen izler.
Arama sonraki öğreticiye eklenir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: B IR V E R IT A B A N IY L A IL E R I: A R A M A
Ç A L IŞ M A EKLE
ASP.NET Core Razor Pages arama Ekle
6.12.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Aşağıdaki bölümlerde, film tarzya veya ada göre arama eklenir.
Aşağıdaki Vurgulanan özellikleri sayfalara/filmlere/Index. cshtml. csöğesine ekleyin:

public class IndexModel : PageModel


{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get; set; }


[BindProperty(SupportsGet = true)]
public string SearchString { get; set; }
// Requires using Microsoft.AspNetCore.Mvc.Rendering;
public SelectList Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string MovieGenre { get; set; }

SearchString : kullanıcıların arama metin kutusuna girebileceği metni içerir. SearchString [BindProperty]
özniteliği vardır. [BindProperty] form değerlerini ve Sorgu dizelerini özelliğiyle aynı ada bağlar. GET
isteklerinde bağlama için (SupportsGet = true) gereklidir.
Genres : tarzlar listesini içerir. Genres , kullanıcının listeden bir tarz seçmesine izin verir. SelectList
using Microsoft.AspNetCore.Mvc.Rendering; gerektiriyor
MovieGenre : kullanıcının seçtiği belirli tarzı içerir (örneğin, "Batı").
Genres ve MovieGenre daha sonra bu öğreticide kullanılır.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir. Özelliklerle
eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine veya rota değerlerine
dayanan senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true olarak
ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Dizin sayfasının OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:


public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

Movie = await movies.ToListAsync();


}

OnGetAsync yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

// using System.Linq;
var movies = from m in _context.Movie
select m;

Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.


SearchString özelliği null veya boş değilse, filmler sorgusu arama dizesinde filtrelenecek şekilde değiştirilir:

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() kodu bir lambda ifadesidir. Lambdalar, Yöntem tabanlı LINQ sorgularında, Where
yöntemi veya Contains (önceki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız değişkenler
olarak kullanılır. LINQ sorguları tanımlandıklarında veya bir Yöntem (örneğin, Where , Contains veya OrderBy )
çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir ifadenin
değerlendirmesi, gerçekleştirilmiş değeri yinelenene veya ToListAsync yöntemi çağrılana kadar gecikir. Daha
fazla bilgi için bkz. sorgu yürütme .

NOTE
Contains yöntemi C# kodda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve
harmanlamaya bağlıdır. SQL Server, SQL Ile benzer, büyük/küçük harfe duyarsız Contains eşlenir. SQLite ' da, varsayılan
harmanlama ile büyük/küçük harfe duyarlıdır.

Filmler sayfasına gidin ve URL 'ye gibi bir sorgu dizesi ekleyin (örneğin,
?searchString=Ghost
https://localhost:5001/Movies?searchString=Ghost ). Filtrelenmiş filmler görüntülenir.
Aşağıdaki yol şablonu dizin sayfasına eklendiyse, arama dizesi bir URL segmenti olarak geçirilebilir (örneğin,
https://localhost:5001/Movies/Ghost ).

@page "{searchString?}"

Önceki yol kısıtlaması, başlığın sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak aranmasına
olanak tanır. "{searchString?}" ? , bu isteğe bağlı bir yol parametresi anlamına gelir.

ASP.NET Core çalışma zamanı, SearchString özelliğinin değerini sorgu dizesinden ( ?searchString=Ghost )
veya rota verilerinden ( https://localhost:5001/Movies/Ghost ) ayarlamak için model bağlamayı kullanır. Model
bağlama büyük/küçük harfe duyarlı değildir.
Ancak, kullanıcıların bir filmi aramak için URL 'YI değiştirmesini beklemeniz gerekmez. Bu adımda, filmleri
filtrelemek için Kullanıcı arabirimi eklenir. "{searchString?}" yol kısıtlaması eklediyseniz, kaldırın.
Pages/filmler/Index. cshtml dosyasını açın ve aşağıdaki kodda vurgulanan <form> işaretlemesini ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

HTML <form> etiketi aşağıdaki Etiket Yardımcılarıkullanır:


Form etiketi Yardımcısı. Form gönderildiğinde, filtre dizesi, sorgu dizesi aracılığıyla Sayfalar/filmler/Dizin
sayfasına gönderilir.
Giriş Etiketi Yardımcısı
Değişiklikleri kaydedin ve filtreyi test edin.
Tarza göre ara
OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}

Aşağıdaki kod, veritabanından tüm tarzları alan bir LINQ sorgusudur.

// Use LINQ to get list of genres.


IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

Tarzın SelectList , farklı tarzlar yansıtılayarak oluşturulur.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Türe göre, Razor sayfasına arama ekleme


Index. cshtml 'yi aşağıdaki şekilde güncelleştirin:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: S A Y F A L A R I İL E R I: Y E N I B IR A L A N
G Ü N C E L L E Ş T IR M E EKLEM E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
Aşağıdaki bölümlerde, film tarzya veya ada göre arama eklenir.
Aşağıdaki Vurgulanan özellikleri sayfalara/filmlere/Index. cshtml. csöğesine ekleyin:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;

public IndexModel(RazorPagesMovie.Models.RazorPagesMovieContext context)


{
_context = context;
}

public IList<Movie> Movie { get; set; }


[BindProperty(SupportsGet = true)]
public string SearchString { get; set; }
// Requires using Microsoft.AspNetCore.Mvc.Rendering;
public SelectList Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string MovieGenre { get; set; }

SearchString : kullanıcıların arama metin kutusuna girebileceği metni içerir. SearchString [BindProperty]
özniteliği vardır. [BindProperty] form değerlerini ve Sorgu dizelerini özelliğiyle aynı ada bağlar. GET
isteklerinde bağlama için (SupportsGet = true) gereklidir.
Genres : tarzlar listesini içerir. Genres , kullanıcının listeden bir tarz seçmesine izin verir. SelectList
using Microsoft.AspNetCore.Mvc.Rendering; gerektiriyor
MovieGenre : kullanıcının seçtiği belirli tarzı içerir (örneğin, "Batı").
Genres ve MovieGenre daha sonra bu öğreticide kullanılır.

WARNING
Güvenlik nedenleriyle, GET istek verilerini sayfa modeli özelliklerine bağlamayı tercih etmeniz gerekir. Özelliklerle
eşleştirmadan önce Kullanıcı girişini doğrulayın. GET bağlamaya dönüştürmek, sorgu dizesine veya rota değerlerine
dayanan senaryoları adreslemekte yararlıdır.
GET isteklerindeki bir özelliği bağlamak için, [BindProperty] özniteliğinin SupportsGet özelliğini true olarak
ayarlayın:

[BindProperty(SupportsGet = true)]

Daha fazla bilgi için bkz. ASP.NET Core topluluk alışması: Get tartışmasına bağlama (YouTube) .

Dizin sayfasının OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

Movie = await movies.ToListAsync();


}

OnGetAsync yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:
// using System.Linq;
var movies = from m in _context.Movie
select m;

Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.


SearchString özelliği null veya boş değilse, filmler sorgusu arama dizesinde filtrelenecek şekilde değiştirilir:

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() kodu bir lambda ifadesidir. Lambdalar, Yöntem tabanlı LINQ sorgularında, Where
yöntemi veya Contains (önceki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız değişkenler
olarak kullanılır. LINQ sorguları tanımlandıklarında veya bir Yöntem (örneğin, Where , Contains veya OrderBy )
çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir ifadenin
değerlendirmesi, gerçekleştirilmiş değeri yinelenene veya ToListAsync yöntemi çağrılana kadar gecikir. Daha
fazla bilgi için bkz. sorgu yürütme .
Note: Contains yöntemi C# kodda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı
veritabanına ve harmanlamaya bağlıdır. SQL Server, SQL Ile benzer, büyük/küçük harfe duyarsız Contains
eşlenir. SQLite ' da, varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.
Filmler sayfasına gidin ve URL 'ye ?searchString=Ghost gibi bir sorgu dizesi ekleyin (örneğin,
https://localhost:5001/Movies?searchString=Ghost ). Filtrelenmiş filmler görüntülenir.

Aşağıdaki yol şablonu dizin sayfasına eklendiyse, arama dizesi bir URL segmenti olarak geçirilebilir (örneğin,
https://localhost:5001/Movies/Ghost ).

@page "{searchString?}"
Önceki yol kısıtlaması, başlığın sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak aranmasına
olanak tanır. "{searchString?}" ? , bu isteğe bağlı bir yol parametresi anlamına gelir.

ASP.NET Core çalışma zamanı, SearchString özelliğinin değerini sorgu dizesinden ( ?searchString=Ghost )
veya rota verilerinden ( https://localhost:5001/Movies/Ghost ) ayarlamak için model bağlamayı kullanır. Model
bağlama büyük/küçük harfe duyarlı değildir.
Ancak, kullanıcıların bir filmi aramak için URL 'YI değiştirmesini beklemeniz gerekmez. Bu adımda, filmleri
filtrelemek için Kullanıcı arabirimi eklenir. "{searchString?}" yol kısıtlaması eklediyseniz, kaldırın.
Pages/filmler/Index. cshtml dosyasını açın ve aşağıdaki kodda vurgulanan <form> işaretlemesini ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

HTML <form> etiketi aşağıdaki Etiket Yardımcılarıkullanır:


Form etiketi Yardımcısı. Form gönderildiğinde, filtre dizesi, sorgu dizesi aracılığıyla Sayfalar/filmler/Dizin
sayfasına gönderilir.
Giriş Etiketi Yardımcısı
Değişiklikleri kaydedin ve filtreyi test edin.

Tarza göre ara


OnGetAsync yöntemini aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync()


{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}

if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}

Aşağıdaki kod, veritabanından tüm tarzları alan bir LINQ sorgusudur.


// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

Tarzın SelectList , farklı tarzlar yansıtılayarak oluşturulur.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Türe göre, Razor sayfasına arama ekleme


Index. cshtml 'yi aşağıdaki şekilde güncelleştirin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
@*Markup removed for brevity.*@

Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin. Önceki kod, Select etiketi
yardımcısını ve seçenek etiketi yardımcısını kullanır.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: S A Y F A L A R I İL E R I: Y E N I B IR A L A N
G Ü N C E L L E Ş T IR M E EKLEM E
ASP.NET Core Razor sayfasına yeni bir alan ekleyin
23.11.2019 • 17 minutes to read • Edit Online

Tarafından Rick Anderson


Örnek kodu görüntüle veya indir (indirme).
Örnek kodu görüntüle veya indir (indirme).
Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alan şeması değişikliğini veritabanına geçirin.
Bir veritabanını otomatik olarak oluşturmak için EF Code First kullanırken Code First:
Veritabanı şemasının oluşturulduğu model sınıflarıyla eşitlenmiş olup olmadığını izlemek için veritabanına
bir __EFMigrationsHistory tablosu ekler.
Model sınıfları DB ile eşitlenmiyorsa, EF bir özel durum oluşturur.
Şema/modelin eşitlemede otomatik olarak doğrulanması, tutarsız veritabanı/kod sorunlarını bulmayı
kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleme


Modeller/film. cs dosyasını açın ve bir Rating özelliği ekleyin:

public class Movie


{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulamayı derleyin.
Sayfaları/filmleri/dizini. cshtml'yi düzenleyin ve bir Rating alanı ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Aşağıdaki sayfaları güncelleştirin:


Silme ve Ayrıntılar sayfalarına Rating alanını ekleyin.
Create. cshtml dosyasını bir Rating alanla güncelleştirin.
Düzenleme sayfasına Rating alanını ekleyin.

VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Veritabanını
güncelleştirmeden uygulamayı çalıştırmak bir SqlException oluşturur:
SqlException: Invalid column name 'Rating'.

SqlException özel durumu, güncelleştirilmiş film modeli sınıfının, veritabanının film tablosunun şemasından
farklı olmasından kaynaklanır. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Yeni model sınıfı şemasını kullanarak veritabanını otomatik olarak bırakıp yeniden oluşturmaya Entity
Framework. Bu yaklaşım, geliştirme döngüsünün başlarında daha erken bir yoldur; modeli ve veritabanı
şemasını birlikte hızla gelişmenize olanak tanır. Downsıde, veritabanında var olan verileri kaybetmeniz.
Bu yaklaşımı bir üretim veritabanında kullanmayın! DB 'yi şema değişikliklerinde bırakıp bir başlatıcı
kullanarak veritabanının test verileriyle otomatik olarak çekirdeğini oluşturmak, genellikle bir uygulama
geliştirmeye yönelik üretken bir yoldur.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın
avantajı, verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği
oluşturarak yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanın.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie bloğu için bu değişikliği yapmak isteyeceksiniz.

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M,
Rating = "R"
},

Tamamlanan SeedData.cs dosyasınabakın.


Çözümü oluşturun.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Derecelendirme alanı için bir geçiş ekleyin
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC'de aşağıdaki
komutları girin:

Add-Migration Rating
Update-Database

Add-Migration komutu, çerçeveye şunları belirtir:


Moviemodelini Movie DB şemasıyla karşılaştırın.
DB şemasını yeni modele geçirmek için kod oluşturun.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir
ad kullanılması yararlı olur.
Update-Database komutu, çerçeveye şema değişikliklerini uygulamaya ve var olan verileri korumanıza bildirir.
VERITABANıNDAKI tüm kayıtları silerseniz, başlatıcı DB 'yi temel alır ve Rating alanını içerir. Bunu, tarayıcıda
veya SQL Server Nesne Gezgini (ssox) silme bağlantılarıyla yapabilirsiniz.
Başka bir seçenek de veritabanını silmek ve geçişleri kullanarak veritabanını yeniden oluşturmaktır. SSOX 'te
veritabanını silmek için:
SSOX 'te veritabanını seçin.
Veritabanına sağ tıklayın ve Sil' i seçin.
Mevcut bağlantıları kapat' a bakın.
Seçin Tamam.
PMC'de veritabanını güncelleştirin:

Update-Database

Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi


doğrulayın. Veritabanı birlikte olmazsa, SeedData.Initialize yönteminde bir kesme noktası ayarlayın.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: ekleme S O N R A K I: D O Ğ R U L A M A
A RA M A EKLEM E

Örnek kodu görüntüle veya indir (indirme).


Örnek kodu görüntüle veya indir (indirme).
Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alan şeması değişikliğini veritabanına geçirin.
Bir veritabanını otomatik olarak oluşturmak için EF Code First kullanırken Code First:
Veritabanı şemasının oluşturulduğu model sınıflarıyla uyumlu olup olmadığını izlemek için veritabanına bir
tablo ekler.
Model sınıfları DB ile eşitlenmiyorsa, EF bir özel durum oluşturur.
Şema/modelin eşitlemede otomatik olarak doğrulanması, tutarsız veritabanı/kod sorunlarını bulmayı
kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleme


Modeller/film. cs dosyasını açın ve bir Rating özelliği ekleyin:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulamayı derleyin.
Sayfaları/filmleri/dizini. cshtml'yi düzenleyin ve bir Rating alanı ekleyin:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-page="Create">Create New</a>
</p>

<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie)
{
<tr><td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Aşağıdaki sayfaları güncelleştirin:


Silme ve Ayrıntılar sayfalarına Rating alanını ekleyin.
Create. cshtml dosyasını bir Rating alanla güncelleştirin.
Düzenleme sayfasına Rating alanını ekleyin.

VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Şimdi çalıştırırsanız,
uygulama bir SqlException oluşturur:
SqlException: Invalid column name 'Rating'.

Bu hata, güncelleştirilmiş film modeli sınıfının, veritabanının film tablosunun şemasından farklı olmasından
kaynaklanır. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Yeni model sınıfı şemasını kullanarak veritabanını otomatik olarak bırakıp yeniden oluşturmaya Entity
Framework. Bu yaklaşım, geliştirme döngüsünün başlarında daha erken bir yoldur; modeli ve veritabanı
şemasını birlikte hızla gelişmenize olanak tanır. Downsıde, veritabanında var olan verileri kaybetmeniz.
Bu yaklaşımı bir üretim veritabanında kullanmayın! DB 'yi şema değişikliklerinde bırakıp bir başlatıcı
kullanarak veritabanının test verileriyle otomatik olarak çekirdeğini oluşturmak, genellikle bir uygulama
geliştirmeye yönelik üretken bir yoldur.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın
avantajı, verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği
oluşturarak yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanın.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie bloğu için bu değişikliği yapmak isteyeceksiniz.
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M,
Rating = "R"
},

Tamamlanan SeedData.cs dosyasınabakın.


Çözümü oluşturun.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Derecelendirme alanı için bir geçiş ekleyin
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC'de aşağıdaki
komutları girin:

Add-Migration Rating
Update-Database

Add-Migration komutu, çerçeveye şunları belirtir:


Moviemodelini Movie DB şemasıyla karşılaştırın.
DB şemasını yeni modele geçirmek için kod oluşturun.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir
ad kullanılması yararlı olur.
Update-Database komutu, çerçeveye şema değişikliklerini veritabanına uygulamasını söyler.
VERITABANıNDAKI tüm kayıtları silerseniz, başlatıcı DB 'yi temel alır ve Rating alanını içerir. Bunu, tarayıcıda
veya SQL Server Nesne Gezgini (ssox) silme bağlantılarıyla yapabilirsiniz.
Başka bir seçenek de veritabanını silmek ve geçişleri kullanarak veritabanını yeniden oluşturmaktır. SSOX 'te
veritabanını silmek için:
SSOX 'te veritabanını seçin.
Veritabanına sağ tıklayın ve Sil' i seçin.
Mevcut bağlantıları kapat' a bakın.
Seçin Tamam.
PMC'de veritabanını güncelleştirin:

Update-Database

Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi


doğrulayın. Veritabanı birlikte olmazsa, SeedData.Initialize yönteminde bir kesme noktası ayarlayın.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

Ö N C E K I: ekleme S O N R A K I: D O Ğ R U L A M A
A RA M A EKLEM E
ASP.NET Core Razor sayfasına doğrulama ekleme
15.10.2019 • 15 minutes to read • Edit Online

Rick Anderson tarafından


Bu bölümde, Movie modeline doğrulama mantığı eklenir. Doğrulama kuralları, bir Kullanıcı bir filmi
oluşturduğunda veya düzenleişinizde zorlanır.

Doğrulama
Yazılım geliştirmeye yönelik temel bir temel kuru ("Don't Repeon Yourself") olarak adlandırılır. Razor Pages,
işlevselliği bir kez belirtildiğinde geliştirme ve uygulama genelinde yansıtılmıştır. Kuru şu şekilde yardımcı
olabilir:
Uygulamadaki kod miktarını azaltın.
Kodu daha az hata haline getirin ve test ve bakım yapmayı kolaylaştırın.
Razor Pages ve Entity Framework tarafından sunulan doğrulama desteği, Kuru ilkesine iyi bir örnektir.
Doğrulama kuralları tek bir yerde (model sınıfında) bildirimli olarak belirtilir ve kurallar uygulamada her yerde
zorlanır.

Film modeline doğrulama kuralları ekleme


Dataaçıklamalarda ad alanı, bir sınıfa veya özelliğe bildirimli olarak uygulanan bir yerleşik doğrulama
öznitelikleri kümesi sağlar. Veri açıklamaları, biçimlendirme ile yardım eden ve herhangi bir doğrulama
sağlamayan DataType gibi biçimlendirme öznitelikleri de içerir.
@No__t-0 sınıfını, yerleşik Required , StringLength , RegularExpression ve Range doğrulama özniteliklerinden
faydalanmak için güncelleştirin.
public class Movie
{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}

Doğrulama öznitelikleri, uygulanan model özellikleri üzerinde zorlamak istediğiniz davranışı belirtir:
@No__t-0 ve MinimumLength öznitelikleri bir özelliğin bir değere sahip olması gerektiğini belirtir; Ancak
hiçbir şey, kullanıcının bu doğrulamayı karşılamak için boşluk girmesini engeller.
@No__t-0 özniteliği, hangi karakterlerin girişi yapabileceğini sınırlamak için kullanılır. Yukarıdaki kodda,
"tarz":
Yalnızca harfler kullanılmalıdır.
İlk harfin büyük harfle olması gerekir. Boşluk, sayı ve özel karakterlere izin verilmez.
@No__t-0 "derecelendirmesi":
İlk karakterin büyük harf olmasını gerektirir.
Sonraki boşlukların içindeki özel karakter ve sayılara izin verir. "PG -13" bir derecelendirme için
geçerlidir, ancak bir "tarz" için başarısız olur.
@No__t-0 özniteliği, bir değeri belirtilen bir Aralık içinde kısıtlar.
@No__t-0 özniteliği, bir dize özelliğinin en büyük uzunluğunu ve isteğe bağlı olarak en düşük
uzunluğunu ayarlamanıza olanak sağlar.
Değer türleri (örneğin decimal , int , float , DateTime ), doğal olarak gereklidir ve [Required]
özniteliğine gerek kalmaz.
Doğrulama kurallarının otomatik olarak uygulanmasını ASP.NET Core uygulamanızın daha sağlam olmasına
yardımcı olur. Ayrıca, bir şeyi doğrulamayı unutmanızı ve veritabanına yanlışlıkla veri vermemesini de sağlar.
Razor Pages 'de doğrulama hatası Kullanıcı arabirimi
Uygulamayı çalıştırın ve sayfalar/Filmler ' e gidin.
Yeni oluştur bağlantısını seçin. Formu, bazı geçersiz değerlerle doldurun. JQuery istemci tarafı doğrulaması
hatayı algıladığında, bir hata iletisi görüntüler.
NOTE
Ondalık alanlara ondalık virgüller giremeyebilirsiniz. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih biçimleri için virgül
(",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı globalize için adımlar
uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .

Formun geçersiz bir değer içeren her alanda otomatik olarak bir doğrulama hata iletisi nasıl oluşturulduğuna
dikkat edin. Hatalar hem istemci tarafında (JavaScript ve jQuery kullanılarak) hem de sunucu tarafında (bir
Kullanıcı JavaScript devre dışı bırakıldığında) zorlanır.
Önemli bir avantaj, oluşturma veya düzenleme sayfalarında hiçbir kod değişikliği gerekli değildir. Veri ek
açıklamaları modele uygulandıktan sonra, doğrulama kullanıcı arabirimi etkinleştirilmiştir. Bu öğreticide
oluşturulan Razor Pages otomatik olarak doğrulama kurallarını ( Movie Model sınıfının özelliklerinde
doğrulama özniteliklerini kullanarak) otomatik olarak alır. Düzenleme sayfasını kullanarak doğrulama testi, aynı
doğrulama uygulanır.
Form verileri, istemci tarafı doğrulama hatası kalmayana kadar sunucuya nakledilmez. Form verilerinin
aşağıdaki yaklaşımlardan bir veya daha fazlası tarafından nakledilmediğinden emin olun:
@No__t-0 yöntemine bir kesme noktası koyun. Formu gönder ( Oluştur veya Kaydet' i seçin). Kesme
noktası hiçbir şekilde isabet ettirilmez.
Fiddler aracınıkullanın.
Ağ trafiğini izlemek için tarayıcı Geliştirici Araçları ' nı kullanın.
Sunucu tarafı doğrulaması
Tarayıcıda JavaScript devre dışı bırakıldığında, formun hatalarla gönderilmesi sunucuya gönderilir.
İsteğe bağlı, test sunucusu-tarafı doğrulaması:
Tarayıcıda JavaScript 'ı devre dışı bırakın. Tarayıcının geliştirici araçlarını kullanarak JavaScript 'ı devre
dışı bırakabilirsiniz. Tarayıcıda JavaScript 'ı devre dışı bırakadıysanız başka bir tarayıcı deneyin.
Oluşturma veya düzenleme sayfasının OnPostAsync yönteminde bir kesme noktası ayarlayın.
Geçersiz verilerle form gönderme.
Model durumunun geçersiz olduğunu doğrulayın:

if (!ModelState.IsValid)
{
return Page();
}

Aşağıdaki kod, öğreticide daha önce Create. cshtml sayfa scafkatın bir bölümünü gösterir. İlk formu
görüntülemek ve bir hata durumunda formu yeniden görüntülemek için sayfa oluşturma ve düzenleme sayfaları
tarafından kullanılır.

<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>

Giriş etiketi Yardımcısı , dataaçıklamaların özniteliklerini kullanır ve istemci tarafında jQuery doğrulaması için
gerekli HTML özniteliklerini üretir. Doğrulama etiketi Yardımcısı doğrulama hatalarını görüntüler. Daha fazla
bilgi için bkz. doğrulama .
Oluşturma ve düzenleme sayfalarında hiçbir doğrulama kuralı yoktur. Doğrulama kuralları ve hata dizeleri
yalnızca Movie sınıfında belirtilmiştir. Bu doğrulama kuralları, Movie modelini düzenleyebilen Razor Pages
otomatik olarak uygulanır.
Doğrulama mantığının değişmesi gerektiğinde, yalnızca modelde yapılır. Doğrulama, uygulamanın tamamında
tutarlı bir şekilde uygulanır (doğrulama mantığı tek bir yerde tanımlanır). Tek bir yerde doğrulama, kodun temiz
kalmasına yardımcı olur ve bakım ve güncelleştirme işlemlerini kolaylaştırır.

DataType özniteliklerini kullanma


@No__t-0 sınıfını inceleyin. @No__t-0 ad alanı, yerleşik doğrulama öznitelikleri kümesine ek olarak
biçimlendirme öznitelikleri sağlar. @No__t-0 özniteliği ReleaseDate ve Price özelliklerine uygulanır.
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

@No__t-0 öznitelikleri yalnızca görünüm altyapısının verileri biçimlendirmek için ipuçları sağlar (ve URL için
<a> ve e-posta için <a href="mailto:EmailAddress.com"> gibi öznitelikleri sağlar ). Verilerin biçimini doğrulamak
için RegularExpression özniteliğini kullanın. @No__t-0 özniteliği, veritabanı iç türünden daha belirgin bir veri
türü belirtmek için kullanılır. DataType öznitelikleri doğrulama öznitelikleri değildir. Örnek uygulamada, yalnızca
tarih ve saat olmadan görüntülenir.
@No__t-0 numaralandırması, tarih, saat, PhoneNumber, para birimi, Emaadresi ve daha fazlası gibi birçok veri
türü sağlar. @No__t-0 özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak sağlamasını da
sağlayabilir. Örneğin, DataType.EmailAddress için mailto: bağlantısı oluşturulabilir. HTML5 'i destekleyen
tarayıcılarda DataType.Date için bir tarih seçici sağlanmış olabilir. @No__t-0 öznitelikleri HTML 5 tarayıcıların
kullandığı HTML 5 data- (veri Dash) özniteliklerini yayar. @No__t-0 öznitelikleri herhangi bir doğrulama
sağlamaz.
DataType.Date , görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, veri alanı, sunucunun CultureInfo '
a göre varsayılan biçimlere göre görüntülenir.
@No__t-0 veri ek açıklaması gereklidir, bu nedenle Entity Framework Core veritabanındaki para birimine Price
' i doğru şekilde eşleyebilir. Daha fazla bilgi için bkz. veri türleri.
@No__t-0 özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]


public DateTime ReleaseDate { get; set; }

@No__t-0 ayarı, değer düzenlenmek üzere görüntülendiğinde biçimlendirmenin uygulanacağını belirtir. Bazı
alanlar için bu davranışı istemiyor olabilirsiniz. Örneğin, para birimi değerlerinde, büyük olasılıkla düzenleme
kullanıcı arabirimindeki para birimi sembolünü istemezsiniz.
@No__t-0 özniteliği kendisi tarafından kullanılabilir, ancak genellikle DataType özniteliğini kullanmak iyi bir fikir
olabilir. @No__t-0 özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini değil ve DisplayFormat ile elde
olmadığınız avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını vb. göstermek için)
Varsayılan olarak tarayıcı, verileri yerel ayarınızı temel alarak doğru biçimi kullanarak işleyebilir.
@No__t-0 özniteliği, ASP.NET Core çerçevesinin verileri işlemek için doğru alan şablonunu seçmesini
sağlayabilir. Kendisi tarafından kullanılıyorsa DisplayFormat , dize şablonunu kullanır.
Note: jQuery doğrulaması Range özniteliğiyle ve DateTime ile çalışmaz. Örneğin, aşağıdaki kod, tarih belirtilen
aralıkta olduğunda bile her zaman bir istemci tarafı doğrulama hatası görüntüler:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Modellerinizde sabit tarihleri derlemek genellikle iyi bir uygulamadır, bu nedenle Range özniteliği ve DateTime
kullanılması önerilmez.
Aşağıdaki kod, öznitelikleri tek bir satırda birleştirmeyi gösterir:
public class Movie
{
public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


public string Title { get; set; }

[Display(Name = "Release Date"), DataType(DataType.Date)]


public DateTime ReleaseDate { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$"), Required, StringLength(30)]


public string Genre { get; set; }

[Range(1, 100), DataType(DataType.Currency)]


[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; }
}

Razor Pages kullanmaya başlayın ve EF Core gelişmiş EF Core işlemlerini Razor Pages gösterir.
Geçişleri Uygula
Sınıfa uygulanan Dataek açıklamaları şemayı değiştirir. Örneğin, Title alanına uygulanan veri ek açıklamaları:

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

Karakterleri 60 olarak sınırlandırır.


@No__t-0 değerine izin vermez.
Visual Studio
Visual Studio Code/Mac için Visual Studio
@No__t-0 tablosu şu anda aşağıdaki şemaya sahiptir:

CREATE TABLE [dbo].[Movie] (


[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (MAX) NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (MAX) NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Önceki şema değişiklikleri, EF 'in özel durum oluşturmasına neden olmaz. Ancak, şemanın modelle tutarlı
olması için bir geçiş oluşturun.
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin. PMC 'de aşağıdaki
komutları girin:

Add-Migration New_DataAnnotations
Update-Database

Update-Database New_DataAnnotations sınıfının Up yöntemlerini çalıştırır. @No__t-0 yöntemini inceleyin:


public partial class New_DataAnnotations : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Movie",
maxLength: 60,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);

migrationBuilder.AlterColumn<string>(
name: "Rating",
table: "Movie",
maxLength: 5,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);

migrationBuilder.AlterColumn<string>(
name: "Genre",
table: "Movie",
maxLength: 30,
nullable: false,
oldClrType: typeof(string),
oldNullable: true);
}

Güncelleştirilmiş Movie tablosu aşağıdaki şemaya sahiptir:

CREATE TABLE [dbo].[Movie] (


[ID] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (60) NOT NULL,
[ReleaseDate] DATETIME2 (7) NOT NULL,
[Genre] NVARCHAR (30) NOT NULL,
[Price] DECIMAL (18, 2) NOT NULL,
[Rating] NVARCHAR (5) NOT NULL,
CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure'a Yayımlama
Azure 'a dağıtma hakkında bilgi için bkz. öğretici: Azure 'DA SQL veritabanı ile ASP.NET Core uygulama
oluşturma.
Razor Pages için bu giriş tamamlanırken teşekkürler. Razor Pages kullanmaya başlayın ve Bu öğreticiye en
uygun harika bir izleme EF Core.

Ek kaynaklar
ASP.NET Core formlardaki etiket yardımcıları
ASP.NET Core Genelleştirme ve yerelleştirme
ASP.NET Core etiket yardımcıları
ASP.NET core'da Yazar etiket Yardımcıları
Bu öğreticinin YouTube sürümü

Ö N C E K I: Y E N I B IR A L A N
EKLEM E
ASP.NET Core Razor Pages için filtre yöntemleri
19.10.2019 • 6 minutes to read • Edit Online

Rick Anderson tarafından


Razor sayfa filtreleri ıpagefilter ve ıasyncpagefilter Razor Pages, bir Razor sayfa işleyicisi çalıştırılmadan önce ve
sonra kodu çalıştırmasına izin verir. Razor sayfası filtreleri, tek sayfa işleyicisi yöntemlerine uygulanamadığından,
ASP.NET Core MVC eylem filtrelerinebenzerdir.
Razor sayfası filtreleri:
Bir işleyici yöntemi seçildikten sonra, ancak model bağlama gerçekleşmeden önce kodu çalıştırın.
Model bağlama işlemi tamamlandıktan sonra işleyici metodu yürütülmeden önce kodu çalıştırın.
İşleyici yöntemi yürütüldükten sonra kodu çalıştırın.
, Bir sayfada veya genel olarak uygulanabilir.
Belirli sayfa işleyici yöntemlerine uygulanamaz.
Bir işleyici yöntemi sayfa Oluşturucusu veya ara yazılım kullanılarak yürütülmeden önce kod çalıştırılabilir, ancak
yalnızca Razor sayfası filtrelerinin HttpContext'e erişimi vardır. Filtrelerin HttpContext erişim sağlayan bir
Filtercontext türetilmiş parametresi vardır. Örneğin, bir filtre uygula özniteliği örneği yanıta, oluşturucular veya ara
yazılım ile yapılamadığını belirten bir üst bilgi ekler.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Razor sayfası filtreleri, genel olarak veya sayfa düzeyinde uygulanabilecek aşağıdaki yöntemleri sağlar:
Zaman uyumlu Yöntemler:
Onpagehandlerselected : bir işleyici yöntemi seçildikten sonra, ancak model bağlama gerçekleşmeden
önce çağırılır.
Onpagehandlerexecuting : Işleyici Yöntemi yürütülmeden önce çağırılır, model bağlama işlemi
tamamlandıktan sonra.
Onpagehandleryürütüldü : işleyici yöntemi yürütüldükten sonra, eylem sonucundan önce çağırılır.
Zaman uyumsuz yöntemler:
Onpagehandlerselectionasync : Handler yöntemi seçildikten sonra zaman uyumsuz olarak çağırılır, ancak
model bağlama gerçekleşmeden önce.
Onpagehandlerexecutionasync : Handler yöntemi çağrılmadan önce zaman uyumsuz olarak çağrıldı,
model bağlama işlemi tamamlandıktan sonra.

NOTE
Her ikisini de değil, bir filtre arabiriminin zaman uyumlu veya zaman uyumsuz sürümünü uygulayın. Çerçeve ö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. Her iki arabirim de uygulanmışsa yalnızca zaman uyumsuz yöntemler çağrılır. Aynı
kural sayfalardaki geçersiz kılmalara uygulanır, her ikisine de değil, geçersiz kılmanın zaman uyumlu veya zaman uyumsuz
sürümünü uygular.

Razor sayfası filtrelerini küresel olarak uygulama


Aşağıdaki kod IAsyncPageFilter uygular:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace PageFilter.Filters
{
public class SampleAsyncPageFilter : IAsyncPageFilter
{
private readonly ILogger _logger;

public SampleAsyncPageFilter(ILogger logger)


{
_logger = logger;
}

public async Task OnPageHandlerSelectionAsync(


PageHandlerSelectedContext context)
{
_logger.LogDebug("Global OnPageHandlerSelectionAsync called.");
await Task.CompletedTask;
}

public async Task OnPageHandlerExecutionAsync(


PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
_logger.LogDebug("Global OnPageHandlerExecutionAsync called.");
await next.Invoke();
}
}
}

Yukarıdaki kodda, ILogger gerekli değildir. Uygulama için izleme bilgilerini sağlamak üzere örnekte kullanılır.
Aşağıdaki kod Startup sınıfındaki SampleAsyncPageFilter sunar:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(_logger));
});
}

Aşağıdaki kod, tüm Startup sınıfını gösterir:


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PageFilter.Filters;

namespace PageFilter
{
public class Startup
{
ILogger _logger;
public Startup(ILoggerFactory loggerFactory, IConfiguration configuration)
{
_logger = loggerFactory.CreateLogger<GlobalFiltersLogger>();
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(_logger));
});
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc();
}
}
}

Aşağıdaki kod, SampleAsyncPageFilter yalnızca /alt klasöründekisayfalara uygulamak için


AddFolderApplicationModelConvention çağırır:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddFolderApplicationModelConvention(
"/subFolder",
model => model.Filters.Add(new SampleAsyncPageFilter(_logger)));
});
}

Aşağıdaki kod, zaman uyumlu IPageFilter uygular:


using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

namespace PageFilter.Filters
{
public class SamplePageFilter : IPageFilter
{
private readonly ILogger _logger;

public SamplePageFilter(ILogger logger)


{
_logger = logger;
}

public void OnPageHandlerSelected(PageHandlerSelectedContext context)


{
_logger.LogDebug("Global sync OnPageHandlerSelected called.");
}

public void OnPageHandlerExecuting(PageHandlerExecutingContext context)


{
_logger.LogDebug("Global sync PageHandlerExecutingContext called.");
}

public void OnPageHandlerExecuted(PageHandlerExecutedContext context)


{
_logger.LogDebug("Global sync OnPageHandlerExecuted called.");
}
}
}

Aşağıdaki kod SamplePageFilter etkinleştirilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Filters.Add(new SamplePageFilter(_logger));
});
}

Filtre yöntemlerini geçersiz kılarak Razor sayfası filtrelerini uygulama


Aşağıdaki kod, zaman uyumlu Razor sayfası filtrelerini geçersiz kılar:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace PageFilter.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger _logger;

public IndexModel(ILogger<IndexModel> logger)


{
_logger = logger;
}
public string Message { get; set; }

public void OnGet()


{
_logger.LogDebug("IndexModel/OnGet");
}

public override void OnPageHandlerSelected(


PageHandlerSelectedContext context)
{
_logger.LogDebug("IndexModel/OnPageHandlerSelected");
}

public override void OnPageHandlerExecuting(


PageHandlerExecutingContext context)
{
Message = "Message set in handler executing";
_logger.LogDebug("IndexModel/OnPageHandlerExecuting");
}

public override void OnPageHandlerExecuted(


PageHandlerExecutedContext context)
{
_logger.LogDebug("IndexModel/OnPageHandlerExecuted");
}
}
}

Filtre özniteliği uygulama


Yerleşik öznitelik tabanlı filtre Onresultexecutionasync filtresi, alt sınıflı olabilir. Aşağıdaki filtre yanıta bir üst bilgi
ekler:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;

namespace PageFilter.Filters
{
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 });
}
}
}

Aşağıdaki kod AddHeader özniteliğini uygular:

[AddHeader("Author", "Rick")]
public class ContactModel : PageModel
{
private readonly ILogger _logger;

public ContactModel(ILogger<ContactModel> logger)


{
_logger = logger;
}
public string Message { get; set; }

public async Task OnGetAsync()


{
Message = "Your contact page.";
_logger.LogDebug("Contact/OnGet");
await Task.CompletedTask;
}
}

Sıralamayı geçersiz kılma yönergeleri için bkz. varsayılan sırayı geçersiz kılma .
Filtre işlem hattının bir filtreden kısa devre dışı olması için bkz. iptal ve kısa devre.

Yetkilendir filtre özniteliği


Yetkilendir özniteliği bir PageModel uygulanabilir:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace PageFilter.Pages
{
[Authorize]
public class ModelWithAuthFilterModel : PageModel
{
public IActionResult OnGet() => Page();
}
}
ASP.NET Core Razor Pages yol ve uygulama
kuralları
24.10.2019 • 21 minutes to read • Edit Online

Luke Latham tarafından


Razor Pages uygulamalarında sayfa yönlendirmeyi, bulmayı ve işlemeyi denetlemek için sayfa yolu ve
uygulama modeli sağlayıcısı kurallarını nasıl kullanacağınızı öğrenin.
Ayrı sayfalar için özel sayfa yolları yapılandırmanız gerektiğinde, bu konunun ilerleyen kısımlarında açıklanan
Addpageroute kuralına sahip sayfalara yönlendirmeyi yapılandırın.
Bir sayfa yolu belirtmek, yol kesimleri eklemek veya bir rotaya parametreler eklemek için, sayfanın @page
yönergesini kullanın. Daha fazla bilgi için bkz. özel rotalar.
Yol kesimleri veya parametre adları olarak kullanılamayan ayrılmış sözcükler vardır. Daha fazla bilgi için bkz.
Yönlendirme: ayrılmış yönlendirme adları.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SENARYO ÖRNEK GÖSTERILMEKTEDIR...

Model kuralları Uygulamanın sayfalarına bir yol şablonu ve üst bilgi ekleyin.

Kurallar. Add
Ipageroutemodelconvention
Ipageapplicationmodelconvention
Ipagehandlermodelconvention

Sayfa yolu eylem kuralları Bir klasördeki sayfalara ve tek bir sayfaya rota şablonu
AddFolderRouteModelConvention ekleyin.
AddPageRouteModelConvention
AddPageRoute

Sayfa modeli eylem kuralları Bir klasördeki sayfalara üst bilgi ekleyin, tek bir sayfaya üst
AddFolderApplicationModelConvention bilgi ekleyin ve bir filtre fabrikası yapılandırarak
AddPageApplicationModelConvention uygulamanın sayfalarına üst bilgi ekleyin.
ConfigureFilter (filtre sınıfı, lambda ifadesi veya filtre
fabrikası)

Razor Pages kuralları, Startup sınıfında hizmet koleksiyonuna AddMvc için AddRazorPagesOptions uzantısı
yöntemi kullanılarak eklenir ve yapılandırılır. Aşağıdaki kural örnekleri bu konunun ilerleyen kısımlarında
açıklanmıştır:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}

Rota sırası
Rotalar işleme için bir Order belirtir (rota eşleştirme).

SIPARIŞI DAVRANIŞ

-1 Yol, diğer rotalar işlenmeden önce işlenir.

0 Sıra belirtilmemiş (varsayılan değer). @No__t_0 atanmazsa (


Order = null ), yolun işlenmek üzere 0 (sıfır) olarak
Order .

1, 2, … n Yol işleme sırasını belirtir.

Yol işleme, kurala göre belirlenir:


Yollar sıralı sırada işlenir (-1, 0, 1, 2, … n).
Yolların aynı Order olduğunda, en belirli yol önce daha az özel yollarla eşleştirilir.
Aynı Order ve aynı parametre sayısı ile rotalar bir istek URL 'siyle eşleşiyorsa, rotalar
PageConventionCollection eklendiği sırada işlenir.
Mümkünse, belirlenen bir yol işleme sırasına bağlı olarak kullanmaktan kaçının. Genellikle Yönlendirme, URL
eşleştirme ile doğru yolu seçer. İstekleri doğru yönlendirmek için yol Order özelliklerini ayarlamanız
gerekiyorsa, uygulamanın yönlendirme şeması büyük olasılıkla istemciler için kafa karıştırıcı olur ve bakımını
yapmak için kırıcı olur. Uygulamanın yönlendirme şemasını basitleştirecek şekilde arama yapın. Örnek
uygulama, tek bir uygulama kullanarak birkaç yönlendirme senaryosunu göstermek için açık bir yol işleme
sırası gerektirir. Ancak, üretim uygulamalarında rota Order ayarlama uygulamalarından kaçınmaya çalışın.
Razor Pages yönlendirme ve MVC denetleyici yönlendirme bir uygulamayı paylaşır. MVC konularındaki yol
sırasıyla ilgili bilgiler, Denetleyici eylemlerine yönlendirme sırasında mevcuttur: öznitelik yollarını sıralama.

Model kuralları
Razor Pages için uygulanan model kuralları eklemek üzere IPageConvention için bir temsilci ekleyin.
Tüm sayfalara bir rota modeli kuralı ekleme
Sayfa yönlendirme modeli oluşturma sırasında uygulanan IPageConvention örnekleri koleksiyonuna bir
IPageRouteModelConvention oluşturmak ve eklemek için Conventions kullanın.
Örnek uygulama, uygulamadaki tüm sayfalara bir {globalTemplate?} Route şablonu ekler:

public class GlobalTemplatePageRouteModelConvention


: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}
public class GlobalTemplatePageRouteModelConvention
: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}

@No__t_1 için Order özelliği 1 olarak ayarlanmıştır. Bu, örnek uygulamada aşağıdaki yol eşleştirme
davranışını sağlar:
@No__t_0 için bir yol şablonu konuya daha sonra eklenir. Iletişim sayfası yolu, null ( Order = 0 )
varsayılan sırasına sahiptir, bu nedenle {globalTemplate?} Route şablonundan önce eşleşir.
Konunun ilerleyen kısımlarında {aboutTemplate?} yol şablonu eklenir. @No__t_0 şablonuna 2 Order
verilir. @No__t_0 sayfası istendiğinde, Order = 2 özelliğinin ayarlanması nedeniyle "RouteDataValue"
RouteData.Values["globalTemplate"] ( Order = 1 ) ve RouteData.Values["aboutTemplate"] ( Order ) değil.
Konunun ilerleyen kısımlarında {otherPagesTemplate?} yol şablonu eklenir. @No__t_0 şablonuna 2
Order verilir. Sayfalar/diğer sayfalar klasöründeki herhangi bir sayfa bir yol parametresiyle (örneğin,
/OtherPages/Page1/RouteDataValue ) istendiğinde, Order = 2 özelliğinin ayarlanması nedeniyle
"routedatavalue", RouteData.Values["otherPagesTemplate"] ( Order ) değil
RouteData.Values["globalTemplate"] ( Order = 1 ) olarak yüklenir.

Mümkün olan yerlerde, Order Order = 0 sonuç olarak ayarlanmayın. Doğru yolu seçmek için
yönlendirmeyi güvenin.
@No__t_0 ekleme gibi Razor Pages seçenekler, MVC Startup.ConfigureServices hizmet koleksiyonuna
eklendiğinde eklenir. Örnek için bkz. örnek uygulama.

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

@No__t_0 'de örneğin hakkında sayfasını isteyin ve sonucu inceleyin:


Tüm sayfalara uygulama modeli kuralı ekleme
@No__t_0 kullanarak, sayfa uygulama modeli oluşturma sırasında uygulanan IPageConvention örnekleri
koleksiyonuna bir IPageApplicationModelConvention ekleyin.
Bu ve diğer kuralları konunun ilerleyen kısımlarında göstermek için, örnek uygulama bir AddHeaderAttribute
sınıfı içerir. Sınıf Oluşturucusu bir name dize ve bir values dize dizisi kabul eder. Bu değerler, yanıt üst
bilgisini ayarlamak için OnResultExecuting yönteminde kullanılır. Tam sınıf, konusunun ilerleyen kısımlarında
sayfa modeli eylem kuralları bölümünde gösterilir.
Örnek uygulama, uygulamadaki tüm sayfalara bir başlık, GlobalHeader eklemek için AddHeaderAttribute
sınıfını kullanır:

public class GlobalHeaderPageApplicationModelConvention


: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}

public class GlobalHeaderPageApplicationModelConvention


: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}

Startup.cs:

options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());

options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());

@No__t_0 sırasında örneğin hakkında daha fazla bilgi isteyin ve sonucu görüntülemek için üst bilgileri
inceleyin:

Tüm sayfalara bir işleyici modeli kuralı ekleme


Sayfa işleyicisi modelinin oluşturulması sırasında uygulanan IPageConvention örnekleri koleksiyonuna bir
IPageHandlerModelConvention oluşturmak ve eklemek için Conventions kullanın.

public class GlobalPageHandlerModelConvention


: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}

public class GlobalPageHandlerModelConvention


: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}

Startup.cs:

options.Conventions.Add(new GlobalPageHandlerModelConvention());

options.Conventions.Add(new GlobalPageHandlerModelConvention());

Sayfa yolu eylem kuralları


@No__t_0 türetilen varsayılan yol modeli sağlayıcısı, sayfa yollarını yapılandırmak için genişletilebilirlik
noktaları sağlamak üzere tasarlanan kuralları çağırır.
Klasör Yönlendirme modeli kuralı
Belirtilen klasör altındaki tüm sayfalar için PageRouteModel bir eylemi çağıran bir
IPageRouteModelConvention oluşturmak ve eklemek için AddFolderRouteModelConvention kullanın.
Örnek uygulama, diğer sayfalar klasöründeki sayfalara bir {otherPagesTemplate?} yol şablonu eklemek için
AddFolderRouteModelConvention kullanır:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});

options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>


{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});

@No__t_1 için Order özelliği 2 olarak ayarlanmıştır. Bu, tek bir rota değeri sağlandığında {globalTemplate?}
(konuda daha önce 1 olarak ayarlanan) şablonunun ilk yol veri değeri konumu için öncelik verilmesini
sağlar. Sayfalar/otherpages klasöründeki bir sayfa bir yol parametresi değeri (örneğin,
/OtherPages/Page1/RouteDataValue ) ile isteniyorsa, Order = 2 özelliğinin ayarlanması nedeniyle
"routedatavalue", RouteData.Values["otherPagesTemplate"] ( Order ) değil RouteData.Values["globalTemplate"]
( Order = 1 ) olarak yüklenir.
Mümkün olan yerlerde, Order Order = 0 sonuç olarak ayarlanmayın. Doğru yolu seçmek için
yönlendirmeyi güvenin.
Örnekteki Sayfa1 sayfasını localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue isteyin ve
sonucu inceleyin:
Sayfa yönlendirme modeli kuralı
Belirtilen ada sahip sayfanın PageRouteModel bir eylemi çağıran bir IPageRouteModelConvention
oluşturmak ve eklemek için AddPageRouteModelConvention kullanın.
Örnek uygulama, hakkında sayfasına bir {aboutTemplate?} yol şablonu eklemek için
AddPageRouteModelConvention kullanır:

options.Conventions.AddPageRouteModelConvention("/About", model =>


{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});

options.Conventions.AddPageRouteModelConvention("/About", model =>


{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});

@No__t_1 için Order özelliği 2 olarak ayarlanmıştır. Bu, tek bir rota değeri sağlandığında {globalTemplate?}
(konuda daha önce 1 olarak ayarlanan) şablonunun ilk yol veri değeri konumu için öncelik verilmesini
sağlar. @No__t_0 sayfasında yol parametresi değeri varsa, Order = 2 özelliğinin ayarlanması nedeniyle
"RouteDataValue" RouteData.Values["globalTemplate"] ( Order = 1 ) ve RouteData.Values["aboutTemplate"] (
Order ) değil.

Mümkün olan yerlerde, Order Order = 0 sonuç olarak ayarlanmayın. Doğru yolu seçmek için
yönlendirmeyi güvenin.
@No__t_0 'de örneğin hakkında sayfasını isteyin ve sonucu inceleyin:

Sayfa yollarını özelleştirmek için bir parametre transformatörü


kullanın
ASP.NET Core tarafından oluşturulan sayfa yolları, bir parametre transformatörü kullanılarak özelleştirilebilir.
Bir parametre transformatörü IOutboundParameterTransformer uygular ve parametrelerin değerini dönüştürür.
Örneğin, özel bir SlugifyParameterTransformer parametresi transformatörü SubscriptionManagement Route
değerini subscription-management olarak değiştirir.
@No__t_0 Page Route model kuralı, bir uygulamadaki otomatik olarak oluşturulan sayfa yollarının klasör ve
dosya adı kesimlerine bir parametre transformatörü uygular. Örneğin,
/Pages/subscriptionmanagement/viewAll.exe konumundaki Razor Pages dosyasında yol
/SubscriptionManagement/ViewAll /subscription-management/view-all olarak yeniden yazılabilir.

PageRouteTransformerConvention , yalnızca Razor Pages klasöründen ve dosya adından gelen bir sayfa yolunun
otomatik olarak oluşturulan segmentlerini dönüştürür. @No__t_0 yönergesiyle eklenen yol kesimlerini
dönüştürmez. Kural, AddPageRoute eklenen yolları da dönüştürmez.
@No__t_0, Startup.ConfigureServices bir seçenek olarak kaydedilir:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add(
new PageRouteTransformerConvention(
new SlugifyParameterTransformer()));
});
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer


{
public string TransformOutbound(object value)
{
if (value == null) { return null; }

// Slugify value
return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
}
}

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add(
new PageRouteTransformerConvention(
new SlugifyParameterTransformer()));
});
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer


{
public string TransformOutbound(object value)
{
if (value == null) { return null; }

// Slugify value
return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
}
}

Sayfa yolu yapılandırma


Belirtilen sayfa yolundaki bir sayfaya bir yol yapılandırmak için AddPageRoute kullanın. Sayfa için
oluşturulan bağlantılar belirtilen rotayı kullanır. AddPageRoute , yolu oluşturmak için
AddPageRouteModelConvention kullanır.

Örnek uygulama, Contact. cshtmliçin /TheContactPage bir yol oluşturur:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

Iletişim sayfasına, varsayılan yolu aracılığıyla /Contact de erişilebilir.


Örnek uygulamanın kişi sayfasına özel yolu, isteğe bağlı text yol segmentine ( {text?} ) izin verir. Bu sayfa,
ziyaretçinin /Contact rotasında sayfaya erişmesi durumunda @page yönergesinde bu isteğe bağlı segmenti
de içerir:

@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}

<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>

<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<p>@Model.RouteDataTextTemplateValue</p>

@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}

<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>

<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<p>@Model.RouteDataTextTemplateValue</p>

İşlenmiş sayfadaki kişi bağlantısı IÇIN oluşturulan URL 'nin güncelleştirilmiş yolu yansıttığını unutmayın:

@No__t_0, kendi sıradan yönlendirmekte olan kişi sayfasını ziyaret edin, veya özel yol /TheContactPage . Ek
bir text yol kesimi sağlarsanız, sayfada sağladığınız HTML kodlu segment görüntülenir:

Sayfa modeli eylem kuralları


@No__t_0 uygulayan varsayılan sayfa modeli sağlayıcısı, sayfa modellerini yapılandırmak için
genişletilebilirlik noktaları sağlamak üzere tasarlanan kuralları çağırır. Bu kurallar sayfa bulma ve işleme
senaryolarını oluştururken ve değiştirirken yararlıdır.
Bu bölümdeki örneklerde örnek uygulama, yanıt üst bilgisini uygulayan bir ResultFilterAttribute
AddHeaderAttribute sınıfı kullanır:

public class AddHeaderAttribute : ResultFilterAttribute


{
private readonly string _name;
private readonly string[] _values;

public AddHeaderAttribute(string name, string[] values)


{
_name = name;
_values = values;
}

public override void OnResultExecuting(ResultExecutingContext context)


{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;

public AddHeaderAttribute(string name, string[] values)


{
_name = name;
_values = values;
}

public override void OnResultExecuting(ResultExecutingContext context)


{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}

Kurallar kullanılarak, örnek bir klasördeki tüm sayfalara ve tek bir sayfaya özniteliğin nasıl uygulanacağını
gösterir.
Klasör uygulama modeli kuralı
Belirtilen klasör altındaki tüm sayfalar için PageApplicationModel örneklerine bir eylem çağıran bir
IPageApplicationModelConvention oluşturmak ve eklemek için AddFolderApplicationModelConvention
kullanın.
Örnek, uygulamanın diğer sayfalar klasörünün içindeki sayfalara bir başlık, OtherPagesHeader ekleyerek
AddFolderApplicationModelConvention kullanımını gösterir:

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>


{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>


{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

Örnekteki Sayfa1 sayfasını localhost:5000/OtherPages/Page1 isteyin ve sonucu görüntülemek için üst bilgileri
inceleyin:

Sayfa uygulama modeli kuralı


Belirtilen ada sahip sayfanın PageApplicationModel bir eylemi çağıran bir IPageApplicationModelConvention
oluşturmak ve eklemek için AddPageApplicationModelConvention kullanın.
Örnek, hakkında sayfasına AboutHeader bir başlık ekleyerek AddPageApplicationModelConvention kullanımını
gösterir:

options.Conventions.AddPageApplicationModelConvention("/About", model =>


{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});

options.Conventions.AddPageApplicationModelConvention("/About", model =>


{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});

@No__t_0 sırasında örneğin hakkında daha fazla bilgi isteyin ve sonucu görüntülemek için üst bilgileri
inceleyin:

Filtre yapılandırma
ConfigureFilter, belirtilen filtreyi uygulamak üzere yapılandırır. Bir filtre sınıfı uygulayabilirsiniz, ancak örnek
uygulama bir lambda ifadesinde bir filtrenin nasıl uygulanacağını gösterir, bu da bir filtre döndüren bir
fabrika olarak arka planda uygulandı:

options.Conventions.ConfigureFilter(model =>
{
if (model.RelativePath.Contains("OtherPages/Page2"))
{
return new AddHeaderAttribute(
"OtherPagesPage2Header",
new string[] { "OtherPages/Page2 Header Value" });
}
return new EmptyFilter();
});

options.Conventions.ConfigureFilter(model =>
{
if (model.RelativePath.Contains("OtherPages/Page2"))
{
return new AddHeaderAttribute(
"OtherPagesPage2Header",
new string[] { "OtherPages/Page2 Header Value" });
}
return new EmptyFilter();
});

Sayfa uygulama modeli, diğer sayfalar klasöründeki Page2 sayfasına yol açan parçaların göreli yolunu
denetlemek için kullanılır. Koşul geçerse, bir üst bilgi eklenir. Aksi takdirde, EmptyFilter uygulanır.
EmptyFilter bir eylem filtresidir. Eylem filtreleri Razor Pages tarafından yoksayıldığından, yolun
OtherPages/Page2 içermiyorsa EmptyFilter hiçbir etkisi yoktur.

@No__t_0 'de örneğin Page2 sayfasını isteyin ve sonucu görüntülemek için üst bilgileri inceleyin:

Filtre fabrikası yapılandırma


ConfigureFilter, belirtilen fabrikayı tüm Razor Pages filtre uygulayacak şekilde yapılandırır.
Örnek uygulama, uygulamanın sayfalarına iki değer içeren FilterFactoryHeader bir üst bilgi ekleyerek bir
filtre fabrikası kullanılmasına bir örnek sağlar:

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

AddHeaderWithFactory.cs:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}

private class AddHeaderFilter : IResultFilter


{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}

public void OnResultExecuted(ResultExecutedContext context)


{
}
}

public bool IsReusable


{
get
{
return false;
}
}
}
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}

private class AddHeaderFilter : IResultFilter


{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}

public void OnResultExecuted(ResultExecutedContext context)


{
}
}

public bool IsReusable


{
get
{
return false;
}
}
}

@No__t_0 sırasında örneğin hakkında daha fazla bilgi isteyin ve sonucu görüntülemek için üst bilgileri
inceleyin:

MVC filtreleri ve sayfa filtresi (ıpagefilter)


Razor Pages işleyici yöntemleri kullandığından, MVC eylem filtreleri Razor Pages tarafından yok sayılır. Diğer
MVC filtresi türleri şunlardır: Yetkilendirme, özel durum, kaynakve sonuç. Daha fazla bilgi için Filtreler
konusuna bakın.
Sayfa filtresi (IPageFilter) Razor Pages için geçerli bir filtredir. Daha fazla bilgi için bkz. Razor Pages Için filtre
yöntemleri.

Ek kaynaklar
ASP.NET Core Razor Pages yetkilendirme kuralları
ASP.NET Core bölgeler
ASP.NET Core Razor SDK 'Sı
13.11.2019 • 10 minutes to read • Edit Online

Rick Anderson tarafından

Genel bakış
.NET core 2.1 SDK veya üzeri, Microsoft.NET.Sdk.Razor MSBuild SDK 'sını (Razor SDK) içerir. Razor SDK 'Sı:
ASP.NET Core MVC tabanlı veya Blazor projeleri için Razor dosyaları içeren projeleri derlemek, paketlemek
ve yayımlamak için gereklidir.
, Razor ( . cshtml veya . Razor) dosyalarının derlemesini özelleştirmeye izin veren bir dizi önceden tanımlanmış
hedef, özellik ve öğe içerir.
Razor SDK, **\*.cshtml ve **\*.razor glob desenlerine ayarlanmış Include öznitelikleri olan Content
öğelerini içerir. Eşleşen dosyalar yayımlandı.
ASP.NET Core MVC tabanlı projeler için Razor dosyaları içeren projeleri oluşturma, paketleme ve yayımlama
ile ilgili deneyimi standartlaştırır.
Razor dosyalarının derlemesini özelleştirmeye izin veren bir dizi önceden tanımlanmış hedef, özellik ve öğe
içerir.
Razor SDK, **\*.cshtml glob düzenine ayarlanmış bir Include özniteliğine sahip Content öğesi içerir. Eşleşen
dosyalar yayımlandı.

Prerequisites
.NET core 2.1 SDK veya üzeri

Razor SDK 'sını kullanma


Çoğu Web uygulaması Razor SDK 'ya açıkça başvurmak için gerekli değildir.
Razor görünümlerini veya Razor Pages içeren sınıf kitaplıkları oluşturmak için Razor SDK 'yı kullanmak için
Razor sınıf kitaplığı (RCL ) proje şablonuyla başlamasını öneririz. Blazor ( . Razor) dosyalarını derlemek için
kullanılan bir RCL, Microsoft. Aspnetcore. Components paketine en az bir başvuru gerektirir. Razor
görünümlerini veya sayfalarını ( . cshtml dosyaları) derlemek için kullanılan bir rcl, netcoreapp3.0 veya üzeri
hedeflemeyi gerektirir ve proje dosyasındaki Microsoft. Aspnetcore. app metapackage öğesine
FrameworkReference ' ye sahip olmalıdır.

Razor görünümlerini veya Razor Pages içeren sınıf kitaplıkları derlemek için Razor SDK 'yı kullanmak için:
Microsoft.NET.Sdk yerine Microsoft.NET.Sdk.Razor kullanın:

<Project SDK="Microsoft.NET.Sdk.Razor">
<!-- omitted for brevity -->
</Project>

Genellikle, Razor Pages ve Razor görünümlerini derlemek ve derlemek için gerekli ek bağımlılıklar almak
için Microsoft.AspNetCore.Mvc ' a yönelik bir paket başvurusu gerekir. En azından, projenizin paket
başvurularını şu şekilde eklemesi gerekir:
Microsoft.AspNetCore.Razor.Design
Microsoft.AspNetCore.Mvc.Razor.Extensions
Microsoft.AspNetCore.Mvc.Razor

Microsoft.AspNetCore.Razor.Design paketi, proje için Razor derleme görevlerini ve hedeflerini sağlar.


Önceki paketler Microsoft.AspNetCore.Mvc ' a dahildir. Aşağıdaki biçimlendirme, bir ASP.NET Core Razor
Pages uygulaması için Razor dosyaları derlemek için Razor SDK 'sını kullanan bir proje dosyası gösterir:

<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.3" />
</ItemGroup>

</Project>

WARNING
Microsoft.AspNetCore.Razor.Design ve Microsoft.AspNetCore.Mvc.Razor.Extensions paketleri Microsoft.
AspNetCore. app metapackageiçinde yer alır. Ancak, sürüm-daha az Microsoft.AspNetCore.App paket başvurusu, en son
Microsoft.AspNetCore.Razor.Design sürümünü içermeyen uygulamaya bir metapackage sağlar. , Razor için en son
derleme zamanı düzeltmelerinin dahil olması için projeler Microsoft.AspNetCore.Razor.Design ' ın (veya
Microsoft.AspNetCore.Mvc ) tutarlı bir sürümüne başvurmalıdır. Daha fazla bilgi için Bu GitHub sorununabakın.

Özellikler
Aşağıdaki özellikler, bir proje derlemesinin parçası olarak Razor SDK davranışını denetler:
RazorCompileOnBuild – olduğunda, proje oluşturmanın bir parçası olarak Razor derlemesini derler ve
true
yayar. Varsayılan değer true ' dır.
RazorCompileOnPublish – true olduğunda, projenin yayımlaması kapsamında Razor derlemesini derler ve
yayar. Varsayılan değer true ' dır.

Aşağıdaki tablodaki Özellikler ve öğeler, Razor SDK 'ya giriş ve çıkış yapılandırmak için kullanılır.

WARNING
ASP.NET Core 3,0 ' den başlayarak, MVC görünümleri veya Razor Pages, proje dosyasındaki RazorCompileOnBuild veya
RazorCompileOnPublish MSBuild özellikleri devre dışı bırakılmışsa varsayılan olarak sunulmuyor. Uygulama, . cshtml
dosyalarını işlemek üzere çalışma zamanı derlemesini kullanıyorsa, uygulamalar Microsoft. Aspnetcore. Mvc. Razor.
runtimecompilation paketine açık bir başvuru eklememelidir.

ÖĞELER AÇIKLAMA

RazorGenerate Kod oluşturmaya giriş olan öğe öğeleri ( . cshtml dosyaları).

RazorComponent Razor bileşen kodu oluşturmaya giriş olan öğe öğeleri ( .


Razor dosyaları).
ÖĞELER AÇIKLAMA

RazorCompile Razor derleme hedeflerine giriş olan öğe öğeleri ( . cs


dosyaları). Razor derlemesine derlenecek ek dosyaları
belirtmek için bu ItemGroup kullanın.

RazorTargetAssemblyAttribute Razor derlemesi için kod oluşturma öznitelikleri için kullanılan


öğe öğeleri. Örneğin:
RazorAssemblyAttribute
Include="System.Reflection.AssemblyMetadataAttribute"
_Parameter1="BuildSource"
_Parameter2="https://docs.microsoft.com/">

RazorEmbeddedResource Oluşturulan Razor derlemesine gömülü kaynaklar olarak


eklenen öğe öğeleri.

ÖZELLIK AÇIKLAMA

RazorTargetName Razor tarafından üretilen derlemenin dosya adı (uzantısı


olmadan).

RazorOutputPath Razor çıkış dizini.

RazorCompileToolset Razor derlemesini derlemek için kullanılan araç takımını tespit


etmek için kullanılır. Geçerli değerler Implicit , RazorSDK
ve PrecompilationTool ' dir.

Enabledefaultcontentıtems Varsayılan değer true . true , Web. config, . JSONve .


cshtml dosyalarını projeye içerik olarak ekler.
Microsoft.NET.Sdk.Web aracılığıyla başvuruluyorsa,
Wwwroot ve yapılandırma dosyaları altındaki dosyalar da
dahil edilir.

EnableDefaultRazorGenerateItems true , RazorGenerate öğelerinde Content öğelerden .


cshtml dosyalarını ekler.

GenerateRazorTargetAssemblyInfo true , RazorAssemblyAttribute tarafından belirtilen


öznitelikleri içeren bir . cs dosyası oluşturur ve derleme
çıkışında dosyayı içerir.

EnableDefaultRazorTargetAssemblyInfoAttributes true , RazorAssemblyAttribute derleme özniteliklerinin


varsayılan bir kümesini ekler.

CopyRazorGenerateFilesToPublishDirectory true , RazorGenerate öğeleri ( . cshtml) dosyalarını


Yayımla dizinine kopyalar. Genellikle, derleme zamanında veya
yayımlama zamanında derlemeye katılırsanız yayımlanmış bir
uygulama için Razor dosyaları gerekli değildir. Varsayılan
değer false ' dır.
ÖZELLIK AÇIKLAMA

CopyRefAssembliesToPublishDirectory true , başvuru derleme öğelerini yayımlama dizinine


kopyalayın. Genellikle, derleme zamanında veya yayımlama
zamanında Razor derlemesi gerçekleşirse, yayımlanan bir
uygulama için başvuru derlemeleri gerekli değildir.
Yayımlanmış uygulamanız çalışma zamanı derlemesi
gerektiriyorsa, true olarak ayarlayın. Örneğin, uygulama
çalışma zamanında . cshtml dosyalarını değiştirirse veya
gömülü görünümleri kullanıyorsa değeri true olarak
ayarlayın. Varsayılan değer false ' dır.

IncludeRazorContentInPack true , tüm Razor içerik öğeleri ( . cshtml dosyaları)


oluşturulan NuGet paketine eklenmek üzere işaretlenir.
Varsayılan değer false ' dır.

EmbedRazorGenerateSources true , oluşturulan Razor derlemesine gömülü dosyalar


olarak RazorGenerate ( . cshtml) öğelerini ekler. Varsayılan
değer false ' dır.

UseRazorBuildServer true , kod oluşturma işinin yükünü boşaltmak için kalıcı bir
yapı sunucusu işlemi kullanır. Varsayılan değer
UseSharedCompilation ' dır.

GenerateMvcApplicationPartsAssemblyAttributes true , SDK, uygulama bölümü keşfi gerçekleştirmek için


çalışma zamanında MVC tarafından kullanılan ek öznitelikler
üretir.

Özellikler hakkında daha fazla bilgi için bkz. MSBuild özellikleri.


Hedefler
Razor SDK iki birincil hedefi tanımlar:
RazorGenerate – kod RazorGenerate öğe öğelerinden . cs dosyaları oluşturur. Bu hedeften önce veya sonra
çalışabilecek ek hedefleri belirtmek için RazorGenerateDependsOn özelliğini kullanın.
RazorCompile – bir Razor derlemesinde oluşturulan . cs dosyalarını derler. Bu hedeften önce veya sonra
çalışabilecek ek hedefleri belirtmek için RazorCompileDependsOn kullanın.
RazorComponentGenerate – kod RazorComponent öğe öğeleri için . cs dosyaları oluşturur. Bu hedeften önce veya
sonra çalışabilecek ek hedefleri belirtmek için RazorComponentGenerateDependsOn özelliğini kullanın.
Razor görünümlerinin çalışma zamanı derlemesi
Varsayılan olarak, Razor SDK, çalışma zamanı derlemesini gerçekleştirmek için gerekli olan başvuru
derlemelerini yayımlamaz. Bu durum, uygulama modeli bir çalışma zamanı derlemesini kullandığında
derleme hatalarıyla sonuçlanır. Örneğin, uygulama yayımlandıktan sonra katıştırılmış görünümleri veya
değişiklik görünümlerini kullanır. Başvuru derlemelerini yayımlamaya devam etmek için
CopyRefAssembliesToPublishDirectory ' i true olarak ayarlayın.

Bir Web uygulaması için uygulamanızın Microsoft.NET.Sdk.Web SDK 'Yı hedeflediğinden emin olun.

Razor dili sürümü


Microsoft.NET.Sdk.Web SDK 'Sı hedeflenirken, Razor dili sürümü uygulamanın hedef Framework sürümünden
algılanır. Microsoft.NET.Sdk.Razor SDK 'Yı hedefleyen projeler veya uygulamanın çıkarılan değerden farklı bir
Razor dili sürümü gerektirmesi durumunda, uygulamanın proje dosyasındaki <RazorLangVersion> özelliği
ayarlanarak bir sürüm yapılandırılabilir:
<PropertyGroup>
<RazorLangVersion>{VERSION}</RazorLangVersion>
</PropertyGroup>

Razor 'nin dil sürümü, için oluşturulduğu çalışma zamanının sürümü ile sıkı bir şekilde tümleşiktir. Çalışma
zamanı için tasarlanmamış bir dil sürümünü hedeflemek desteklenmez ve muhtemelen derleme hataları üretir.

Ek kaynaklar
.NET Core için csproj biçimine eklemeler
Ortak MSBuild proje öğeleri
ASP.NET Core MVC’ye Genel Bakış
8.11.2019 • 16 minutes to read • Edit Online

Steve Smith tarafından


ASP.NET Core MVC, Model-View -Controller tasarım modelini kullanarak Web uygulamaları ve API 'Ler
oluşturmaya yönelik zengin bir çerçevedir.

MVC deseninin anlamı nedir?


Model-View -Controller (MVC ) mimari modeli, bir uygulamayı üç ana bileşen grubuna ayırır: modeller,
görünümler ve denetleyiciler. Bu model , kaygıları ayrımıelde etmeye yardımcı olur. Bu modeli kullanarak
Kullanıcı istekleri, kullanıcı eylemlerini gerçekleştirmek ve/veya sorguların sonuçlarını almak için modeliyle
çalışmaktan sorumlu bir denetleyiciye yönlendirilir. Denetleyici, kullanıcıya görüntülenecek görünümü seçer ve
gereken model verilerini sağlar.
Aşağıdaki diyagramda üç ana bileşen gösterilmektedir ve bunlar diğerlerine başvuramazlar:

Bu sorumlulukların bu şekilde çıkarılması, tek bir işi olan bir şeyi (model, görünüm veya denetleyici)
kodlanmasını, hata ayıklamayı ve test etmek daha kolay olduğundan, uygulamayı karmaşıklık bakımından
ölçeklendirmenize yardımcı olur. Bu üç alandan oluşan iki veya daha fazla bağımlılığı kapsayan bağımlılıklara
sahip kodu güncelleştirmek, test etmek ve hata ayıklamak daha zordur. Örneğin, Kullanıcı arabirimi mantığı iş
mantığından daha sık değişmeyi eğilimi gösterir. Sunum kodu ve iş mantığı tek bir nesnede birleştirilirse,
Kullanıcı arabirimi her değiştirildiğinde iş mantığı içeren bir nesne değiştirilmelidir. Bu genellikle hataları tanıtır
ve her bir en az kullanıcı arabirimi değişikliğinden sonra iş mantığının yeniden test edilmesini gerektirir.

NOTE
Hem görünüm hem de denetleyici modele bağlıdır. Ancak, model ne görünüm ne de yoksa denetleyiciye bağlıdır. Bu,
ayrımı önemli avantajlarından biridir. Bu ayrım, modelin görsel sunudan bağımsız olarak oluşturulup test etmesine olanak
tanır.

Model sorumlulukları
MVC uygulamasındaki model, uygulamanın durumunu ve bunun gerçekleştirilmesi gereken tüm iş mantığını
veya işlemlerini temsil eder. İş mantığı, uygulamanın durumunu kalıcı hale getirme için herhangi bir uygulama
mantığıyla birlikte, modelde kapsüllenmelidir. Türü kesin belirlenmiş görünümler genellikle bu görünümde
görüntülenecek verileri içerecek şekilde tasarlanan ViewModel türlerini kullanır. Denetleyici bu ViewModel
örneklerini modelden oluşturur ve doldurur.
Sorumlulukları görüntüle
Görünümler, kullanıcı arabiriminden içerik sunmadan sorumludur. .NET kodunu HTML biçimlendirmesine
eklemek için Razor görüntüleme altyapısını kullanırlar. Görünümler içinde en az mantık olmalıdır ve içerdikleri
tüm mantığın içerik sunumu ile ilişkilendirilmesi gerekir. Karmaşık bir modelden veri görüntülemek için
dosyaları görüntüle bölümünde harika bir mantık kullanımı gereksinimini fark ederseniz, görünümü
basitleştirmek için bir Görünüm bileşeni, ViewModel veya görünüm şablonu kullanmayı düşünün.
Denetleyici sorumlulukları
Denetleyiciler, kullanıcı etkileşimini işleyen, modeliyle çalışan ve sonunda işlenecek bir görünüm olan
bileşenleridir. MVC uygulamasında, görünüm yalnızca bilgileri görüntüler; denetleyici, Kullanıcı girişini ve
etkileşimini işler ve yanıtlar. MVC modelinde, denetleyici ilk giriş noktasıdır ve hangi model türlerinin birlikte
çalışacağını ve hangi görünümün işleneceğini seçmekten sorumludur (Bu nedenle adı, uygulamanın belirli bir
istek için nasıl yanıt verdiğini denetler).

NOTE
Denetleyiciler çok fazla sorumluluk tarafından aşırı karmaşık olmamalıdır. Denetleyici mantığının aşırı karmaşık hale
gelmesini sağlamak için, denetleyiciden ve etki alanı modeline kadar iş mantığı gönderin.

TIP
Denetleyici eylemlerinizin aynı tür eylemleri sıklıkla gerçekleştirmesini fark ederseniz, bu ortak eylemleri filtreleretaşıyın.

ASP.NET Core MVC nedir?


ASP.NET Core MVC çerçevesi, ASP.NET Core birlikte kullanılmak üzere en iyi duruma getirilmiş hafif, açık
kaynaklı ve yüksek düzeyde bir sunum çerçevesidir.
ASP.NET Core MVC, sorunların temiz bir şekilde ayrılmasını sağlayan dinamik Web siteleri oluşturmak için
desen tabanlı bir yol sağlar. Biçimlendirme üzerinde tam denetim elde etmenizi sağlar, TDD kullanımı kolay
geliştirmeyi destekler ve en son web standartlarını kullanır.

Özellikler
ASP.NET Core MVC şunları içerir:
Yönlendirme
Model bağlama
Model doğrulaması
Bağımlılık ekleme
Filtreler
Alanlar
Web API 'Leri
Test edilebilirlik
Razor Görünüm altyapısı
Türü kesin belirlenmiş görünümler
Etiket Yardımcıları
Bileşenleri görüntüle
Yönlendirme
ASP.NET Core MVC, gelişmiş ve aranabilir URL 'Ler içeren uygulamalar oluşturmanıza olanak tanıyan güçlü
bir URL eşleme bileşeni olan ASP.NET Core yönlendirmeninüzerine kurulmuştur. Bu, uygulamanızın URL
adlandırma düzenlerini, Web sunucunuzdaki dosyaların nasıl düzenleneceğine bakılmaksızın, arama motoru
iyileştirmesi (SEO ) ve bağlantı oluşturma için iyi bir şekilde tanımlamanıza olanak sağlar. Yol değer
kısıtlamalarını, Varsayılanları ve isteğe bağlı değerleri destekleyen uygun bir yol şablonu sözdizimi kullanarak
rotalarınızı tanımlayabilirsiniz.
Kural tabanlı yönlendirme , uygulamanızın kabul ettiği URL biçimlerini ve bu biçimlerin her birinin verilen
denetleyicide belirli bir eylem yöntemiyle nasıl eşlendiğini genel olarak tanımlamanızı sağlar. Gelen bir istek
alındığında, yönlendirme altyapısı URL 'YI ayrıştırır ve tanımlanan URL biçimlerinden biriyle eşleştirir ve
ardından ilişkili denetleyicinin eylem yöntemini çağırır.

routes.MapRoute(name: "Default", template: "{controller=Home}/{action=Index}/{id?}");

Öznitelik yönlendirme , denetleyicilerinizi ve eylemlerinizi uygulamanızın yollarını tanımlayan özniteliklerle


süsleyerek yönlendirme bilgilerini belirtmenizi sağlar. Bu, yol tanımlarınızın ilişkili oldukları denetleyicinin ve
eylemin yanına yerleştirildiği anlamına gelir.

[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
...
}
}

Model bağlama
ASP.NET Core MVC model bağlama , istemci isteği verilerini (form değerleri, rota verileri, sorgu dizesi
PARAMETRELERI, http üstbilgileri) denetleyicinin işleyebileceği nesnelere dönüştürür. Sonuç olarak,
denetleyici mantığınızın gelen istek verilerini oluşturma işini yapması gerekmez; Yalnızca Eylem yöntemlerine
parametre olarak verileri içerir.

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { ... }

Model doğrulaması
ASP.NET Core MVC, model nesneniz veri ek açıklaması doğrulama öznitelikleriyle süsleyerek doğrulamayı
destekler. Doğrulama öznitelikleri, değerler sunucuya gönderilmeden önce istemci tarafında ve denetleyici
eylemi çağrılmadan önce sunucuda denetlenir.
using System.ComponentModel.DataAnnotations;
public class LoginViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[Display(Name = "Remember me?")]


public bool RememberMe { get; set; }
}

Bir denetleyici eylemi:

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)


{
if (ModelState.IsValid)
{
// work with the model
}
// At this point, something failed, redisplay form
return View(model);
}

Çerçeve, istek verilerini hem istemcide hem de sunucuda doğrulamayı işler. Model türlerinde belirtilen
doğrulama mantığı, işlenen görünümlere obtrusive ek açıklamaları olarak eklenir ve jQuery doğrulamasıile
tarayıcıda zorlanır.
Bağımlılık ekleme
ASP.NET Core, bağımlılık ekleme (dı)için yerleşik desteğe sahiptir. ASP.NET Core MVC 'de, denetleyiciler
oluşturucuları aracılığıyla gerekli hizmetleri talep edebilir ve bu kullanıcıların Açık bağımlılıklar
ilkesiniizleyebilmesine olanak tanır.
Uygulamanız Ayrıca, @inject yönergesini kullanarak, görüntüleme dosyalarına bağımlılık eklemeişlemini de
kullanabilir:

@inject SomeService ServiceName

<!DOCTYPE html>
<html lang="en">
<head>
<title>@ServiceName.GetTitle</title>
</head>
<body>
<h1>@ServiceName.GetTitle</h1>
</body>
</html>

FilTReleri
Filtreler , geliştiricilerin özel durum işleme veya yetkilendirme gibi çapraz sorunları yalıtmalarına yardımcı olur.
Filtreler, eylem yöntemleri için özel ön ve son işlem dışı mantığı çalıştırmayı etkinleştirir ve belirli bir istek için
yürütme işlem hattının içindeki belirli noktalarda çalışacak şekilde yapılandırılabilir. Filtreler, denetleyicilere
veya eylemlere öznitelik olarak uygulanabilir (veya küresel olarak çalıştırılabilir). Çeşitli filtreler (örneğin
Authorize ) çerçeveye dahil edilir. [Authorize] , MVC yetkilendirme filtrelerini oluşturmak için kullanılan
özniteliktir.
[Authorize]
public class AccountController : Controller

Alanlar
Bölgeler , büyük BIR ASP.NET Core MVC web uygulamasını daha küçük işlevsel gruplandırmalar halinde
bölümlemek için bir yol sağlar. Bir alan, bir uygulamanın içindeki bir MVC yapısıdır. MVC projesinde model,
denetleyici ve görünüm gibi mantıksal bileşenler farklı klasörlerde tutulur ve MVC bu bileşenler arasındaki
ilişkiyi oluşturmak için adlandırma kurallarını kullanır. Büyük bir uygulama için, uygulamayı işlevlerin ayrı üst
düzey alanlarında bölümlemek avantajlı olabilir. Örneğin, kullanıma alma, faturalandırma ve arama gibi birden
çok iş birimi içeren bir e-ticaret uygulaması. Bu birimlerin her birinin kendi mantıksal bileşen görünümleri,
denetleyicileri ve modelleri vardır.
Web API'leri
Web siteleri oluşturmak için harika bir platform olmanın yanı sıra, ASP.NET Core MVC, Web API 'Leri
oluşturmaya yönelik harika destek içerir. Tarayıcılar ve mobil cihazlar dahil olmak üzere çok çeşitli istemcilere
ulaşan hizmetler oluşturabilirsiniz.
Framework, verileri JSON veya XML olarak biçimlendirmeye yönelik yerleşik destek ile http içerik anlaşması
için destek içerir. Kendi biçimlerinizin desteğini eklemek için özel biçimleri yazın.
Hiper medya desteğini etkinleştirmek için bağlantı oluşturma kullanın. Web API 'lerinizin birden çok Web
uygulaması arasında paylaşılabilmesi için, çıkış noktaları arası kaynak paylaşımı (CORS ) desteğini kolayca
etkinleştirin.
Test edilebilirlik
Çerçevenin arabirimlerin ve bağımlılık ekleme özelliğinin kullanımı, birim testine uygun hale getirir ve
Framework, tümleştirme testlerini hızlı ve kolay hale getirmek için özellikler (Entity Framework Için bir testhost
ve InMemory sağlayıcısı gibi) içerir. Denetleyici mantığını test etmehakkında daha fazla bilgi edinin.
Razor Görünüm altyapısı
MVC görünümleri ASP.NET Core , görünümleri Işlemek için Razor görüntüleme altyapısını kullanır. Razor,
gömülü C# kod kullanarak görünümler tanımlamaya yönelik kompakt, açıklayıcı ve akışkan şablonu
biçimlendirme dilidir. Razor, sunucu üzerinde dinamik olarak Web içeriği oluşturmak için kullanılır. Sunucu
kodunu istemci tarafı içeriğiyle ve kodla düzgün bir şekilde karıştırabilirsiniz.

<ul>
@for (int i = 0; i < 5; i++) {
<li>List item @i</li>
}
</ul>

Razor görünüm altyapısını kullanarak düzenler, kısmi görünümler ve değiştirilebilir bölümler


tanımlayabilirsiniz.
Türü kesin belirlenmiş görünümler
MVC 'de Razor görünümleri modelinize göre kesin bir şekilde yazılabilir. Denetleyiciler, görünümlerinizin tür
denetlemesi ve IntelliSense desteği olmasını sağlayan görünümlere kesin olarak belirlenmiş bir model
geçirebilir.
Örneğin, aşağıdaki görünüm IEnumerable<Product> türünde bir model işler:
@model IEnumerable<Product>
<ul>
@foreach (Product p in Model)
{
<li>@p.Name</li>
}
</ul>

Etiket Yardımcıları
Etiket Yardımcıları , Razor dosyalarında HTML öğeleri oluşturma ve oluşturma ile sunucu tarafı kodunun
katılmasını sağlar. Etiket Yardımcıları kullanarak özel Etiketler tanımlayabilir (örneğin, <environment> ) veya
varolan etiketlerin davranışını değiştirebilirsiniz (örneğin, <label> ). Etiket Yardımcıları, öğe adı ve öznitelikleri
temelinde belirli öğelere bağlanır. Bunlar, hala HTML düzenlemesi deneyimini korurken sunucu tarafı
işlemenin avantajlarını sağlar.
Yaygın görevler için, genel GitHub depolarında ve NuGet paketleri olarak formlar, bağlantılar, yükleme varlıkları
ve daha fazlasını ve daha fazlasını oluşturma gibi birçok yerleşik etiket yardımcıları vardır. Etiket Yardımcıları '
de C#yazılır ve öğe adı, öznitelik adı veya üst etıkete göre HTML öğelerini hedefleyin. Örneğin, yerleşik
Linakghelper, AccountsController``Login eylemine bir bağlantı oluşturmak için kullanılabilir:

<p>
Thank you for confirming your email.
Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>.
</p>

EnvironmentTagHelper , geliştirme, hazırlama veya üretim gibi çalışma zamanı ortamına göre görünümlerinizde
farklı betikler örneğin, ham veya küçültülmüş) dahil etmek için kullanılabilir:
(

<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
</environment>

Etiket Yardımcıları, HTML ve Razor biçimlendirmesi oluşturmaya yönelik zengin bir IntelliSense ortamı ve
HTML kullanımı kolay bir geliştirme deneyimi sağlar. Yerleşik etiket yardımcıların çoğu, var olan HTML
öğelerini hedefleyin ve öğesi için sunucu tarafı öznitelikleri sağlar.
Bileşenleri görüntüle
Görünüm bileşenleri , işleme mantığını paketlemenize ve uygulamanın tamamında yeniden kullanmanıza
olanak tanır. Bunlar, kısmen görünümlerebenzer ancak ilişkili mantığa benzer.

Uyumluluk sürümü
SetCompatibilityVersion yöntemi, bir uygulamanın, ASP.NET Core MVC 2,1 veya sonraki sürümlerde ortaya
çıkan olası davranış değişikliklerinin kabul etmesine veya devre dışı olmasına izin verir.
Daha fazla bilgi için bkz. ASP.NET Core MVC için uyumluluk sürümü.

Ek kaynaklar
ASP.NET Core – MVC Için Mysınanan. AspNetCore. Mvc-Floent test Kitaplığı , MVC ve Web API
uygulamalarını test etmek için akıcı bir arabirim sağlar. (Microsoft tarafından korunmaz veya desteklenmez.
)
ASP.NET Core MVC ile bir web uygulaması oluşturma
10.05.2019 • 2 minutes to read • Edit Online

Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay bir
başlangıç noktası sağlar.
Öğretici serisinin aşağıdakileri içerir:
1. Kullanmaya başlama
2. Denetleyici ekleme
3. Görünüm ekleme
4. Model ekleme
5. SQL Server LocalDB ile çalışma
6. Denetleyici metotları ve görünümleri
7. Arama ekleme
8. Yeni alan ekleme
9. Doğrulama ekleme
10. Details ve Delete metotlarını inceleme
ASP.NET Core MVC ile çalışmaya başlama
7.11.2019 • 20 minutes to read • Edit Online

Rick Anderson tarafından


Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay
bir başlangıç noktası sağlar.
Bu öğretici, ASP.NET Core MVC web uygulaması oluşturma hakkında temel bilgileri öğretir.
Uygulama, bir film başlıkları veritabanını yönetir. Aşağıdakilerin nasıl yapıldığını öğreneceksiniz:
Bir Web uygulaması oluşturun.
Bir modeli ekleyin ve yapı iskelesi yapın.
Bir veritabanıyla çalışın.
Arama ve doğrulama ekleyin.
Sonunda, film verilerini yönetebilen ve görüntüleyebilen bir uygulamanız vardır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini).

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'da Yeni proje oluştur' u seçin.
ASP.NET Core Web uygulaması ' nı seçin ve ardından İleri' yi seçin.
Projeyi Mvcfilmi olarak adlandırın ve Oluştur' u seçin. Kodu kopyaladığınızda, ad alanının eşleşmesi
için, projeyi Mvcfilmi olarak adlandırmak önemlidir.

Web uygulaması (Model-View-Controller) öğesini seçin ve ardından Oluştur' u seçin.


Visual Studio, az önce oluşturduğunuz MVC projesi için varsayılan şablonu kullandı. Şimdi bir proje adı girip
birkaç seçenek belirleyerek, çalışan bir uygulamanız var. Bu, temel bir başlatıcı projem.
Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamasız modda çalıştırmak için CTRL -F5 ' i seçin.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve
example.com gibi bir şey gösterilmediğine dikkat edin. Bunun nedeni, localhost yerel bilgisayarınız için
Standart ana bilgisayar adıdır. Visual Studio bir Web projesi oluşturduğunda, Web sunucusu için rastgele
bir bağlantı noktası kullanılır.
Uygulamayı CTRL + F5 (hata ayıklama modu) ile başlatmak, kod değişiklikleri yapmanıza, dosyayı
kaydetmenize, tarayıcıyı yenilemanıza ve kod değişikliklerini görmenize olanak tanır. Birçok geliştirici,
uygulamayı hızlı bir şekilde başlatmak ve değişiklikleri görüntülemek için hata ayıklama olmayan modu
kullanmayı tercih eder.
Hata ayıklama menü öğesinden uygulamayı hata ayıklama veya hata ayıklama olmayan modda
başlatabilirsiniz:

IIS Express düğmesini seçerek uygulamada hata ayıklaması yapabilirsiniz


Aşağıdaki görüntüde uygulama gösterilmektedir:

Visual Studio
Visual Studio Code
Mac için Visual Studio

Visual Studio Yardım


Hata ayıklamayı öğrenin C# kullanarak Visual Studio code
Visual Studio IDE'yi giriş
Bu öğreticinin bir sonraki bölümünde, MVC hakkında bilgi edinirsiniz ve kod yazmaya başlayabilirsiniz.

NEXT

Bu öğretici, ASP.NET Core MVC denetleyicileri ve görünümleri ile web geliştirme öğretir. ASP.NET Core web
geliştirmeye yeni başladıysanız göz önünde bulundurun Razor sayfaları sürümü bu öğreticinin bir daha kolay
bir başlangıç noktası sağlar.
Bu öğretici, ASP.NET Core MVC web uygulaması oluşturma hakkında temel bilgileri öğretir.
Uygulama, bir film başlıkları veritabanını yönetir. Aşağıdakilerin nasıl yapıldığını öğreneceksiniz:
Bir Web uygulaması oluşturun.
Bir modeli ekleyin ve yapı iskelesi yapın.
Bir veritabanıyla çalışın.
Arama ve doğrulama ekleyin.
Sonunda, film verilerini yönetebilen ve görüntüleyebilen bir uygulamanız vardır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini).

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'da Yeni proje oluştur' u seçin.
ASP.NET Core Web uygulaması ' nı seçin ve ardından İleri' yi seçin.
Projeyi Mvcfilmi olarak adlandırın ve Oluştur' u seçin. Kodu kopyaladığınızda, ad alanının eşleşmesi
için, projeyi Mvcfilmi olarak adlandırmak önemlidir.

Web uygulaması (Model-View-Controller) öğesini seçin ve ardından Oluştur' u seçin.


Visual Studio, az önce oluşturduğunuz MVC projesi için varsayılan şablonu kullandı. Şimdi bir proje adı girip
birkaç seçenek belirleyerek, çalışan bir uygulamanız var. Bu, temel bir başlatıcı projem ve başlamak için iyi bir
yerdir.
Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamasız modda çalıştırmak için CTRL -F5 ' i seçin.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.
Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve
example.com gibi bir şey gösterilmediğine dikkat edin. Bunun nedeni, localhost yerel bilgisayarınız için
Standart ana bilgisayar adıdır. Visual Studio bir Web projesi oluşturduğunda, Web sunucusu için rastgele
bir bağlantı noktası kullanılır.
Uygulamayı CTRL + F5 (hata ayıklama modu) ile başlatmak, kod değişiklikleri yapmanıza, dosyayı
kaydetmenize, tarayıcıyı yenilemanıza ve kod değişikliklerini görmenize olanak tanır. Birçok geliştirici,
uygulamayı hızlı bir şekilde başlatmak ve değişiklikleri görüntülemek için hata ayıklama olmayan modu
kullanmayı tercih eder.
Hata ayıklama menü öğesinden uygulamayı hata ayıklama veya hata ayıklama olmayan modda
başlatabilirsiniz:

IIS Express düğmesini seçerek uygulamada hata ayıklaması yapabilirsiniz


İzlemeye izin vermek için kabul et ' i seçin. Bu uygulama kişisel bilgileri izlemez. Şablon tarafından
oluşturulan kod, genel veri koruma yönetmeliği (GDPR )buluşmanıza yardımcı olan varlıkları içerir.

Aşağıdaki görüntüde izlemeyi kabul ettikten sonra uygulama gösterilmektedir:


Visual Studio
Visual Studio Code
Mac için Visual Studio

Visual Studio Yardım


Hata ayıklamayı öğrenin C# kullanarak Visual Studio code
Visual Studio IDE'yi giriş
Bu öğreticinin bir sonraki bölümünde, MVC hakkında bilgi edinirsiniz ve kod yazmaya başlayabilirsiniz.

NEXT
ASP.NET Core MVC uygulamasına denetleyici
ekleme
7.08.2019 • 21 minutes to read • Edit Online

Tarafından Rick Anderson


Model-View -Controller (MVC ) mimari modeli, bir uygulamayı üç ana bileşene ayırır: Model, VIEW ve
Controller. MVC deseninin daha kararlı ve geleneksel tek parçalı uygulamalardan güncelleştirilmesi daha kolay
olan uygulamalar oluşturmanıza yardımcı olur. MVC tabanlı uygulamalar şunları içerir:
Aodels: Uygulamanın verilerini temsil eden sınıflar. Model sınıfları, bu veriler için iş kurallarını zorlamak
üzere doğrulama mantığını kullanır. Genellikle, model nesneleri bir veritabanında model durumunu alır
ve saklar. Bu öğreticide, bir Movie model bir veritabanından film verileri alır, bunu görünüme sağlar veya
güncelleştirir. Güncelleştirilmiş veriler bir veritabanına yazılır.
Vıews: Görünümler, uygulamanın kullanıcı arabirimini (UI) görüntüleyen bileşenlerdir. Genellikle, bu
kullanıcı arabirimi model verilerini görüntüler.
Controlleyiciler: Tarayıcı isteklerini işleyen sınıflar. Model verileri alır ve yanıt döndüren çağrı görünümü
şablonları. MVC uygulamasında, görünüm yalnızca bilgileri görüntüler; denetleyici, Kullanıcı girişini ve
etkileşimini işler ve yanıtlar. Örneğin, denetleyici rota verilerini ve sorgu dizesi değerlerini işler ve bu
değerleri modele geçirir. Model bu değerleri veritabanını sorgulamak için kullanabilir. Örneğin,
https://localhost:5001/Home/Privacy Home (denetleyici) ve Privacy (ana denetleyicide çağrılacak eylem
yöntemi) verilerinin yolunu içerir. https://localhost:5001/Movies/Edit/5 filmi film denetleyicisi
kullanarak, ID = 5 olan filmi düzenleme isteği. Rota verileri öğreticide daha sonra açıklanmaktadır.
MVC deseninin uygulamanın farklı yönlerini (Giriş mantığı, iş mantığı ve Kullanıcı arabirimi mantığı) ayıran
uygulamalar oluşturmanıza yardımcı olur. bu öğeler arasında gevşek bir bağ sağlanır. Bu model, her bir mantık
türünün uygulamada nerede bulunması gerektiğini belirtir. Kullanıcı arabirimi mantığı görünüme aittir. Giriş
mantığı denetleyiciye aittir. İş mantığı modele aittir. Bu ayrım, bir uygulama oluşturduğunuzda karmaşıklığın
yönetilmesine yardımcı olur, çünkü uygulamanın bir tek tarafında, başka bir kodu etkilemeden bir kez
çalışmanıza olanak sağlar. Örneğin, iş mantığı koduna bağlı kalmadan görünüm kodu üzerinde çalışabilirsiniz.
Bu kavramları, bu öğretici serisinde ele alınmaktadır ve bir film uygulaması oluşturmak için nasıl kullanacağınızı
gösterir. MVC projesi denetleyiciler ve Görünümleriçin klasörler içerir.

Denetleyici ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler öğesine sağ tıklayın > > denetleyicisi
Yapı Iskelesi Ekle iletişim kutusunda, MVC denetleyicisi-boş seçeneğini belirleyin

Boş MVC denetleyicisi Ekle iletişim kutusunda, Merhaba worldcontroller yazın ve Ekle' yi seçin.
Controllers/HelloWorldController. cs içeriğini aşağıdakiler ile değiştirin:
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/

public string Index()


{
return "This is my default action...";
}

//
// GET: /HelloWorld/Welcome/

public string Welcome()


{
return "This is the Welcome action method...";
}
}
}

Bir public denetleyicideki her yöntem bir HTTP uç noktası olarak çağrılabilir. Yukarıdaki örnekte her iki
yöntem de bir dize döndürür. Her yöntemden önceki açıklamalara göz önüne alın.
HTTP uç noktası, https://localhost:5001/HelloWorld gibi Web uygulamasındaki bir hedeflenebilir URL 'sidir ve
HTTPS kullanılan protokolü, Web sunucusunun ağ konumunu ( TCP bağlantı noktası dahil): localhost:5001 ve
hedef URI HelloWorld 'yi birleştirir.
İlk açıklama bu, temel URL 'ye eklenerek /HelloWorld/ çağrılan bir http get yöntemi olduğunu belirtir. İkinci
açıklama URL 'ye eklenerek /HelloWorld/Welcome/ çağrılan bir http get yöntemini belirtir. Öğreticide daha
sonra, verileri güncelleştiren Yöntemler oluşturmak HTTP POST için scafkatlama altyapısı kullanılır.
Uygulamayı hata ayıklama modunda çalıştırın ve adres çubuğundaki yola "HelloWorld" ekleyin. Index Yöntemi
bir dize döndürür.
MVC, gelen URL 'ye bağlı olarak denetleyici sınıflarını (ve içindeki eylem yöntemlerini) çağırır. MVC tarafından
kullanılan varsayılan URL yönlendirme mantığı , çağrılacak kodu belirlemek için şöyle bir biçim kullanır:
/[Controller]/[ActionName]/[Parameters]

Yönlendirme biçimi Configure Startup.cs dosyasındaki yönteminde ayarlanır.

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

Uygulamaya gözatıp hiçbir URL kesimini sağlamadığınızda, varsayılan olarak "giriş" denetleyicisi ve yukarıda
vurgulanan şablon satırında belirtilen "Dizin" yöntemi varsayılan olarak belirtilir.
İlk URL segmenti, çalıştırılacak denetleyici sınıfını belirler. Bu localhost:{PORT}/HelloWorld nedenle
HelloWorldController sınıfıyla eşlenir. URL segmentinin ikinci bölümü, sınıfındaki Action metodunu belirler. Bu
localhost:{PORT}/HelloWorld/Index nedenle, HelloWorldController sınıfın Index yönteminin çalışmasına neden
olur. Yalnızca göz atmanızı localhost:{PORT}/HelloWorld Index ve yönteme varsayılan olarak çağrıldığına dikkat
edin. Bunun nedeni Index , açıkça bir yöntem adı belirtilmemişse bir denetleyicide çağrılacak varsayılan
yöntemdir. URL segmentinin ( id ) üçüncü bölümü rota verileri içindir. Rota verileri öğreticide daha sonra
açıklanmaktadır.
konumuna gözatın . Yöntemi çalışır ve dizeyi
https://localhost:{PORT}/HelloWorld/Welcome
This is the Welcome action method... döndürür. Welcome Bu URL için denetleyici HelloWorld , ve Welcome
eylem yöntemidir. URL 'nin bir [Parameters] bölümünü henüz kullanmadınız.

URL 'den denetleyiciye bazı parametre bilgilerini geçirmek için kodu değiştirin. Örneğin:
/HelloWorld/Welcome?name=Rick&numtimes=4 . Welcome Yöntemi aşağıdaki kodda gösterildiği gibi iki parametre
içerecek şekilde değiştirin.
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is: {numTimes}");
}

Yukarıdaki kod:
Parametresi için C# hiçbir değer geçirilmemişse, numTimes parametrenin varsayılan olarak 1 ' e ait olduğunu
belirtmek için isteğe bağlı parametre özelliğini kullanır.
Uygulamayı HtmlEncoder.Default.Encode kötü amaçlı girişten korumak için kullanır (yani JavaScript).
Içinde $"Hello {name}, NumTimes is: {numTimes}" enterpolasyonlu dizeler kullanır.

Uygulamayı çalıştırın ve şu konuma gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

(Bağlantı {PORT} noktası numaranız ile değiştirin.) URL 'de ve name numtimes için farklı değerler
deneyebilirsiniz. MVC model bağlama sistemi, adlandırılmış parametreleri adres çubuğundaki sorgu dizesinden
yöntemdeki parametrelere otomatik olarak eşler. Daha fazla bilgi için bkz. model bağlama .

Yukarıdaki görüntüde, Parameters URL segmenti () kullanılmaz name , ve numTimes parametreleri sorgu
dizeleriolarak geçirilir. Yukarıdaki URL 'deki (soru işareti) bir ayırıcı ve sorgu dizeleri izler. ? & Karakter Sorgu
dizelerini ayırır.
Welcome Yöntemini aşağıdaki kodla değiştirin:

public string Welcome(string name, int ID = 1)


{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}

Uygulamayı çalıştırın ve aşağıdaki URL 'YI girin: https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick


Bu kez, üçüncü URL segmenti rota parametresiyle id eşleşti. Yöntemi, MapControllerRoute yöntemindeki URL
şablonuyla id eşleşen bir parametre içerir. Welcome Sondaki ? (içinde id? ) id parametresinin isteğe bağlı
olduğunu gösterir.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

Bu örneklerde, denetleyici MVC 'nin "VC" bölümünü (yani, VIEW ve C ) çalışır. Denetleyici HTML 'i doğrudan
döndürüyor. Genellikle, bu, kod ve bakım için çok daha fazla hale geldiği için denetleyicilerin doğrudan HTML
döndürmesini istemezsiniz. Bunun yerine, genellikle HTML yanıtı oluşturmak için ayrı bir Razor görünümü
şablon dosyası kullanırsınız. Bunu bir sonraki öğreticide yapabilirsiniz.

ÖN CEKI İleri

Model-View -Controller (MVC ) mimari modeli, bir uygulamayı üç ana bileşene ayırır: Model, VIEW ve
Controller. MVC deseninin daha kararlı ve geleneksel tek parçalı uygulamalardan güncelleştirilmesi daha kolay
olan uygulamalar oluşturmanıza yardımcı olur. MVC tabanlı uygulamalar şunları içerir:
Aodels: Uygulamanın verilerini temsil eden sınıflar. Model sınıfları, bu veriler için iş kurallarını zorlamak
üzere doğrulama mantığını kullanır. Genellikle, model nesneleri bir veritabanında model durumunu alır
ve saklar. Bu öğreticide, bir Movie model bir veritabanından film verileri alır, bunu görünüme sağlar veya
güncelleştirir. Güncelleştirilmiş veriler bir veritabanına yazılır.
Vıews: Görünümler, uygulamanın kullanıcı arabirimini (UI) görüntüleyen bileşenlerdir. Genellikle, bu
kullanıcı arabirimi model verilerini görüntüler.
Controlleyiciler: Tarayıcı isteklerini işleyen sınıflar. Model verileri alır ve yanıt döndüren çağrı görünümü
şablonları. MVC uygulamasında, görünüm yalnızca bilgileri görüntüler; denetleyici, Kullanıcı girişini ve
etkileşimini işler ve yanıtlar. Örneğin, denetleyici rota verilerini ve sorgu dizesi değerlerini işler ve bu
değerleri modele geçirir. Model bu değerleri veritabanını sorgulamak için kullanabilir. Örneğin,
https://localhost:5001/Home/About Home (denetleyici) ve About (ana denetleyicide çağrılacak eylem
yöntemi) verilerinin yolunu içerir. https://localhost:5001/Movies/Edit/5 filmi film denetleyicisi
kullanarak, ID = 5 olan filmi düzenleme isteği. Rota verileri öğreticide daha sonra açıklanmaktadır.
MVC deseninin uygulamanın farklı yönlerini (Giriş mantığı, iş mantığı ve Kullanıcı arabirimi mantığı) ayıran
uygulamalar oluşturmanıza yardımcı olur. bu öğeler arasında gevşek bir bağ sağlanır. Bu model, her bir mantık
türünün uygulamada nerede bulunması gerektiğini belirtir. Kullanıcı arabirimi mantığı görünüme aittir. Giriş
mantığı denetleyiciye aittir. İş mantığı modele aittir. Bu ayrım, bir uygulama oluşturduğunuzda karmaşıklığın
yönetilmesine yardımcı olur, çünkü uygulamanın bir tek tarafında, başka bir kodu etkilemeden bir kez
çalışmanıza olanak sağlar. Örneğin, iş mantığı koduna bağlı kalmadan görünüm kodu üzerinde çalışabilirsiniz.
Bu kavramları, bu öğretici serisinde ele alınmaktadır ve bir film uygulaması oluşturmak için nasıl kullanacağınızı
gösterir. MVC projesi denetleyiciler ve Görünümleriçin klasörler içerir.

Denetleyici ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler öğesine sağ tıklayın > > denetleyicisi
Yapı Iskelesi Ekle iletişim kutusunda, MVC denetleyicisi-boş seçeneğini belirleyin

Boş MVC denetleyicisi Ekle iletişim kutusunda, Merhaba worldcontroller yazın ve Ekle' yi seçin.
Controllers/HelloWorldController. cs içeriğini aşağıdakiler ile değiştirin:
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/

public string Index()


{
return "This is my default action...";
}

//
// GET: /HelloWorld/Welcome/

public string Welcome()


{
return "This is the Welcome action method...";
}
}
}

Bir public denetleyicideki her yöntem bir HTTP uç noktası olarak çağrılabilir. Yukarıdaki örnekte her iki
yöntem de bir dize döndürür. Her yöntemden önceki açıklamalara göz önüne alın.
HTTP uç noktası, https://localhost:5001/HelloWorld gibi Web uygulamasındaki bir hedeflenebilir URL 'sidir ve
HTTPS kullanılan protokolü, Web sunucusunun ağ konumunu ( TCP bağlantı noktası dahil): localhost:5001 ve
hedef URI HelloWorld 'yi birleştirir.
İlk açıklama bu, temel URL 'ye eklenerek /HelloWorld/ çağrılan bir http get yöntemi olduğunu belirtir. İkinci
açıklama URL 'ye eklenerek /HelloWorld/Welcome/ çağrılan bir http get yöntemini belirtir. Öğreticide daha
sonra, verileri güncelleştiren Yöntemler oluşturmak HTTP POST için scafkatlama altyapısı kullanılır.
Uygulamayı hata ayıklama modunda çalıştırın ve adres çubuğundaki yola "HelloWorld" ekleyin. Index Yöntemi
bir dize döndürür.
MVC, gelen URL 'ye bağlı olarak denetleyici sınıflarını (ve içindeki eylem yöntemlerini) çağırır. MVC tarafından
kullanılan varsayılan URL yönlendirme mantığı , çağrılacak kodu belirlemek için şöyle bir biçim kullanır:
/[Controller]/[ActionName]/[Parameters]

Yönlendirme biçimi Configure Startup.cs dosyasındaki yönteminde ayarlanır.

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Uygulamaya gözatıp hiçbir URL kesimini sağlamadığınızda, varsayılan olarak "giriş" denetleyicisi ve yukarıda
vurgulanan şablon satırında belirtilen "Dizin" yöntemi varsayılan olarak belirtilir.
İlk URL segmenti, çalıştırılacak denetleyici sınıfını belirler. Bu localhost:{PORT}/HelloWorld nedenle,
HelloWorldController sınıfıyla eşlenir. URL segmentinin ikinci bölümü, sınıfındaki Action metodunu belirler. Bu
localhost:{PORT}/HelloWorld/Index nedenle, HelloWorldController sınıfın Index yönteminin çalışmasına neden
olur. Yalnızca göz atmanızı localhost:{PORT}/HelloWorld Index ve yönteme varsayılan olarak çağrıldığına dikkat
edin. Bunun nedeni Index , açıkça bir yöntem adı belirtilmemişse bir denetleyicide çağrılacak varsayılan
yöntemdir. URL segmentinin ( id ) üçüncü bölümü rota verileri içindir. Rota verileri öğreticide daha sonra
açıklanmaktadır.
konumuna gözatın . Yöntemi çalışır ve dizeyi
https://localhost:{PORT}/HelloWorld/Welcome
This is the Welcome action method... döndürür. Welcome Bu URL için denetleyici HelloWorld , ve Welcome
eylem yöntemidir. URL 'nin bir [Parameters] bölümünü henüz kullanmadınız.

URL 'den denetleyiciye bazı parametre bilgilerini geçirmek için kodu değiştirin. Örneğin:
/HelloWorld/Welcome?name=Rick&numtimes=4 . Welcome Yöntemi aşağıdaki kodda gösterildiği gibi iki parametre
içerecek şekilde değiştirin.
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is: {numTimes}");
}

Yukarıdaki kod:
Parametresi için C# hiçbir değer geçirilmemişse, numTimes parametrenin varsayılan olarak 1 ' e ait olduğunu
belirtmek için isteğe bağlı parametre özelliğini kullanır.
Uygulamayı HtmlEncoder.Default.Encode kötü amaçlı girişten korumak için kullanır (yani JavaScript).
Içinde $"Hello {name}, NumTimes is: {numTimes}" enterpolasyonlu dizeler kullanır.

Uygulamayı çalıştırın ve şu konuma gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

(Bağlantı {PORT} noktası numaranız ile değiştirin.) URL 'de ve name numtimes için farklı değerler
deneyebilirsiniz. MVC model bağlama sistemi, adlandırılmış parametreleri adres çubuğundaki sorgu dizesinden
yöntemdeki parametrelere otomatik olarak eşler. Daha fazla bilgi için bkz. model bağlama .

Yukarıdaki görüntüde, Parameters URL segmenti () kullanılmaz name , ve numTimes parametreleri sorgu
dizeleriolarak geçirilir. Yukarıdaki URL 'deki (soru işareti) bir ayırıcı ve sorgu dizeleri izler. ? & Karakter Sorgu
dizelerini ayırır.
Welcome Yöntemini aşağıdaki kodla değiştirin:

public string Welcome(string name, int ID = 1)


{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}

Uygulamayı çalıştırın ve aşağıdaki URL 'YI girin: https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick


Bu kez, üçüncü URL segmenti rota parametresiyle id eşleşti. Yöntemi, MapRoute yöntemindeki URL şablonuyla
id eşleşen bir parametre içerir. Welcome Sondaki ? (içinde id? ) id parametresinin isteğe bağlı olduğunu
gösterir.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Bu örneklerde, denetleyici MVC 'nin "VC" bölümünü (yani, görünüm ve denetleyici çalışır) yapıyor. Denetleyici
HTML 'i doğrudan döndürüyor. Genellikle, bu, kod ve bakım için çok daha fazla hale geldiği için denetleyicilerin
doğrudan HTML döndürmesini istemezsiniz. Bunun yerine, genellikle HTML yanıtı oluşturmaya yardımcı
olması için ayrı bir Razor görünümü şablon dosyası kullanırsınız. Bunu bir sonraki öğreticide yapabilirsiniz.

ÖN CEKI İleri
ASP.NET Core MVC uygulamasına görünüm
ekleme
23.11.2019 • 26 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, bir istemciye HTML yanıtları oluşturma işlemini düzgün bir şekilde kapsüllemek için
HelloWorldController sınıfını Razor görünümü dosyalarını kullanacak şekilde değiştirirsiniz.

Razor kullanarak bir görünüm şablonu dosyası oluşturursunuz. Razor tabanlı görünüm şablonlarının . cshtml
dosya uzantısı vardır. Bu kişiler ile C#HTML çıktısı oluşturmanın zarif bir yolunu sağlarlar.
Şu anda Indexyöntemi, denetleyici sınıfında sabit kodlanmış bir ileti içeren bir dize döndürür.
HelloWorldController sınıfında, Index yöntemini aşağıdaki kodla değiştirin:

public IActionResult Index()


{
return View();
}

Yukarıdaki kod denetleyicinin View yöntemini çağırır. HTML yanıtı oluşturmak için bir görünüm şablonu
kullanır. Yukarıdaki Index yöntemi gibi denetleyici Yöntemleri ( eylem yöntemleriolarak da bilinir), genellikle,
string gibi bir tür değil, genellikle bir IActionResult (veya ActionResulttüretilen bir sınıf) döndürür.

Görünüm ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Görünümler klasörüne sağ tıklayın ve ardından Yeni > klasör ekleyin ve HelloWorldklasörünü
adlandırın.
Görünümler/HelloWorld klasörüne sağ tıklayın ve ardından > yeni öğe ekleyin.
Yeni öğe Ekle-Mvcfilmi iletişim kutusunda
Sağ üst köşedeki arama kutusuna Görünüm girin
Razor görünümü seçin
Index. cshtml adlı ad kutusu değerini saklayın.
Ekle 'yi seçin
Views/HelloWorld/Index. cshtml Razor görünüm dosyasının içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://test-cors.org sayfasına gidin. HelloWorldController Index yöntemi çok bitmedi; Bu, yönteminin
tarayıcıya yanıt işlemek için bir görünüm şablonu dosyası kullanması gerektiğini belirten return View();
ifadesini çalıştırdı. Bir görünüm şablonu dosya adı belirtilmediğinden, MVC varsayılan görünüm dosyasını
kullanmaya göre varsayılan olarak ayarlanmış. Varsayılan görünüm dosyası yöntemiyle aynı ada sahiptir (
Index ), bu nedenle /views/HelloWorld/Index.cshtml kullanılır. Aşağıdaki görüntüde "görünüm
Şablonumuzdan Merhaba!" dizesi gösterilmektedir görünümde sabit kodlanmış.
Görünümleri ve düzen sayfalarını değiştirme
Menü bağlantılarını (Mvcmovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü
düzeni Görünümler/Shared/_Layout. cshtml dosyasında uygulanır. Görünümler/paylaşılan/_Layout. cshtml
dosyasını açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden
çok sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm
görünüme özgü sayfaların, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını
seçerseniz, Görünümler/Home/privacy. cshtml görünümü RenderBody yöntemi içinde işlenir.

Düzen dosyasındaki başlık, altbilgi ve menü bağlantısını değiştirme


Görünümler/paylaşılan/_Layout. cshtml dosyasının içeriğini aşağıdaki biçimlendirme ile değiştirin.
Değişiklikler vurgulanır:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie App</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-
shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Movie App - <a asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>

Yukarıdaki biçimlendirme aşağıdaki değişiklikleri yaptı:


MvcMovie Movie App için 3 oluşum.
Tutturucu öğe
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>``<a class="navbar-
brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a>
.
Yukarıdaki biçimlendirmede, bu uygulama alankullandığından asp-area="" tutturucu etiketi Yardımcısı
özniteliği ve öznitelik değeri atlandı.
Not: Movies denetleyicisi uygulanmadı. Bu noktada, Movie App bağlantısı işlevsel değildir.
Değişikliklerinizi kaydedin ve Gizlilik bağlantısını seçin. Tarayıcı sekmesindeki başlığın Gizlilik ilkesi yerine bir
film uygulaması (Gizlilik ilkesi değil) nasıl görüntülediğini fark edin -MVC filmi:

Giriş bağlantısını seçin ve başlık ve bağlantı metninin film uygulamasınıda görüntülediğine dikkat edin.
Düzen şablonunda değişikliği bir kez yapabildik ve sitedeki tüm sayfalar yeni bağlantı metnini ve yeni başlığı
yansıtmaktadır.
Views/_ViewStart. cshtml dosyasını inceleyin:

@{
Layout = "_Layout";
}

Views/_ViewStart. cshtml dosyası her bir görünüm için views/Shared/_Layout. cshtml dosyasını getirir.
Layout özelliği, farklı bir düzen görünümü ayarlamak veya null olarak ayarlamak için kullanılabilir; Bu
nedenle hiçbir düzen dosyası kullanılmayacak.
Views/HelloWorld/Index. cshtml görünüm dosyasının başlığını ve <h2> öğesini değiştirin:

@{
ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

Başlık ve <h2> öğesi biraz farklıdır, bu sayede kodun hangi bitini görüntülemesini görebilirsiniz.
yukarıdaki koddaki ViewData["Title"] = "Movie List"; , ViewData sözlüğün Title özelliğini "film listesi"
olarak ayarlar. Title özelliği, Düzen sayfasındaki <title> HTML öğesinde kullanılır:

<title>@ViewData["Title"] - Movie App</title>

Değişikliği kaydedin ve https://localhost:{PORT}/HelloWorld gidin. Tarayıcı başlığı, birincil başlık ve ikincil


başlıkların değiştirildiğini unutmayın. (Tarayıcıda değişiklik görmüyorsanız, önbelleğe alınmış içeriği
görüntülüyor olabilirsiniz. Sunucudan gelen yanıtı zorlamak için tarayıcınızda CTRL + F5 tuşlarına basın.)
Tarayıcı başlığı, Index. cshtml görünüm şablonunda belirlediğimiz ViewData["Title"] ve düzen dosyasına
eklenen ek "-film uygulaması" ile oluşturulur.
Index. cshtml görünüm şablonundaki içerik views/Shared/_Layout. cshtml görünüm şablonuyla birleştirilir.
Tarayıcıya tek bir HTML yanıtı gönderilir. Düzen şablonları, bir uygulamadaki tüm sayfalara uygulanan
değişiklikler yapmayı kolaylaştırır. Daha fazla bilgi için bkz. Düzen.

"Data" (Bu durumda "Görünümümüzden Merhaba!") çok az. ileti) sabit kodludur, ancak. MVC uygulamasında
bir "V" (görünüm) var ve bir "C" (denetleyici) var, ancak henüz "M" (model) yok.

Denetleyiciden görünüme veri geçirme


Gelen URL isteğine yanıt olarak denetleyici eylemleri çağrılır. Bir denetleyici sınıfı, gelen tarayıcı isteklerini
işleyen kodun yazıldığı yerdir. Denetleyici verileri bir veri kaynağından alır ve tarayıcıya ne tür bir yanıt
gönderileceğini belirler. Görünüm şablonları bir denetleyiciden, tarayıcıya HTML yanıtı oluşturmak ve
biçimlendirmek için kullanılabilir.
Bir görünüm şablonunun yanıt işlemesi için gereken verileri sağlamaktan denetleyiciler sorumludur. En iyi
yöntem: Görünüm şablonları iş mantığı gerçekleştirmemelidir veya doğrudan bir veritabanıyla etkileşime
girmemelidir. Bunun yerine, bir görünüm şablonu yalnızca denetleyici tarafından sunulan verilerle birlikte
çalışmalıdır. Bu "kaygıları ayrımı", kodun temiz, test edilebilir ve sürdürülebilir kalmasına yardımcı olur.
Şu anda, HelloWorldController sınıfındaki Welcome yöntemi bir name ve ID parametresi alır ve sonra
değerleri doğrudan tarayıcıya çıkarır. Denetleyicinin bu yanıtı bir dize olarak işlemesini sağlamak yerine,
denetleyiciyi bir görünüm şablonu kullanacak şekilde değiştirin. Görünüm şablonu dinamik bir yanıt üretir, bu,
yanıtı oluşturmak için denetleyiciden görünüme uygun veri bitlerinin geçirilmesi gereken anlamına gelir. Bu,
denetleyicinin görünüm şablonu tarafından daha sonra erişebileceği bir ViewData sözlüğünde bulunan
dinamik verileri (parametreler) yerleştirerek bunu yapın.
HelloWorldController.cs' de, ViewData sözlüğüne bir Message ve NumTimes değeri eklemek için Welcome
yöntemini değiştirin. ViewData sözlüğü dinamik bir nesnedir, yani herhangi bir tür kullanılabilir; ViewData
nesnenin içine bir öğe yerleştirene kadar tanımlanmış özellikleri yok. MVC modeli bağlama sistemi ,
adlandırılmış parametreleri ( name ve numTimes ), adres çubuğundaki sorgu dizesinden yöntemdeki
parametrelere otomatik olarak eşler. Tüm HelloWorldController.cs dosyası şuna benzer:

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Welcome(string name, int numTimes = 1)


{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;

return View();
}
}
}

ViewData Dictionary nesnesi görünüme geçirilecek verileri içerir.


Görünümler/HelloWorld/Welcome. cshtmladlı bir hoş geldiniz görünüm şablonu oluşturun.
Welcome. cshtml görünüm şablonunda "Hello" NumTimes görüntüleyen bir döngü oluşturacaksınız.
Views/HelloWorld/Welcome. cshtml içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>

Değişikliklerinizi kaydedin ve aşağıdaki URL 'ye gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

Veriler URL 'den alınır ve MVC model Bağlayıcısı kullanılarak denetleyiciye geçirilir. Denetleyici, verileri bir
ViewData sözlüğüne paketler ve bu nesneyi görünüme geçirir. Daha sonra Görünüm, verileri tarayıcıda
HTML olarak işler.
Yukarıdaki örnekte ViewData sözlüğü denetleyiciden bir görünüme veri geçirmek için kullanılmıştır.
Öğreticide daha sonra bir görünüm modeli, bir denetleyicideki verileri bir görünüme geçirmek için kullanılır.
Veri geçirme yaklaşımına yönelik görünüm modeli, ViewData sözlük yaklaşımına göre genel olarak çok tercih
edilir. Daha fazla bilgi için bkz. ViewBag, ViewData veya TempData kullanma .
Sonraki öğreticide, bir film veritabanı oluşturulur.

ÖN CEKI İL E R I

Bu bölümde, bir istemciye HTML yanıtları oluşturma işlemini düzgün bir şekilde kapsüllemek için
HelloWorldController sınıfını Razor görünümü dosyalarını kullanacak şekilde değiştirirsiniz.

Razor kullanarak bir görünüm şablonu dosyası oluşturursunuz. Razor tabanlı görünüm şablonlarının . cshtml
dosya uzantısı vardır. Bu kişiler ile C#HTML çıktısı oluşturmanın zarif bir yolunu sağlarlar.
Şu anda Indexyöntemi, denetleyici sınıfında sabit kodlanmış bir ileti içeren bir dize döndürür.
HelloWorldController sınıfında, Index yöntemini aşağıdaki kodla değiştirin:

public IActionResult Index()


{
return View();
}

Yukarıdaki kod denetleyicinin View yöntemini çağırır. HTML yanıtı oluşturmak için bir görünüm şablonu
kullanır. Yukarıdaki Index yöntemi gibi denetleyici Yöntemleri ( eylem yöntemleriolarak da bilinir), genellikle,
string gibi bir tür değil, genellikle bir IActionResult (veya ActionResulttüretilen bir sınıf) döndürür.

Görünüm ekleme
Visual Studio
Visual Studio Code
Mac için Visual Studio
Görünümler klasörüne sağ tıklayın ve ardından Yeni > klasör ekleyin ve HelloWorldklasörünü
adlandırın.
Görünümler/HelloWorld klasörüne sağ tıklayın ve ardından > yeni öğe ekleyin.
Yeni öğe Ekle-Mvcfilmi iletişim kutusunda
Sağ üst köşedeki arama kutusuna Görünüm girin
Razor görünümü seçin
Index. cshtml adlı ad kutusu değerini saklayın.
Ekle 'yi seçin

Views/HelloWorld/Index. cshtml Razor görünüm dosyasının içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://test-cors.org sayfasına gidin. HelloWorldController Index yöntemi çok bitmedi; Bu, yönteminin
tarayıcıya yanıt işlemek için bir görünüm şablonu dosyası kullanması gerektiğini belirten return View();
ifadesini çalıştırdı. Bir görünüm şablonu dosya adı belirtilmediğinden, MVC varsayılan görünüm dosyasını
kullanmaya göre varsayılan olarak ayarlanmış. Varsayılan görünüm dosyası yöntemiyle aynı ada sahiptir (
Index ), bu nedenle /views/HelloWorld/Index.cshtml kullanılır. Aşağıdaki görüntüde "görünüm
Şablonumuzdan Merhaba!" dizesi gösterilmektedir görünümde sabit kodlanmış.
Görünümleri ve düzen sayfalarını değiştirme
Menü bağlantılarını (Mvcmovie, Homeve Gizlilik) seçin. Her sayfada aynı menü düzeni gösterilir. Menü
düzeni Görünümler/Shared/_Layout. cshtml dosyasında uygulanır. Görünümler/paylaşılan/_Layout. cshtml
dosyasını açın.
Düzen şablonları, sitenizin HTML kapsayıcı yerleşimini tek bir yerde belirtmenize ve sonra sitenizdeki birden
çok sayfaya uygulamanıza olanak tanır. @RenderBody() satırını bulun. RenderBody , oluşturduğunuz tüm
görünüme özgü sayfaların, Düzen sayfasında kaydırılan bir yer tutucudur. Örneğin, Gizlilik bağlantısını
seçerseniz, Görünümler/Home/privacy. cshtml görünümü RenderBody yöntemi içinde işlenir.

Düzen dosyasındaki başlık, altbilgi ve menü bağlantısını değiştirme


Başlık ve altbilgi öğelerinde MvcMovie Movie App olarak değiştirin.
Tutturucu öğe
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a>
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a> olarak değiştirin.

Aşağıdaki biçimlendirme vurgulanan değişiklikleri göstermektedir:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie App</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.1.3/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute"
crossorigin="anonymous"
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
</environment>
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-
shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-
collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<partial name="_CookieConsentPartial" />
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Movie App - <a asp-area="" asp-controller="Home" asp-
action="Privacy">Privacy</a>
</div>
</footer>

<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.1.3/js/bootstrap.bundle.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
</script>
</environment>
<script src="~/js/site.js" asp-append-version="true"></script>

@RenderSection("Scripts", required: false)


</body>
</html>

Yukarıdaki biçimlendirmede, bu uygulama alankullandığından asp-area tutturucu etiketi yardımcı özniteliği


atlandı.
Not: Movies denetleyicisi uygulanmadı. Bu noktada, Movie App bağlantısı işlevsel değildir.
Değişikliklerinizi kaydedin ve Gizlilik bağlantısını seçin. Tarayıcı sekmesindeki başlığın Gizlilik ilkesi yerine bir
film uygulaması (Gizlilik ilkesi değil) nasıl görüntülediğini fark edin -MVC filmi:

Giriş bağlantısını seçin ve başlık ve bağlantı metninin film uygulamasınıda görüntülediğine dikkat edin.
Düzen şablonunda değişikliği bir kez yapabildik ve sitedeki tüm sayfalar yeni bağlantı metnini ve yeni başlığı
yansıtmaktadır.
Views/_ViewStart. cshtml dosyasını inceleyin:

@{
Layout = "_Layout";
}

Views/_ViewStart. cshtml dosyası her bir görünüm için views/Shared/_Layout. cshtml dosyasını getirir.
Layout özelliği, farklı bir düzen görünümü ayarlamak veya null olarak ayarlamak için kullanılabilir; Bu
nedenle hiçbir düzen dosyası kullanılmayacak.
Views/HelloWorld/Index. cshtml görünüm dosyasının başlığını ve <h2> öğesini değiştirin:

@{
ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

Başlık ve <h2> öğesi biraz farklıdır, bu sayede kodun hangi bitini görüntülemesini görebilirsiniz.
yukarıdaki koddaki ViewData["Title"] = "Movie List"; , ViewData sözlüğün Title özelliğini "film listesi"
olarak ayarlar. Title özelliği, Düzen sayfasındaki <title> HTML öğesinde kullanılır:

<title>@ViewData["Title"] - Movie App</title>

Değişikliği kaydedin ve https://localhost:{PORT}/HelloWorld gidin. Tarayıcı başlığı, birincil başlık ve ikincil


başlıkların değiştirildiğini unutmayın. (Tarayıcıda değişiklik görmüyorsanız, önbelleğe alınmış içeriği
görüntülüyor olabilirsiniz. Sunucudan gelen yanıtı zorlamak için tarayıcınızda CTRL + F5 tuşlarına basın.)
Tarayıcı başlığı, Index. cshtml görünüm şablonunda belirlediğimiz ViewData["Title"] ve düzen dosyasına
eklenen ek "-film uygulaması" ile oluşturulur.
Ayrıca, Index. cshtml görünüm şablonundaki içeriğin Görünümler/paylaşılan/_Layout. cshtml görünüm
şablonuyla nasıl birleştirildiğini ve tarayıcıya tek bir HTML yanıtı gönderildiğini de unutmayın. Düzen
şablonları, uygulamanızdaki tüm sayfalara uygulanan değişiklikler yapmayı gerçekten kolaylaştırır. Daha fazla
bilgi için bkz. Düzen.

"Data" (Bu durumda "Görünümümüzden Merhaba!") çok az. ileti) sabit kodludur, ancak. MVC uygulamasında
bir "V" (görünüm) var ve bir "C" (denetleyici) var, ancak henüz "M" (model) yok.

Denetleyiciden görünüme veri geçirme


Gelen URL isteğine yanıt olarak denetleyici eylemleri çağrılır. Bir denetleyici sınıfı, gelen tarayıcı isteklerini
işleyen kodun yazıldığı yerdir. Denetleyici verileri bir veri kaynağından alır ve tarayıcıya ne tür bir yanıt
gönderileceğini belirler. Görünüm şablonları bir denetleyiciden, tarayıcıya HTML yanıtı oluşturmak ve
biçimlendirmek için kullanılabilir.
Bir görünüm şablonunun yanıt işlemesi için gereken verileri sağlamaktan denetleyiciler sorumludur. En iyi
yöntem: Görünüm şablonları iş mantığı gerçekleştirmemelidir veya doğrudan bir veritabanıyla etkileşime
girmemelidir. Bunun yerine, bir görünüm şablonu yalnızca denetleyici tarafından sunulan verilerle birlikte
çalışmalıdır. Bu "kaygıları ayrımı", kodun temiz, test edilebilir ve sürdürülebilir kalmasına yardımcı olur.
Şu anda, HelloWorldController sınıfındaki Welcome yöntemi bir name ve ID parametresi alır ve sonra
değerleri doğrudan tarayıcıya çıkarır. Denetleyicinin bu yanıtı bir dize olarak işlemesini sağlamak yerine,
denetleyiciyi bir görünüm şablonu kullanacak şekilde değiştirin. Görünüm şablonu dinamik bir yanıt üretir, bu,
yanıtı oluşturmak için denetleyiciden görünüme uygun veri bitlerinin geçirilmesi gereken anlamına gelir. Bu,
denetleyicinin görünüm şablonu tarafından daha sonra erişebileceği bir ViewData sözlüğünde bulunan
dinamik verileri (parametreler) yerleştirerek bunu yapın.
HelloWorldController.cs' de, ViewData sözlüğüne bir Message ve NumTimes değeri eklemek için Welcome
yöntemini değiştirin. ViewData sözlüğü dinamik bir nesnedir, yani herhangi bir tür kullanılabilir; ViewData
nesnenin içine bir öğe yerleştirene kadar tanımlanmış özellikleri yok. MVC modeli bağlama sistemi ,
adlandırılmış parametreleri ( name ve numTimes ), adres çubuğundaki sorgu dizesinden yöntemdeki
parametrelere otomatik olarak eşler. Tüm HelloWorldController.cs dosyası şuna benzer:

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Welcome(string name, int numTimes = 1)


{
ViewData["Message"] = "Hello " + name;
ViewData["NumTimes"] = numTimes;

return View();
}
}
}

ViewData Dictionary nesnesi görünüme geçirilecek verileri içerir.


Görünümler/HelloWorld/Welcome. cshtmladlı bir hoş geldiniz görünüm şablonu oluşturun.
Welcome. cshtml görünüm şablonunda "Hello" NumTimes görüntüleyen bir döngü oluşturacaksınız.
Views/HelloWorld/Welcome. cshtml içeriğini aşağıdakiler ile değiştirin:

@{
ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
@for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
{
<li>@ViewData["Message"]</li>
}
</ul>

Değişikliklerinizi kaydedin ve aşağıdaki URL 'ye gidin:


https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

Veriler URL 'den alınır ve MVC model Bağlayıcısı kullanılarak denetleyiciye geçirilir. Denetleyici, verileri bir
ViewData sözlüğüne paketler ve bu nesneyi görünüme geçirir. Daha sonra Görünüm, verileri tarayıcıda
HTML olarak işler.
Yukarıdaki örnekte ViewData sözlüğü denetleyiciden bir görünüme veri geçirmek için kullanılmıştır.
Öğreticide daha sonra bir görünüm modeli, bir denetleyicideki verileri bir görünüme geçirmek için kullanılır.
Veri geçirme yaklaşımına yönelik görünüm modeli, ViewData sözlük yaklaşımına göre genel olarak çok tercih
edilir. Daha fazla bilgi için bkz. ViewBag, ViewData veya TempData kullanma .
Sonraki öğreticide, bir film veritabanı oluşturulur.

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına model ekleme
23.11.2019 • 43 minutes to read • Edit Online

Rick Anderson ve Tom Dykstra tarafından


Bu bölümde, bir veritabanında film yönetmeye yönelik sınıflar eklersiniz. Bu sınıflar, dVC uygulamasının
"dodel" parçası olacaktır.
Bu sınıfları bir veritabanıyla çalışmak için Entity Framework Core (EF Core) ile birlikte kullanırsınız. EF Core,
yazmanız gereken veri erişim kodunu kolaylaştıran bir nesne ilişkisel eşleme (ORM ) çerçevesidir.
Oluşturduğunuz model sınıfları, EF Core hiçbir bağımlılığı olmadığından, POCO sınıfları olarak bilinir ( PLain
O ). Yalnızca veritabanında depolanacak verilerin özelliklerini tanımlar.
Bu öğreticide, önce model sınıflarını yazdığınızda EF Core veritabanını oluşturur. Burada kapsanmayan
alternatif bir yaklaşım var olan bir veritabanından model sınıfları oluşturmaktır. Bu yaklaşım hakkında daha
fazla bilgi için bkz. ASP.NET Core-var olan veritabanı.

Veri modeli sınıfı ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
> sınıf eklemek > modeller klasörüne sağ tıklayın. Dosyayı Movie.csolarak adlandırın.
Movie.cs dosyasını aşağıdaki kodla güncelleştirin:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie sınıfı, birincil anahtar için veritabanı için gerekli olan bir Id alanı içerir.
ReleaseDate veri türü özniteliği, verilerin türünü belirtir ( Date ). Bu öznitelikle:
Kullanıcının Tarih alanına saat bilgilerini girmesi gerekli değildir.
Zaman bilgisi değil yalnızca tarih görüntülenir.
Veri açıklamaları sonraki bir öğreticide ele alınmıştır.

NuGet paketleri Ekle


Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.

PMC 'de şu komutu çalıştırın:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Yukarıdaki komut, EF Core SQL Server sağlayıcısını ekler. Sağlayıcı paketi, EF Core paketini bir bağımlılık
olarak yüklüyor. Ek paketler, öğreticinin sonraki bölümlerinde bulunan yapı iskelesi adımında otomatik olarak
yüklenir.

Veritabanı bağlamı sınıfı oluşturma


Movie modeli için EF Core işlevselliği (oluşturma, okuma, güncelleştirme, silme) koordine etmek için bir
veritabanı bağlamı sınıfı gerekir. Veritabanı bağlamı Microsoft. EntityFrameworkCore. DbContext öğesinden
türetilir ve veri modeline dahil edilecek varlıkları belirtir.
Bir veri klasörü oluşturun.
Aşağıdaki kodla bir Data/MvcMovieContext. cs dosyası ekleyin:

using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;

namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}

public DbSet<Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.

Veritabanı bağlamı Kaydet


ASP.NET Core, bağımlılık ekleme (dı)ile oluşturulmuştur. Hizmetlerin (EF Core DB bağlamı gibi) uygulama
başlatma sırasında DI ile kayıtlı olması gerekir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu
hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin
ilerleyen bölümlerinde gösterilmektedir. Bu bölümde, veritabanı bağlamını dı kapsayıcısına kaydedersiniz.
Aşağıdaki using deyimlerini Startup.csüst kısmına ekleyin:

using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;

Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:


Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddControllersWithViews();

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.

Veritabanı bağlantı dizesi Ekle


AppSettings. JSON dosyasına bir bağlantı dizesi ekleyin:
Visual Studio
Visual Studio Code/Mac için Visual Studio

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Projeyi derleyici hatalarına yönelik bir denetim olarak derleyin.

Yapı iskelesi film sayfaları


Film modeli için oluşturma, okuma, güncelleştirme ve silme (CRUD ) sayfaları üretmek için scafkatlama aracını
kullanın.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler klasörüne sağ tıklayıp yeni > yapı iskelesi > öğesi ekleyin.

Yapı Ekle iletişim kutusunda, Entity Framework > Ekle ' yi kullanarak views ile MVC denetleyicisi ' ni
seçin.

Denetleyici Ekle iletişim kutusunu doldurun:


Model sınıfı: Film (mvcmovie. modeller )
Veri bağlamı sınıfı: mvcmoviecontext (mvcmovie. Data )

Görünümler: Her seçeneğin varsayılan kısmını işaretli tut


Denetleyici adı: Varsayılan MoviesController tut
Ekle 'yi seçin
Visual Studio şunları oluşturur:
Bir filmler denetleyicisi (denetleyiciler/MoviesController. cs)
Razor oluşturma, silme, ayrıntılar, düzenleme ve dizin sayfaları için dosyaları görüntüleme
(Görünümler/filmler/*. cshtml)

Bu dosyaların otomatik olarak oluşturulması, Yapı iskelesiolarak bilinir.


Veritabanı mevcut olmadığından, scafkatmış sayfaları henüz kullanamazsınız. Uygulamayı çalıştırır ve film
uygulaması bağlantısına tıklarsanız, bir veritabanı açılamıyor veya böyle bir tablo yok: film hata iletisi.

İlk geçiş
Veritabanını oluşturmak için EF Core geçişleri özelliğini kullanın. Geçişler, veri modelinizle eşleşecek bir
veritabanı oluşturmanıza ve güncelleştirmenize olanak sağlayan bir araç kümesidir.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.
PMC'de aşağıdaki komutları girin:

Add-Migration InitialCreate
Update-Database

Add-Migration InitialCreate : bir geçişler/{timestamp } _InitialCreate. cs geçiş dosyası oluşturuyor.


InitialCreate bağımsız değişkeni geçiş adıdır. Herhangi bir ad kullanılabilir, ancak kurala göre, geçişi
açıklayan bir ad seçilidir. Bu ilk geçiş olduğundan, oluşturulan sınıf veritabanı şemasını oluşturmak için
kod içerir. Veritabanı şeması, MvcMovieContext sınıfında belirtilen modeli temel alır.
Update-Database : veritabanını, önceki komutun oluşturulduğu en son geçişe güncelleştirir. Bu komut,
veritabanını oluşturan geçişler/{Time-damga } _InitialCreate. cs dosyasında Up yöntemini çalıştırır.
Database Update komutu aşağıdaki uyarıyı üretir:

' Movie ' varlık türündeki ' Price ' ondalık sütunu için tür belirtilmedi. Bu, varsayılan duyarlık ve
ölçeğe uygun olmadıkları takdirde değerlerin sessizce kesilmesine neden olur. ' Hasccolumntype () '
kullanarak tüm değerleri barındırabilecek SQL Server sütun türünü açıkça belirtin.

Bu uyarıyı yoksayabilirsiniz, daha sonraki bir öğreticide düzeltilecektir.


EF Core için PMC araçları hakkında daha fazla bilgi için bkz. Visual Studio 'da EF Core araçları başvurusu-
PMC.
Initialcreate sınıfı
Geçişleri/{timestamp } _InitialCreate. cs geçiş dosyasını inceleyin:

public partial class Initial : Migration


{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Title = table.Column<string>(nullable: true),
ReleaseDate = table.Column<DateTime>(nullable: false),
Genre = table.Column<string>(nullable: true),
Price = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}

protected override void Down(MigrationBuilder migrationBuilder)


{
migrationBuilder.DropTable(
name: "Movie");
}
}

Up yöntemi, film tablosunu oluşturur ve Id birincil anahtar olarak yapılandırır. Down yöntemi, Up geçişi
tarafından yapılan şema değişikliklerini geri alır.

Uygulamayı test etme


Uygulamayı çalıştırın ve film uygulaması bağlantısına tıklayın.
Aşağıdakilerden birine benzer bir özel durum alırsanız:
Visual Studio
Visual Studio Code/Mac için Visual Studio

SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Muhtemelen geçişler adımınıkaçırdınız.
Oluştur sayfasını test edin. Veri girin ve gönderebilirsiniz.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül
İngilizce olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer
gerekir. Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Düzenleme, Ayrıntılarve silme sayfalarını test edin.

Denetleyiciye bağımlılık ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
Controllers/MoviesController. cs dosyasını açın ve oluşturucuyu inceleyin:

public class MoviesController : Controller


{
private readonly MvcMovieContext _context;

public MoviesController(MvcMovieContext context)


{
_context = context;
}

Oluşturucu, veritabanı bağlamını ( MvcMovieContext ) denetleyiciye eklemek için bağımlılık ekleme işlemini
kullanır. Her bir veritabanı bağlamı kullanılan CRUD denetleyici yöntemleri.

Türü kesin belirlenmiş modeller ve @model anahtar sözcüğü


Bu öğreticide daha önce, bir denetleyicinin ViewData sözlüğünü kullanarak bir görünüme nasıl veri veya nesne
geçirekullanabileceğinizi gördünüz. ViewData sözlüğü bir görünüme bilgi geçirmek için uygun, geç bağlanan
bir yol sağlayan dinamik bir nesnedir.
MVC Ayrıca, kesin olarak belirlenmiş model nesnelerini bir görünüme geçirmeye olanak tanır. Bu kesin türü
belirtilmiş yaklaşım derleme zamanı kodu denetimini sunar. Yapı iskelesi mekanizması, MoviesController sınıfı
ve görünümleriyle bu yaklaşımı (türü kesin belirlenmiş bir modeli geçirerek) kullandı.
Controllers/MoviesController. cs dosyasında oluşturulan Details yöntemini inceleyin:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

id parametresi genellikle rota verileri olarak geçirilir. Örneğin https://localhost:5001/movies/details/1


kümeler:
movies denetleyicisine denetleyici (ilk URL segmenti).
details eylemi (ikinci URL segmenti).
Kimliği 1 ' e (son URL segmenti).
Aşağıdaki gibi bir sorgu dizesiyle id de geçirebilirsiniz:
https://localhost:5001/movies/details?id=1

KIMLIK değeri sağlanmazsa id parametresi null yapılabilir bir tür ( int? ) olarak tanımlanır.
Bir lambda ifadesi , rota verileriyle veya sorgu dizesi değeriyle eşleşen film varlıklarını seçmek üzere
FirstOrDefaultAsync ' A geçirilir.

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);

Bir film bulunursa, Movie modelinin bir örneği Details görünümüne geçirilir:

return View(movie);

Görünümler/filmler/ayrıntılar. cshtml dosyasının içeriğini inceleyin:


@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Movie</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Genre)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Görünüm dosyasının en üstündeki @model ifade, görünümün beklediği nesne türünü belirtir. Film denetleyicisi
oluşturulduğunda, aşağıdaki @model deyimleri eklenmiştir:

@model MvcMovie.Models.Movie

Bu @model yönergesi, denetleyicinin görünüme geçirildiği filme erişimine izin verir. Model nesne kesin olarak
belirlenmiş. Örneğin, details. cshtml görünümünde, kod her bir film alanını DisplayNameFor DisplayFor ve
HTML yardımcılarını türü kesin belirlenmiş Model nesnesiyle geçirir. Create ve Edit yöntemleri ve
görünümleri bir Movie model nesnesi de iletir.
Dizin. cshtml görünümünü ve film denetleyicisindeki Index yöntemini inceleyin. List , View yöntemini
çağırdığında kodun bir nesne nasıl oluşturduğunu fark edin. Kod, Index eylem yönteminden bu Movies
listesini görünüme geçirir:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}

Film denetleyicisi oluşturulduğunda, yapı iskelesi Index. cshtml dosyasının en üstüne aşağıdaki @model
ifadesini içeriyordu:

@model IEnumerable<MvcMovie.Models.Movie>

@model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak, denetleyicinin görünüme geçirildiği
film listesine erişmenizi sağlar. Örneğin, Index. cshtml görünümünde, kod kesin türü belirtilmiş Model nesnesi
üzerinde foreach bir ifadesiyle filmlerle döngü yapılır:
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Model nesne kesin olarak yazıldığı için (bir IEnumerable<Movie> nesnesi olarak), döngüdeki her öğe Movie
olarak yazılır. Diğer avantajların yanı sıra, kodu derleme zaman denetimini alacağınız anlamına gelir.

Ek kaynaklar
Etiket Yardımcıları
Genelleştirme ve yerelleştirme
Daha Ö N C E B IR G Ö R Ü N Ü M D A H A S O N R A S Q L IL E
EKLEM E Ç A L IŞ M A

Veri modeli sınıfı ekleme


Visual Studio
Visual Studio Code/Mac için Visual Studio
> sınıf eklemek > modeller klasörüne sağ tıklayın. Sınıf adı film.
Aşağıdaki özellikleri Movie sınıfı:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}

Movie Sınıfı içerir:


Id Alanı ve veritabanı için birincil anahtarı gereklidir.
[DataType(DataType.Date)] : DataType özniteliği veri türünü belirtir ( Date ). Bu öznitelik ile:
Kullanıcının tarih alanı saat bilgilerini girmek için gerekli değildir.
Yalnızca tarih görüntülenen, olmayan zaman bilgilerdir.
DataAnnotations bir sonraki öğreticide ele alınmaktadır.

Film modeli iskelesini


Bu bölümde, film modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için oluşturma, okuma,
güncelleştirme ve silme (CRUD ) işlemlerine yönelik film modeli oluşturur.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, denetleyiciler klasörüne sağ tıklayıp yeni > yapı iskelesi > öğesi ekleyin.
Yapı Ekle iletişim kutusunda, Entity Framework > Ekle ' yi kullanarak views ile MVC denetleyicisi ' ni
seçin.

Denetleyici Ekle iletişim kutusunu doldurun:


Model sınıfı: Film (mvcmovie. modeller )
Veri bağlamı sınıfı: + simgesini seçin ve varsayılan Mvcmovie. modeller. MvcMovieContext öğesini
ekleyin
Görünümler: Her seçeneğin varsayılan kısmını işaretli tut
Denetleyici adı: Varsayılan MoviesController tut
Ekle 'yi seçin

Visual Studio şunları oluşturur:


Entity Framework Core veritabanı bağlam sınıfı (Data/MvcMovieContext. cs)
Bir filmler denetleyicisi (denetleyiciler/MoviesController. cs)
Razor oluşturma, silme, ayrıntılar, düzenleme ve dizin sayfaları için dosyaları görüntüleme
(Görünümler/filmler/*. cshtml)

Veritabanı bağlamı ve CRUD (oluşturma, okuma, güncelleştirme ve silme) eylem yöntemlerinin ve


görünümlerinin otomatik olarak oluşturulması, Yapı iskelesiolarak bilinir.
Uygulamayı çalıştırır ve MVC filmi bağlantısına tıklarsanız aşağıdakine benzer bir hata alırsınız:
Visual Studio
Visual Studio Code/Mac için Visual Studio
An unhandled exception occurred while processing the request.

SqlException: Cannot open database "MvcMovieContext-<GUID removed>" requested by the login. The login
failed.
Login failed for user 'Rick'.

System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity,
SqlConnectionString

Veritabanını oluşturmanız ve bunu yapmak için EF Core geçişleri özelliğini kullanmanız gerekir. Geçişler veri
modelinize uyan bir veritabanı oluşturmanıza ve veri modeliniz değiştiğinde veritabanı şemasını
güncelleştirmenize olanak tanır.

İlk geçiş
Bu bölümde, aşağıdaki görevler tamamlanır:
Bir başlangıç geçiş ekleyin.
Veritabanı, ilk geçiş ile güncelleştirin.
Visual Studio
Visual Studio Code/Mac için Visual Studio
1. Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu (PMC ) öğesini seçin.

2. PMC'de aşağıdaki komutları girin:

Add-Migration Initial
Update-Database

Add-Migration Komut, ilk veritabanı şeması oluşturmak için kod oluşturur.


Veritabanı şeması, MvcMovieContext sınıfında belirtilen modeli temel alır. Initial bağımsız değişkeni
geçiş adıdır. Herhangi bir ad kullanılabilir, ancak kurala göre, geçişi açıklayan bir ad kullanılır.Daha fazla
bilgi için bkz. Öğretici: EF Core ile geçiş özelliğini kullanma-ASP.NET MVC.
Update-Database Komutu çalıştırmaları Up yöntemi geçişleri / {zaman damgası} _InitialCreate.cs
dosyasını veritabanı oluşturur.
Bağımlılık ekleme ile kayıtlı bağlamını İnceleme
ASP.NET Core, bağımlılık ekleme (dı)ile oluşturulmuştur. Hizmetler (EF Core DB bağlamı gibi) uygulama
başlatma sırasında dı ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları) gerektiren bileşenler bu hizmetler
Oluşturucu parametresi üzerinden sağlanır. Bir DB bağlamı örneği alır Oluşturucu kodu öğreticinin ilerleyen
bölümlerinde gösterilmektedir.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Scafkatlama aracı otomatik olarak bir DB bağlamı oluşturup dı kapsayıcısına kaydetti.
Aşağıdaki Startup.ConfigureServices yöntemini inceleyin. Vurgulanan satırı iskele kurucu tarafından eklendi:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

MvcMovieContext EF Core işlevleri (oluşturma, okuma, güncelleştirme, silme, vb.) için koordinatları Movie
modeli. Veri bağlamı ( MvcMovieContext ) türetilir Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı, veri
modeline hangi varlıkların ekleneceğini belirtir:

// Unused usings removed.


using Microsoft.EntityFrameworkCore;
using MvcMovie.Models; // Enables public DbSet<Movie> Movie

namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}

public DbSet<Movie> Movie { get; set; }


}
}

Önceki kod, varlık kümesi için bir Dbset<filmi > özelliği oluşturur. Entity Framework terminolojisinde, bir varlık
kümesini genellikle bir veritabanı tablosuna karşılık gelir. Bir varlık tablosunda bir satıra karşılık gelir.
Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne. Yerel
geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json dosya.
Uygulamayı test etme
Uygulamayı çalıştırın ve ekleme /Movies tarayıcıda URL'sine ( http://localhost:port/movies ).
Aşağıdakine benzer bir veritabanı özel durumu alırsanız:

SqlException: Cannot open database "MvcMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Eksik geçişler adım.


Test Oluştur bağlantı. Veri girin ve gönderebilirsiniz.

NOTE
Ondalık virgül kullanımı girmeniz mümkün olmayabilir Price alan. Desteklemek için jQuery doğrulama virgül
İngilizce olmayan yerel (",") bir ondalık noktasının ve ABD İngilizce olmayan tarih biçimleri, uygulamayı Eğer
gerekir. Genelleştirme hakkında yönergeler için bkz. bu GitHub sorunu.

Test Düzenle, ayrıntıları, ve Sil bağlantıları.


Startup sınıfını inceleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Önceki vurgulanan kod, bağımlılık ekleme kapsayıcısına eklenen film veritabanı bağlamını gösterir:
services.AddDbContext<MvcMovieContext>(options => kullanılacak veritabanını ve bağlantı dizesini belirtir.
=> lambda operatörü

Controllers/MoviesController. cs dosyasını açın ve oluşturucuyu inceleyin:

public class MoviesController : Controller


{
private readonly MvcMovieContext _context;

public MoviesController(MvcMovieContext context)


{
_context = context;
}

Oluşturucu, veritabanı bağlamını ( MvcMovieContext ) denetleyiciye eklemek için bağımlılık ekleme işlemini
kullanır. Her bir veritabanı bağlamı kullanılan CRUD denetleyici yöntemleri.

Türü kesin belirlenmiş modeller ve @model anahtar sözcüğü


Bu öğreticide daha önce, bir denetleyicinin ViewData sözlüğünü kullanarak bir görünüme nasıl veri veya nesne
geçirekullanabileceğinizi gördünüz. ViewData sözlüğü bir görünüme bilgi geçirmek için uygun, geç bağlanan
bir yol sağlayan dinamik bir nesnedir.
MVC Ayrıca, kesin olarak belirlenmiş model nesnelerini bir görünüme geçirmeye olanak tanır. Bu kesin türü
belirtilmiş yaklaşım, kodunuzun daha iyi derleme zaman denetimini sunar. Yapı iskelesi mekanizması, yöntem
ve görünümleri oluştururken MoviesController sınıfı ve görünümleriyle bu yaklaşımı (türü kesin belirlenmiş
bir model geçirme) kullanır.
Controllers/MoviesController. cs dosyasında oluşturulan Details yöntemini inceleyin:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

id parametresi genellikle rota verileri olarak geçirilir. Örneğin https://localhost:5001/movies/details/1


kümeler:
movies denetleyicisine denetleyici (ilk URL segmenti).
details eylemi (ikinci URL segmenti).
Kimliği 1 ' e (son URL segmenti).
Aşağıdaki gibi bir sorgu dizesiyle id de geçirebilirsiniz:
https://localhost:5001/movies/details?id=1

KIMLIK değeri sağlanmazsa id parametresi null yapılabilir bir tür ( int? ) olarak tanımlanır.
Bir lambda ifadesi , rota verileriyle veya sorgu dizesi değeriyle eşleşen film varlıklarını seçmek üzere
FirstOrDefaultAsync ' A geçirilir.

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);

Bir film bulunursa, Movie modelinin bir örneği Details görünümüne geçirilir:

return View(movie);

Görünümler/filmler/ayrıntılar. cshtml dosyasının içeriğini inceleyin:


@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Movie</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.ReleaseDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.ReleaseDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Genre)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Genre)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Görünüm dosyasının üst kısmına bir @model ifadesini ekleyerek, görünümün beklediği nesne türünü
belirtebilirsiniz. Film denetleyicisini oluştururken, Ayrıntılar. cshtml dosyasının en üstüne aşağıdaki @model
deyimleri otomatik olarak eklenmiştir:

@model MvcMovie.Models.Movie

Bu @model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak denetleyicinin görünüme
geçirildiği filme erişmenizi sağlar. Örneğin, details. cshtml görünümünde, kod her bir film alanını
DisplayNameFor DisplayFor ve HTML yardımcılarını türü kesin belirlenmiş Model nesnesiyle geçirir. Create
ve Edit yöntemleri ve görünümleri bir Movie model nesnesi de iletir.
Dizin. cshtml görünümünü ve film denetleyicisindeki Index yöntemini inceleyin. List , View yöntemini
çağırdığında kodun bir nesne nasıl oluşturduğunu fark edin. Kod, Index eylem yönteminden bu Movies
listesini görünüme geçirir:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}

Film denetleyicisini oluştururken, yapı iskelesi Index. cshtml dosyasının en üstüne aşağıdaki @model ifadesini
otomatik olarak dahil edin:

@model IEnumerable<MvcMovie.Models.Movie>

@model yönergesi, kesin olarak belirlenmiş bir Model nesnesi kullanarak, denetleyicinin görünüme geçirildiği
film listesine erişmenizi sağlar. Örneğin, Index. cshtml görünümünde, kod kesin türü belirtilmiş Model nesnesi
üzerinde foreach bir ifadesiyle filmlerle döngü yapılır:
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Model nesne kesin olarak yazıldığı için (bir IEnumerable<Movie> nesnesi olarak), döngüdeki her öğe Movie
olarak yazılır. Diğer avantajların yanı sıra, kodun derleme zaman denetimini alacağınız anlamına gelir:

Ek kaynaklar
Etiket Yardımcıları
Genelleştirme ve yerelleştirme
Daha Ö N C E B IR G Ö R Ü N Ü M D A H A S O N R A S Q L IL E
EKLEM E Ç A L IŞ M A
ASP.NET Core 'de SQL ile çalışma
23.11.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


MvcMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini işler.
Veritabanı bağlamı, Startup.cs dosyasındaki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.AddControllersWithViews();

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON
dosyasından bağlantı dizesini alır:

"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
2;Trusted_Connection=True;MultipleActiveResultSets=true"
}

Uygulama bir test veya üretim sunucusuna dağıtıldığında, bağlantı dizesini bir üretim SQL Server ayarlamak
için bir ortam değişkeni kullanılabilir. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür.
LocalDB, isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan
olarak, LocalDB veritabanı C:/Users/{User } dizininde . mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.
Movie tablo > görünüm tasarımcısına sağ tıklayın
ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar ID adlı bir özellik
oluşturacak.
Movie tabloya sağ tıklayarak verileri görüntüleyin >
Veritabanının çekirdeğini oluşturma
Modeller klasöründe SeedData adlı yeni bir sınıf oluşturun. Oluşturulan kodu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MvcMovie.Data;
using System;
using System.Linq;

namespace MvcMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


Program.cs içeriğini aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MvcMovie.Data;
using MvcMovie.Models;
using System;

namespace MvcMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Uygulamayı test etme


Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya SSOX 'ten silme bağlantılarıyla
yapabilirsiniz.
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur ' a
dokunun

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 'e
basın
VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir.

ÖN CEKI İL E R I
Tarafından Rick Anderson
MvcMovieContext nesnesi veritabanına bağlanma ve Movie nesneleri veritabanı kayıtlarına eşleme görevini işler.
Veritabanı bağlamı, Startup.cs dosyasındaki ConfigureServices yönteminde bağımlılık ekleme kapsayıcısına
kaydedilir:
Visual Studio
Visual Studio Code/Mac için Visual Studio

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies
// is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

ASP.NET Core yapılandırma sistemi ConnectionString okur. Yerel geliştirme için, appSettings. JSON
dosyasından bağlantı dizesini alır:

"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-
2;Trusted_Connection=True;MultipleActiveResultSets=true"
}

Uygulamayı bir test veya üretim sunucusuna dağıtırken, bağlantı dizesini gerçek bir SQL Server ayarlamak için
bir ortam değişkeni veya başka bir yaklaşım kullanabilirsiniz. Daha fazla bilgi için bkz. yapılandırma .
Visual Studio
Visual Studio Code/Mac için Visual Studio

SQL Server Express LocalDB


LocalDB, program geliştirmeye yönelik SQL Server Express veritabanı altyapısının hafif bir sürümüdür.
LocalDB, isteğe bağlı olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan
olarak, LocalDB veritabanı C:/Users/{User } dizininde . mdf dosyaları oluşturur.
Görünüm menüsünden SQL Server Nesne Gezgini (ssox) öğesini açın.
Movie tablo > görünüm tasarımcısına sağ tıklayın
ID yanındaki anahtar simgesine göz önünde edin. Varsayılan olarak, EF birincil anahtar ID adlı bir özellik
oluşturacak.
Movie tabloya sağ tıklayarak verileri görüntüleyin >
Veritabanının çekirdeğini oluşturma
Modeller klasöründe SeedData adlı yeni bir sınıf oluşturun. Oluşturulan kodu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace MvcMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}

context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},

new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},

new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},

new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}

VERITABANıNDA herhangi bir film varsa, tohum başlatıcısı döner ve hiçbir film eklenmez.
if (context.Movie.Any())
{
return; // DB has been seeded.
}

Tohum başlatıcısı ekleme


Program.cs içeriğini aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
using MvcMovie;

namespace MvcMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<MvcMovieContext>();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

Uygulamayı test etme


Visual Studio
Visual Studio Code/Mac için Visual Studio
VERITABANıNDAKI tüm kayıtları silin. Bunu, tarayıcıda veya SSOX 'ten silme bağlantılarıyla
yapabilirsiniz.
Çekirdek yöntemin çalışması için uygulamayı başlamaya zorlayın ( Startup sınıfında yöntemleri çağırın).
Başlatmayı zorlamak için IIS Express durdurulup yeniden başlatılması gerekir. Bunu aşağıdaki
yaklaşımlardan biriyle yapabilirsiniz:
Bildirim alanında IIS Express sistem tepsisi simgesine sağ tıklayın ve Çıkış veya siteyi durdur ' a
dokunun

VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklama modunda çalıştırmak için F5 'e
basın
VS hata ayıklama modunda çalıştırıyorsanız, hata ayıklayıcıyı durdurun ve F5 tuşuna basın.
Uygulama, sağlanan verileri gösterir.

ÖN CEKI İL E R I
Denetleyici metotları ve görünümleri ASP.NET Core
11.07.2019 • 14 minutes to read • Edit Online

Tarafından Rick Anderson


Film uygulaması için iyi bir başlangıç sahibiz ancak sunu Örneğin, ideal olarak, değildir ReleaseDate iki
kelimeye olmalıdır.

Açık Models/Movie.cs dosya ve aşağıda vurgulanan satırları ekleyin:


using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
}
}

Biz karşılarız DataAnnotations sonraki öğreticide. Görüntüleme öznitelik adı (Bu durumda "ReleaseDate" yerine
"yayın tarihi") bir alan için görüntülenecek öğeleri belirtir. DataType öznitelik alanında depolanan saat bilgilerini
görüntülenmediğini şekilde (tarih), veri türünü belirtir.
[Column(TypeName = "decimal(18, 2)")] Veri ek açıklama, Entity Framework Core doğru şekilde eşleyebilirsiniz
biçimde gereklidir Price veritabanında para birimi. Daha fazla bilgi için veri türleri.
Gözat Movies denetleyicisi ve fare işaretçisini tutun bir Düzenle hedef URL'ye görmek için bağlantıyı.

Düzenle, ayrıntıları, ve Sil bağlantıları Core MVC yer işareti etiketi Yardımcısı tarafından üretilen
Views/Movies/Index.cshtml dosya.
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>

Etiket Yardımcıları, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun
katılmasını etkinleştir. Yukarıdaki kodda AnchorTagHelper dinamik olarak HTML oluşturan href denetleyici
eylem yöntemi ve rota kimliğinden öznitelik değeri. Kullandığınız kaynağı görüntüle sık kullandığınız
tarayıcıyı ya da kullanım oluşturulan biçimlendirme incelemek için geliştirici araçları. Oluşturulan HTML
değerinin bir bölümü aşağıda gösterilmiştir:

<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>

Biçim için geri çağırma yönlendirme kümesinde Startup.cs dosyası:

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

ASP.NET Core çevirir https://localhost:5001/Movies/Edit/4 bir istek halinde Edit eylem yöntemi Movies
denetleyicisi parametresiyle Id 4. (Denetleyici olarak da bilinen eylem yöntemleri yöntemlerdir.)
Etiket Yardımcıları ASP.NET Core en popüler yeni özellikler biridir. Daha fazla bilgi için ek kaynaklar.
Açık Movies denetleyicisi ve iki inceleyin Edit eylem yöntemleri. Aşağıdaki kodda gösterildiği HTTP GET Edit
film getirir ve tarafından oluşturulan düzenleme formu dolduran yöntemi Edit.cshtml Razor dosya.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.FindAsync(id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Aşağıdaki kodda gösterildiği HTTP POST Edit gönderilen film değerleri işleyen yöntemi:
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Aşağıdaki kodda gösterildiği HTTP POST Edit gönderilen film değerleri işleyen yöntemi:
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

[Bind] Özniteliktir karşı korumak için bir yol aşırı yayınlayarak. Özellikler yalnızca içermelidir [Bind]
değiştirmek istediğiniz özniteliği. Daha fazla bilgi için denetleyicinizin atlayarak nakil korumak. Viewmodel'lar
atlayarak önlemek için alternatif bir yaklaşım sağlar.
İkinci fark Edit eylem yöntemine öncesinde [HttpPost] özniteliği.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

HttpPost Özniteliği belirtir bu Edit yöntemi çağrılacak yalnızca için POST istekleri. Geçerli olabilir [HttpGet]
ilk özniteliği Düzenle yöntemi, ancak gerekli değildir çünkü [HttpGet] varsayılandır.
ValidateAntiForgeryToken Özniteliktir için kullanılan istek sahteciliğini önleme ve düzenleme görünümü
dosyasında oluşturulan bir sahteciliğe karşı koruma belirteci ile eşleştirilmiş (Views/Movies/Edit.cshtml).
Sahteciliğe karşı koruma belirteci ile düzenleme görünüm dosyası oluşturur Form etiketi Yardımcısı.

<form asp-action="Edit">

Form etiketi Yardımcısı eşleşmelidir gizli bir sahteciliğe karşı koruma belirteci oluşturan
[ValidateAntiForgeryToken] oluşturulan sahteciliğe karşı koruma belirtecine Edit denetleyici filmler yöntemi.
Daha fazla bilgi için istek sahteciliğinden koruma.
HttpGet Edit Yöntemi alır film ID parametresini arar Entity Framework kullanarak filmi FindAsync yöntemi
ve düzenleme görünümü seçili film döndürür. Bir filmi bulunamazsa NotFound (HTTP 404) döndürülür.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie.FindAsync(id);


if (movie == null)
{
return NotFound();
}
return View(movie);
}

Yapı iskelesi sistem düzenleme görünümü oluşturduğunuzda, onu incelenirken Movie sınıfı ve işlemek için
oluşturulan kodu <label> ve <input> sınıfın her bir özellik için öğeleri. Aşağıdaki örnek, Visual Studio yapı
iskelesi sistem tarafından oluşturulan düzenleme görünümünü gösterir:
@model MvcMovie.Models.Movie

@{
ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>

<div>
<a asp-action="Index">Back to List</a>
</div>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Şablonu Görüntüle nasıl olduğunu fark bir @model MvcMovie.Models.Movie deyimini dosyanın üst.
@model MvcMovie.Models.Movie Görünüm model görünüm şablonu türünde olmasını bekliyor belirtir Movie .
İskele kurulan kodu birkaç etiketi Yardımcısı yöntemleri HTML biçimlendirmeyi kolaylaştırmak için kullanır.
Etiket etiketi Yardımcısı ("Title", "ReleaseDate", "Tarzı" veya "Price") alanın adını görüntüler. Giriş etiketi
Yardımcısı bir HTML işleyen <input> öğesi. Doğrulama etiketi Yardımcısı bu özellikle ilişkili herhangi bir
doğrulama iletisi görüntüler.
Uygulamayı çalıştırmak ve gidin /Movies URL'si. ' A tıklayın bir Düzenle bağlantı. Tarayıcıda, sayfa için
kaynağı görüntüleyin. İçin oluşturulan HTML <form> öğesi aşağıda gösterilmektedir.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID"
name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-
replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price
must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-
replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-
MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

<input> Öğeler içinde bir HTML <form> öğesi olan action özniteliğinin ayarlanmış gönderinin yayımlanacağı
/Movies/Edit/id URL'si. Form verileri sunucuya yayımlanacak olduğunda Save düğmesine tıklandığında. Son
satırı kapatmadan önce </form> öğenin gizli gösterir XSRF tarafından oluşturulan belirteç Form etiketi
Yardımcısı.

POST isteğini işleme


Aşağıdaki liste gösterildiği [HttpPost] sürümünü Edit eylem yöntemi.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}

if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}

[ValidateAntiForgeryToken] Özniteliği gizli doğrular XSRF içinde sahteciliğe karşı koruma belirteci Oluşturucu
tarafından oluşturulan belirteç Form etiketi Yardımcısı
Model bağlama sistem gönderilen form değerlerini alır ve oluşturan bir Movie olarak geçirilen nesne movie
parametresi. ModelState.IsValid Yöntemi doğrular (düzenleme veya güncelleştirme) değiştirileceğini biçiminde
gönderilen veriler kullanılabilir bir Movie nesne. Veriler geçerliyse kaydedilir. Güncelleştirilmiş (düzenlenen)
film verileri çağırarak veritabanına kaydedilir SaveChangesAsync veritabanı bağlamının yöntemi. Verileri
kaydettikten sonra kodu kullanıcı için yönlendiren Index eylem yöntemi MoviesController yaptığınız
değişiklikleri içeren film koleksiyonu görüntüleyen sınıfı.
Form, sunucuya gönderilen önce istemci tarafı doğrulama alanlarda tüm doğrulama kurallarını denetler.
Herhangi bir doğrulama hatası varsa, bir hata iletisi görüntülenir ve form gönderilen değil. JavaScript devre dışı
bırakılırsa, istemci tarafı doğrulama olmaz ancak sunucu, geçerli olmayan gönderilen değerlerden algılar ve
form değerleri, hata iletileri ile yeniden. Öğreticinin ilerleyen bölümlerinde inceleyeceğiz Model doğrulama
daha ayrıntılı bir şekilde. Doğrulama etiketi Yardımcısı içinde Views/Movies/Edit.cshtml görünüm şablonu
uygun hata iletilerini görüntüleme üstlenir.
Tüm HttpGet film denetleyici yöntemleri benzer bir desen uygulayın. Bir film nesnesi aldıkları (veya
durumunda nesnelerin listesini Index ) ve ' % s'nesne (modeli) görünümüne geçirin. Create Boş film nesneye
yöntemi geçirir Create görünümü. Bu nedenle, oluşturmak, düzenlemek, silmek veya aksi halde verileri
değiştiren tüm yöntemler yapmak [HttpPost] yöntemi aşırı yüklemesi. Verileri değiştirme bir HTTP GET bir
güvenlik riski yöntemidir. Verileri değiştirme bir HTTP GET yöntemi de ihlal HTTP en iyi yöntemler ve mimari
REST desen, GET istekleri, uygulamanızın durumunu değiştirmemeniz belirtir. Diğer bir deyişle, bir GET işlemi
gerçekleştirilirken yan etkileri olan ve verilerinizi kalıcı değiştirmez güvenli bir işlem olmalıdır.

Ek kaynaklar
Genelleştirme ve yerelleştirme
Etiket Yardımcıları giriş
Yazma etiketi Yardımcıları
İstek Sahteciliğinden Koruma
Denetleyicinizden korumak aşırı gönderme
Viewmodel'lar
Form Etiketi Yardımcısı
Giriş Etiketi Yardımcısı
Etiket Etiketi Yardımcısı
Seçim Etiketi Yardımcısı
Doğrulama etiketi Yardımcısı

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına arama ekleme
13.08.2019 • 10 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde, film metoduna tarz veya adagöre arama Index özelliği ekleyebilirsiniz.
Controllers/MoviesController. cs içinde bulunan yöntemiaşağıdakikodlagüncelleştirin: Index

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}

Index Eylem yönteminin ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

var movies = from m in _context.Movie


select m;

Sorgu yalnızca bu noktada tanımlanmış, veritabanında çalıştırılmadı.


searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtrelenecek şekilde
değiştirilir:

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

Yukarıdaki kod bir lambda ifadesidir. s => s.Title.Contains() Lambdalar, Yöntem tabanlı LINQ sorgularında
WHERE yöntemi veya Contains (Yukarıdaki kodda kullanılan) gibi standart sorgu işleci yöntemlerine bağımsız
değişkenler olarak kullanılır. LINQ sorguları tanımlandıklarında veya Where , Contains ya OrderBy da gibi bir
yöntem çağırarak değiştirildiklerinde yürütülmez. Bunun yerine sorgu yürütmesi ertelenir. Diğer bir deyişle, bir
ifadenin değerlendirmesi, gerçekleştirilmiş değeri gerçekten yineleneceği veya ToListAsync Yöntem çağrılana
kadar geciktirilen anlamına gelir. Ertelenmiş sorgu yürütme hakkında daha fazla bilgi için bkz. sorgu yürütme.
Not: Contains yöntemi yukarıda gösterilen c# kodunda değil, veritabanında çalıştırılır. Sorgudaki büyük/küçük
harf duyarlılığı veritabanına ve harmanlamaya bağlıdır. SQL Server üzerinde SQL gibieşlemeler içerir ,
büyük/küçük harfe duyarsız olur. SQLite ' da, varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.
/Movies/Index sayfasına gidin. URL 'ye gibi ?searchString=Ghost bir sorgu dizesi ekleyin. Filtrelenmiş filmler
görüntülenir.
Index Yönteminin imzasını adlı id bir parametreye sahip olacak şekilde değiştirirseniz, id parametresi
Startup.csiçinde ayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuya eşleşir.

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Parametresini id ve searchString değişikliğin tümoluşumlarınıolarakdeğiştirin. id


Önceki Index Yöntem:

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}

Parametresi ile Index id güncelleştirilmiş Yöntem:


public async Task<IActionResult> Index(string id)
{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title.Contains(id));
}

return View(await movies.ToListAsync());


}

Artık arama başlığını sorgu dizesi değeri yerine rota verileri (bir URL segmenti) olarak geçirebilirsiniz.

Ancak, kullanıcıların bir filmi her arayışınızda URL 'YI değiştirmesini beklemeniz gerekmez. Böylece, filmlerin
filtrelemesine yardımcı olmak için UI öğeleri ekleyeceğiz. Yol ile bağlantılı ID parametrenin nasıl geçirileceğini
test Index etmek için yönteminin imzasını değiştirdiyseniz, adlı searchString bir parametre alması için geri
değiştirin:

public async Task<IActionResult> Index(string searchString)


{
var movies = from m in _context.Movie
select m;

if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

return View(await movies.ToListAsync());


}
Views/filmler/Index. cshtml dosyasını açın ve aşağıda vurgulanan <form> biçimlendirmeyi ekleyin:

ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-action="Create">Create New</a>
</p>

<form asp-controller="Movies" asp-action="Index">


<p>
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>

HTML <form> etiketi, form etiketi yardımcısınıkullanır, bu nedenle formu gönderdiğinizde, filtre dizesi film
denetleyicisinin Index eylemine gönderilir. Değişikliklerinizi kaydedin ve sonra filtreyi test edin.

Bekleneceğiniz gibi [HttpPost] Index metodun aşırı yüklemesi yoktur. Bunun için gerekli değildir, çünkü
yöntem uygulamanın durumunu değiştirmediğinden verileri filtrelememeniz yeterlidir.
Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}

notUsed Parametresi , Index yöntemi için bir aşırı yükleme oluşturmak için kullanılır. Öğreticide daha sonra
konuşacağız.
Bu yöntemi eklerseniz, Invoker [HttpPost] Index yöntemi yöntemiyle eşleşir [HttpPost] Index ve yöntemi
aşağıdaki görüntüde gösterildiği gibi çalışır.

Ancak, bu [HttpPost] Index yöntemin bu sürümünü eklemeseniz bile, tümünün nasıl uygulandığını gösteren
bir sınırlama vardır. Belirli bir arama için yer işareti koymak istediğinizi veya aynı film filtrelenmiş listesini
görmek için onlara tıklabilecekleri bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL 'SI
GET isteğinin URL 'siyle (localhost: {PORT}/filmler/dizin) aynı olduğunu fark edin; URL 'de arama bilgisi yok.
Arama dizesi bilgileri sunucuya form alanı değeriolarak gönderilir. Tarayıcı geliştirici araçları veya harika Fiddler
aracınınolduğunu doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı geliştirici araçları gösterilmektedir:
Arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Bu şekilde, önceki öğreticide
bahsedildiği gibi, form etiketi Yardımcısı , bir XSRF Anti-forgery belirteci oluşturur. Verileri değiştiriyoruz, bu
nedenle denetleyiciyi denetleyici yönteminde doğrulamamız gerekmiyor.
Arama parametresi, URL değil, istek gövdesinde olduğundan, bu arama bilgilerini, yer işareti veya başkalarıyla
paylaşmak için yakalayamazsınız. İsteğin, HTTP GET Görünümler/filmler/Index. cshtml dosyasında bulunması
gerektiğini belirterek bunu düzeltemedi.
@model IEnumerable<MvcMovie.Models.Movie>

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)

Artık bir arama gönderdiğinizde, URL arama sorgu dizesini içerir. HttpGet Index Bir HttpPost Index yönteminiz
olsa da, arama eylem yöntemine de gidecektir.

Aşağıdaki biçimlendirme form etiketine olan değişikliği gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre arama Ekle


Aşağıdaki MovieGenreViewModel sınıfının modelleri klasörü:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
public List<Movie> Movies { get; set; }
public SelectList Genres { get; set; }
public string MovieGenre { get; set; }
public string SearchString { get; set; }
}
}

Film tarzı görünüm modeli şunları içerir:


Bir film listesi.
Tarzlar listesini içeren bir SelectList . Bu, kullanıcının listeden bir tarz seçmesine olanak sağlar.
MovieGenre , seçilen tarzı içeren.
SearchString , kullanıcılar arama metin kutusuna girdiğiniz metni içerir.

Index İçindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;

var movies = from m in _context.Movie


select m;

if (!string.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}

if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}

var movieGenreVM = new MovieGenreViewModel


{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};

return View(movieGenreVM);
}

Aşağıdaki kod, veritabanından tüm LINQ tarzları alan bir sorgudur.

// Use LINQ to get list of genres.


IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
SelectList Tarzlar ayrı tarzlar yansıtıyor (Select listenizin yinelenen tarzlar olmasını istemiyorum).
Kullanıcı öğeyi aradığında arama değeri arama kutusuna tutulur.

Tarzı, dizin görünümüne göre ara ekleme


Şu Index.cshtml şekilde görünümlerde/filmlerde bulunan güncelleştirme:
@model MvcMovie.Models.MovieGenreViewModel

@{
ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>

<select asp-for="MovieGenre" asp-items="Model.Genres">


<option value="">All</option>
</select>

Title: <input type="text" asp-for="SearchString" />


<input type="submit" value="Filter" />
</p>
</form>

<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Aşağıdaki HTML Yardımcısı 'nda kullanılan lambda ifadesini inceleyin:
@Html.DisplayNameFor(model => model.Movies[0].Title)

Yukarıdaki kodda, DisplayNameFor HTML Yardımcısı, görünen adı belirlemede Lambda Title ifadesinde
başvurulan özelliği inceler. Lambda model ifadesi değerlendirilmek yerine incelenebileceğinden,, model.Movies ,
veya model.Movies[0] null boş olduğunda bir erişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde
(örneğin, @Html.DisplayFor(modelItem => item.Title) ), modelin özellik değerleri değerlendirilir.
Türe göre, film başlığına göre ve her ikisine birden arayarak uygulamayı test edin:

ÖN CEKI İleri
ASP.NET Core MVC uygulamasına yeni bir alan
ekleme
23.11.2019 • 8 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde Entity Framework için Code First Migrations kullanılır:
Modele yeni bir alan ekleyin.
Yeni alanı veritabanına geçirin.
EF Code First otomatik olarak bir veritabanı oluşturmak için kullanıldığında, Code First:
Veritabanının şemasını izlemek için veritabanına tablo ekler.
Veritabanının oluşturulduğu model sınıflarıyla eşitlenmiş olduğunu doğrular. Bunlar eşitlenmiş değilse EF bir
özel durum oluşturur. Bu, tutarsız veritabanı/kod sorunlarını bulmayı kolaylaştırır.

Film modeline bir derecelendirme özelliği ekleyin


Modeller/film. cs' ye bir Rating özelliği ekleyin:

public class Movie


{
public int Id { get; set; }
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }

[Column(TypeName = "decimal(18, 2)")]


public decimal Price { get; set; }
public string Rating { get; set; }
}

Uygulama oluşturma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Ctrl+Shift+B
Movie sınıfına yeni bir alan eklediyseniz, bu yeni özellik dahil edilecek şekilde bağlama beyaz listesini
güncelleştirmeniz gerekir. MoviesController.cs' de, Rating özelliği dahil etmek için hem Create hem de Edit
eylem yöntemlerinin [Bind] özniteliğini güncelleştirin:

[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]

Yeni Rating özelliğini tarayıcı görünümünde görüntülemek, oluşturmak ve düzenlemek için görünüm
şablonlarını güncelleştirin.
/Views/movies/Index.cshtml dosyasını düzenleyin ve bir Rating alanı ekleyin:

<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Rating)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |

Bir Rating alanla /views/movies/Create.cshtml güncelleştirin.


Visual Studio/Mac için Visual Studio
Visual Studio Code
Önceki "form grubunu kopyalayabilir/yapıştırabilir" ve IntelliSense 'in alanları güncelleştirmenize yardımcı
olmasına izin verebilirsiniz. IntelliSense, Etiket Yardımcılarıile birlikte çalışmaktadır.
Kalan şablonları güncelleştirin.
SeedData sınıfını yeni sütun için bir değer sağlayacak şekilde güncelleştirin. Aşağıda örnek bir değişiklik
gösterilmektedir, ancak her bir new Movie için bu değişikliği yapmak isteyeceksiniz.

new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-1-11"),
Genre = "Romantic Comedy",
Rating = "R",
Price = 7.99M
},

VERITABANı yeni alanı içerecek şekilde güncelleştirilene kadar uygulama çalışmaz. Şimdi çalıştırıldığında,
aşağıdaki SqlException atılır:
SqlException: Invalid column name 'Rating'.

Bu hata, güncelleştirilmiş film modeli sınıfı varolan veritabanının film tablosunun şemasından farklı olduğu için
oluşur. (Veritabanı tablosunda Rating sütunu yoktur.)
Hatayı çözmek için birkaç yaklaşım vardır:
1. Entity Framework yeni model sınıfı şemasına göre otomatik olarak veritabanını bırakıp yeniden
oluşturmayı sağlayabilirsiniz. Bu yaklaşım, bir test veritabanı üzerinde etkin geliştirme yaparken geliştirme
döngüsünün başlarında çok daha kolay. modeli ve veritabanı şemasını birlikte hızla gelişmenize olanak
tanır. Bunun yanında, bu yaklaşımı bir üretim veritabanında kullanmak istemezsiniz, ancak bu,
veritabanında var olan verileri kaybetmeniz olur. Bir veritabanının test verileriyle otomatik olarak çekirdeği
oluşturmak için bir başlatıcı kullanılması, genellikle bir uygulama geliştirmenin üretken bir yoludur. Bu,
erken geliştirme ve SQLite kullanılırken iyi bir yaklaşımdır.
2. Mevcut veritabanının şemasını model sınıflarıyla eşleşecek şekilde açıkça değiştirin. Bu yaklaşımın
avantajı, verilerinizi tutmanızı kullanmaktır. Bu değişikliği el ile ya da bir veritabanı değişiklik betiği
oluşturarak yapabilirsiniz.
3. Veritabanı şemasını güncelleştirmek için Code First Migrations kullanın.
Bu öğretici için Code First Migrations kullanılır.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Araçlar menüsünde NuGet Paket Yöneticisi > Paket Yöneticisi konsolu' nu seçin.

PMC'de aşağıdaki komutları girin:

Add-Migration Rating
Update-Database

komutu, geçiş çerçevesinin geçerli Movie modelini geçerli Movie DB şemasıyla incelemesini ve
Add-Migration
VERITABANıNı yeni modele geçirmek için gerekli kodu oluşturmasını söyler.
"Derecelendirme" adı rastgele olur ve geçiş dosyasını adlandırmak için kullanılır. Geçiş dosyası için anlamlı bir ad
kullanılması yararlı olur.
VERITABANıNDAKI tüm kayıtlar silinirse, Initialize yöntemi VERITABANıNı temel alır ve Rating alanını içerir.
Uygulamayı çalıştırın ve bir Rating alanı ile film oluşturabileceğiniz/düzenleyebileceğiniz/görüntüleydiğinizi
doğrulayın. Edit , Details ve Delete görünüm şablonlarına Rating alanı eklemeniz gerekir.

ÖN CEKI İL E R I
ASP.NET Core MVC uygulamasına doğrulama
ekleme
23.11.2019 • 15 minutes to read • Edit Online

Tarafından Rick Anderson


Bu bölümde:
Doğrulama mantığı Movie modeline eklenir.
Bir Kullanıcı bir filmi oluşturduğunda veya düzenleişinizde doğrulama kurallarının uygulanmasını
sağlayabilirsiniz.

İşleri güncel tutma


MVC 'nin tasarımdan biri (" kendini tekrarlama"). ASP.NET Core MVC, işlevselliği veya davranışı yalnızca bir kez
belirtmenizi ve bir uygulamada her yerde yansıtıldığını önerir. Bu, yazmanız gereken kod miktarını azaltır ve daha
az hata yazmanızı, daha kolay test yapmayı ve bakımını daha kolay hale getirir.
MVC ve Entity Framework Core Code First tarafından sunulan doğrulama desteği, işlem içindeki kuru ilkeye
uygun bir örnektir. Doğrulama kurallarını tek bir yerde (model sınıfında) bildirimli olarak belirtebilir ve kurallar
uygulamada her yerde zorlanır.

Film modeline doğrulama kuralları ekleme


Dataaçıklamalarda ad alanı, bir sınıfa veya özelliğe bildirimli olarak uygulanan bir yerleşik doğrulama öznitelikleri
kümesi sağlar. Dataaçıklamalarda, biçimlendirme ile ilgili Yardım DataType ve herhangi bir doğrulama
sağlamayan gibi biçimlendirme öznitelikleri de bulunur.
Yerleşik Required , , RegularExpression vedoğrulama özniteliklerinden yararlanmak için sınıfıgüncelleştirin. Movie
StringLength Range
public class Movie
{
public int Id { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Title { get; set; }

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
[StringLength(5)]
[Required]
public string Rating { get; set; }
}

Doğrulama öznitelikleri, uygulanan model özellikleri üzerinde zorlamak istediğiniz davranışı belirtir:
Required Ve MinimumLength öznitelikleri bir özelliğin bir değere sahip olması gerektiğini belirtir; ancak
hiçbir şey, bir kullanıcının bu doğrulamayı karşılamak için boşluk girmesini engeller.
RegularExpression Öznitelik, hangi karakterlerin girişi yapabileceğini sınırlamak için kullanılır. Yukarıdaki
kodda, "tarz":
Yalnızca harfler kullanılmalıdır.
İlk harfin büyük harfle olması gerekir. Boşluk, sayı ve özel karakterlere izin verilmez.
RegularExpression "Derecelendirme":

İlk karakterin büyük harf olmasını gerektirir.


Sonraki boşlukların içindeki özel karakter ve sayılara izin verir. "PG -13" bir derecelendirme için
geçerlidir, ancak bir "tarz" için başarısız olur.
Range Özniteliği bir değeri belirtilen bir Aralık içinde kısıtlar.

StringLengthÖzniteliği, bir dize özelliğinin en büyük uzunluğunu ve isteğe bağlı olarak en düşük
uzunluğunu ayarlamanıza olanak sağlar.
Değer türleri (örneğin, decimal , int , float DateTime ), doğal olarak gereklidir ve [Required] özniteliğe
gerek kalmaz.
Doğrulama kurallarının otomatik olarak uygulanmasını ASP.NET Core uygulamanızın daha sağlam olmasına
yardımcı olur. Ayrıca, bir şeyi doğrulamayı unutmanızı ve veritabanına yanlışlıkla veri vermemesini de sağlar.

Doğrulama hatası Kullanıcı arabirimi


Uygulamayı çalıştırın ve filmler denetleyicisine gidin.
Yeni bir film eklemek için Yeni oluştur bağlantısına dokunun. Formu, bazı geçersiz değerlerle doldurun. JQuery
istemci tarafı doğrulaması hatayı algıladıktan hemen sonra bir hata iletisi görüntüler.
NOTE
Ondalık alanlara ondalık virgüller giremeyebilirsiniz. Ondalık bir nokta ve ABD Ingilizcesi olmayan tarih biçimleri için virgül
(",") kullanan Ingilizce olmayan yerel ayarlarda jQuery doğrulamasını desteklemek için, uygulamanızı globalize için adımlar
uygulamanız gerekir. Ondalık virgülden ekleme hakkında yönergeler için bkz. GitHub sorunu 4076 .

Formun, geçersiz bir değer içeren her bir alanda uygun bir doğrulama hata iletisini nasıl otomatik olarak
oluşturduğuna dikkat edin. Hatalar hem istemci tarafında (JavaScript ve jQuery kullanılarak) hem de sunucu
tarafında (kullanıcının JavaScript devre dışı bırakılmış olması durumunda) zorlanır.
Önemli bir avantaj, bu doğrulama kullanıcı arabirimini etkinleştirmek için MoviesController sınıfında veya
Create. cshtml görünümündeki tek bir kod satırını değiştirmeniz gerekmez. Bu öğreticide daha önce
oluşturduğunuz denetleyici ve görünümler, Movie model sınıfının özelliklerinde doğrulama özniteliklerini
kullanarak belirttiğiniz doğrulama kurallarını otomatik olarak çekti. Edit Action yöntemini kullanarak test
doğrulaması ve aynı doğrulama uygulanır.
Form verileri, istemci tarafı doğrulama hatası kalmayana kadar sunucuya gönderilmez. Bunu, Fiddler aracını veya
F12 geliştirici araçlarınıkullanarak HTTP Post yöntemine bir kesme noktası koyarak doğrulayabilirsiniz.

Doğrulamanın çalışması
Doğrulama Kullanıcı arabiriminin denetleyici veya görünümlerde kodda herhangi bir güncelleştirme yapmadan
nasıl oluşturulduğunu merak edebilirsiniz. Aşağıdaki kod iki Create yöntemini gösterir.

// GET: Movies/Create
public IActionResult Create()
{
return View();
}

// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("ID,Title,ReleaseDate,Genre,Price, Rating")] Movie movie)
{
if (ModelState.IsValid)
{
_context.Add(movie);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(movie);
}

İlk (HTTP GET) Create Action yöntemi ilk oluşturma formunu görüntüler. İkinci ( [HttpPost] ) sürüm, form
gönderisini işler. İkinci Create yöntemi ( [HttpPost] sürümü), filmin herhangi bir doğrulama hatası olup
olmadığını denetlemek için ModelState.IsValid çağırır. Bu yöntemi çağırmak, nesnesine uygulanmış olan tüm
doğrulama özniteliklerini değerlendirir. Nesnede doğrulama hataları varsa Create yöntemi formu yeniden
görüntüler. Hata yoksa, yöntemi yeni filmi veritabanına kaydeder. Film örneğimizde, istemci tarafında algılanan
doğrulama hataları olduğunda form sunucuya nakledilmez; istemci tarafı doğrulama hataları olduğunda ikinci
Create yöntemi hiçbir zaman çağrılmaz. Tarayıcınızda JavaScript 'i devre dışı bırakırsanız, istemci doğrulaması
devre dışıdır ve herhangi bir doğrulama hatasını tespit ModelState.IsValid HTTP POST Create yöntemini test
edebilirsiniz.
[HttpPost] Create yönteminde bir kesme noktası ayarlayabilir ve yöntemin hiçbir zaman çağrılmadığını
doğrulayabilirsiniz, doğrulama hataları algılandığında istemci tarafı doğrulaması form verilerini göndermez.
Tarayıcınızda JavaScript 'i devre dışı bırakır, ardından formu hatalarla gönderirseniz, kesme noktası isabet eder.
JavaScript olmadan tam doğrulama almaya devam edersiniz.
Aşağıdaki görüntüde, FireFox tarayıcısında JavaScript 'In nasıl devre dışı bırakılacağı gösterilmektedir.
Aşağıdaki görüntüde, Chrome tarayıcısında JavaScript 'In nasıl devre dışı bırakılacağı gösterilmektedir.

JavaScript 'i devre dışı bıraktıktan sonra, geçersiz veri gönderin ve hata ayıklayıcıda adım adım ilerleyin.
Create. cshtml görünüm şablonunun bölümü aşağıdaki biçimlendirmede gösterilmiştir:

<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>

@*Markup removed for brevity.*@

Yukarıdaki biçimlendirme eylem yöntemleri tarafından ilk formu görüntülemek ve bir hata durumunda onu
yeniden görüntülemek için kullanılır.
Giriş etiketi Yardımcısı , dataaçıklamaların özniteliklerini kullanır ve istemci tarafında jQuery doğrulaması için
gerekli HTML özniteliklerini üretir. Doğrulama etiketi Yardımcısı doğrulama hatalarını görüntüler. Daha fazla bilgi
için bkz. doğrulama .
Bu yaklaşım ne kadar iyi bir şeydir, denetleyicinin ne de Create görünüm şablonunun zorlanmakta olan gerçek
doğrulama kuralları ya da görüntülenen belirli hata iletileri hakkında herhangi bir şeyi biliyor olması önemlidir.
Doğrulama kuralları ve hata dizeleri yalnızca Movie sınıfında belirtilmiştir. Aynı doğrulama kuralları Edit
görünümüne ve modelinizi düzenleyebilecek oluşturabileceğiniz diğer tüm görünümler şablonlarına otomatik
olarak uygulanır.
Doğrulama mantığını değiştirmeniz gerektiğinde, modele doğrulama öznitelikleri ekleyerek tam olarak bir yerde
bunu yapabilirsiniz (Bu örnekte, Movie sınıfı). Kuralların nasıl zorlandığından, uygulamanın farklı bölümlerinin
tutarsız olması konusunda endişelenmeniz gerekmez; tüm doğrulama mantığı tek bir yerde tanımlanır ve her
yerde kullanılır. Bu, kodun temiz kalmasını sağlar ve bakımını ve gelişmesini kolaylaştırır. Ayrıca, KURULAMA
ilkesini tam olarak sunabileceksiniz anlamına gelir.

DataType özniteliklerini kullanma


Movie.cs dosyasını açın ve Movie sınıfını inceleyin. System.ComponentModel.DataAnnotations ad alanı, yerleşik
doğrulama öznitelikleri kümesine ek olarak biçimlendirme öznitelikleri sağlar. Yayın tarihine ve fiyat alanlarına
DataType bir numaralandırma değeri zaten uyguladık. Aşağıdaki kod, uygun DataType özniteliğiyle ReleaseDate
ve Price özelliklerini gösterir.

[Display(Name = "Release Date")]


[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

DataType öznitelikleri yalnızca görünüm altyapısının verileri biçimlendirmek için ipuçları sağlar (ve URL 'ler için
<a> gibi öğeleri/öznitelikleri ve e-posta için <a href="mailto:EmailAddress.com"> sağlar. RegularExpression
özniteliğini kullanarak verilerin biçimini doğrulayabilirsiniz. DataType özniteliği, veritabanı iç türünden daha özel
bir veri türü belirtmek için kullanılır, bunlar doğrulama öznitelikleri değildir. Bu durumda, zamanı değil yalnızca
tarihi izlemek istiyoruz. DataType numaralandırması, tarih, saat, PhoneNumber, para birimi, Emaadresi ve daha
fazlası gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin, DataType.EmailAddress için mailto: bir bağlantı oluşturulabilir ve HTML5 'i
destekleyen tarayıcılarda DataType.Date için bir tarih seçici sağlaneklenebilir. DataType öznitelikleri HTML 5
tarayıcıların anlayabilmesi için HTML 5 data- (bir veri Dash) öznitelikleri yayar. DataType öznitelikleri herhangi
bir doğrulama sağlamaz.
DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, veri alanı, sunucunun CultureInfo
göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]


public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode ayarı, bir metin kutusunda değer görüntülenmek üzere görüntülendiğinde


biçimlendirmenin de uygulanacağını belirtir. (Örneğin, para birimi değerleri için, büyük olasılıkla, metin
kutusundaki para birimi sembolünü, bazı alanlar için istemiyor olabilirsiniz.)
DisplayFormat özniteliğini kendisi kullanabilirsiniz, ancak bu genellikle DataType özniteliğini kullanmak iyi bir
fikir olabilir. DataType özniteliği, bir ekranda nasıl işlenirim aksine verilerin semantiğini sunar ve DisplayFormat
ile elde olmadığınız aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını vb. göstermek için)
Varsayılan olarak tarayıcı, verileri yerel ayarınızı temel alarak doğru biçimi kullanarak işleyebilir.
DataType özniteliği, verileri işlemek için doğru alan şablonunu seçmek üzere MVC 'yi etkinleştirebilir
(kendisi tarafından kullanılırsa, dize şablonunu kullanıyorsa DisplayFormat ).

NOTE
jQuery doğrulaması, Range özniteliğiyle ve DateTime birlikte çalışmaz. Örneğin, aşağıdaki kod, tarih belirtilen aralıkta
olduğunda bile her zaman bir istemci tarafı doğrulama hatası görüntüler:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

DateTime``Range özniteliğini kullanmak için jQuery Tarih doğrulamasını devre dışı bırakmanız gerekir.
Modellerinizde sabit tarihleri derlemek genellikle iyi bir uygulamadır, bu nedenle Range özniteliği ve DateTime
kullanılması önerilmez.
Aşağıdaki kod, öznitelikleri tek bir satırda birleştirmeyi gösterir:

public class Movie


{
public int Id { get; set; }

[StringLength(60, MinimumLength = 3)]


public string Title { get; set; }

[Display(Name = "Release Date"), DataType(DataType.Date)]


public DateTime ReleaseDate { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$"), Required, StringLength(30)]


public string Genre { get; set; }

[Range(1, 100), DataType(DataType.Currency)]


[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
public string Rating { get; set; }
}

Serinin bir sonraki bölümünde, uygulamayı gözden geçiririz ve otomatik olarak oluşturulan Details ve Delete
yöntemlerinde bazı geliştirmeler yaparsınız.

Ek kaynaklar
Formlarla Çalışma
Genelleştirme ve yerelleştirme
Etiket yardımcılarına giriş
Yazar etiketi yardımcıları

ÖN CEKI İL E R I
ASP.NET Core uygulamasının Ayrıntılar ve silme
yöntemlerini inceleyin
4.12.2019 • 4 minutes to read • Edit Online

Tarafından Rick Anderson


Film denetleyicisini açın ve Details yöntemi inceleyin:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

Bu eylem yöntemini oluşturan MVC yapı iskelesi altyapısı, yöntemi çağıran bir HTTP isteğini gösteren bir
açıklama ekler. Bu durumda, üç URL segmentine sahip bir GET isteği, Movies denetleyicisi, Details yöntemi ve
bir id değeri. Bu kesimleri geri çağır Startup.csiçinde tanımlanmıştır.

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

EF, FirstOrDefaultAsync yöntemini kullanarak verileri aramanızı kolaylaştırır. Yöntemi içinde yerleşik olarak
bulunan önemli bir güvenlik özelliği, kodun, onunla herhangi bir şey yapmayı denemeden önce arama
yönteminin bir filmi buldığını doğrulamasından kaynaklanmaktadır. Örneğin, bir korsan
http://localhost:{PORT}/Movies/Details/1 bağlantıları tarafından oluşturulan URL 'yi
http://localhost:{PORT}/Movies/Details/12345 (veya gerçek bir filmi temsil eden başka bir değer ) gibi bir şeye
değiştirerek siteye hata verebilir. Null bir filmi denetmediyseniz, uygulama bir özel durum oluşturur.
Delete ve DeleteConfirmed yöntemlerini inceleyin.
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}

var movie = await _context.Movie


.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}

return View(movie);
}

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var movie = await _context.Movie.FindAsync(id);
_context.Movie.Remove(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}

HTTP GET Delete yöntemi belirtilen filmi silmediğini unutmayın. Bu, silme işlemini gönderebileceğiniz (HttpPost)
filmin bir görünümünü döndürür. Bir GET isteğine yanıt olarak silme işlemi gerçekleştirme (veya bu konuyla ilgili
olarak, düzenleme işlemi gerçekleştirme, oluşturma işlemi yapma veya verileri değiştiren başka bir işlem) bir
güvenlik deliği açılır.
Verileri silen [HttpPost] yöntemi, HTTP POST yöntemine benzersiz bir imza veya ad vermek için
DeleteConfirmed olarak adlandırılır. İki yöntem imzası aşağıda gösterilmiştir:

// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{

// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{

Ortak dil çalışma zamanı (CLR ), aşırı yüklenmiş yöntemlerin benzersiz bir parametre imzasına sahip olmasını
gerektirir (aynı yöntem adı ancak farklı parametre listesi). Bununla birlikte, her ikisi de aynı parametre imzasına
sahip olmak üzere iki Delete yöntemi (GET için bir tane ve diğeri) gerekir. (Her ikisi de parametre olarak tek bir
tamsayıyı kabul etmelidir.)
Bu sorunun iki yaklaşımı vardır, biri yöntemlere farklı adlar vermektir.Bu, önceki örnekte bulunan yapı iskelesi
mekanizmasına göre yapılır. Ancak, bu küçük bir sorun ortaya çıkarır: ASP.NET bir URL 'nin segmentlerini ada
göre eylem yöntemlerine eşler ve bir yöntemi yeniden adlandırırsanız, yönlendirme normalde bu yöntemi
bulamaz. Çözüm, örnekte gördüğünüz şeydir. Bu, DeleteConfirmed yöntemine ActionName("Delete") özniteliğini
eklemektir. Bu öznitelik, yönlendirme sistemi için eşleme gerçekleştirerek, bir POST isteği için/Delete/içeren bir
URL 'nin DeleteConfirmed yöntemi bulacaktır.
Özdeş adlara ve imzalara sahip yöntemler için bir diğer yaygın çalışma yapay, POST yönteminin imzasını bir ek
(kullanılmamış) parametre içerecek şekilde değiştirecek. Bu, notUsed parametresini eklediğimiz sırada önceki bir
gönderimiz tarafından yaptığımız şeydir. [HttpPost] Delete yöntemi için burada aynı şeyi yapabilirsiniz:

// POST: Movies/Delete/6
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

Azure'a Yayımlama
Azure 'a dağıtma hakkında bilgi için bkz. öğretici: Azure App Service .NET Core ve SQL veritabanı Web
uygulaması oluşturma.

ÖN CEKI
ASP.NET Core MVC 'deki görünümler
6.12.2019 • 23 minutes to read • Edit Online

Steve Smith ve Luke Latham tarafından


Bu belgede ASP.NET Core MVC uygulamalarında kullanılan görünümler açıklanmaktadır. Razor Pages
hakkında bilgi için bkz. Razor Pages giriş.
Model-View -Controller (MVC ) modelinde, Görünüm uygulamanın veri sunumunu ve kullanıcı etkileşimini işler.
Görünüm, gömülü Razor işaretlemesiIÇEREN bir HTML şablonudur. Razor işaretleme, istemciye gönderilen bir
Web sayfası oluşturmak için HTML işaretlemesi ile etkileşen koddur.
ASP.NET Core MVC 'de, görünümler Razor biçimlendirmesinde C# programlama dilini kullanan . cshtml
dosyalarıdır. Genellikle, görünüm dosyaları uygulama denetleyicilerininher biri için adlandırılmış klasörler
halinde gruplandırılır. Klasörler, uygulamanın kökündeki bir Görünümler klasöründe depolanır:

Ana denetleyici, Görünümler klasörünün içindeki bir giriş klasörüyle temsil edilir. Giriş klasörü, hakkında,
iletişimve Dizin (giriş sayfası) Web sayfalarının görünümlerini içerir. Bir Kullanıcı bu üç Web sayfasından birini
istediğinde, ana denetleyicideki denetleyici eylemleri, Kullanıcı için bir Web sayfası oluşturmak ve döndürmek
için kullanılan üç görünümden hangisinin kullanıldığını tespit ediyor.
Tutarlı Web sayfası bölümleri sağlamak ve kod tekrarlamayı azaltmak için düzenleri kullanın. Düzenler
genellikle üstbilgiyi, gezinti ve menü öğelerini ve alt bilgisini içerir. Üst bilgi ve altbilgi genellikle birçok meta veri
öğesi için ortak biçimlendirme ve betik ve stil varlıklarına bağlantılar içerir. Düzenler, görünümlerinizde bu ortak
biçimlendirmeyi önlemenize yardımcı olur.
Kısmi görünümler , görünümlerin yeniden kullanılabilir parçalarını yöneterek kod yinelemeyi azaltır. Örneğin,
kısmi bir görünüm çeşitli görünümlerde görüntülenen bir blog web sitesinde yazar biyografı için yararlıdır. Yazar
biyografları sıradan görünüm içeriğine sahiptir ve Web sayfasının içeriğini üretmek için kodun yürütülmesi
gerekmez. Yazar biyografları, tek başına model bağlama tarafından kullanılabilir, bu nedenle bu içerik türü için
kısmi bir görünüm kullanmak idealdir.
Görünüm bileşenleri , yinelenen kodu azaltmanıza izin veren kısmi görünümlere benzerdir, ancak Web sayfasını
işlemek için kodun sunucuda çalıştırılmasını gerektiren içeriği görüntüleme için uygundur. Görüntüleme
bileşenleri, işlenen içerik bir Web sitesi alışveriş sepeti gibi veritabanı etkileşimi gerektirdiğinde yararlıdır. Web
sayfası çıkışı oluşturmak için, görünüm bileşenlerini model bağlama ile sınırlı değildir.

Görünümleri kullanmanın avantajları


Görünümler, Kullanıcı arabirimi işaretlemesini uygulamanın diğer bölümlerinden ayırarak bir MVC
uygulamasında kaygıların ayrılmasını sağlamaya yardımcı olur. Aşağıdaki SoC tasarımı, uygulamanızın modüler
olmasını sağlayarak çeşitli avantajlar sağlar:
Daha iyi bir şekilde düzenlendiğinden, uygulamanın bakımını daha kolay hale getirir. Görünümler genellikle
uygulama özelliğine göre gruplandırılır. Bu, bir özellik üzerinde çalışırken ilgili görünümleri bulmayı
kolaylaştırır.
Uygulamanın parçaları gevşek olarak bağlanmış. Uygulamanın görünümlerini iş mantığı ve veri erişim
bileşenlerinden ayrı olarak oluşturup güncelleştirebilirsiniz. Uygulamanın diğer bölümlerini güncelleştirmek
zorunda kalmadan uygulamanın görünümlerini değiştirebilirsiniz.
Görünümler ayrı birimler olduğundan uygulamanın kullanıcı arabirimi parçalarını test etmek daha kolay.
Daha iyi bir kuruluş nedeniyle, Kullanıcı arabiriminin bölümlerini yanlışlıkla tekrarlamanız daha az olabilir.

Görünüm oluşturma
Denetleyiciye özgü görünümler, Görünümler/[ControllerName] klasöründe oluşturulur. Denetleyiciler arasında
paylaşılan görünümler Görünümler/paylaşılan klasörüne yerleştirilir. Bir görünüm oluşturmak için yeni bir
dosya ekleyin ve . cshtml dosya uzantısıyla ilişkili denetleyici eylemiyle aynı adı verin. Giriş denetleyicisindeki
hakkında eylemine karşılık gelen bir görünüm oluşturmak Için, Görünümler/giriş klasöründe bir About. cshtml
dosyası oluşturun:

@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>

Razor biçimlendirmesi @ simgesiyle başlar. İfadeleri C# , C# Razor kod blokları içine kod yerleştirerek küme
ayraçları ( { ... } ) tarafından kapalı olarak ayarlayarak çalıştırın. Örneğin, yukarıda gösterilen
ViewData["Title"] için "hakkında" atamasını inceleyin. Yalnızca @ simgesiyle bir değere başvurarak, HTML
içindeki değerleri görüntüleyebilirsiniz. Yukarıdaki <h2> ve <h3> öğelerinin içeriğine bakın.
Yukarıda gösterilen görünüm içeriği yalnızca kullanıcıya işlenmiş olan tüm Web sayfasının bir parçasıdır.
Sayfanın düzeninin geri kalanı ve görünümün diğer yaygın yönleri diğer görünüm dosyalarında belirtilir. Daha
fazla bilgi için Düzen konusunabakın.

Denetleyiciler görünümleri nasıl belirler


Görünümler genellikle eylemlerden bir ActionResulttürü olan ViewResultolarak döndürülür. Eylem yönteminiz
doğrudan bir ViewResult oluşturup döndürebilir, ancak yaygın olarak yapılmaz. Çoğu Denetleyici
denetleyicisindendevraldığı için, ViewResult döndürmek üzere View yardımcı yöntemini kullanmanız yeterlidir:
HomeController.cs

public IActionResult About()


{
ViewData["Message"] = "Your application description page.";

return View();
}

Bu eylem döndüğünde, son bölümde gösterilen hakkında. cshtml görünümü aşağıdaki Web sayfası olarak
işlenir:
View Yardımcısı yönteminde birkaç aşırı yükleme vardır. İsteğe bağlı olarak şunları belirtebilirsiniz:
Döndürülecek açık bir görünüm:

return View("Orders");

Görünüme geçirilecek bir model :

return View(Orders);

Hem görünüm hem de model:

return View("Orders", Orders);

Bulmayı görüntüle
Bir eylem bir görünüm döndürdüğünde, görünüm bulma adlı bir işlem gerçekleşir. Bu işlem, görünüm adına
göre hangi görünüm dosyasının kullanıldığını belirler.
View yönteminin varsayılan davranışı ( return View(); ), çağrılan eylem yöntemiyle aynı ada sahip bir görünüm
döndürmemelidir. Örneğin, denetleyicinin yaklaşık ActionResult Yöntem adı . cshtmladlı bir görünüm dosyasını
aramak için kullanılır. İlk olarak, çalışma zamanı görünümün Görünümler/[ControllerName] klasörüne bakar.
Burada eşleşen bir görünüm bulamazsa, görünümün paylaşılan klasörünü arar.
ViewResult örtülü olarak return View(); döndürmeniz ya da görünüm adını return View("<ViewName>"); ile
View yöntemine açıkça geçirmeniz önemlidir. Her iki durumda da, eşleşen bir görünüm dosyası için bulma
aramalarını şu sırayla görüntüleyin:
1. Görünümler/[ControllerName]/[ViewName]. cshtml
2. Görünümler/paylaşılan/[ViewName]. cshtml
Görünüm adı yerine bir görünüm dosyası yolu sağlanıyor. Uygulama kökünde başlayan mutlak bir yol
kullanılıyorsa (isteğe bağlı olarak "/" veya "~/" ile başlayan), . cshtml uzantısı belirtilmelidir:

return View("Views/Home/About.cshtml");

Ayrıca, . cshtml uzantısı olmadan farklı dizinlerdeki görünümleri belirtmek için göreli bir yol da kullanabilirsiniz.
HomeController içinde, Yönetim görünümlerinizin Dizin görünümünü göreli bir yol ile döndürebilirsiniz:
return View("../Manage/Index");

Benzer şekilde, "./" önekiyle geçerli denetleyiciye özgü dizini belirtebilirsiniz:

return View("./About");

Kısmi görünümler ve Görünüm bileşenleri benzer (ancak aynı) bulma mekanizmalarını kullanır.
Özel bir ıviewlocationgenişleticisikullanarak, görünümler uygulama içinde nasıl konumlandırılabilir varsayılan
kuralı özelleştirebilirsiniz.
Görünüm bulma, dosya adına göre görünüm dosyalarını bulmayı kullanır. Temeldeki dosya sistemi büyük/küçük
harfe duyarlı ise, görünüm adları büyük olasılıkla büyük küçük harfe duyarlıdır. İşletim sistemleri arasında
uyumluluk için, denetleyici ve eylem adları ile ilişkili görünüm klasörleri ve dosya adları arasındaki büyük/küçük
harfe eşleştirin. Büyük/küçük harfe duyarlı dosya sistemiyle çalışırken bir görünüm dosyasının bulunamadığını
belirten bir hatayla karşılaşırsanız, istenen görünüm dosyası ile gerçek görünüm dosyası adı arasında
büyük/küçük harf eşleştiğini doğrulayın.
Görünümlerinizin dosya yapısını, bakım ve açıklık için denetleyiciler, Eylemler ve görünümler arasındaki ilişkileri
yansıtacak şekilde düzenleme konusunda en iyi yöntemi izleyin.

Verileri görünümlere geçirme


Çeşitli yaklaşımlar kullanarak verileri görünümlere geçirin:
Kesin türü belirtilmiş veri: ViewModel
Zayıf yazılmış veriler
ViewData ( ViewDataAttribute )
ViewBag

Kesin tür belirtilmiş veriler (ViewModel)


En güçlü yaklaşım, görünümde bir model türü belirtmektir. Bu model genellikle ViewModelolarak adlandırılır.
ViewModel türünün bir örneğini eylemden görünüme geçirirsiniz.
Görünümü bir görünüme aktarmak için ViewModel kullanmak, görünümün tanımlayıcı tür denetlemesinin
avantajlarından yararlanmasını sağlar. Kesin yazma (veya türü kesin belirlenmiş), her değişken ve sabitin açıkça
tanımlanmış bir tür (örneğin, string , int veya DateTime ) olduğu anlamına gelir. Bir görünümde kullanılan
türlerin geçerliliği derleme zamanında denetlenir.
Visual Studio ve Visual Studio Code listesi IntelliSenseadlı bir özellik kullanılarak türü kesin belirlenmiş sınıf
üyeleridir. ViewModel özelliklerini görmek istediğinizde, ViewModel için değişken adını ve ardından bir nokta (
. ) yazın. Bu, daha az hata vererek kodu daha hızlı yazmanıza yardımcı olur.

@model yönergesini kullanarak bir model belirtin. Modeli @Model ile birlikte kullanın:

@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
@Model.Street<br>
@Model.City, @Model.State @Model.PostalCode<br>
<abbr title="Phone">P:</abbr> 425.555.0100
</address>

Modeli görünüme sağlamak için, denetleyici bu parametreyi bir parametre olarak geçirir:
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";

var viewModel = new Address()


{
Name = "Microsoft",
Street = "One Microsoft Way",
City = "Redmond",
State = "WA",
PostalCode = "98052-6399"
};

return View(viewModel);
}

Bir görünüme sağlayabilmeniz için model türlerinde hiçbir kısıtlama yoktur. Basit eski CLR nesnesi (POCO )
viewmodeller için çok az veya hiç davranış (Yöntem) tanımlanmış olarak kullanılması önerilir. Genellikle
ViewModel sınıfları, uygulamanın kökündeki modeller klasöründe veya ayrı bir viewmodeller klasöründe
depolanır. Yukarıdaki örnekte kullanılan Adres viewmodel, Address.csadlı bir dosyada depolanan bir poco
ViewModel modelidir:

namespace WebApplication1.ViewModels
{
public class Address
{
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
}

Hiçbir şey, hem ViewModel türleriniz hem de iş modeli türleriniz için aynı sınıfları kullanmanızı önler. Ancak, ayrı
modeller kullanmak görünümlerinizin, uygulamanızın iş mantığı ve veri erişimi bölümlerinden bağımsız olarak
değişiklik yapmasına izin verir. Modeller ve ViewModel ayrımı, modeller Kullanıcı tarafından uygulamaya
gönderilen veriler için model bağlama ve doğrulama kullanırken de güvenlik avantajları sağlar.
Zayıf yazılmış veriler (ViewData, ViewData özniteliği ve ViewBag)
ViewBag Razor Pages kullanılamaz.

Türü kesin belirlenmiş görünümlere ek olarak, görünümler, verilerin bir zayıf türü olan ( gevşek olarak yazılmış)
bir veri koleksiyonu erişimi vardır. Güçlü türlerin aksine, zayıf türler (veya gevşek türler), kullanmakta olduğunuz
veri türünü açıkça bildirmeyeceğiniz anlamına gelir. Denetleyicilerde ve görünümlerde küçük miktarlarda veri
iletmek için zayıf yazılmış verilerin toplanmasını kullanabilirsiniz.

VERILERI BIR... ARASINDA GEÇIRME ÖRNEK

Denetleyici ve görünüm Açılan listeyi verilerle doldurma.

Görünüm ve Düzen görünümü <başlığını bir görünüm dosyasındaki düzen görünümünde


> öğe içeriğini ayarlama.

Kısmi görünüm ve görünüm Kullanıcı tarafından istenen web sayfasını temel alan verileri
görüntüleyen pencere öğesi.

Bu koleksiyona, denetleyiciler ve görünümlerde ViewData ya da ViewBag özellikleri aracılığıyla başvurulabilir.


ViewData özelliği, Zayıf yazılmış nesnelerin bir sözlüğüdür. ViewBag özelliği, temel ViewData koleksiyonu için
dinamik özellikler sağlayan ViewData çevresindeki bir sarmalayıcıdır. Note: anahtar aramaları hem ViewData
hem de ViewBag için büyük/küçük harfe duyarsızdır.
ViewData ve ViewBag , çalışma zamanında dinamik olarak çözümlenir. Derleme zamanı tür denetimi sunmadığı
için, her ikisi de bir ViewModel kullanmaktan daha fazla hataya açıktır. Bu nedenle, bazı geliştiriciler ViewData
ve ViewBag en düşük düzeyde bir süre önce kullanmaz veya hiç kullanmayın.
ViewData
ViewData , string anahtarlar aracılığıyla erişilen bir ViewDataDictionary nesnesidir. Dize verileri doğrudan bir
dönüştürme gerektirmeden depolanabilir ve kullanılabilir, ancak diğer ViewData nesne değerlerini
ayıkladığınızda belirli türlere atamalısınız. ViewData kullanarak, kısmen görünümler ve düzenlerdahil olmak
üzere denetleyicilerden görünümlere ve görünümlere veri geçirebilirsiniz.
Aşağıda, bir bir eylem içinde ViewData kullanarak bir selamlama ve adres değerlerini ayarlayan bir örnek
verilmiştir:

public IActionResult SomeAction()


{
ViewData["Greeting"] = "Hello";
ViewData["Address"] = new Address()
{
Name = "Steve",
Street = "123 Main St",
City = "Hudson",
State = "OH",
PostalCode = "44236"
};

return View();
}

Bir görünümdeki verilerle çalışın:

@{
// Since Address isn't a string, it requires a cast.
var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
@address.Name<br>
@address.Street<br>
@address.City, @address.State @address.PostalCode
</address>

ViewData özniteliği
ViewDataDictionary ' i kullanan başka bir yaklaşım da viewdataattribute. [ViewData] özniteliğiyle işaretlenmiş
denetleyiciler veya Razor sayfa modelleriyle ilgili özellikler, değerlerinin depolandığı ve sözlükten yüklendiği
değerlerdir.
Aşağıdaki örnekte, giriş denetleyicisi [ViewData] işaretli bir Title özelliği içerir. About yöntemi, hakkında bilgi
görünümü için başlığı ayarlar:
public class HomeController : Controller
{
[ViewData]
public string Title { get; set; }

public IActionResult About()


{
Title = "About Us";
ViewData["Message"] = "Your application description page.";

return View();
}
}

Hakkında görünümünde, Title özelliğine model özelliği olarak erişin:

<h1>@Model.Title</h1>

Mizanpajda, başlık ViewData sözlüğünden okundu:

<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"] - WebApplication</title>
...

ViewBag
ViewBag Razor Pages kullanılamaz.
ViewBag , ViewData depolanan nesnelere dinamik erişim sağlayan bir Dynamicviewdata nesnesidir. ViewBag ,
atama gerektirmediğinden, ile çalışmak daha uygun olabilir. Aşağıdaki örnek, yukarıdaki ViewData kullanmayla
aynı sonuçla ViewBag nasıl kullanacağınızı gösterir:

public IActionResult SomeAction()


{
ViewBag.Greeting = "Hello";
ViewBag.Address = new Address()
{
Name = "Steve",
Street = "123 Main St",
City = "Hudson",
State = "OH",
PostalCode = "44236"
};

return View();
}

@ViewBag.Greeting World!

<address>
@ViewBag.Address.Name<br>
@ViewBag.Address.Street<br>
@ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

ViewData ve ViewBag 'i aynı anda kullanma


ViewBag Razor Pages kullanılamaz.
ViewData ve ViewBag aynı temel ViewData koleksiyonuna başvurduğundan, değerleri okurken ve yazarken
aralarında hem ViewData hem de ViewBag ve karıştırma ve eşleştirme kullanabilirsiniz.
Bir About. cshtml görünümünün en üstündeki ViewData kullanarak ViewBag ve açıklamayı kullanarak başlığı
ayarlayın:

@{
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "About Contoso";
ViewData["Description"] = "Let us tell you about Contoso's philosophy and mission.";
}

Özellikleri okuyun, ancak ViewData ve ViewBag kullanımını ters çevirin. _Layout. cshtml dosyasında, ViewData
kullanarak başlığı alın ve ViewBag kullanarak açıklamayı alın:

<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewData["Title"]</title>
<meta name="description" content="@ViewBag.Description">
...

Dizelerin ViewData için bir dönüştürme gerektirmemenizi unutmayın. @ViewData["Title"] , atama olmadan
kullanabilirsiniz.
Hem ViewData hem de ViewBag aynı anda kullanmak, özellikleri karıştırarak ve eşleştirirken de geçerlidir.
Aşağıdaki biçimlendirme işlenir:

<!DOCTYPE html>
<html lang="en">
<head>
<title>About Contoso</title>
<meta name="description" content="Let us tell you about Contoso's philosophy and mission.">
...

ViewData ve ViewBag arasındaki farkların Özeti


ViewBag Razor Pages yok.
ViewData
ViewDataDictionaryöğesinden türetilir, bu nedenle ContainsKey , Add , Remove ve Clear gibi yararlı
olabilecek Sözlük özellikleri vardır.
Sözlükteki anahtarlar dizelerdir, bu nedenle boşluğa izin verilir.Örnek:
ViewData["Some Key With Whitespace"]
string dışında herhangi bir tür ViewData kullanmak için görünümde tür dönüştürme yapılmalıdır.
ViewBag
Dynamicviewdataöğesinden türetilir, bu nedenle, nokta gösterimini (
@ViewBag.SomeKey = <value or object> ) kullanarak dinamik özellikler oluşturulmasına izin verir ve
hiçbir atama gerekmez. ViewBag söz dizimi, denetleyicilere ve görünümlere daha hızlı eklemenizi
sağlar.
Null değerleri denetlemek için daha basittir. Örnek: @ViewBag.Person?.Name

ViewData veya ViewBag ne zaman kullanılır?


Hem ViewData hem de ViewBag , denetleyiciler ve görünümler arasında küçük miktarlarda veri iletmek için eşit
ölçüde geçerli yaklaşımlar. Hangisinin kullanılacağı seçimi tercihi temel alır. ViewData ve ViewBag nesneleri
karıştırıp eşleştirebilirsiniz, ancak kod, sürekli olarak kullanılan tek bir yaklaşımla daha kolay okunabilir ve
devam edebilir. Her iki yaklaşım da çalışma zamanında dinamik olarak çözümlenir ve bu nedenle çalışma
zamanı hatalarına neden olur. Bazı geliştirme ekipleri bunlardan kaçınır.
Dinamik Görünümler
@model kullanarak bir model türü bildirmeyen ancak bunlara bir model örneği geçirmeyen görünümler
(örneğin, return View(Address); ), örnek özelliklerine dinamik olarak başvurabilir:

<address>
@Model.Street<br>
@Model.City, @Model.State @Model.PostalCode<br>
<abbr title="Phone">P:</abbr> 425.555.0100
</address>

Bu özellik esneklik sunar, ancak derleme koruması veya IntelliSense sunmaz. Özellik yoksa, Web sayfası
oluşturma çalışma zamanında başarısız olur.

Daha fazla görünüm özelliği


Etiket Yardımcıları , var olan HTML etiketlerine sunucu tarafı davranışı eklemenizi kolaylaştırır. Etiket
yardımcılarının kullanılması, görünümleriniz içinde özel kod veya yardımcılar yazma ihtiyacını önler. Etiket
Yardımcıları HTML öğelerine öznitelikler olarak uygulanır ve bunları işleyeamayan düzenleyiciler tarafından yok
sayılır. Bu, çeşitli araçlarındaki görünüm işaretlemesini düzenlemenizi ve işlemeyi sağlar.
Özel HTML işaretlemesi oluşturmak birçok yerleşik HTML Yardımcıda sağlanabilir. Daha karmaşık kullanıcı
arabirimi mantığı, Görünüm bileşenleritarafından işlenebilir. Görüntüleme bileşenleri, denetleyiciler ve
görünümler tarafından sunulan aynı SoC öğesine sahiptir. Ortak kullanıcı arabirimi öğeleri tarafından kullanılan
verilerle ilgili eylemler ve görünümler gereksinimini ortadan kaldırabilir.
ASP.NET Core diğer birçok yönü gibi, görünümler bağımlılık eklemeişlemini destekler ve hizmetlerin
görünümlereeklenmesine izin verir.
ASP.NET Core kısmi görünümler
14.09.2019 • 14 minutes to read • Edit Online

Steve Smith, Luke Latham, madan Jendoubı, Rick Andersonve Scott Sauber tarafından
Kısmi görünüm , başka bir biçimlendirme dosyasının işlenmiş ÇıKTıSıNDAKI HTML çıkışını Işleyen bir Razor
biçimlendirme dosyasıdır ( . cshtml).
Kısmi görünüm terimi, biçimlendirme dosyaları Görünümlerolarak adlandırılan bir MVC uygulaması veya
biçimlendirme dosyalarının Sayfalarolarak adlandırıldığını Razor Pages bir uygulama geliştirirken kullanılır.
Bu konu, MVC görünümlerini ve Razor Pages sayfalarını biçimlendirme dosyalarıolarak gösterir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Kısmi görünümlerin ne zaman kullanılacağı


Kısmi görünümler şu şekilde etkili bir yoldur:
Büyük biçimlendirme dosyalarını daha küçük bileşenlere bölün.
Birkaç mantıksal parçadan oluşan büyük, karmaşık bir biçimlendirme dosyasında, her bir parçada
kısmi bir görünümde yalıtılmış olarak çalışmanın bir avantajı vardır. Biçimlendirme dosyasındaki kod,
biçimlendirme yalnızca genel sayfa yapısını ve kısmi görünümlere yönelik başvuruları içerdiğinden
yönetilebilir.
Biçimlendirme dosyaları arasında ortak biçimlendirme içeriğinin çoğaltılmasını azaltın.
Biçimlendirme dosyalarında aynı biçimlendirme öğeleri kullanıldığında, kısmi bir görünüm
biçimlendirme içeriğinin tek bir kısmi görünüm dosyasına çoğaltılmasını kaldırır. Kısmi görünümdeki
biçimlendirme değiştirildiğinde, kısmi görünümü kullanan biçimlendirme dosyalarının işlenmiş çıkışını
günceller.
Yaygın düzen öğelerini korumak için kısmi görünümler kullanılmamalıdır. _Layout. cshtml dosyalarında ortak
düzen öğeleri belirtilmelidir.
Biçimlendirmeyi işlemek için karmaşık işleme mantığının veya kod yürütmenin gerekli olduğu kısmi bir
görünüm kullanmayın. Kısmi bir görünüm yerine bir Görünüm bileşenikullanın.

Kısmi görünümler bildirme


Kısmi görünüm, Görünümler klasörü (MVC ) veya sayfalar klasörü (Razor Pages) içinde tutulan bir . cshtml
biçimlendirme dosyasıdır.
ASP.NET Core MVC 'de, denetleyici ViewResult bir görünüm veya kısmi görünüm döndürmektedir. Razor
Pages, bir PageModel PartialViewResult nesnesi olarak temsil edilen kısmi bir görünüm döndürebilir. Kısmi
görünümlere başvurmak ve işlemek kısmi görünüm başvurusu bölümünde açıklanmaktadır.
MVC görünümü veya sayfa işleme farklı olarak, kısmi bir görünüm _Viewstart. cshtmlçalıştırmaz. _Viewstart.
cshtmlhakkında daha fazla bilgi için bkz ASP.NET Core düzen.
Kısmi görünüm dosya adları genellikle bir alt çizgi ( _ ) ile başlar. Bu adlandırma kuralı gerekli değildir, ancak
görünüm ve sayfalardan kısmi görünümleri görsel açıdan ayırt etmeye yardımcı olur.
Kısmi görünüm, Görünümler klasörü içinde tutulan bir . cshtml biçimlendirme dosyasıdır.
Denetleyicinin bir görünüm ViewResult veya kısmi görünüm döndürme özelliği vardır. Kısmi görünümlere
başvurmak ve işlemek kısmi görünüm başvurusu bölümünde açıklanmaktadır.
MVC görünüm işlemenin aksine, kısmi bir görünüm _Viewstart. cshtmlçalıştırmaz. _Viewstart.
cshtmlhakkında daha fazla bilgi için bkz ASP.NET Core düzen.
Kısmi görünüm dosya adları genellikle bir alt çizgi ( _ ) ile başlar. Bu adlandırma kuralı gerekli değildir, ancak
kısmen görünümlerini görünümlerde görsel açıdan ayırt etmeye yardımcı olur.

Kısmi görünüme başvur


Razor Pages PageModel içinde kısmi bir görünüm kullanma
ASP.NET Core 2,0 veya 2,1 ' de, aşağıdaki işleyici yöntemi _authorpartialrp. cshtml kısmi görünümünü yanıta
işler:

public IActionResult OnGetPartial() =>


new PartialViewResult
{
ViewName = "_AuthorPartialRP",
ViewData = ViewData,
};

ASP.NET Core 2,2 veya sonraki sürümlerde, bir işleyici yöntemi alternatif olarak bir Partial
PartialViewResult nesnesi oluşturmak için yöntemini çağırabilir:

public IActionResult OnGetPartial() =>


Partial("_AuthorPartialRP");

Biçimlendirme dosyasında kısmi görünüm kullanma


Bir biçimlendirme dosyasında kısmi bir görünüme başvurmak için birkaç yol vardır. Uygulamaların aşağıdaki
zaman uyumsuz işleme yaklaşımlardan birini kullanmasını öneririz:
Kısmi Etiket Yardımcısı
Zaman uyumsuz HTML Yardımcısı
Bir biçimlendirme dosyasında, kısmi bir görünüme başvurmak için iki yol vardır:
Zaman uyumsuz HTML Yardımcısı
Zaman uyumlu HTML Yardımcısı
Uygulamaların zaman uyumsuz HTML yardımcısınıkullanmasını öneririz.
Kısmi etiket Yardımcısı
Kısmi etiket yardımcısı ASP.NET Core 2,1 veya sonraki bir sürümü gerektirir.
Kısmi etiket Yardımcısı içeriği zaman uyumsuz olarak işler ve HTML benzeri bir sözdizimi kullanır:

<partial name="_PartialName" />

Bir dosya uzantısı mevcut olduğunda, etiket Yardımcısı kısmi görünümü çağıran biçimlendirme dosyasıyla
aynı klasörde olması gereken kısmi bir görünüme başvurur:

<partial name="_PartialName.cshtml" />


Aşağıdaki örnek, uygulama kökünden kısmi bir görünüme başvurur. Bir tilde işareti ( ~/ ) veya eğik çizgi ( / )
ile başlayan yollar uygulama köküne başvurur:
Razor Sayfaları

<partial name="~/Pages/Folder/_PartialName.cshtml" />


<partial name="/Pages/Folder/_PartialName.cshtml" />

MVC

<partial name="~/Views/Folder/_PartialName.cshtml" />


<partial name="/Views/Folder/_PartialName.cshtml" />

Aşağıdaki örnek, göreli bir yol ile kısmi bir görünüme başvurur:

<partial name="../Account/_PartialName.cshtml" />

Daha fazla bilgi için bkz. ASP.NET Core kısmi etiket Yardımcısı.
Zaman uyumsuz HTML Yardımcısı
Bir HTML Yardımcısı kullanırken en iyi yöntem PartialAsynckullanılır. PartialAsync içinde Sarmalanan bir
IHtmlContent tür döndürür. Task<TResult> Yöntemine, beklenen çağrının bir @ karakterle önek olarak
eklenerek başvurulur:

@await Html.PartialAsync("_PartialName")

Dosya uzantısı varsa, HTML Yardımcısı kısmi görünümü çağıran biçimlendirme dosyasıyla aynı klasörde
olması gereken kısmi bir görünüme başvurur:

@await Html.PartialAsync("_PartialName.cshtml")

Aşağıdaki örnek, uygulama kökünden kısmi bir görünüme başvurur. Bir tilde işareti ( ~/ ) veya eğik çizgi ( / )
ile başlayan yollar uygulama köküne başvurur:
Razor Sayfaları

@await Html.PartialAsync("~/Pages/Folder/_PartialName.cshtml")
@await Html.PartialAsync("/Pages/Folder/_PartialName.cshtml")

MVC

@await Html.PartialAsync("~/Views/Folder/_PartialName.cshtml")
@await Html.PartialAsync("/Views/Folder/_PartialName.cshtml")

Aşağıdaki örnek, göreli bir yol ile kısmi bir görünüme başvurur:

@await Html.PartialAsync("../Account/_LoginPartial.cshtml")

Alternatif olarak, ile RenderPartialAsynckısmi bir görünüm işleyebilirsiniz. Bu yöntem bir


IHtmlContentdöndürmez. İşlenmiş çıktıyı doğrudan yanıta akıp. Yöntem bir sonuç döndürmediği için, bir
Razor kod bloğu içinde çağrılmalıdır:
@{
await Html.RenderPartialAsync("_AuthorPartial");
}

RenderPartialAsync , İçeriği oluşturduğundan, bazı senaryolarda daha iyi performans sağlar. Performans
açısından kritik durumlarda, her iki yaklaşımı kullanarak sayfayı kıyaslar ve daha hızlı bir yanıt üreten
yaklaşımı kullanır.
Zaman uyumlu HTML Yardımcısı
Partialve sırasıyla zaman uyumlu RenderPartialAsync PartialAsync RenderPartial eşdeğerlerdir. Zaman
uyumlu eşdeğerleri, kilitlendikleri senaryolar olduğu için önerilmez. Zaman uyumlu yöntemler gelecek
sürümlerde kaldırılmak üzere hedeflenmiştir.

IMPORTANT
Kodu yürütmeniz gerekiyorsa, kısmi bir görünüm yerine bir Görünüm bileşeni kullanın.

Bir Partial Visual RenderPartial Studio Çözümleyicisi uyarısıyla çağırma veya sonuç. Örneğin, varlığı
Partial aşağıdaki uyarı iletisini verir:

Ihtmlhelper. Partial kullanımı uygulama kilitlenmeleri oluşmasına neden olabilir. <Kısmi> etiket
Yardımcısı veya ıhtmlhelper. partıalasync kullanmayı düşünün.

Çağrıları @Html.Partial ile veya kısmi etiket Yardımcısıile @await Html.PartialAsync değiştirin. Kısmi etiket
Yardımcısı geçişi hakkında daha fazla bilgi için bkz. HTML Yardımcısı 'Ndan geçiş.

Kısmi görünüm bulma


Bir dosya uzantısı olmayan kısmi bir görünüme ad ile başvurulduğunda, aşağıdaki konumlar belirtilen sırada
aranır:
Razor Sayfaları
1. Şu anda sayfanın klasörü yürütülüyor
2. Sayfanın klasörünün üzerindeki Dizin grafiği
3. /Shared
4. /Pages/Shared
5. /Views/Shared

MVC
1. /Areas/<Area-Name>/Views/<Controller-Name>
2. /Areas/<Area-Name>/Views/Shared
3. /Views/Shared
4. /Pages/Shared

1. /Areas/<Area-Name>/Views/<Controller-Name>
2. /Areas/<Area-Name>/Views/Shared
3. /Views/Shared

Kısmi görünüm bulma için aşağıdaki kurallar geçerlidir:


Kısmi görünümler farklı klasörlerde olduğunda aynı dosya adına sahip farklı kısmi görünümlere izin verilir.
Dosya uzantısı olmadan kısmi bir görünüme ada göre başvurulması ve kısmi görünümün hem arayanın
klasöründe hem de paylaşılan klasörde mevcut olması halinde, çağıranın klasöründeki kısmi görünüm
kısmi görünümü sağlar. Kısmi görünüm çağıranın klasöründe yoksa, kısmi görünüm paylaşılan klasörden
sağlanır. Paylaşılan klasördeki kısmi görünümler, paylaşılan kısmi görünümler veya varsayılan kısmi
görünümlerolarak adlandırılır.
Kısmi Görünümler zincirleme—olabilir kısmi görünüm, çağrılar tarafından bir döngüsel başvuru
oluşturulmadığı durumlarda başka bir kısmi görünümü çağırabilir. Göreli yollar her zaman geçerli dosyaya
göredir, dosyanın köküne veya üst öğesine göre değil.

NOTE
Kısmi görünümde tanımlanan bir Razor section , üst biçimlendirme dosyaları için görünmez değildir. section
Yalnızca tanımlandığı kısmi görünüm için görülebilir.

Kısmi görünümlerde verilere erişin


Kısmi bir görünüm örneği oluşturulduğunda, üst öğenin ViewData sözlüğünün bir kopyasını alır. Kısmi
görünüm içindeki verilerde yapılan güncelleştirmeler üst görünümde kalıcı değildir. ViewData kısmi görünüm
geri döndüğünde kısmi görünümdeki değişiklikler kaybolur.
Aşağıdaki örnek, bir ViewDataDictionary örneğinin kısmi bir görünüme nasıl geçirileceğini göstermektedir:

@await Html.PartialAsync("_PartialName", customViewData)

Bir modeli kısmi bir görünüme geçirebilirsiniz. Model özel bir nesne olabilir. Bir modeli ile PartialAsync
geçirebilirsiniz (bir içerik bloğunu çağırana kaydedebilir) veya RenderPartialAsync (içeriği çıkışa akıp):

@await Html.PartialAsync("_PartialName", model)

Razor Sayfaları
Örnek uygulamada aşağıdaki biçimlendirme, Pages/ArticlesRP/ReadRP. cshtml sayfasından yapılır. Sayfada iki
kısmi görünüm bulunur. İkinci kısmi görünüm bir modelde ve ViewData kısmi görünüme geçer. Oluşturucu
aşırı yüklemesi, var olan ViewData sözlüğü korurken yeni ViewData bir sözlüğü geçirmek için kullanılır.
ViewDataDictionary
@model ReadRPModel

<h2>@Model.Article.Title</h2>
@* Pass the author's name to Pages\Shared\_AuthorPartialRP.cshtml *@
@await Html.PartialAsync("../Shared/_AuthorPartialRP", Model.Article.AuthorName)
@Model.Article.PublicationDate

@* Loop over the Sections and pass in a section and additional ViewData to
the strongly typed Pages\ArticlesRP\_ArticleSectionRP.cshtml partial view. *@
@{
var index = 0;

foreach (var section in Model.Article.Sections)


{
await Html.PartialAsync("_ArticleSectionRP",
section,
new ViewDataDictionary(ViewData)
{
{ "index", index }
});

index++;
}
}

Pages/Shared/_AuthorPartialRP. cshtml , readrp. cshtml işaretleme dosyası tarafından başvurulan ilk kısmi
görünümüdür:

@model string
<div>
<h3>@Model</h3>
This partial view from /Pages/Shared/_AuthorPartialRP.cshtml.
</div>

Pages/ArticlesRP/_ArticleSectionRP. cshtml , readrp. cshtml biçimlendirme dosyası tarafından başvurulan


ikinci kısmi görünümüdür:

@using PartialViewsSample.ViewModels
@model ArticleSection

<h3>@Model.Title Index: @ViewData["index"]</h3>


<div>
@Model.Content
</div>

MVC
Örnek uygulamada aşağıdaki biçimlendirme görünümleri/makaleleri/Read. cshtml görünümünü gösterir.
Görünüm iki kısmi görünüm içerir. İkinci kısmi görünüm bir modelde ve ViewData kısmi görünüme geçer.
Oluşturucu aşırı yüklemesi, var olan ViewData sözlüğü korurken yeni ViewData bir sözlüğü geçirmek için
kullanılır. ViewDataDictionary
@model PartialViewsSample.ViewModels.Article

<h2>@Model.Title</h2>
@* Pass the author's name to Views\Shared\_AuthorPartial.cshtml *@
@await Html.PartialAsync("_AuthorPartial", Model.AuthorName)
@Model.PublicationDate

@* Loop over the Sections and pass in a section and additional ViewData to
the strongly typed Views\Articles\_ArticleSection.cshtml partial view. *@
@{
var index = 0;

foreach (var section in Model.Sections)


{
await Html.PartialAsync("_ArticleSection",
section,
new ViewDataDictionary(ViewData)
{
{ "index", index }
});

index++;
}
}

Views/Shared/_AuthorPartial. cshtml , Read. cshtml biçimlendirme dosyası tarafından başvurulan ilk kısmi
görünümdür:

@model string
<div>
<h3>@Model</h3>
This partial view from /Views/Shared/_AuthorPartial.cshtml.
</div>

Görünümler/makaleler/_ArticleSection. cshtml , Read. cshtml biçimlendirme dosyası tarafından başvurulan


ikinci kısmi görünümdür:

@using PartialViewsSample.ViewModels
@model ArticleSection

<h3>@Model.Title Index: @ViewData["index"]</h3>


<div>
@Model.Content
</div>

Çalışma zamanında, partiler, kendisini paylaşılan _Layout. cshtmliçinde işlenen üst biçimlendirme dosyasının
işlenmiş çıktısına işlenir. İlk kısmi görünüm, makalenin adını ve yayımlama tarihini işler:

Abrayhelincoln
<Paylaşılan kısmi görünüm dosyası yolundan>bu kısmi görünüm. 11/19/1863 12:00:00

İkinci kısmi görünüm, makalenin bölümlerini işler:

Bölüm bir dizin: 0


Dört puan ve yedi yıl önce...
Bölüm Iki Dizin: 1.
Artık harika bir hukuki War, test ediyor...
Bölüm üç Dizin: 2
Ancak, daha büyük bir fikir için ayıramıyoruz...

Ek kaynaklar
ASP.NET Core Razor söz dizimi başvurusu
ASP.NET Core etiket yardımcıları
ASP.NET Core kısmi etiket Yardımcısı
ASP.NET Core bileşenleri görüntüleme
ASP.NET Core bölgeler
ASP.NET Core Razor söz dizimi başvurusu
ASP.NET Core bileşenleri görüntüleme
ASP.NET Core bölgeler
ASP.NET Core MVC 'de denetleyicilerle istekleri
işleme
6.12.2019 • 9 minutes to read • Edit Online

Tarafından Steve Smith ve Scott Addie


Denetleyiciler, Eylemler ve eylem sonuçları, geliştiricilerin ASP.NET Core MVC kullanarak uygulama oluşturma
konusunda temel bir parçasıdır.

Denetleyici nedir?
Bir denetleyici, bir dizi eylemi tanımlamak ve gruplandırmak için kullanılır. Bir eylem (veya eylem yöntemi), bir
denetleyicide istekleri işleyen bir yöntemdir. Denetleyiciler benzer eylemleri birlikte mantıksal olarak gruplayın.
Bu eylemlerin toplamı, yönlendirme, önbelleğe alma ve yetkilendirme gibi ortak kural kümelerinin toplu olarak
uygulanmasını sağlar. İstekler, yönlendirmearacılığıyla eylemlerle eşleştirilir.
Kurala göre, denetleyici sınıfları:
Projenin kök düzeyi denetleyiciler klasöründe bulunur.
Microsoft.AspNetCore.Mvc.Controller 'den devralma.

Denetleyici, aşağıdaki koşullardan en az birinin doğru olduğu bir instantiable sınıfıdır:


Sınıf adı Controller ile Sonya düzeltildi.
Sınıfı, adı Controller sonındaki bir sınıftan devralır.
[Controller] özniteliği sınıfa uygulanır.

Denetleyici sınıfı ilişkili bir [NonController] özniteliğine sahip olmamalıdır.


Denetleyiciler Açık bağımlılıklar ilkesiniizlemelidir. Bu ilkeyi uygulamak için birkaç yaklaşım vardır. Birden çok
denetleyici eylemi aynı hizmeti gerektiriyorsa, bu bağımlılıkları istemek için Oluşturucu Ekleme kullanmayı
düşünün. Hizmet yalnızca tek bir eylem yöntemiyle gerekliyse, bağımlılığı istemek için eylem ekleme işlemini
kullanmayı düşünün.
Model-VIEW -Controller düzeninde bir denetleyici, modelin istek ve örneklemesinin ilk işlemeden sorumludur.
Genellikle, iş kararları model içinde gerçekleştirilmelidir.
Denetleyici, modelin işleme sonucunu alır (varsa) ve uygun görünümü ve ilgili görünüm verilerini ya da API
çağrısının sonucunu döndürür. ASP.NET Core MVC 'ye genel bakış ve ASP.NET Core MVC ve Visual Studio ile
çalışmaya başlamahakkında daha fazla bilgi edinin.
Denetleyici bir UI düzeyi soyutlamadır. Sorumlulukları, istek verilerinin geçerli olduğundan ve hangi görünümün
(ya da bir API 'nin sonucunun) döndürüldüğünden emin sağlamaktır. İyi şekilde uyumlu olmayan
uygulamalarda, doğrudan veri erişimi veya iş mantığı dahil değildir. Bunun yerine, denetleyici bu sorumlulukları
işleyen hizmetlere temsilci seçer.

Eylemleri tanımlama
Bir denetleyicide, [NonAction] özniteliği olanlar hariç genel yöntemler eylemlerdir. Eylemlerdeki Parametreler
istek verilerine bağlıdır ve model bağlamakullanılarak onaylanır. Model-bağlantılı her şey için model
doğrulaması oluşur. ModelState.IsValid özelliği değeri, model bağlamanın ve doğrulamanın başarılı olup
olmadığını gösterir.
Eylem yöntemleri bir sorunu iş açısından eşlemek için mantık içermelidir. İş kaygıları genellikle denetleyicinin
bağımlılık eklemeyoluyla eriştiği hizmetler olarak temsil edilmelidir. Eylemler daha sonra iş eyleminin sonucunu
bir uygulama durumuna eşler.
Eylemler her şeyi döndürebilir, ancak bir yanıt üreten IActionResult (veya zaman uyumsuz metotlar için
Task<IActionResult> ) bir örneğini döndürür. Eylem yöntemi, ne tür bir yanıtseçmekten sorumludur. Eylem
sonucu Yanıtverir.
Denetleyici Yardımcısı yöntemleri
Denetleyiciler genellikle denetleyicidendevralınır, ancak bu gerekli değildir. Controller türetmek, üç yardımcı
yöntem kategorisine erişim sağlar:
1. Yöntemler boş bir yanıt gövdesine yol açar
Yanıt gövdesinde betimleyen içerik olmadığından Content-Type HTTP yanıt üst bilgisi dahil değildir.
Bu kategori içinde iki sonuç türü vardır: Redirect ve HTTP durum kodu.
HTTP durum kodu
Bu tür bir HTTP durum kodu döndürür. Bu türden birkaç yardımcı yöntem BadRequest , NotFound ve Ok .
Örneğin, return BadRequest(); yürütüldüğünde 400 durum kodu üretir. BadRequest , NotFound ve Ok
gibi yöntemler aşırı yüklendiğinde, içerik anlaşması gerçekleşdiğinden artık HTTP durum kodu
Yanıtlayıcıları olarak niteleyemez.
Meniz
Bu tür bir eyleme veya hedefe yeniden yönlendirme döndürür ( Redirect , LocalRedirect ,
RedirectToAction veya RedirectToRoute kullanarak). Örneğin, Complete bir anonim nesne geçirerek
return RedirectToAction("Complete", new {id = 123}); yeniden yönlendirir.

Yeniden yönlendirme sonuç türü, birincil olarak Location HTTP yanıt üst bilgisi ekleme içindeki HTTP
durum kodu türünden farklıdır.
2. Yöntemler, önceden tanımlanmış bir içerik türüyle boş olmayan bir yanıt gövdesine yol açar
Bu kategorideki birçok yardımcı yöntem bir ContentType özelliği içerir ve bu da yanıt gövdesini tanımlayacak
Content-Type yanıt üst bilgisini ayarlamanıza olanak sağlar.

Bu kategori içinde iki sonuç türü vardır: görüntüleme ve biçimli yanıt.


Görünümü
Bu tür, HTML işlemek için bir model kullanan bir görünüm döndürür.Örneğin return View(customer); ,
veri bağlama için bir modeli bir modele geçirir.
Biçimlendirilen yanıt
Bu tür, bir nesneyi belirli bir şekilde göstermek için JSON veya benzer bir veri değişimi biçimi döndürür.
Örneğin, return Json(customer); , belirtilen nesneyi JSON biçimine dizleştirir.
Bu türün diğer yaygın yöntemleri File ve PhysicalFileiçerir. Örneğin,
return PhysicalFile(customerFilePath, "text/xml"); Physicalfileresultdöndürür.
3. Yöntemler, istemci ile anlaşan bir içerik türünde biçimlendirilen boş olmayan bir yanıt gövdesinin oluşmasına neden olur
Bu kategori, Içerik anlaşmasıolarak daha iyi bilinir. İçerik anlaşması , bir eylem bir ObjectResult türü ya da
ıactionresult uygulaması dışında bir şey döndürdüğünde geçerlidir. IActionResult olmayan bir uygulama
döndüren bir eylem (örneğin, object ), aynı zamanda biçimli bir yanıt döndürür.
Bu türden bazı yardımcı yöntemler BadRequest , CreatedAtRoute ve Ok içerir. Bu yöntemlere örnek olarak
sırasıyla return BadRequest(modelState); , return CreatedAtRoute("routename", values, newobject); ve
return Ok(value); verilebilir. BadRequest ve Ok yalnızca bir değer geçirildiğinde içerik anlaşması
gerçekleştirdiğine unutmayın; bir değer geçirilmeden, bunun yerine HTTP durum kodu sonuç türleri olarak işlev
görür. Diğer taraftan CreatedAtRoute yöntemi her zaman içerik anlaşması gerçekleştirir, çünkü aşırı
yüklemelerinin hepsi bir değer geçirilmesini gerektirir.
Çapraz kesme konuları
Uygulamalar genellikle iş akışının parçalarını paylaşır. Örnek olarak, alışveriş sepetine erişmek için kimlik
doğrulaması gerektiren bir uygulama veya bazı sayfalarda verileri önbelleğe alan bir uygulama verilebilir. Bir
eylem yönteminden önce veya sonra mantık gerçekleştirmek için bir filtrekullanın. Çapraz kesme sorunları
üzerinde filtrelerin kullanılması, yinelemeyi azaltabilir.
[Authorize] gibi çoğu filtre özniteliği, istenen ayrıntı düzeyi düzeyine bağlı olarak denetleyiciye veya eylem
düzeyine uygulanabilir.
Hata işleme ve yanıt önbelleklemesi genellikle çapraz kesme kaygılardır:
Hataları işleme
Yanıtları Önbelleğe Alma
Birçok çapraz kesme konusu, filtreler veya özel Ara yazılımkullanılarak işlenebilir.
ASP.NET Core denetleyici eylemlerine
yönlendirme
6.12.2019 • 51 minutes to read • Edit Online

Ryan şimdi ak ve Rick Anderson


ASP.NET Core MVC, gelen isteklerin URL 'Leriyle eşleştirmek ve bunları eylemlerle eşlemek için
yönlendirme Ara yazılımını kullanır. Yollar başlangıç kodunda veya özniteliklerde tanımlanmıştır. Yollar
URL yollarının eylemlerle nasıl eşleştirileceği açıklanır. Yollar, yanıt olarak gönderilen URL 'Leri
(bağlantılar için) oluşturmak için de kullanılır.
Eylemler genel olarak Dolaştırılan veya Attribute olarak yönlendirilir. Bir yolu denetleyiciye koymak veya
eylemi, BT özniteliği yönlendirilmesini sağlar. Daha fazla bilgi için bkz. karma yönlendirme .
Bu belge, MVC ve yönlendirme arasındaki etkileşimleri ve tipik MVC uygulamalarının yönlendirme
özelliklerini nasıl kullandığını açıklar. Gelişmiş yönlendirme hakkında ayrıntılar için bkz. yönlendirme .

Yönlendirme ara yazılımını ayarlama


Yapılandırma yönteminde şuna benzer bir kod görebilirsiniz:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc çağrısının içinde MapRoute , default rota olarak başvurabileceğiniz tek bir yol oluşturmak için
kullanılır. Çoğu MVC uygulaması, default yoluna benzer bir şablon içeren bir yol kullanır.
Yol şablonu "{controller=Home}/{action=Index}/{id?}" /Products/Details/5 gibi bir URL yoluyla
eşleştirebilir ve yolu simgeleştirerek { controller = Products, action = Details, id = 5 } yol değerlerini
ayıklar. MVC, ProductsController adlı bir denetleyiciyi bulmaya çalışır ve Details eylemi çalıştırır:

public class ProductsController : Controller


{
public IActionResult Details(int id) { ... }
}

Bu örnekte model bağlamanın, bu eylemi çağırırken id parametresini 5 olarak ayarlamak için id = 5


değerini kullanabileceğini unutmayın. Daha fazla ayrıntı için model bağlamaya bakın.
default yolunu kullanma:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

Yol şablonu:
{controller=Home} varsayılan olarak Home tanımlar controller

{action=Index} varsayılan olarak Index tanımlar action


{id?} id isteğe bağlı olarak tanımlar
Bir eşleşme için URL yolunda varsayılan ve isteğe bağlı yol parametrelerinin mevcut olması gerekmez.
Yol şablonu sözdiziminin ayrıntılı açıklaması için bkz. route Template Reference .
"{controller=Home}/{action=Index}/{id?}" ,
URL yolu ile eşleştirebilir ve
/
{ controller = Home, action = Index } yol değerlerini üretecektir. controller ve action değerleri
varsayılan değerleri kullanır id , URL yolunda karşılık gelen bir kesim olmadığından, bu değer
oluşturmaz. MVC bu yol değerlerini kullanarak HomeController ve Index eylemini seçer:

public class HomeController : Controller


{
public IActionResult Index() { ... }
}

Bu denetleyici tanımı ve yönlendirme şablonunu kullanarak, aşağıdaki URL yollarından herhangi biri için
HomeController.Index eylemi yürütülür:

/Home/Index/17

/Home/Index

/Home

Kolaylık yöntemi UseMvcWithDefaultRoute :

app.UseMvcWithDefaultRoute();

Değiştirmek için kullanılabilir:

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc ve UseMvcWithDefaultRoute ara yazılım ardışık düzenine bir RouterMiddleware örneği ekleyin.
MVC, doğrudan ara yazılım ile etkileşime girmez ve istekleri işlemek için yönlendirmeyi kullanır. MVC bir
MvcRouteHandler örneği aracılığıyla yollara bağlanır. UseMvc içindeki kod aşağıdaki gibidir:

var routes = new RouteBuilder(app);

// Add connection to MVC, will be hooked up by calls to MapRoute.


routes.DefaultHandler = new MvcRouteHandler(...);

// Execute callback to register routes.


// routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

// Create route collection and add the middleware.


app.UseRouter(routes.Build());

UseMvc doğrudan hiçbir yol tanımlamıyor, yol koleksiyonuna attribute yolu için bir yer tutucu ekler.
Aşırı yükleme UseMvc(Action<IRouteBuilder>) kendi rotalarınızı eklemenize ve öznitelik yönlendirmeyi de
desteklemenizi sağlar. UseMvc ve tüm çeşitlemeleri, UseMvc yapılandırma şeklinden bağımsız olarak her
zaman kullanılabilir öznitelik yönlendirme özniteliği. UseMvcWithDefaultRoute varsayılan bir yol tanımlar
ve öznitelik yönlendirmeyi destekler. Öznitelik yönlendirme bölümü öznitelik yönlendirme hakkında daha
fazla ayrıntı içerir.

Geleneksel yönlendirme
default yolu:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

, geleneksel yönlendirmeyebir örnektir. Bu stil geleneksel yönlendirmeyi , URL yolları için bir kural
oluşturduğundan çağırıyoruz:
ilk yol kesimi denetleyicinin adıyla eşlenir
İkincisi eylem adıyla eşlenir.
üçüncü segment bir model varlığına eşlemek için kullanılan isteğe bağlı id kullanılır

Bu default yolunu kullanarak, URL yolu /Products/List ProductsController.List eylemine eşlenir ve


/Blog/Article/17 eşlenir BlogController.Article . Bu eşleme yalnızca denetleyiciye ve eylem adlarına
dayalıdır ve ad alanları, kaynak dosya konumları veya yöntem parametrelerine göre değildir.

TIP
Varsayılan yol ile geleneksel yönlendirmeyi kullanmak, tanımladığınız her eylem için yeni bir URL düzeniyle
karşılaşmanıza gerek kalmadan uygulamayı hızlı bir şekilde oluşturmanıza olanak tanır. CRUD stilinde eylemlere
sahip bir uygulama için denetleyicilerinizdeki URL 'Lerin tutarlılığı, kodunuzun basitleştirilmesine ve Kullanıcı
arabiriminizi daha öngörülebilir hale getirmenize yardımcı olabilir.

WARNING
id , yol şablonu tarafından isteğe bağlı olarak tanımlanır ve bu, eylemlerinizin URL 'nin bir parçası olarak
sağlanmadan yürütebileceği anlamına gelir. Genellikle, URL 'den id atlandığında ne olur, bu durum model
bağlama tarafından 0 olarak ayarlanır ve sonuç olarak veritabanında eşleşen id == 0 hiçbir varlık
bulunamacaktır. Öznitelik yönlendirme, bazı eylemler için gereken KIMLIĞI, diğerleri için değil, daha ayrıntılı bir
denetim sağlayabilir. Kurala göre belgeler, doğru kullanımlarda görünebilecekleri id gibi isteğe bağlı
parametreleri de içerecektir.

Birden çok yol


MapRoute daha fazla çağrı ekleyerek UseMvc içine birden çok yol ekleyebilirsiniz. Bunun yapılması, birden
çok kural tanımlamanızı veya belirli bir eyleme adanmış geleneksel yollar eklemenizi sağlar; örneğin:

app.UseMvc(routes =>
{
routes.MapRoute("blog", "blog/{*article}",
defaults: new { controller = "Blog", action = "Article" });
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Buradaki blog yol, geleneksel bir geleneksel yoldur, yani geleneksel yönlendirme sistemini kullanır,
ancak belirli bir eyleme ayrılmıştır. controller ve action yol şablonunda parametre olarak
görünmadığından, bu yol yalnızca varsayılan değerlere sahip olabilir ve bu nedenle bu yol her zaman
eylem BlogController.Article eşlenir.
Rota koleksiyonundaki yollar sıralanır ve eklendikleri sırada işlenir. Bu örnekte, blog yolu default
rotadan önce denenecek.

NOTE
Adanmış geleneksel yollar genellıkle, URL yolunun kalan kısmını yakalamak için {*article} gibi catch-all Route
parametrelerini kullanır. Bu, ' çok Greedy ' yolunu diğer yollarla eşleştirirken hedeflediğiniz URL 'Lerle eşleşen bir
yol haline getirir. Bunu çözümlemek için ' Greedy ' yollarını daha sonra yol tablosuna koyun.

Geri dönüş
İstek işlemenin bir parçası olarak, MVC, uygulamanızdaki bir denetleyiciyi ve eylemi bulmak için yol
değerlerinin kullanılabileceğini doğrular. Rota değerleri bir eylemle eşleşmezse, yol eşleşme olarak kabul
edilmez ve sonraki rota denenir. Buna geri dönüşdenir ve geleneksel yolların çakıştığı durumları
basitleştirmek için tasarlanmıştır.
Kesinleştirme eylemleri
İki eylem yönlendirme aracılığıyla eşleşiyorsa, MVC ' en iyi ' adayı seçmek için bir özel durum
oluşturması veya bir özel durum oluşturmak için, MVC 'nin belirsizliğini Örneğin:

public class ProductsController : Controller


{
public IActionResult Edit(int id) { ... }

[HttpPost]
public IActionResult Edit(int id, Product product) { ... }
}

Bu denetleyici, URL yolu ile eşleşen iki eylemi tanımlar ve verileri


/Products/Edit/17
{ controller = Products, action = Edit, id = 17 } yönlendirir. Bu, Edit(int) bir ürünü düzenlemek
üzere bir form gösterdiği ve Edit(int, Product) postalanan formu işleyen MVC denetleyicileri için tipik
bir modeldir. Bunu yapmak için bu olası MVC, istek bir HTTP POST olduğunda Edit(int, Product) ve
HTTP fiili başka bir şey olduğunda Edit(int) ' ı seçmeniz gerekir.
HttpPostAttribute ( [HttpPost] ), yalnızca HTTP fiili POST olduğunda eylemin seçili olmasını sağlayacak
IActionConstraint uygulamasıdır. IActionConstraint olması, Edit(int, Product) ' daha iyi bir eşleşme
Edit(int) , bu nedenle önce Edit(int, Product) denenmesini sağlar.

Yalnızca özelleştirilmiş senaryolarda özel IActionConstraint uygulamalar yazmanız gerekir, ancak diğer
HTTP fiilleri için HttpPostAttribute benzer öznitelikler gibi özniteliklerin rol olduğunu anlamak
önemlidir. Geleneksel yönlendirmesinde, eylemler bir show form -> submit form iş akışının parçası
olduğunda aynı eylem adını kullanmak yaygındır. Bu düzenin rahatlığı, ıactionconstraint 'ı anlama
bölümünde daha sonra görünür hale gelir.
Birden çok yol eşleşirse ve MVC ' en iyi ' yolu bulamazsa, bir AmbiguousActionException oluşturur.
Yol adları
Aşağıdaki örneklerde "blog" ve "default" dizeler yol adlarıdır:
app.UseMvc(routes =>
{
routes.MapRoute("blog", "blog/{*article}",
defaults: new { controller = "Blog", action = "Article" });
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Yol adları, URL oluşturma için adlandırılmış yolun kullanılabilmesi için yola mantıksal bir ad verir. Bu,
yolların sıralaması URL oluşturma karmaşık hale geldiğinde URL oluşturmayı büyük ölçüde basitleştirir.
Yol adları, uygulama genelinde benzersiz olmalıdır.
Yol adları, isteklerin URL 'SI ile eşleşmesini veya işlenmesini etkilemez; Bunlar yalnızca URL oluşturma
için kullanılır. Yönlendirme , MVC 'ye özgü yardımcılardaki URL oluşturma da dahil olmak üzere URL
oluşturma hakkında daha ayrıntılı bilgiler içerir.

Öznitelik yönlendirme
Öznitelik yönlendirme eylemleri doğrudan yönlendirme şablonlarına eşlemek için bir öznitelik kümesi
kullanır. Aşağıdaki örnekte, app.UseMvc(); Configure yönteminde kullanılır ve hiçbir yol geçirilir.
HomeController , varsayılan yol {controller=Home}/{action=Index}/{id?} eşleşeceğinize benzer bir URL
kümesiyle eşleşir:

public class HomeController : Controller


{
[Route("")]
[Route("Home")]
[Route("Home/Index")]
public IActionResult Index()
{
return View();
}
[Route("Home/About")]
public IActionResult About()
{
return View();
}
[Route("Home/Contact")]
public IActionResult Contact()
{
return View();
}
}

HomeController.Index() eylem, / , /Home veya /Home/Index URL yollarından herhangi biri için yürütülür.

NOTE
Bu örnek, öznitelik yönlendirme ve geleneksel yönlendirme arasında bir temel programlama farkı vurgulamaktadır.
Öznitelik yönlendirme, bir yol belirtmek için daha fazla giriş gerektirir; geleneksel varsayılan yol, yönlendirmeleri
daha succinctly işler. Ancak, öznitelik yönlendirme (ve gerektirir) her eylem için hangi rota şablonlarının
uygulanacağını kesin olarak denetler.

Öznitelik yönlendirme ile, denetleyici adı ve eylem adları, herhangi bir eylem seçildiği hiçbir rol oynar.
Bu örnek, önceki örnekle aynı URL 'Lerle eşleştirecektir.
public class MyDemoController : Controller
{
[Route("")]
[Route("Home")]
[Route("Home/Index")]
public IActionResult MyIndex()
{
return View("Index");
}
[Route("Home/About")]
public IActionResult MyAbout()
{
return View("About");
}
[Route("Home/Contact")]
public IActionResult MyContact()
{
return View("Contact");
}
}

NOTE
Yukarıdaki yol şablonları action , area ve controller için yol parametreleri tanımlamaz. Aslında, öznitelik
rotalarında bu yol parametrelerine izin verilmez. Yol şablonu bir eylemle zaten ilişkili olduğundan, URL 'den eylem
adını ayrıştırmak mantıklı değildir.

Http [fiil] öznitelikleriyle öznitelik yönlendirme


Öznitelik yönlendirme Ayrıca, HttpPostAttribute gibi Http[Verb] özniteliklerini de kullanabilir. Bu
özniteliklerin hepsi bir yol şablonunu kabul edebilir. Bu örnekte, aynı rota şablonuyla eşleşen iki eylem
gösterilmektedir:

[HttpGet("/products")]
public IActionResult ListProducts()
{
// ...
}

[HttpPost("/products")]
public IActionResult CreateProduct(...)
{
// ...
}

/products gibi bir URL yolu için, HTTP fiili GET olduğunda ProductsApi.ListProducts eylemi yürütülür
ve HTTP fiili POST olduğunda ProductsApi.CreateProduct yürütülür. Öznitelik yönlendirme öncelikle URL
ile yol öznitelikleri tarafından tanımlanan yol şablonları kümesine göre eşleşir. Bir rota şablonu
eşleştiğinde, hangi eylemlerin yürütüleceğini belirleyen IActionConstraint kısıtlamalar uygulanır.

TIP
Bir REST API oluştururken, eylem tüm HTTP yöntemlerini kabul edecek şekilde bir eylem yönteminde
[Route(...)] kullanmak isteyeceksiniz. API 'nizin neleri desteklediği hakkında kesin olması için daha özel
Http*Verb*Attributes kullanmak daha iyidir. REST API 'lerinin istemcileri, hangi yolların ve HTTP fiillerinin belirli
mantıksal işlemlere eşlendiğini bilmelidir.
Bir öznitelik yolu belirli bir eyleme uyguladığı için, yol şablonu tanımının bir parçası olarak gerekli
parametreleri yapmak kolaydır. Bu örnekte, URL yolunun bir parçası olarak id gereklidir.

public class ProductsApiController : Controller


{
[HttpGet("/products/{id}", Name = "Products_List")]
public IActionResult GetProduct(int id) { ... }
}

ProductsApi.GetProduct(int) eylemi, /products/3 gibi bir URL yolu için yürütülür, ancak /products gibi
bir URL yolu için değil. Yol şablonlarının ve ilgili seçeneklerin tam açıklaması için bkz. yönlendirme .

Yol adı
Aşağıdaki kod Products_List yol adını tanımlar:

public class ProductsApiController : Controller


{
[HttpGet("/products/{id}", Name = "Products_List")]
public IActionResult GetProduct(int id) { ... }
}

Yol adları, belirli bir yolu temel alan bir URL oluşturmak için kullanılabilir. Rota adlarının, yönlendirmenin
URL eşleştirme davranışına etkisi yoktur ve yalnızca URL oluşturma için kullanılır. Yol adları, uygulama
genelinde benzersiz olmalıdır.

NOTE
Bunu, id parametresini isteğe bağlı ( {id?} ) olarak tanımlayan geleneksel varsayılan rotaylakarşıtın. API 'Leri
tam olarak belirtme özelliği, /products ve /products/5 farklı eylemlere dağıtılması gibi avantajlar sağlar.

Yolları birleştirme
Öznitelik yönlendirmeyi daha az tekrarlı hale getirmek için, denetleyicideki yol öznitelikleri, bireysel
eylemlerdeki rota öznitelikleriyle birleştirilir. Denetleyicide tanımlanan tüm yol şablonları, eylemlerdeki
rota şablonlarına eklenir. Bir Route özniteliğinin denetleyiciye yerleştirilmesi, denetleyicideki Tüm
eylemlerin öznitelik yönlendirme kullanmasını sağlar.

[Route("products")]
public class ProductsApiController : Controller
{
[HttpGet]
public IActionResult ListProducts() { ... }

[HttpGet("{id}")]
public ActionResult GetProduct(int id) { ... }
}

Bu örnekte, URL yolu /products ile eşleştirebilir ve URL yolu /products/5


ProductsApi.ListProducts
ProductsApi.GetProduct(int) eşleştirebilir. Bu eylemlerin her ikisi de, HttpGetAttribute olarak
işaretlendiğinden HTTP GET eşleşir.
/ veya ~/ ile başlayan bir eyleme uygulanan yol şablonları denetleyiciye uygulanan yol şablonları ile
birleştirilmemelidir. Bu örnek, varsayılan rotayabenzer bir URL yolları kümesiyle eşleşir.
[Route("Home")]
public class HomeController : Controller
{
[Route("")] // Combines to define the route template "Home"
[Route("Index")] // Combines to define the route template "Home/Index"
[Route("/")] // Doesn't combine, defines the route template ""
public IActionResult Index()
{
ViewData["Message"] = "Home index";
var url = Url.Action("Index", "Home");
ViewData["Message"] = "Home index" + "var url = Url.Action; = " + url;
return View();
}

[Route("About")] // Combines to define the route template "Home/About"


public IActionResult About()
{
return View();
}
}

Öznitelik yollarını sıralama


Tanımlı sırada yürütülen geleneksel yolların aksine, öznitelik yönlendirme bir ağaç oluşturur ve tüm
yollarla aynı anda eşleşir. Bu, yol girişleri ideal bir sıralamaya yerleştirildiyse olduğu gibi davranır; en özel
yolların, daha genel yollardan önce yürütülmesi şansınız vardır.
Örneğin, blog/search/{topic} gibi bir yol blog/{*article} gibi bir yol daha özgüdür. İlk olarak '
çalıştırmaları ' blog/search/{topic} yolu için, varsayılan olarak, tek yapmanız gereken tek bir sıralama
olduğundan mantıksal olarak konuşun. Geleneksel yönlendirmeyi kullanarak, yolları istenen sırada
yerleştirmekten geliştirici sorumludur.
Öznitelik yolları, tüm Framework yol özniteliklerinin Order özelliğini kullanarak bir sıra yapılandırabilir.
Yollar Order özelliğinin artan sıralamasına göre işlenir. Varsayılan sıra 0 . Order = -1 kullanarak bir
yolun ayarlanması, bir sipariş ayarlamadan önce çalıştırılacak rotalardan önce çalıştırılır. Order = 1
kullanarak bir yolun ayarlanması, varsayılan yol sıralaması sonrasında çalışacaktır.

TIP
Order bağlı olmadığından kaçının. URL alanınız, doğru sıralama değerlerinin doğru şekilde yönlendirilmesini
gerektiriyorsa, istemciler de kafa karıştırıcı olabilir. Genel öznitelik yönlendirme ' de, URL eşleştirme ile doğru yolu
seçer. URL oluşturma için kullanılan varsayılan sıra çalışmıyorsa, yol adının bir geçersiz kılma olarak kullanılması
genellikle Order özelliğini uygulamaktan daha basittir.

Razor Pages yönlendirme ve MVC denetleyici yönlendirme bir uygulamayı paylaşır. Razor Pages
konularındaki yol siparişi hakkında bilgiler Razor Pages yol ve uygulama kuralları: yol sıralaması' nda
bulunabilir.

Yol şablonlarında belirteç değiştirme ([denetleyici], [eylem],


[alan])
Özellik yolları, bir belirteci köşeli ayraç içine alarak belirteç değişimini destekler ( [ , ] ). [action] ,
[area] ve [controller] belirteçleri, yolun tanımlandığı eylemden eylem adı, alan adı ve denetleyici adı
değerleriyle değiştirilmiştir. Aşağıdaki örnekte, Eylemler, açıklamalarda açıklandığı gibi URL yollarıyla
eşleşir:
[Route("[controller]/[action]")]
public class ProductsController : Controller
{
[HttpGet] // Matches '/Products/List'
public IActionResult List() {
// ...
}

[HttpGet("{id}")] // Matches '/Products/Edit/{id}'


public IActionResult Edit(int id) {
// ...
}
}

Belirteç değişikliği, öznitelik yollarının oluşturulması için son adım olarak gerçekleşir. Yukarıdaki örnek
aşağıdaki kodla aynı şekilde davranır:

public class ProductsController : Controller


{
[HttpGet("[controller]/[action]")] // Matches '/Products/List'
public IActionResult List() {
// ...
}

[HttpGet("[controller]/[action]/{id}")] // Matches '/Products/Edit/{id}'


public IActionResult Edit(int id) {
// ...
}
}

Öznitelik rotaları de devralma ile birleştirilebilir. Bu özellikle, belirteç değiştirme ile güçlü bir şekilde
birleştirilir.

[Route("api/[controller]")]
public abstract class MyBaseController : Controller { ... }

public class ProductsController : MyBaseController


{
[HttpGet] // Matches '/api/Products'
public IActionResult List() { ... }

[HttpPut("{id}")] // Matches '/api/Products/{id}'


public IActionResult Edit(int id) { ... }
}

Belirteç değişikliği, öznitelik rotaları tarafından tanımlanan yol adları için de geçerlidir.
[Route("[controller]/[action]", Name="[controller]_[action]")] her eylem için benzersiz bir yol adı
üretir.
Sabit belirteç değiştirme sınırlayıcısı [ veya ] eşleştirmek için, karakteri ( [[ veya ]] ) tekrarlayarak
kaçış.
Belirteç değişimini özelleştirmek için bir parametre transformatörü kullanın
Belirteç değiştirme, bir parametre transformatörü kullanılarak özelleştirilebilir. Bir parametre
transformatörü IOutboundParameterTransformer uygular ve parametrelerin değerini dönüştürür. Örneğin,
özel bir SlugifyParameterTransformer parametresi transformatörü SubscriptionManagement Route
değerini subscription-management olarak değiştirir.
RouteTokenTransformerConvention , şu şekilde bir uygulama modeli kuralıdır:
Bir uygulamadaki tüm öznitelik yollarına bir parametre transformatörü uygular.
Öznitelik yol belirteci değerlerini değiştirildikleri gibi özelleştirir.

public class SubscriptionManagementController : Controller


{
[HttpGet("[controller]/[action]")] // Matches '/subscription-management/list-all'
public IActionResult ListAll() { ... }
}

RouteTokenTransformerConvention , ConfigureServices bir seçenek olarak kaydedilir.

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Conventions.Add(new RouteTokenTransformerConvention(
new SlugifyParameterTransformer()));
});
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer


{
public string TransformOutbound(object value)
{
if (value == null) { return null; }

// Slugify value
return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
}
}

Birden çok yol


Öznitelik yönlendirme, aynı eyleme ulaşan birden çok yolun tanımlanmasını destekler. Bunun en yaygın
kullanımları, aşağıdaki örnekte gösterildiği gibi varsayılan geleneksel yolun davranışını taklit etmek olur:

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

Denetleyiciye birden çok yol özniteliği koymak, her birinin eylem yöntemlerinde yol özniteliklerinin her
biriyle birleşmesi anlamına gelir.

[Route("Store")]
[Route("[controller]")]
public class ProductsController : Controller
{
[HttpPost("Buy")] // Matches 'Products/Buy' and 'Store/Buy'
[HttpPost("Checkout")] // Matches 'Products/Checkout' and 'Store/Checkout'
public IActionResult Buy()
}

Birden çok yol özniteliği ( IActionConstraint uygulayan) bir eyleme yerleştirildiğinde, her eylem
kısıtlaması, onu tanımlayan öznitelikten yol şablonuyla birleştirir.
[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpPut("Buy")] // Matches PUT 'api/Products/Buy'
[HttpPost("Checkout")] // Matches POST 'api/Products/Checkout'
public IActionResult Buy()
}

TIP
Eylemlerde birden çok yolun kullanılması güçlü görünse de, uygulamanızın URL alanının basit ve iyi tanımlanmış
tutulması daha iyidir. Yalnızca gerektiğinde eylemler üzerinde birden çok yol kullanın, örneğin mevcut istemcileri
desteklemek için.

Öznitelik rotası isteğe bağlı parametreler, varsayılan değerler ve kısıtlamalar belirtme


Öznitelik yolları, isteğe bağlı parametreleri, varsayılan değerleri ve kısıtlamaları belirtmek için geleneksel
yollarla aynı satır içi sözdizimini destekler.

[HttpPost("product/{id:int}")]
public IActionResult ShowProduct(int id)
{
// ...
}

Yol şablonu sözdiziminin ayrıntılı açıklaması için bkz. route Template Reference .
IRouteTemplateProvider kullanarak özel yol öznitelikleri
Çerçevede ( [Route(...)] , [HttpGet(...)] , vb.) sunulan yol özniteliklerinin hepsi
IRouteTemplateProvider arabirimini uygular. MVC, uygulama başlatıldığında denetleyici sınıflarında ve
eylem yöntemlerinde öznitelikler arar ve ilk yol kümesini oluşturmak için IRouteTemplateProvider
uygulayan uygulamaları kullanır.
Kendi yol öznitelerinizi tanımlamak için IRouteTemplateProvider uygulayabilirsiniz. Her
IRouteTemplateProvider , özel bir yol şablonu, sırası ve adı ile tek bir yol tanımlamanızı sağlar:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider


{
public string Template => "api/[controller]";

public int? Order { get; set; }

public string Name { get; set; }


}

Yukarıdaki örnekteki özniteliği, [MyApiController] uygulandığında otomatik olarak Template


"api/[controller]" olarak ayarlar.

Öznitelik yollarını özelleştirmek için uygulama modelini kullanma


Uygulama modeli , MVC tarafından eylemlerinizi yönlendirmek ve yürütmek için kullanılan tüm meta
veriler ile başlangıçta oluşturulan bir nesne modelidir. Uygulama modeli , yol özniteliklerinden toplanan
tüm verileri içerir ( IRouteTemplateProvider aracılığıyla). Yönlendirme işleminin nasıl davranacağını
özelleştirmek için, Başlangıç zamanında uygulama modelini değiştirmek üzere kurallar yazabilirsiniz. Bu
bölümde, uygulama modeli kullanılarak yönlendirmeyi özelleştirmenin basit bir örneği gösterilmektedir.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
using System.Text;
public class NamespaceRoutingConvention : IControllerModelConvention
{
private readonly string _baseNamespace;

public NamespaceRoutingConvention(string baseNamespace)


{
_baseNamespace = baseNamespace;
}

public void Apply(ControllerModel controller)


{
var hasRouteAttributes = controller.Selectors.Any(selector =>
selector.AttributeRouteModel != null);
if (hasRouteAttributes)
{
// This controller manually defined some routes, so treat this
// as an override and not apply the convention here.
return;
}

// Use the namespace and controller name to infer a route for the controller.
//
// Example:
//
// controller.ControllerTypeInfo -> "My.Application.Admin.UsersController"
// baseNamespace -> "My.Application"
//
// template => "Admin/[controller]"
//
// This makes your routes roughly line up with the folder structure of your project.
//
var namespc = controller.ControllerType.Namespace;
if (namespc == null)
return;
var template = new StringBuilder();
template.Append(namespc, _baseNamespace.Length + 1,
namespc.Length - _baseNamespace.Length - 1);
template.Replace('.', '/');
template.Append("/[controller]");

foreach (var selector in controller.Selectors)


{
selector.AttributeRouteModel = new AttributeRouteModel()
{
Template = template.ToString()
};
}
}
}

Karma yönlendirme: öznitelik yönlendirme vs geleneksel


yönlendirme
MVC uygulamaları, geleneksel yönlendirme ve öznitelik yönlendirmenin kullanımını karıştırabilir.
Tarayıcılar için HTML sayfalarına hizmet veren denetleyiciler için geleneksel yollar ve REST API 'Lerine
hizmet veren denetleyiciler için öznitelik yönlendirme kullanılması normaldir.
Eylemler genel olarak Dolaştırılan veya Attribute olarak yönlendirilir. Bir yolu denetleyiciye koymak veya
eylemi, BT özniteliği yönlendirilmesini sağlar. Öznitelik yollarını tanımlayan eylemlere geleneksel yollar
üzerinden ulaşılamıyor ve bunun tersi de geçerlidir. Denetleyicideki herhangi bir rota özniteliği,
denetleyici özniteliğindeki tüm eylemlerin yönlendirilmesini sağlar.

NOTE
İki tür yönlendirme sisteminin ayırt edilmesini ne kadar ayırt eden, bir URL bir yol şablonuyla eşleştirdikten sonra
uygulanan işlemdir. Geleneksel yönlendirmesinde, eşleşmeden yol değerleri, tüm geleneksel yönlendirilmiş
eylemlerin arama tablosundan eylemi ve denetleyiciyi seçmek için kullanılır. Öznitelik yönlendirmesinde, her şablon
zaten bir eylemle ilişkilendirilir ve başka bir arama gerekmez.

Karmaşık segmentler
Karmaşık segmentler (örneğin, [Route("/dog{token}cat")] ), sabit değerli olmayan değişmez değerler ile
sağdan sola eşleştirilirken işlenir. Bir açıklama için bkz. kaynak kodu . Daha fazla bilgi için Bu
sorunabakın.

URL oluşturma
MVC uygulamaları, eylemlere URL bağlantıları oluşturmak için yönlendirmenin URL oluşturma
özelliklerini kullanabilir. URL oluşturma, kodlarınızın daha sağlam ve sürdürülebilir hale getirilmesi için
sorunsuz kodlama URL 'Lerini ortadan kaldırır. Bu bölüm, MVC tarafından sunulan URL oluşturma
özelliklerine odaklanır ve yalnızca URL oluşturmanın nasıl çalıştığına ilişkin temel bilgileri kapsar. URL
oluşturma hakkında ayrıntılı bir açıklama için bkz. yönlendirme .
IUrlHelper arabirimi, URL oluşturma için MVC ve yönlendirme arasındaki temel altyapı parçasıdır.
Denetleyiciler, görünümler ve görünüm bileşenlerinde Url özelliği aracılığıyla kullanılabilen bir
IUrlHelper örneğini bulacaksınız.

Bu örnekte IUrlHelper arabirimi, başka bir eyleme yönelik bir URL oluşturmak için Controller.Url
özelliği aracılığıyla kullanılır.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller


{
public IActionResult Source()
{
// Generates /UrlGeneration/Destination
var url = Url.Action("Destination");
return Content($"Go check out {url}, it's really great.");
}

public IActionResult Destination()


{
return View();
}
}

Uygulama varsayılan geleneksel rotayı kullanıyorsa, url değişkenin değeri /UrlGeneration/Destination


URL yol dizesi olacaktır. Bu URL yolu, yönlendirme değerlerini, geçerli istekten (çevresel değerler),
Url.Action aktarılan değerlerle ve bu değerleri yol şablonuna geçirerek birleştirerek oluşturulur.

ambient values: { controller = "UrlGeneration", action = "Source" }


values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination
Yol şablonundaki her bir rota parametresinin değeri, değerler ve ortam değerleri ile eşleşen adlara sahip
olacak şekilde değiştirilir. Bir değere sahip olmayan bir rota parametresi, varsa varsayılan bir değer
kullanabilir veya isteğe bağlı ise (Bu örnekteki id olduğu gibi) atlanır. Gerekli yol parametresinin karşılık
gelen bir değeri yoksa, URL oluşturma başarısız olur. Bir yol için URL oluşturma başarısız olursa, tüm
yollar Denenene veya bir eşleşme bulunana kadar sonraki yol denenir.
Yukarıdaki Url.Action örneği geleneksel yönlendirmeyi varsayar, ancak URL oluşturma, öznitelik
yönlendirimiyle benzer şekilde çalışır, ancak kavramlar farklıdır. Geleneksel yönlendirme ile, bir şablonu
genişletmek için yol değerleri kullanılır ve controller ve action için rota değerleri genellikle bu
şablonda görünür-bu, yönlendirme ile eşleşen URL 'Ler bir kuralabağlı olduğundan, bu işe yarar.
Öznitelik yönlendirmesinde, controller ve action için yol değerlerinin şablonda görünmesine izin
verilmez; bunun yerine kullanılacak şablonu aramak için kullanılır.
Bu örnek öznitelik yönlendirme kullanır:

// In Startup class
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller


{
[HttpGet("")]
public IActionResult Source()
{
var url = Url.Action("Destination"); // Generates /custom/url/to/destination
return Content($"Go check out {url}, it's really great.");
}

[HttpGet("custom/url/to/destination")]
public IActionResult Destination() {
return View();
}
}

MVC, tüm öznitelik yönlendirilmiş eylemlerinin bir arama tablosunu oluşturur ve URL oluşturma için
kullanılacak yol şablonunu seçmek üzere controller ve action değerleriyle eşleşir. Yukarıdaki örnekte
custom/url/to/destination oluşturulur.

Eylem adına göre URL 'Leri oluşturma


Url.Action ( IUrlHelper . Action ) ve tüm ilgili aşırı yüklemeler, bir denetleyici adı ve eylem adı
belirterek ne bağlandığınızı belirtmek istediğinizi temel alır.

NOTE
Url.Action kullanırken, controller ve action için geçerli yol değerleri sizin için belirtilir; controller
değeri, action hem ortam değerlerinin hem de değerlerininbir parçasıdır. Url.Action yöntemi her zaman
action ve controller geçerli değerlerini kullanır ve geçerli eyleme yönlendiren bir URL yolu oluşturacaktır.

Yönlendirme, bir URL oluştururken sağlamadığınız bilgileri doldurmanızı sağlamak için çevresel
değerlerde değerleri kullanmayı dener. Yönlendirme parametrelerinin bir değere sahip olduğundan,
{a}/{b}/{c}/{d} ve çevresel değerler { a = Alice, b = Bob, c = Carol, d = David } gibi bir yol
kullanarak yönlendirme için ek değer olmadan bir URL oluşturmaya yetecek kadar bilgi vardır. Değer
{ d = Donovan } eklediyseniz, { d = David } değeri yok sayılır ve oluşturulan URL yolu
Alice/Bob/Carol/Donovan olur.

WARNING
URL yolları hiyerarşiktir. Yukarıdaki örnekte, değeri { c = Cheryl } eklediyseniz her iki değer de
{ c = Carol, d = David } yok sayılır. Bu durumda artık d için bir değer yoktur ve URL oluşturma başarısız
olur. İstediğiniz c ve d değerini belirtmeniz gerekir. Bu sorunu varsayılan yol ( {controller}/{action}/{id?} )
ile () beklemeniz gerekebilir; ancak, Url.Action her zaman açıkça bir controller ve action değeri belirtmesi
gibi uygulamada bu davranış hakkında nadiren karşılaşacaksınız.

Daha uzun Url.Action aşırı yüklemeleri, controller ve action dışındaki rota parametreleri için
değerler sağlamak üzere ek bir yol değerleri nesnesi de alır. Bu, en yaygın olarak
Url.Action("Buy", "Products", new { id = 17 }) gibi id kullanıldığını görürsünüz. Kurala göre yol
değerleri nesnesi genellikle anonim türdeki bir nesnedir, ancak bir IDictionary<> veya düz bir .net
nesneside olabilir. Yol parametreleriyle eşleşmeyen ek rota değerleri sorgu dizesine konur.

using Microsoft.AspNetCore.Mvc;

public class TestController : Controller


{
public IActionResult Index()
{
// Generates /Products/Buy/17?color=red
var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
return Content(url);
}
}

TIP
Mutlak URL oluşturmak için, protocol kabul eden bir aşırı yükleme kullanın:
Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)

Rotaya göre URL oluşturma


Yukarıdaki kod, denetleyiciyi ve eylem adını geçirerek bir URL oluşturmayı göstermiştir. IUrlHelper
Ayrıca Url.RouteUrl Yöntem ailesini da sağlar. Bu yöntemler Url.Action benzerdir, ancak action ve
controller geçerli değerlerini rota değerlerine kopyalamaz. En yaygın kullanım, genellikle bir
denetleyici veya eylem adı belirtmeden, URL oluşturmak için belirli bir yolu kullanmak üzere bir yol adı
belirtmektir.
using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller


{
[HttpGet("")]
public IActionResult Source()
{
var url = Url.RouteUrl("Destination_Route"); // Generates /custom/url/to/destination
return Content($"See {url}, it's really great.");
}

[HttpGet("custom/url/to/destination", Name = "Destination_Route")]


public IActionResult Destination() {
return View();
}
}

HTML 'de URL oluşturma


IHtmlHelper , <form> ve <a> öğeleri oluşturmak için HtmlHelper yöntemleri Html.BeginForm ve
Html.ActionLink sağlar. Bu yöntemler bir URL oluşturmak için Url.Action yöntemini kullanır ve benzer
bağımsız değişkenleri kabul ederler. HtmlHelper için Url.RouteUrl compan, benzer işlevlere sahip
Html.BeginRouteForm ve Html.RouteLink .

Taghelmakalar, form TagHelper ve <a> TagHelper aracılığıyla URL 'Ler oluşturur. Bunların her ikisi de
kendi uygulamaları için IUrlHelper . Daha fazla bilgi için bkz. formlarla çalışma .
Görünümler içinde IUrlHelper , yukarıdaki herhangi bir geçici URL nesli için Url özelliği aracılığıyla
kullanılabilir.
Eylem sonuçlarında URL oluşturma
Yukarıdaki örnekler, bir denetleyicide IUrlHelper kullanılarak gösterilmektedir, ancak denetleyicideki en
yaygın kullanım, bir eylem sonucunun parçası olarak bir URL oluşturmak olur.
ControllerBase ve Controller Taban sınıfları, başka bir eyleme başvuruda bulunan eylem sonuçları için
kolay yöntemler sağlar. Tipik bir kullanım, Kullanıcı girişi kabul edildikten sonra yeniden
yönlendirilmelidir.

public IActionResult Edit(int id, Customer customer)


{
if (ModelState.IsValid)
{
// Update DB with new details.
return RedirectToAction("Index");
}
return View(customer);
}

Eylem sonuçları Fabrika yöntemleri IUrlHelper yöntemlere benzer bir model izler.
Adanmış geleneksel yollar için özel durum
Geleneksel yönlendirme, adanmış geleneksel yololarak adlandırılan özel bir yol tanımı türünü
kullanabilir. Aşağıdaki örnekte, blog adlı yol adanmış bir geleneksel yoldur.
app.UseMvc(routes =>
{
routes.MapRoute("blog", "blog/{*article}",
defaults: new { controller = "Blog", action = "Article" });
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Url.Action("Index", "Home") , bu yol tanımlarını kullanarak / URL yolunu default rotası ile
oluşturacak, ancak neden? Yol değerlerini tahmin edebilirsiniz { controller = Home, action = Index }
blog kullanarak URL oluşturmak için yeterli olacaktır ve sonuç /blog?action=Index&controller=Home .

Adanmış geleneksel yollar, URL oluşturmayla "çok Greedy" olmasını önleyen karşılık gelen bir yol
parametresi olmayan varsayılan değerlerin özel bir davranışına bağımlıdır. Bu durumda, varsayılan
değerler { controller = Blog, action = Article } ve ne controller ne de action yol parametresi
olarak görünmez. Yönlendirme URL oluşturma işlemi gerçekleştirdiğinde, belirtilen değerler varsayılan
değerlerle eşleşmelidir. blog kullanılarak URL oluşturma başarısız olur çünkü değerler
{ controller = Home, action = Index } { controller = Blog, action = Article } eşleşmiyor. Ardından
yönlendirme default denemeye geri döner ve başarılı olur.

Alanlar
Bölgeler , ilgili işlevselliği ayrı bir yönlendirme-ad alanı (denetleyici eylemleri için) ve klasör yapısı
(görünümler için) olarak bir grupla düzenlemek için kullanılan bir MVC özelliğidir. Alanların kullanılması,
bir uygulamanın farklı alanlarasahip oldukları sürece aynı ada sahip birden çok denetleyicisi olmasına
olanak sağlar. Alanların kullanılması, başka bir yol parametresi ekleyerek yönlendirme amacına yönelik
bir hiyerarşi oluşturur, controller ve action``area . Bu bölüm, yönlendirmenin alanlarla nasıl etkileşime
gireceğini tartışır. alanların görünümlerle nasıl kullanıldığı hakkında ayrıntılar için bkz. alanlara bakın.
Aşağıdaki örnek, MVC 'yi, Blog adlı bir alan için varsayılan geleneksel yolu ve bir alan yolunu kullanacak
şekilde yapılandırır:

app.UseMvc(routes =>
{
routes.MapAreaRoute("blog_route", "Blog",
"Manage/{controller}/{action}/{id?}");
routes.MapRoute("default_route", "{controller}/{action}/{id?}");
});

/Manage/Users/AddUser gibi bir URL yolu eşleştirilirken, ilk yol


{ area = Blog, controller = Users, action = AddUser } yol değerlerini oluşturur. area yol değeri, area
için varsayılan bir değer tarafından üretilir, aslında MapAreaRoute tarafından oluşturulan yol, aşağıdaki
değere eşdeğerdir:

app.UseMvc(routes =>
{
routes.MapRoute("blog_route", "Manage/{controller}/{action}/{id?}",
defaults: new { area = "Blog" }, constraints: new { area = "Blog" });
routes.MapRoute("default_route", "{controller}/{action}/{id?}");
});

MapAreaRoute , area için hem varsayılan değer hem de kısıtlama (Bu durumda Blog ) kullanarak bir yol
oluşturur. Varsayılan değer, yolun her zaman { area = Blog, ... } üretmesini sağlar, kısıtlama, URL
oluşturma için { area = Blog, ... } değer gerektirir.
TIP
Geleneksel yönlendirme sıra bağımlıdır. Genel olarak, alanlar içeren rotalar, alan olmayan rotalardan daha belirgin
olduklarından daha önce rota tablosuna yerleştirilmelidir.

Yukarıdaki örneği kullanarak, yol değerleri aşağıdaki eylemle eşleşir:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
[Area("Blog")]
public class UsersController : Controller
{
public IActionResult AddUser()
{
return View();
}
}
}

AreaAttribute , bir alanın parçası olarak denetleyiciyi belirtir, bu denetleyicinin Blog alanında olduğunu
varsayalım. [Area] özniteliği olmayan denetleyiciler hiçbir alanın üyesi değildir ve area yol değeri
yönlendirme tarafından sağlandığında eşleşmeyecektir . Aşağıdaki örnekte, yalnızca listelenen ilk
denetleyici { area = Blog, controller = Users, action = AddUser } rota değerleriyle eşleştirebilir.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
[Area("Blog")]
public class UsersController : Controller
{
public IActionResult AddUser()
{
return View();
}
}
}

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
// Matches { area = Zebra, controller = Users, action = AddUser }
[Area("Zebra")]
public class UsersController : Controller
{
public IActionResult AddUser()
{
return View();
}
}
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
// Matches { area = string.Empty, controller = Users, action = AddUser }
// Matches { area = null, controller = Users, action = AddUser }
// Matches { controller = Users, action = AddUser }
public class UsersController : Controller
{
public IActionResult AddUser()
{
return View();

}
}
}

NOTE
Her denetleyicinin ad alanı, tamamlanma için burada gösterilir. Aksi takdirde, denetleyicilerde adlandırma çakışması
olur ve derleyici hatası oluşturur. Sınıf ad alanlarının MVC 'nin yönlendirme üzerinde hiçbir etkisi yoktur.

İlk iki denetleyici alanların üyeleridir ve yalnızca ilgili alan adı area rota değeri tarafından sağlandığında
eşleşir. Üçüncü denetleyici hiçbir alanın üyesi değildir ve yalnızca Yönlendirme tarafından area hiçbir
değer sağlanmıyorsa eşleşemez.

NOTE
Değer olmadaneşleşme açısından, area değerinin yokluğu, area değeri null ya da boş dize olarak aynıdır.

Bir alan içinde bir eylem yürütürken, area için rota değeri, yönlendirme için, URL oluşturma için
kullanılacak çevresel bir değer olarak kullanılabilir. Bu, varsayılan olarak, aşağıdaki örnekte gösterildiği
gibi, URL oluşturma için yapışkan olarak hareket ettiği anlamına gelir.

app.UseMvc(routes =>
{
routes.MapAreaRoute("duck_route", "Duck",
"Manage/{controller}/{action}/{id?}");
routes.MapRoute("default", "Manage/{controller=Home}/{action=Index}/{id?}");
});
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
[Area("Duck")]
public class UsersController : Controller
{
public IActionResult GenerateURLInArea()
{
// Uses the 'ambient' value of area
var url = Url.Action("Index", "Home");
// returns /Manage
return Content(url);
}

public IActionResult GenerateURLOutsideOfArea()


{
// Uses the empty value for area
var url = Url.Action("Index", "Home", new { area = "" });
// returns /Manage/Home/Index
return Content(url);
}
}
}

Iactionconstraint 'i anlama


NOTE
Bu bölüm, Framework iç işlevleri hakkında ayrıntılı bir bakış ve MVC 'nin yürütülecek eylemi nasıl seçtiği. Tipik bir
uygulama özel bir IActionConstraint gerektirmez

Büyük olasılıkla, arabirime tanıdık olmasanız bile IActionConstraint zaten kullandık. [HttpGet]
özniteliği ve benzer [Http-VERB] öznitelikleri, bir eylem yönteminin yürütülmesini sınırlandırmak için
IActionConstraint uygular.

public class ProductsController : Controller


{
[HttpGet]
public IActionResult Edit() { }

public IActionResult Edit(...) { }


}

Varsayılan geleneksel yolun kabul edilmesinden, URL yolunun /Products/Edit , burada gösterilen
eylemlerle her ikisi de eşleşen değerler { controller = Products, action = Edit } üretecektir.
IActionConstraint terminolojisinde, her ikisi de rota verileriyle eşleştiğinden, bu eylemlerin her ikisi de
aday olarak kabul edilir.
HttpGetAttribute yürütüldüğünde, Edit () , Get için bir EŞLEŞMEDIR ve diğer http fiili için bir eşleşme
değildir. Edit(...) eyleminde tanımlı kısıtlama yok ve bu nedenle herhangi bir HTTP fiili ile eşleşir. Bu
nedenle, yalnızca POST bir Edit(...) eşleştiğini kabul eder. Ancak GET için her iki eylem de eşleşemez,
ancak IActionConstraint bir eylem, olmadan bir eylemden en iyi şekilde değerlendirilir. Bu nedenle
Edit() , [HttpGet] daha belirgin olarak değerlendirilir ve her iki eylemin da eşleşeceğinden seçilecek.

Kavramsal olarak, IActionConstraint aşırı yüklemebiçimidir, ancak aynı ada sahip yöntemlerin aşırı
yüklenmesi yerıne aynı URL ile eşleşen eylemler arasında aşırı yüklenir. Öznitelik yönlendirme
IActionConstraint de kullanır ve farklı denetleyicilerden gelen eylemlere her ikisi de aday olarak kabul
edilebilir.
Iactionconstraint uygulama
IActionConstraint kullanmanın en kolay yolu, System.Attribute türetilmiş bir sınıf oluşturmaktır ve
bunları eylemleriniz ve denetleyicilerinize yerleştirmelidir. MVC, öznitelik olarak uygulanan
IActionConstraint otomatik olarak bulur. Kısıtlama uygulamak için uygulama modelini kullanabilirsiniz
ve bu, büyük olasılıkla en esnek yaklaşımdır ve bu sayede, nasıl uygulanabileceğini meta
programlayabilirsiniz.
Aşağıdaki örnekte bir kısıtlama, rota verilerinden bir ülke kodunu temel alan bir eylem seçer. GitHub
'daki tam örnek.

public class CountrySpecificAttribute : Attribute, IActionConstraint


{
private readonly string _countryCode;

public CountrySpecificAttribute(string countryCode)


{
_countryCode = countryCode;
}

public int Order


{
get
{
return 0;
}
}

public bool Accept(ActionConstraintContext context)


{
return string.Equals(
context.RouteContext.RouteData.Values["country"].ToString(),
_countryCode,
StringComparison.OrdinalIgnoreCase);
}
}

Accept yöntemi uygulamaktan ve kısıtlamanın yürütülmesi için bir ' Order ' seçmeye sorumlusunuz. Bu
durumda Accept yöntemi, country rota değeri eşleştiğinde eylemin bir eşleşme olduğunu göstermek
için true döndürür. Bu, varolmayan bir eyleme geri dönüş sağlayan bir RouteValueAttribute farklıdır.
Örnek, bir en-US eylemi tanımlarsanız fr-FR gibi bir ülke kodunun [CountrySpecific(...)]
uygulanmamış daha genel bir denetleyiciye geri dönemeyeceğini gösterir.
Order özelliği, kısıtlamanın parçası olan aşamayı belirler. Eylem kısıtlamaları Order göre gruplar halinde
çalışır. Örneğin, tüm Framework tarafından sunulan HTTP yöntemi öznitelikleri aynı aşamada çalışacak
şekilde aynı Order değerini kullanır. İstediğiniz ilkeleri uygulamak için ihtiyacınız olan çok sayıda
aşamaya sahip olabilirsiniz.

TIP
Order bir değere karar vermek için, kısıtlamalarınızın HTTP yöntemlerinden önce uygulanıp uygulanmayacağı
hakkında düşünün. Daha az sayı önce çalışır.
ASP.NET core'da denetleyicilere bağımlılık ekleme
10.05.2019 • 3 minutes to read • Edit Online

Tarafından Shadi Namrouti, Rick Anderson, ve Steve Smith


ASP.NET Core MVC denetleyicileri oluşturucular açıkça aracılığıyla bağımlılıkları isteyin. ASP.NET Core için
yerleşik desteği vardır bağımlılık ekleme (dı). DI uygulamaları test edin ve bakımını kolaylaştırır.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Oluşturucu ekleme
Hizmet bir oluşturucu parametresi eklenir ve çalışma zamanı hizmet kapsayıcı hizmetinden giderir. Hizmetleri,
genellikle arabirimleri kullanılarak tanımlanır. Örneğin, geçerli zamanı gerektiren bir uygulama düşünün.
Aşağıdaki kullanıma sunan arabirim IDateTime hizmeti:

public interface IDateTime


{
DateTime Now { get; }
}

Aşağıdaki kod uygulayan IDateTime arabirimi:

public class SystemDateTime : IDateTime


{
public DateTime Now
{
get { return DateTime.Now; }
}
}

Hizmet, hizmet kapsayıcıya ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddSingleton<IDateTime, SystemDateTime>();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Daha fazla bilgi için AddSingleton, bkz: DI hizmet yaşam süreleri.


Aşağıdaki kod bir karşılama günün saatini temel alan kullanıcı için görüntüler:
public class HomeController : Controller
{
private readonly IDateTime _dateTime;

public HomeController(IDateTime dateTime)


{
_dateTime = dateTime;
}

public IActionResult Index()


{
var serverTime = _dateTime.Now;
if (serverTime.Hour < 12)
{
ViewData["Message"] = "It's morning here - Good Morning!";
}
else if (serverTime.Hour < 17)
{
ViewData["Message"] = "It's afternoon here - Good Afternoon!";
}
else
{
ViewData["Message"] = "It's evening here - Good Evening!";
}
return View();
}

Uygulamayı çalıştırın ve saatini temel alan bir ileti görüntülenir.

FromServices ile eylemi ekleme


FromServicesAttribute Oluşturucu ekleme kullanmadan, doğrudan bir eylem yöntemi bir hizmet ekleme sağlar:

public IActionResult About([FromServices] IDateTime dateTime)


{
ViewData["Message"] = $"Current server time: {dateTime.Now}";

return View();
}

Bir denetleyiciden erişim ayarları


Bir denetleyici içinde gelen uygulama veya yapılandırma ayarlarına erişme ortak bir desendir. Seçenekleri deseni
açıklanan ASP.NET Core için seçenek kalıbı ayarlarını yönetmek için tercih edilen yaklaşım. Genellikle doğrudan
ekleme yoksa IConfiguration içine bir denetleyici.
Seçenekleri temsil eden bir sınıf oluşturun. Örneğin:

public class SampleWebSettings


{
public string Title { get; set; }
public int Updates { get; set; }
}

Yapılandırma sınıfı Hizmetleri koleksiyona ekleyin:


public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDateTime, SystemDateTime>();
services.Configure<SampleWebSettings>(Configuration);

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Okumasına JSON biçimli bir dosyadan ayarları yapılandırın:

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("samplewebsettings.json",
optional: false, // File is not optional.
reloadOnChange: false);
})
.UseStartup<Startup>();
}

Aşağıdaki kod istekleri IOptions<SampleWebSettings> hizmet kapsayıcı ayarları ve bunları kullanan Index
yöntemi:

public class SettingsController : Controller


{
private readonly SampleWebSettings _settings;

public SettingsController(IOptions<SampleWebSettings> settingsOptions)


{
_settings = settingsOptions.Value;
}

public IActionResult Index()


{
ViewData["Title"] = _settings.Title;
ViewData["Updates"] = _settings.Updates;
return View();
}
}

Ek kaynaklar
Bkz: ASP.NET Core 'de test denetleyicisi mantığı kod test denetleyicileri bağımlılıkları açıkça isteyerek
daha kolay hale getirmek öğrenin.
Varsayılan bağımlılık ekleme kapsayıcısını üçüncü taraf bir uygulama ile değiştirin.
ASP.NET core'da görünümlere bağımlılık ekleme
11.07.2019 • 6 minutes to read • Edit Online

Tarafından Steve Smith


ASP.NET Core destekler bağımlılık ekleme görünümlere. Bu, yerelleştirme veya yalnızca görünüm öğeleri
doldurmak için gerekli veriler gibi özel görünüm Hizmetleri için yararlı olabilir. Korunacak denemelisiniz görev
ayrımı nettir denetleyici ve görünüm arasında. Kendi görünümlerinizi görüntüleyin verilerden en iyi şekilde
denetleyicisinden geçirilmelidir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Yapılandırma ekleme
appSettings.JSON değerleri doğrudan bir görünüme eklenmiş.
Örnek bir appsettings.json dosyası:

{
"root": {
"parent": {
"child": "myvalue"
}
}
}

Sözdizimi @inject : @inject <type> <name>

Bir örnek kullanarak @inject :

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}

Hizmet ekleme
Bir görünümü kullanarak bir hizmet yerleştirilebilir @inject yönergesi. Düşünebilirsiniz @inject görünüme
özellik ekleme ve DI kullanan özellik dolduruluyor.
@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
<title>To Do Items</title>
</head>
<body>
<div>
<h1>To Do Items</h1>
<ul>
<li>Total Items: @StatsService.GetCount()</li>
<li>Completed: @StatsService.GetCompletedCount()</li>
<li>Avg. Priority: @StatsService.GetAveragePriority()</li>
</ul>
<table>
<tr>
<th>Name</th>
<th>Priority</th>
<th>Is Done?</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Name</td>
<td>@item.Priority</td>
<td>@item.IsDone</td>
</tr>
}
</table>
</div>
</body>
</html>

Bu görünüm listesini görüntüler ToDoItem örnekleri, genel istatistiklerini gösteren bir özetiyle birlikte. Özet
doldurulur eklenen gelen StatisticsService . Bu hizmet bağımlılık ekleme için kayıtlı ConfigureServices içinde
Startup.cs:

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?


LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();

services.AddTransient<IToDoItemRepository, ToDoItemRepository>();
services.AddTransient<StatisticsService>();
services.AddTransient<ProfileOptionsService>();

StatisticsService Dizi üzerinde bazı hesaplamalar yapan ToDoItem bir depo erişir örnekleri:
using System.Linq;
using ViewInjectSample.Interfaces;

namespace ViewInjectSample.Model.Services
{
public class StatisticsService
{
private readonly IToDoItemRepository _toDoItemRepository;

public StatisticsService(IToDoItemRepository toDoItemRepository)


{
_toDoItemRepository = toDoItemRepository;
}

public int GetCount()


{
return _toDoItemRepository.List().Count();
}

public int GetCompletedCount()


{
return _toDoItemRepository.List().Count(x => x.IsDone);
}

public double GetAveragePriority()


{
if (_toDoItemRepository.List().Count() == 0)
{
return 0.0;
}

return _toDoItemRepository.List().Average(x => x.Priority);


}
}
}

Örnek depoyu bir bellek içi koleksiyon kullanır. Yukarıda gösterilen uygulama (Bu, tüm verilerin bellek içinde
çalışır), büyük, uzaktan erişim veri kümeleri için önerilmez.
Örnek verileri modele görünüme bağlı ve görünüme eklenen hizmet görüntüler:

Arama verilerini doldurma


Görünüm ekleme açılır listeleri gibi kullanıcı Arabirimi öğeleri seçeneklerinde doldurmak yararlı olabilir. Cinsiyet,
durumunu ve diğer tercihlerinizi belirtmek için seçenekleri içeren bir kullanıcı profili form göz önünde
bulundurun. Bir standart MVC yaklaşımı kullanarak form işleme her biri, bu seçenekler için veri erişim
Hizmetleri isteyin ve ardından bir model doldurmak için denetleyici içerseydi veya ViewBag her bağlanacak
seçenek kümesi ile.
Alternatif bir yaklaşım Hizmetleri seçenekleri elde etmek için doğrudan görünümüne ekler. Bu görünüme bu
görünüm öğesi oluşturma mantığı taşıma denetleyicisi tarafından gereken kod miktarını azaltır. Profil örneği
form geçirmek bir profil düzenleme formu görüntülemek için denetleyici eylemi yeterlidir:

using Microsoft.AspNetCore.Mvc;
using ViewInjectSample.Model;

namespace ViewInjectSample.Controllers
{
public class ProfileController : Controller
{
[Route("Profile")]
public IActionResult Index()
{
// TODO: look up profile based on logged-in user
var profile = new Profile()
{
Name = "Steve",
FavColor = "Blue",
Gender = "Male",
State = new State("Ohio","OH")
};
return View(profile);
}
}
}

Bu tercihler güncelleştirmek için kullanılan HTML formu açılır listeleri üç özellikleri içerir:

Bu listeler, görünüme eklenmiş bir hizmet tarafından doldurulur:


@using System.Threading.Tasks
@using ViewInjectSample.Model.Services
@model ViewInjectSample.Model.Profile
@inject ProfileOptionsService Options
<!DOCTYPE html>
<html>
<head>
<title>Update Profile</title>
</head>
<body>
<div>
<h1>Update Profile</h1>
Name: @Html.TextBoxFor(m => m.Name)
<br/>
Gender: @Html.DropDownList("Gender",
Options.ListGenders().Select(g =>
new SelectListItem() { Text = g, Value = g }))
<br/>

State: @Html.DropDownListFor(m => m.State.Code,


Options.ListStates().Select(s =>
new SelectListItem() { Text = s.Name, Value = s.Code}))
<br />

Fav. Color: @Html.DropDownList("FavColor",


Options.ListColors().Select(c =>
new SelectListItem() { Text = c, Value = c }))
</div>
</body>
</html>

ProfileOptionsService Yalnızca bu form için gereken verileri sağlamak üzere tasarlanmış bir UI düzeyi hizmeti:

using System.Collections.Generic;

namespace ViewInjectSample.Model.Services
{
public class ProfileOptionsService
{
public List<string> ListGenders()
{
// keeping this simple
return new List<string>() {"Female", "Male"};
}

public List<State> ListStates()


{
// a few states from USA
return new List<State>()
{
new State("Alabama", "AL"),
new State("Alaska", "AK"),
new State("Ohio", "OH")
};
}

public List<string> ListColors()


{
return new List<string>() { "Blue","Green","Red","Yellow" };
}
}
}
IMPORTANT
Bağımlılık ekleme aracılığıyla istek türleri kaydedilecek unutmayın Startup.ConfigureServices . Hizmet sağlayıcısı
aracılığıyla dahili olarak sorgulanır çünkü bir kaydı türü çalışma zamanında bir özel durum oluşturur. GetRequiredService.

Hizmetleri geçersiz kılma


Yeni hizmet ekleme ek olarak, bu tekniği de bir sayfada daha önce eklenen Hizmetleri geçersiz kılmak için
kullanılabilir. Aşağıdaki şekilde ilk örnekte kullanılan sayfasında, kullanılabilir alanların tümünü gösterilmektedir:

Gördüğünüz gibi varsayılan alanları dahil Html , Component , ve Url (yanı sıra StatsService biz hatalara).
Örneği için varsayılan HTML Yardımcıları kendinizinkilerle değiştirildiğinden isteseydiniz, kolayca kullanarak
bunu @inject :

@using System.Threading.Tasks
@using ViewInjectSample.Helpers
@inject MyHtmlHelper Html
<!DOCTYPE html>
<html>
<head>
<title>My Helper</title>
</head>
<body>
<div>
Test: @Html.Value
</div>
</body>
</html>

Var olan hizmetleri genişletmek isterseniz, dan devralan veya mevcut bir uygulama ile kendi sarmalama
sırasında yalnızca bu tekniği kullanabilirsiniz.

Ayrıca Bkz.
Simon Timms Blog: Arama verileri görünümünüzü alma
ASP.NET Core 'de birim test denetleyicisi mantığı
3.12.2019 • 34 minutes to read • Edit Online

Steve Smith tarafından


Birim testleri , bir uygulamanın bir bölümünü altyapısından ve bağımlılıklarından yalıtımıyla test etmeyi içerir. Birim
testi denetleyici mantığı olduğunda, yalnızca tek bir eylemin içerikleri test edilir, onun bağımlılıkları veya çerçevenin
kendisi değildir.

Birim test denetleyicileri


Denetleyicinin davranışına odaklanmak için denetleyici eylemlerinin birim testlerini ayarlayın. Denetleyici birim testi
Filtreler, yönlendirmeve model bağlamagibi senaryoları önler. Bir isteğe topluca yanıt veren bileşenler arasındaki
etkileşimleri kapsayan testler, tümleştirme testleritarafından işlenir. Tümleştirme testleri hakkında daha fazla bilgi
için bkz. ASP.NET Core tümleştirme testleri.
Özel filtreler ve rotalar yazıyorsanız, birim, belirli bir denetleyici eyleminde testlerin bir parçası olarak değil,
yalıtımına göre test eder.
Denetleyici birim testlerini göstermek için örnek uygulamada aşağıdaki denetleyiciyi gözden geçirin.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Ana denetleyici bir beyin fırtınası oturumlarının listesini görüntüler ve yeni beyin fırtınası oturumlarının bir POST
isteğiyle oluşturulmasına izin verir:
public class HomeController : Controller
{
private readonly IBrainstormSessionRepository _sessionRepository;

public HomeController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index()


{
var sessionList = await _sessionRepository.ListAsync();

var model = sessionList.Select(session => new StormSessionViewModel()


{
Id = session.Id,
DateCreated = session.DateCreated,
Name = session.Name,
IdeaCount = session.Ideas.Count
});

return View(model);
}

public class NewSessionModel


{
[Required]
public string SessionName { get; set; }
}

[HttpPost]
public async Task<IActionResult> Index(NewSessionModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
else
{
await _sessionRepository.AddAsync(new BrainstormSession()
{
DateCreated = DateTimeOffset.Now,
Name = model.SessionName
});
}

return RedirectToAction(actionName: nameof(Index));


}
}

Önceki denetleyici:
Açık bağımlılıklar ilkesiniizler.
IBrainstormSessionRepository örneğini sağlamak için bağımlılık ekleme (dı) bekliyor.
, Moqgibi bir sahte nesne çerçevesi kullanılarak bir moclenmiş IBrainstormSessionRepository hizmeti ile test
edilebilir. Bir ilişkili nesne , test için kullanılan önceden tanımlanmış bir özellik ve Yöntem davranışları kümesine
sahip bir fabricobject nesnesidir. Daha fazla bilgi için bkz. tümleştirme testlerine giriş.
HTTP GET Index yöntemi döngü veya dallandırma içermez ve yalnızca bir yöntem çağırır. Bu eylemin birim testi:
GetTestSessions yöntemini kullanarak IBrainstormSessionRepository hizmetini gizler. GetTestSessions , tarihler
ve oturum adlarıyla iki adet sahte beyin fırtınası oturumu oluşturur.
Index yöntemini yürütür.
Yöntemi tarafından döndürülen sonuç üzerinde onaylama işlemleri yapar:
Bir ViewResult döndürülür.
ViewDataDictionary. model bir StormSessionViewModel .
ViewDataDictionary.Model depolanan iki beyin fırtınası oturumu vardır.

[Fact]
public async Task Index_ReturnsAViewResult_WithAListOfBrainstormSessions()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);

// Act
var result = await controller.Index();

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<StormSessionViewModel>>(
viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}

private List<BrainstormSession> GetTestSessions()


{
var sessions = new List<BrainstormSession>();
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 2),
Id = 1,
Name = "Test One"
});
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 1),
Id = 2,
Name = "Test Two"
});
return sessions;
}

Ana denetleyicinin HTTP POST Index yöntemi testleri şunları doğrular:


ModelState. IsValid olduğunda, eylem yöntemi uygun verilerle bir 400 hatalı istek ViewResult döndürür.
false
ModelState.IsValid true :
Depodaki Add yöntemi çağrılır.
Doğru bağımsız değişkenlerle bir RedirectToActionResult döndürülür.
Geçersiz bir model durumu, aşağıdaki ilk testte gösterildiği gibi AddModelError kullanılarak hatalar eklenerek test
edilir:
[Fact]
public async Task IndexPost_ReturnsBadRequestResult_WhenModelStateIsInvalid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);
controller.ModelState.AddModelError("SessionName", "Required");
var newSession = new HomeController.NewSessionModel();

// Act
var result = await controller.Index(newSession);

// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
Assert.IsType<SerializableError>(badRequestResult.Value);
}

[Fact]
public async Task IndexPost_ReturnsARedirectAndAddsSession_WhenModelStateIsValid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.AddAsync(It.IsAny<BrainstormSession>()))
.Returns(Task.CompletedTask)
.Verifiable();
var controller = new HomeController(mockRepo.Object);
var newSession = new HomeController.NewSessionModel()
{
SessionName = "Test Name"
};

// Act
var result = await controller.Index(newSession);

// Assert
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(result);
Assert.Null(redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
mockRepo.Verify();
}

ModelState geçerli olmadığında, bir get isteği için aynı ViewResult döndürülür. Test geçersiz bir modeli geçirmeye
çalışmıyor. Model bağlama çalışmadığından (bir tümleştirme testi model bağlamayı kullansa da), geçersiz bir
modelin geçirilmesi geçerli bir yaklaşım değildir. Bu durumda model bağlama sınanmamıştır. Bu birim testleri
yalnızca eylem yöntemindeki kodu test eder.
İkinci test ModelState geçerli olduğunda doğrular:
Yeni bir BrainstormSession eklenir (depo aracılığıyla).
Yöntemi, beklenen özelliklerle bir RedirectToActionResult döndürür.

Çağrılmayan hiçbir çağrı normalde yok sayılır, ancak kurulum çağrısının sonunda Verifiable çağrısı testte sahte
doğrulamaya izin verir. Bu, beklenen yöntemin çağrılmaması durumunda test başarısız olan mockRepo.Verify
çağrısıyla gerçekleştirilir.
NOTE
Bu örnekte kullanılan moq kitaplığı, doğrulanabilir olmayan bir şekilde ("gevşek" bir veya saplamalar olarak da adlandırılır)
doğrulanabilir veya "katı" olarak karışık bir şekilde karışık bir şekilde karıştırılamaz. Moq Ile sahte davranışı
özelleştirmehakkında daha fazla bilgi edinin.

Örnek uygulamadaki Sessioncontroller , belirli bir beyin fırtınası oturumuyla ilgili bilgileri görüntüler. Denetleyici
geçersiz id değerlerle ilgilenme mantığını içerir (bu senaryoları kapsayan aşağıdaki örnekte iki return senaryo
vardır). Son return ifade görünüme yeni bir StormSessionViewModel döndürür (Controllers/SessionController. cs):

public class SessionController : Controller


{
private readonly IBrainstormSessionRepository _sessionRepository;

public SessionController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index(int? id)


{
if (!id.HasValue)
{
return RedirectToAction(actionName: nameof(Index),
controllerName: "Home");
}

var session = await _sessionRepository.GetByIdAsync(id.Value);


if (session == null)
{
return Content("Session not found.");
}

var viewModel = new StormSessionViewModel()


{
DateCreated = session.DateCreated,
Name = session.Name,
Id = session.Id
};

return View(viewModel);
}
}

Birim testleri, oturum denetleyicisi Index eyleminde her bir return senaryosu için bir test içerir:
[Fact]
public async Task IndexReturnsARedirectToIndexHomeWhenIdIsNull()
{
// Arrange
var controller = new SessionController(sessionRepository: null);

// Act
var result = await controller.Index(id: null);

// Assert
var redirectToActionResult =
Assert.IsType<RedirectToActionResult>(result);
Assert.Equal("Home", redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
}

[Fact]
public async Task IndexReturnsContentWithSessionNotFoundWhenSessionNotFound()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var contentResult = Assert.IsType<ContentResult>(result);
Assert.Equal("Session not found.", contentResult.Content);
}

[Fact]
public async Task IndexReturnsViewResultWithStormSessionViewModel()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSessions().FirstOrDefault(
s => s.Id == testSessionId));
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsType<StormSessionViewModel>(
viewResult.ViewData.Model);
Assert.Equal("Test One", model.Name);
Assert.Equal(2, model.DateCreated.Day);
Assert.Equal(testSessionId, model.Id);
}

Uygulama, fikirler denetleyicisine geçiş yaparken api/ideas rotasında bir Web API 'SI olarak işlevselliği kullanıma
sunar:
Bir beyin fırtınası oturumuyla ilişkili fikirler ( IdeaDTO ) listesi, ForSession yöntemi tarafından döndürülür.
Create yöntemi bir oturuma yeni fikirler ekler.
[HttpGet("forsession/{sessionId}")]
public async Task<IActionResult> ForSession(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);
if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return Ok(result);
}

[HttpPost("create")]
public async Task<IActionResult> Create([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);


if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return Ok(session);
}

İş etki alanı varlıklarını doğrudan API çağrıları aracılığıyla döndürmekten kaçının. Etki alanı varlıkları:
Genellikle istemcinin gerektirdiğinden daha fazla veri içerir.
Genel olarak sunulan API ile uygulamanın iç etki alanı modelini gereksiz bir şekilde yapın.
Etki alanı varlıkları ve istemciye döndürülen türler arasında eşleme gerçekleştirilebilir:
Örnek uygulamanın kullandığı şekilde bir LINQ Select el ile. Daha fazla bilgi için bkz. LINQ (dil Ile tümleşik
sorgu).
Otomatik olarak bir kitaplıkla (örneğin, Automaber).
Ardından, örnek uygulama, fikirler denetleyicisinin Create ve ForSession API yöntemlerine yönelik birim testlerini
gösterir.
Örnek uygulama iki ForSession test içerir. İlk test, ForSession geçersiz bir oturum için NotFoundObjectResult
(HTTP bulunamadı) döndürüp döndürmeyeceğini belirler:
[Fact]
public async Task ForSession_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var notFoundObjectResult = Assert.IsType<NotFoundObjectResult>(result);
Assert.Equal(testSessionId, notFoundObjectResult.Value);
}

İkinci ForSession testi, ForSession geçerli bir oturum için oturum fikirleri ( <List<IdeaDTO>> ) listesini döndürüp
döndürmeyeceğini belirler. Denetimler Ayrıca, Name özelliğinin doğru olduğunu onaylamak için ilk fikri de inceler:

[Fact]
public async Task ForSession_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(okResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

ModelState geçersiz olduğunda Create yönteminin davranışını test etmek için, örnek uygulama, testin bir parçası
olarak denetleyiciye bir model hatası ekler. Birim testlerinde model doğrulama veya model bağlamayı sınamayı
denemeyin—geçersiz bir ModelState sahip olduğunda eylem yönteminin davranışını test edin:

[Fact]
public async Task Create_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.Create(model: null);

// Assert
Assert.IsType<BadRequestObjectResult>(result);
}

Create ikinci testi, null döndüren depoya bağlıdır, bu nedenle, sahte depo null döndürecek şekilde yapılandırılır.
Bir test veritabanı (bellekte veya başka türlü) oluşturmanız gerekmez ve bu sonucu döndüren bir sorgu oluşturun.
Örnek kodun gösterildiği gibi, test tek bir bildirimde gerçekleştirilebilir:

[Fact]
public async Task Create_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.Create(new NewIdeaModel());

// Assert
Assert.IsType<NotFoundObjectResult>(result);
}

Create_ReturnsNewlyCreatedIdeaForSession üçüncü Create testi, deponun UpdateAsync yönteminin çağrıldığını


doğrular. Sahte, Verifiable ile çağrılır ve doğrulanabilen yöntemin yürütüldüğünü onaylamak için, moclenmiş
deponun Verify yöntemi çağırılır. UpdateAsync yönteminin bir tümleştirme testiyle gerçekleştirilebilecek verileri—
kaydettiğinizden emin olmak için birim testinin sorumluluğu yoktur.

[Fact]
public async Task Create_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.Create(newIdea);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnSession = Assert.IsType<BrainstormSession>(okResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnSession.Ideas.Count());
Assert.Equal(testName, returnSession.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnSession.Ideas.LastOrDefault().Description);
}

Test ActionResult<T >


ASP.NET Core 2,1 veya sonraki bir sürümde, actionresult<t > (ActionResult<TValue>) ActionResult türetilen bir
tür döndürmenizi veya belirli bir tür döndürmenizi sağlar.
Örnek uygulama, belirli bir oturum id için List<IdeaDTO> döndüren bir yöntemi içerir. Oturum id yoksa,
denetleyici NotFounddöndürür:

[HttpGet("forsessionactionresult/{sessionId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<ActionResult<List<IdeaDTO>>> ForSessionActionResult(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);

if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return result;
}

ForSessionActionResult denetleyicisinin iki testi ApiIdeasControllerTests dahil edilir.


İlk test, denetleyicinin varolmayan bir oturum id için varolmayan bir fikir listesi ActionResult döndürdüğünü
onaylar:
ActionResult türü ActionResult<List<IdeaDTO>> .
Result bir NotFoundObjectResult.

[Fact]
public async Task ForSessionActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
var nonExistentSessionId = 999;

// Act
var result = await controller.ForSessionActionResult(nonExistentSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için ikinci test, yöntemin döndürdüğünü doğrular:


List<IdeaDTO> türüne sahip bir ActionResult .
ActionResult<t >. Değer bir List<IdeaDTO> türüdür.
Listedeki ilk öğe, sahte oturumda saklanan fikrle eşleşen geçerli bir fikrdir ( GetTestSession çağırarak elde edilir).
[Fact]
public async Task ForSessionActionResult_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSessionActionResult(testSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(actionResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

Örnek uygulama, belirli bir oturum için yeni Idea oluşturmak üzere bir yöntemi de içerir. Denetleyici şunu
döndürür:
geçersiz bir model için BadRequest.
oturum yoksa NotFound.
oturum yeni fikrle güncelleştirildiği zaman CreatedAtAction.

[HttpPost("createactionresult")]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
public async Task<ActionResult<BrainstormSession>> CreateActionResult([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);

if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return CreatedAtAction(nameof(CreateActionResult), new { id = session.Id }, session);


}

CreateActionResult üç test ApiIdeasControllerTests dahil edilir.


İlk metin, geçersiz bir model için BadRequest döndürüldüğünü onaylar.
[Fact]
public async Task CreateActionResult_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.CreateActionResult(model: null);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<BadRequestObjectResult>(actionResult.Result);
}

İkinci test, oturum yoksa NotFound döndürülüp döndürülmediğini denetler.

[Fact]
public async Task CreateActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var nonExistentSessionId = 999;
string testName = "test name";
string testDescription = "test description";
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = nonExistentSessionId
};

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için son test şunları onaylar:


Yöntemi, bir BrainstormSession türü ile ActionResult döndürür.
ActionResult<t >. Sonuç bir CreatedAtActionResult. CreatedAtActionResult , bir Location üst bilgisiyle 201
tarafından oluşturulan bir yanıta benzerdir.
ActionResult<t >. Değer bir BrainstormSession türüdür.
Oturumu güncelleştirmek için kullanılan sahte çağrı, UpdateAsync(testSession) çağrıldı. Verifiable yöntemi
çağrısı onaylamalarda mockRepo.Verify() yürütülerek denetlenir.
Oturum için iki Idea nesnesi döndürülür.
Son öğe (sahte çağrının UpdateAsync tarafından eklenen Idea ) testteki oturuma eklenen newIdea eşleşir.
[Fact]
public async Task CreateActionResult_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
var createdAtActionResult = Assert.IsType<CreatedAtActionResult>(actionResult.Result);
var returnValue = Assert.IsType<BrainstormSession>(createdAtActionResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnValue.Ideas.Count());
Assert.Equal(testName, returnValue.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnValue.Ideas.LastOrDefault().Description);
}

Denetleyiciler herhangi BIR ASP.NET Core MVC uygulamasında merkezi bir rol oynar. Bu nedenle, denetleyicilerin
amaçlanan gibi davrandığına güvenmelisiniz. Otomatik testler, uygulama bir üretim ortamına dağıtılmadan önce
hataları tespit edebilir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Denetleyici mantığının birim testleri


Birim testleri , bir uygulamanın bir bölümünü altyapısından ve bağımlılıklarından yalıtımıyla test etmeyi içerir. Birim
testi denetleyici mantığı olduğunda, yalnızca tek bir eylemin içerikleri test edilir, onun bağımlılıkları veya çerçevenin
kendisi değildir.
Denetleyicinin davranışına odaklanmak için denetleyici eylemlerinin birim testlerini ayarlayın. Denetleyici birim testi
Filtreler, yönlendirmeve model bağlamagibi senaryoları önler. Bir isteğe topluca yanıt veren bileşenler arasındaki
etkileşimleri kapsayan testler, tümleştirme testleritarafından işlenir. Tümleştirme testleri hakkında daha fazla bilgi
için bkz. ASP.NET Core tümleştirme testleri.
Özel filtreler ve rotalar yazıyorsanız, birim, belirli bir denetleyici eyleminde testlerin bir parçası olarak değil,
yalıtımına göre test eder.
Denetleyici birim testlerini göstermek için örnek uygulamada aşağıdaki denetleyiciyi gözden geçirin. Ana
denetleyici bir beyin fırtınası oturumlarının listesini görüntüler ve yeni beyin fırtınası oturumlarının bir POST
isteğiyle oluşturulmasına izin verir:
public class HomeController : Controller
{
private readonly IBrainstormSessionRepository _sessionRepository;

public HomeController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index()


{
var sessionList = await _sessionRepository.ListAsync();

var model = sessionList.Select(session => new StormSessionViewModel()


{
Id = session.Id,
DateCreated = session.DateCreated,
Name = session.Name,
IdeaCount = session.Ideas.Count
});

return View(model);
}

public class NewSessionModel


{
[Required]
public string SessionName { get; set; }
}

[HttpPost]
public async Task<IActionResult> Index(NewSessionModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
else
{
await _sessionRepository.AddAsync(new BrainstormSession()
{
DateCreated = DateTimeOffset.Now,
Name = model.SessionName
});
}

return RedirectToAction(actionName: nameof(Index));


}
}

Önceki denetleyici:
Açık bağımlılıklar ilkesiniizler.
IBrainstormSessionRepository örneğini sağlamak için bağımlılık ekleme (dı) bekliyor.
, Moqgibi bir sahte nesne çerçevesi kullanılarak bir moclenmiş IBrainstormSessionRepository hizmeti ile test
edilebilir. Bir ilişkili nesne , test için kullanılan önceden tanımlanmış bir özellik ve Yöntem davranışları kümesine
sahip bir fabricobject nesnesidir. Daha fazla bilgi için bkz. tümleştirme testlerine giriş.
HTTP GET Index yöntemi döngü veya dallandırma içermez ve yalnızca bir yöntem çağırır. Bu eylemin birim testi:
GetTestSessions yöntemini kullanarak IBrainstormSessionRepository hizmetini gizler. GetTestSessions , tarihler
ve oturum adlarıyla iki adet sahte beyin fırtınası oturumu oluşturur.
Index yöntemini yürütür.
Yöntemi tarafından döndürülen sonuç üzerinde onaylama işlemleri yapar:
Bir ViewResult döndürülür.
ViewDataDictionary. model bir StormSessionViewModel .
ViewDataDictionary.Model depolanan iki beyin fırtınası oturumu vardır.

[Fact]
public async Task Index_ReturnsAViewResult_WithAListOfBrainstormSessions()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);

// Act
var result = await controller.Index();

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<StormSessionViewModel>>(
viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}

private List<BrainstormSession> GetTestSessions()


{
var sessions = new List<BrainstormSession>();
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 2),
Id = 1,
Name = "Test One"
});
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 1),
Id = 2,
Name = "Test Two"
});
return sessions;
}

Ana denetleyicinin HTTP POST Index yöntemi testleri şunları doğrular:


ModelState. IsValid olduğunda, eylem yöntemi uygun verilerle bir 400 hatalı istek ViewResult döndürür.
false
ModelState.IsValid true :
Depodaki Add yöntemi çağrılır.
Doğru bağımsız değişkenlerle bir RedirectToActionResult döndürülür.
Geçersiz bir model durumu, aşağıdaki ilk testte gösterildiği gibi AddModelError kullanılarak hatalar eklenerek test
edilir:
[Fact]
public async Task IndexPost_ReturnsBadRequestResult_WhenModelStateIsInvalid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);
controller.ModelState.AddModelError("SessionName", "Required");
var newSession = new HomeController.NewSessionModel();

// Act
var result = await controller.Index(newSession);

// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
Assert.IsType<SerializableError>(badRequestResult.Value);
}

[Fact]
public async Task IndexPost_ReturnsARedirectAndAddsSession_WhenModelStateIsValid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.AddAsync(It.IsAny<BrainstormSession>()))
.Returns(Task.CompletedTask)
.Verifiable();
var controller = new HomeController(mockRepo.Object);
var newSession = new HomeController.NewSessionModel()
{
SessionName = "Test Name"
};

// Act
var result = await controller.Index(newSession);

// Assert
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(result);
Assert.Null(redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
mockRepo.Verify();
}

ModelState geçerli olmadığında, bir get isteği için aynı ViewResult döndürülür. Test geçersiz bir modeli geçirmeye
çalışmıyor. Model bağlama çalışmadığından (bir tümleştirme testi model bağlamayı kullansa da), geçersiz bir
modelin geçirilmesi geçerli bir yaklaşım değildir. Bu durumda model bağlama sınanmamıştır. Bu birim testleri
yalnızca eylem yöntemindeki kodu test eder.
İkinci test ModelState geçerli olduğunda doğrular:
Yeni bir BrainstormSession eklenir (depo aracılığıyla).
Yöntemi, beklenen özelliklerle bir RedirectToActionResult döndürür.

Çağrılmayan hiçbir çağrı normalde yok sayılır, ancak kurulum çağrısının sonunda Verifiable çağrısı testte sahte
doğrulamaya izin verir. Bu, beklenen yöntemin çağrılmaması durumunda test başarısız olan mockRepo.Verify
çağrısıyla gerçekleştirilir.
NOTE
Bu örnekte kullanılan moq kitaplığı, doğrulanabilir olmayan bir şekilde ("gevşek" bir veya saplamalar olarak da adlandırılır)
doğrulanabilir veya "katı" olarak karışık bir şekilde karışık bir şekilde karıştırılamaz. Moq Ile sahte davranışı
özelleştirmehakkında daha fazla bilgi edinin.

Örnek uygulamadaki Sessioncontroller , belirli bir beyin fırtınası oturumuyla ilgili bilgileri görüntüler. Denetleyici
geçersiz id değerlerle ilgilenme mantığını içerir (bu senaryoları kapsayan aşağıdaki örnekte iki return senaryo
vardır). Son return ifade görünüme yeni bir StormSessionViewModel döndürür (Controllers/SessionController. cs):

public class SessionController : Controller


{
private readonly IBrainstormSessionRepository _sessionRepository;

public SessionController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index(int? id)


{
if (!id.HasValue)
{
return RedirectToAction(actionName: nameof(Index),
controllerName: "Home");
}

var session = await _sessionRepository.GetByIdAsync(id.Value);


if (session == null)
{
return Content("Session not found.");
}

var viewModel = new StormSessionViewModel()


{
DateCreated = session.DateCreated,
Name = session.Name,
Id = session.Id
};

return View(viewModel);
}
}

Birim testleri, oturum denetleyicisi Index eyleminde her bir return senaryosu için bir test içerir:
[Fact]
public async Task IndexReturnsARedirectToIndexHomeWhenIdIsNull()
{
// Arrange
var controller = new SessionController(sessionRepository: null);

// Act
var result = await controller.Index(id: null);

// Assert
var redirectToActionResult =
Assert.IsType<RedirectToActionResult>(result);
Assert.Equal("Home", redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
}

[Fact]
public async Task IndexReturnsContentWithSessionNotFoundWhenSessionNotFound()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var contentResult = Assert.IsType<ContentResult>(result);
Assert.Equal("Session not found.", contentResult.Content);
}

[Fact]
public async Task IndexReturnsViewResultWithStormSessionViewModel()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSessions().FirstOrDefault(
s => s.Id == testSessionId));
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsType<StormSessionViewModel>(
viewResult.ViewData.Model);
Assert.Equal("Test One", model.Name);
Assert.Equal(2, model.DateCreated.Day);
Assert.Equal(testSessionId, model.Id);
}

Uygulama, fikirler denetleyicisine geçiş yaparken api/ideas rotasında bir Web API 'SI olarak işlevselliği kullanıma
sunar:
Bir beyin fırtınası oturumuyla ilişkili fikirler ( IdeaDTO ) listesi, ForSession yöntemi tarafından döndürülür.
Create yöntemi bir oturuma yeni fikirler ekler.
[HttpGet("forsession/{sessionId}")]
public async Task<IActionResult> ForSession(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);
if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return Ok(result);
}

[HttpPost("create")]
public async Task<IActionResult> Create([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);


if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return Ok(session);
}

İş etki alanı varlıklarını doğrudan API çağrıları aracılığıyla döndürmekten kaçının. Etki alanı varlıkları:
Genellikle istemcinin gerektirdiğinden daha fazla veri içerir.
Genel olarak sunulan API ile uygulamanın iç etki alanı modelini gereksiz bir şekilde yapın.
Etki alanı varlıkları ve istemciye döndürülen türler arasında eşleme gerçekleştirilebilir:
Örnek uygulamanın kullandığı şekilde bir LINQ Select el ile. Daha fazla bilgi için bkz. LINQ (dil Ile tümleşik
sorgu).
Otomatik olarak bir kitaplıkla (örneğin, Automaber).
Ardından, örnek uygulama, fikirler denetleyicisinin Create ve ForSession API yöntemlerine yönelik birim testlerini
gösterir.
Örnek uygulama iki ForSession test içerir. İlk test, ForSession geçersiz bir oturum için NotFoundObjectResult
(HTTP bulunamadı) döndürüp döndürmeyeceğini belirler:
[Fact]
public async Task ForSession_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var notFoundObjectResult = Assert.IsType<NotFoundObjectResult>(result);
Assert.Equal(testSessionId, notFoundObjectResult.Value);
}

İkinci ForSession testi, ForSession geçerli bir oturum için oturum fikirleri ( <List<IdeaDTO>> ) listesini döndürüp
döndürmeyeceğini belirler. Denetimler Ayrıca, Name özelliğinin doğru olduğunu onaylamak için ilk fikri de inceler:

[Fact]
public async Task ForSession_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(okResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

ModelState geçersiz olduğunda Create yönteminin davranışını test etmek için, örnek uygulama, testin bir parçası
olarak denetleyiciye bir model hatası ekler. Birim testlerinde model doğrulama veya model bağlamayı sınamayı
denemeyin—geçersiz bir ModelState sahip olduğunda eylem yönteminin davranışını test edin:

[Fact]
public async Task Create_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.Create(model: null);

// Assert
Assert.IsType<BadRequestObjectResult>(result);
}

Create ikinci testi, null döndüren depoya bağlıdır, bu nedenle, sahte depo null döndürecek şekilde yapılandırılır.
Bir test veritabanı (bellekte veya başka türlü) oluşturmanız gerekmez ve bu sonucu döndüren bir sorgu oluşturun.
Örnek kodun gösterildiği gibi, test tek bir bildirimde gerçekleştirilebilir:

[Fact]
public async Task Create_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.Create(new NewIdeaModel());

// Assert
Assert.IsType<NotFoundObjectResult>(result);
}

Create_ReturnsNewlyCreatedIdeaForSession üçüncü Create testi, deponun UpdateAsync yönteminin çağrıldığını


doğrular. Sahte, Verifiable ile çağrılır ve doğrulanabilen yöntemin yürütüldüğünü onaylamak için, moclenmiş
deponun Verify yöntemi çağırılır. UpdateAsync yönteminin bir tümleştirme testiyle gerçekleştirilebilecek verileri—
kaydettiğinizden emin olmak için birim testinin sorumluluğu yoktur.

[Fact]
public async Task Create_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.Create(newIdea);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnSession = Assert.IsType<BrainstormSession>(okResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnSession.Ideas.Count());
Assert.Equal(testName, returnSession.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnSession.Ideas.LastOrDefault().Description);
}

Test ActionResult<T >


ASP.NET Core 2,1 veya sonraki bir sürümde, actionresult<t > (ActionResult<TValue>) ActionResult türetilen bir
tür döndürmenizi veya belirli bir tür döndürmenizi sağlar.
Örnek uygulama, belirli bir oturum id için List<IdeaDTO> döndüren bir yöntemi içerir. Oturum id yoksa,
denetleyici NotFounddöndürür:

[HttpGet("forsessionactionresult/{sessionId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<ActionResult<List<IdeaDTO>>> ForSessionActionResult(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);

if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return result;
}

ForSessionActionResult denetleyicisinin iki testi ApiIdeasControllerTests dahil edilir.


İlk test, denetleyicinin varolmayan bir oturum id için varolmayan bir fikir listesi ActionResult döndürdüğünü
onaylar:
ActionResult türü ActionResult<List<IdeaDTO>> .
Result bir NotFoundObjectResult.

[Fact]
public async Task ForSessionActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
var nonExistentSessionId = 999;

// Act
var result = await controller.ForSessionActionResult(nonExistentSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için ikinci test, yöntemin döndürdüğünü doğrular:


List<IdeaDTO> türüne sahip bir ActionResult .
ActionResult<t >. Değer bir List<IdeaDTO> türüdür.
Listedeki ilk öğe, sahte oturumda saklanan fikrle eşleşen geçerli bir fikrdir ( GetTestSession çağırarak elde edilir).
[Fact]
public async Task ForSessionActionResult_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSessionActionResult(testSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(actionResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

Örnek uygulama, belirli bir oturum için yeni Idea oluşturmak üzere bir yöntemi de içerir. Denetleyici şunu
döndürür:
geçersiz bir model için BadRequest.
oturum yoksa NotFound.
oturum yeni fikrle güncelleştirildiği zaman CreatedAtAction.

[HttpPost("createactionresult")]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
public async Task<ActionResult<BrainstormSession>> CreateActionResult([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);

if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return CreatedAtAction(nameof(CreateActionResult), new { id = session.Id }, session);


}

CreateActionResult üç test ApiIdeasControllerTests dahil edilir.


İlk metin, geçersiz bir model için BadRequest döndürüldüğünü onaylar.
[Fact]
public async Task CreateActionResult_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.CreateActionResult(model: null);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<BadRequestObjectResult>(actionResult.Result);
}

İkinci test, oturum yoksa NotFound döndürülüp döndürülmediğini denetler.

[Fact]
public async Task CreateActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var nonExistentSessionId = 999;
string testName = "test name";
string testDescription = "test description";
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = nonExistentSessionId
};

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için son test şunları onaylar:


Yöntemi, bir BrainstormSession türü ile ActionResult döndürür.
ActionResult<t >. Sonuç bir CreatedAtActionResult. CreatedAtActionResult , bir Location üst bilgisiyle 201
tarafından oluşturulan bir yanıta benzerdir.
ActionResult<t >. Değer bir BrainstormSession türüdür.
Oturumu güncelleştirmek için kullanılan sahte çağrı, UpdateAsync(testSession) çağrıldı. Verifiable yöntemi
çağrısı onaylamalarda mockRepo.Verify() yürütülerek denetlenir.
Oturum için iki Idea nesnesi döndürülür.
Son öğe (sahte çağrının UpdateAsync tarafından eklenen Idea ) testteki oturuma eklenen newIdea eşleşir.
[Fact]
public async Task CreateActionResult_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
var createdAtActionResult = Assert.IsType<CreatedAtActionResult>(actionResult.Result);
var returnValue = Assert.IsType<BrainstormSession>(createdAtActionResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnValue.Ideas.Count());
Assert.Equal(testName, returnValue.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnValue.Ideas.LastOrDefault().Description);
}

Ek kaynaklar
ASP.NET Core tümleştirme testleri
Visual Studio ile birim testleri oluşturma ve çalıştırma
ASP.NET Core – MVC Için Mysınanan. AspNetCore. Mvc-Floent test Kitaplığı , MVC ve Web API uygulamalarını
test etmek için akıcı bir arabirim sağlar. (Microsoft tarafından korunmaz veya desteklenmez. )
ASP.NET Core Blazor giriş
9.12.2019 • 8 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından


Blazorhoş geldiniz!
Blazor, .NET ile etkileşimli istemci tarafı Web Kullanıcı arabirimi oluşturmaya yönelik bir çerçevedir:
JavaScript yerine zengin etkileşimli Uıusing C# oluşturma.
.NET ' te yazılmış sunucu tarafı ve istemci tarafı uygulama mantığını paylaşabilirsiniz.
Mobil tarayıcılar dahil olmak üzere geniş tarayıcı desteği için Kullanıcı arabirimini HTML ve CSS olarak
işleme.
İstemci tarafı web geliştirme için .NET kullanmak aşağıdaki avantajları sunar:
JavaScript C# yerine kodu yazın.
.NET kitaplıklarının mevcut .NET ekosisteminden yararlanın.
Sunucu ve istemci arasında uygulama mantığını paylaşma.
Avantajı. NET ' in performans, güvenilirlik ve güvenlik.
Windows, Linux ve macOS 'ta Visual Studio ile üretken olun.
Kararlı, özellik açısından zengin ve kullanımı kolay olan ortak diller, çerçeveler ve araçlar kümesi oluşturun.

Bileşenler
Blazor uygulamalar bileşenleritemel alır. Blazor bir bileşen, bir sayfa, iletişim kutusu veya veri girişi formu gibi
bir kullanıcı arabirimi öğesidir.
Bileşenler, .NET Derlemeleriyle yerleşik olarak bulunan .NET sınıflarıdır:
Esnek kullanıcı arabirimi işleme mantığını tanımlayın.
Kullanıcı olaylarını işleyin.
İç içe ve yeniden kullanılabilir olabilir.
, Razor sınıfı kitaplıkları veya NuGet paketleriolarak paylaşılabilir ve dağıtılabilir.
Bileşen sınıfı genellikle . Razor dosya uzantısına sahip bir Razor biçimlendirme sayfası biçiminde yazılır. Blazor
bileşenler, resmi olarak Razor bileşenleriolarak adlandırılır. Razor, geliştirici üretkenliği için tasarlanan C# kodla
HTML işaretlemesini birleştirmek için bir sözdizimidir. Razor, IntelliSense desteğiyle aynı dosyada HTML
işaretlemesi ve C# arasında geçiş yapmanıza olanak sağlar . Razor Pages ve MVC de Razor kullanır. İstek/yanıt
modeli etrafında oluşturulan Razor Pages ve MVC 'nin aksine, bileşenler özellikle istemci tarafı UI mantığı ve
bileşimi için kullanılır.
Aşağıdaki Razor biçimlendirmesi, başka bir bileşen içinde iç içe kullanılabilecek bir bileşeni (Iletişim kutusu.
Razor) gösterir:
<div>
<h1>@Title</h1>

@ChildContent

<button @onclick="OnYes">Yes!</button>
</div>

@code {
[Parameter]
public string Title { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

private void OnYes()


{
Console.WriteLine("Write to the console in C#! 'Yes' button was selected.");
}
}

İletişim kutusunun gövde içeriği ( ChildContent ) ve başlığı ( Title ), bu bileşeni Kullanıcı arabiriminde kullanan
bileşen tarafından sağlanır. OnYes düğmenin onclick C# olayı tarafından tetiklenen bir yöntemdir.
Blazor, UI bileşimi için doğal HTML etiketleri kullanır. HTML öğeleri, bileşenleri belirtir ve bir etiketin
öznitelikleri değerleri bir bileşenin özelliklerine iletir.
Aşağıdaki örnekte Index bileşeni Dialog bileşenini kullanır. ChildContent ve Title , <Dialog> öğesinin
özniteliklerine ve içeriğine göre ayarlanır.
Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Dialog Title="Blazor">
Do you want to <i>learn more</i> about Blazor?
</Dialog>

Üst öğeye (Index. Razor) bir tarayıcıda erişildiğinde iletişim kutusu işlenir:

Bu bileşen uygulamada kullanıldığında, Visual Studio 'da ıntellisense ve Visual Studio Code , sözdizimi ve
parametre tamammasıyla geliştirmeyi hızlandırır.
Bileşenler, Kullanıcı arabirimini esnek ve verimli bir şekilde güncelleştirmek için kullanılan bir işleme ağacıadlı,
tarayıcı belge nesne MODELI (DOM ) ' ın bellek içi gösterimine işlenir.

Blazor WebAssembly
IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor WebAssembly, .NET ile etkileşimli istemci tarafı Web uygulamaları oluşturmaya yönelik tek sayfalı bir
uygulama çerçevesidir. Blazor WebAssembly, eklentiler veya Code transpilation olmadan açık Web standartları
kullanır ve mobil tarayıcılar dahil tüm modern web tarayıcılarında kullanılabilir.
Web tarayıcıları içinde .NET kodu çalıştırmak, Webassembly (kısaltılmış) tarafından mümkün hale getirilir.
WebAssembly hızlı indirme ve en yüksek yürütme hızı için iyileştirilmiş bir sıkıştırma kodu biçimidir.
WebAssembly, açık bir web standardıdır ve eklentileri olmayan Web tarayıcılarında desteklenir.
WebAssembly Code, JavaScript ile birlikte çalışabilirlik (veya JavaScript birlikte çalışma) olarak adlandırılan
JavaScript aracılığıyla tarayıcının tüm işlevlerine erişebilir. Tarayıcıda WebAssembly aracılığıyla yürütülen .NET
kodu, sanal makinenin istemci makinesindeki kötü amaçlı eylemlere karşı sağladığı korumalar ile tarayıcının
JavaScript korumalı alanında çalışır.

Blazor WebAssembly uygulaması bir tarayıcıda oluşturulup çalıştırıldığında:


C#kod dosyaları ve Razor dosyaları .NET Derlemeleriyle derlenir.
Derlemeler ve .NET çalışma zamanı tarayıcıya indirilir.
WebAssembly önyükleme .NET çalışma zamanını Blazor ve çalışma zamanını uygulamanın derlemelerini
yükleyecek şekilde yapılandırır. Blazor WebAssembly çalışma zamanı, DOM işleme ve tarayıcı API çağrılarını
işlemek için JavaScript birlikte çalışabilirliği kullanır.
Yayınlanan uygulamanın boyutu, Yük boyutu, uygulamanın useyeteneğinin önemli bir performans etkendir.
Büyük bir uygulamanın tarayıcıya indirmesi oldukça uzun sürer ve bu da Kullanıcı deneyimini azaltabilecek.
Blazor WebAssembly, indirme sürelerini azaltmak için yük boyutunu iyileştirir:
Kullanılmayan kod, ara dil (IL ) bağlayıcıtarafından yayımlandığında uygulamadan çıkarılır.
HTTP yanıtları sıkıştırılır.
.NET çalışma zamanı ve derlemeler tarayıcıda önbelleğe alınır.

Blazor Sunucusu
Blazor, Kullanıcı arabirimi güncelleştirmelerinin uygulanma, bileşen işleme mantığını ayırır. Blazor Server, bir
ASP.NET Core uygulamasındaki sunucuda Razor bileşenlerini barındırmak için destek sağlar. Kullanıcı
Arabirimi güncelleştirmeleri SignalR bir bağlantı üzerinden işlenir.
Çalışma zamanı, tarayıcıdan sunucuya kullanıcı arabirimi olayları göndermeyi ve bileşenleri çalıştırdıktan sonra
sunucu tarafından tarayıcıya geri gönderilen Kullanıcı arabirimi güncelleştirmelerini uygular.
Blazor sunucusu tarafından tarayıcıyla iletişim kurmak için kullanılan bağlantı, JavaScript birlikte çalışma
çağrılarını işlemek için de kullanılır.

JavaScript ile birlikte çalışma


Üçüncü taraf JavaScript kitaplıklarını ve tarayıcı API 'Lerine erişimi gerektiren uygulamalar için, bileşenler
JavaScript ile birlikte çalışır. Bileşenler, JavaScript 'in kullanabileceği herhangi bir kitaplığı veya API kullanma
yeteneğine sahiptir. C#kod JavaScript kodunu çağırabilir ve JavaScript kodu C# koda çağrı yapabilir. Daha fazla
bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği.

Kod paylaşımı ve .NET Standard


Blazor, .NET Standard 2,0uygular. .NET Standard, .NET uygulamaları genelinde ortak olan .NET API 'lerinin
resmi bir belirtimidir. .NET Standard sınıf kitaplıkları, Blazor, .NET Framework, .NET Core, Xamarin, mono ve
Unity gibi farklı .NET platformları arasında paylaşılabilir.
Bir Web tarayıcısı içinde geçerli olmayan API 'Ler (örneğin, dosya sistemine erişmek, bir yuva açmak ve iş
parçacığı açmak) PlatformNotSupportedExceptionoluşturur.

Ek kaynaklar
WebAssembly
Blazor barındırma modellerini ASP.NET Core
C# Kılavuzu
ASP.NET Core Razor söz dizimi başvurusu
HTML
Başar Blazor topluluk bağlantıları
Desteklenen Blazor platformları ASP.NET Core
13.11.2019 • 2 minutes to read • Edit Online

Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Tarayıcı gereksinimleri
Blazor WebAssembly
TARAYICI VERSION

Microsoft Edge Geçerli

Mozilla Firefox Geçerli

Android dahil Google Chrome Geçerli

İOS dahil Safari Geçerli

Microsoft Internet Explorer Desteklenmez†

†Microsoft Internet Explorer Webassembly'yi desteklemez.


Blazor sunucusu
TARAYICI VERSION

Microsoft Edge Geçerli

Mozilla Firefox Geçerli

Android dahil Google Chrome Geçerli

İOS dahil Safari Geçerli

Microsoft Internet Explorer 11†

†Ek polydolgular gereklidir (örneğin, Polyfill.io bir paket aracılığıyla taahhüt eklenebilir).

Ek kaynaklar
Blazor barındırma modellerini ASP.NET Core
ASP.NET Core Blazor kullanmaya başlama
13.12.2019 • 14 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazorkullanmaya başlayın:
1. .NET Core 3,1 SDK 'sınıyükler.
2. İsteğe bağlı olarak Blazor WebAssembly şablonunu yükler:
.NET Core 3,1 veya üzeri (Önizleme) SDK 'sınıyükler.
Komut kabuğu 'nda aşağıdaki komutu çalıştırın. Microsoft. AspNetCore.Blazor. Şablon paketinin
önizleme sürümü varsa Blazor WebAssembly önizleme aşamasındadır.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview4.19579.2

3. Araç seçiminiz için yönergeleri izleyin:


Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core CLI
1 . ASP.net ve Web geliştirme iş yüküyle Visual Studio 16,4 veya üstünü yükledikten sonra .
2 . Yeni bir proje oluşturun.
3 . Blazor uygulama' yı seçin. İleri’yi seçin.
4 . Proje adı alanında bir proje adı girin veya varsayılan proje adını kabul edin. Konum girişinin doğru
olduğunu onaylayın veya proje için bir konum belirtin. Oluştur’u seçin.
5 . Blazor Weelsembly deneyimi için, Webassembly uygulama şablonunuBlazor seçin. Blazor
sunucusu deneyimi için Blazor sunucusu uygulama şablonunu seçin. Oluştur’u seçin. Blazor, Blazor
sunucusu ve Blazor webassembly'yi barındıran iki hakkında bilgi için bkz. Blazor barındırma modellerini
ASP.NET Core.
6 . Uygulamayı çalıştırmak için Ctrl+F5 tuşuna basın.

NOTE
Blazor Visual Studio uzantısını ASP.NET Core Blazor önceki bir önizleme sürümü için yüklediyseniz (Preview 6 veya
daha önceki bir sürümü), uzantıyı kaldırabilirsiniz. Blazor şablonlarının bir komut kabuğu 'na yüklenmesi artık Visual
Studio 'daki şablonları yüzeye eklemek yeterlidir.
1. En son .NET Core 3,0 SDK 'sınıyükler.
2. İsteğe bağlı olarak Blazor WebAssembly şablonunu yükler:
.NET Core 3,1 veya üzeri (Önizleme) SDK 'sınıyükler.
Komut kabuğu 'nda aşağıdaki komutu çalıştırın. Microsoft. AspNetCore.Blazor. Şablon paketinin
önizleme sürümü varsa Blazor WebAssembly önizleme aşamasındadır.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview4.19579.2

3. Araç seçiminiz için yönergeleri izleyin:


Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core CLI
1 . ASP.net ve Web geliştirme iş yüküyle en son Visual Studio 'yu yükler.
2 . İsteğe bağlı olarak Visual Studio 16,4 Preview 2 veya üstünü , ASP.net ve Web geliştirme Iş yüküyle
Blazor webassembly uygulama geliştirmesi ile birlikte yükler.
3 . Yeni bir proje oluşturun.
4 . Blazor uygulama' yı seçin. İleri’yi seçin.
5 . Proje adı alanında bir proje adı girin veya varsayılan proje adını kabul edin. Konum girişinin doğru
olduğunu onaylayın veya proje için bir konum belirtin. Oluştur’u seçin.
6 . Blazor Weelsembly deneyimi için, Webassembly uygulama şablonunuBlazor seçin. Blazor
sunucusu deneyimi için Blazor sunucusu uygulama şablonunu seçin. Oluştur’u seçin. Blazor, Blazor
sunucusu ve Blazor webassembly'yi barındıran iki hakkında bilgi için bkz. Blazor barındırma modellerini
ASP.NET Core.
7 . Uygulamayı çalıştırmak için F5 tuşuna basın.

NOTE
Blazor Visual Studio uzantısını ASP.NET Core Blazor önceki bir önizleme sürümü için yüklediyseniz (Preview 6 veya
daha önceki bir sürümü), uzantıyı kaldırabilirsiniz. Blazor şablonlarının bir komut kabuğu 'na yüklenmesi artık Visual
Studio 'daki şablonları yüzeye eklemek yeterlidir.

Kenar çubuğu 'ndaki sekmelerde birden çok sayfa mevcuttur:


Ana Sayfası
Sayaç
Verileri getir
Sayaç sayfasında, bir sayfa yenilemesi olmadan sayacı artırmak için bana tıklama düğmesini seçin. Bir Web
sayfasında normal olarak bir sayacı artırma, JavaScript yazmayı gerektirir, ancak kullanabilirsiniz C#Blazor.
Pages/Counter. Razor:
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()


{
currentCount++;
}
}

Tarayıcıda /counter için bir istek, en üstteki @page yönergesi tarafından belirtilen şekilde Counter bileşeninin
içeriğini işlemesine neden olur. Bileşenler, daha sonra, Kullanıcı arabirimini esnek ve verimli bir şekilde
güncelleştirmek için kullanılabilen işleme ağacının bellek içi gösterimine işlenir.
Bana tıklama düğmesi her seçildiğinde:
onclick olayı tetiklenir.
IncrementCount yöntemi çağrılır.
currentCount artırılır.
Bileşen yeniden işlenir.
Çalışma zamanı, yeni içeriği önceki içerikle karşılaştırır ve yalnızca değiştirilen içeriği Belge Nesne Modeli
(DOM ) öğesine uygular.
HTML sözdizimini kullanarak başka bir bileşene bileşen ekleyin. Örneğin, Index bileşenine bir <Counter />
öğesi ekleyerek Counter bileşenini uygulamanın giriş sayfasına ekleyin.
Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter />

Uygulamayı çalıştırın. Giriş sayfasının Counter bileşeni tarafından kendi sayacı vardır.
Bileşen parametreleri, alt bileşende özellikler ayarlamanıza olanak tanıyan öznitelikler veya alt içerikkullanılarak
belirtilir. Counter bileşenine bir parametre eklemek için, bileşenin @code bloğunu güncelleştirin:
[Parameter] özniteliğiyle IncrementAmount için ortak özellik ekleyin.
currentCount değerini artırdığınızda IncrementAmount kullanmak için IncrementCount yöntemini değiştirin.
Pages/Counter. Razor:
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

[Parameter]
public int IncrementAmount { get; set; } = 1;

private void IncrementCount()


{
currentCount += IncrementAmount;
}
}

Index bileşenin <Counter> öğesindeki bir özniteliği kullanarak IncrementAmount belirtin.


Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter IncrementAmount="10" />

Uygulamayı çalıştırın. Index bileşeni, bana tıklama düğmesi seçildiğinde her seferinde on ile artan kendi
sayacıdır. /counter Counter bileşeni (Counter. Razor), bir tarafından arttırmaya devam eder.

Sonraki adımlar
İlk Blazor uygulamanızı oluşturma

Ek kaynaklar
ASP.NET Core Blazor şablonları
ASP.NET Core SignalR giriş
Blazor barındırma modellerini ASP.NET Core
9.12.2019 • 25 minutes to read • Edit Online

Daniel Roth tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor, bir Webassemblytabanlı .NET çalışma zamanı ( Blazor webassembly) veya ASP.NET Core ( Blazor
Server) sunucu tarafında tarayıcıda istemci tarafı çalıştırmak için tasarlanan bir Web çerçevesidir. Barındırma
modelinden bağımsız olarak, uygulama ve bileşen modelleri aynıdır.
Bu makalede açıklanan barındırma modelleriyle ilgili bir proje oluşturmak için, bkz. ASP.NET Core Blazor
kullanmaya başlama.

Blazor WebAssembly
Blazor için sorumlu barındırma modeli, WebAssembly üzerinde tarayıcıda istemci tarafında çalışmaktadır.
Blazor uygulaması, bağımlılıkları ve .NET çalışma zamanı tarayıcıya indirilir. Uygulama doğrudan tarayıcı
kullanıcı arabirimi iş parçacığında yürütülür. UI güncelleştirmeleri ve olay işleme aynı işlem içinde oluşur.
Uygulamanın varlıkları, istemcilere statik içerik sunan bir Web sunucusuna veya hizmete statik dosyalar
olarak dağıtılır.

İstemci tarafı barındırma modelini kullanarak bir Blazor uygulaması oluşturmak için, Blazor WebAssembly
uygulama şablonunu (DotNet New blazorwasm ) kullanın.
Blazor WebAssembly uygulama şablonunu seçtikten sonra, ASP.NET Core barındırılan onay kutusunu
(DotNet New blazorwasm--hosted) seçerek uygulamayı ASP.NET Core arka ucunu kullanacak şekilde
yapılandırma seçeneğiniz vardır. ASP.NET Core uygulaması, Blazor uygulamasına istemcilere hizmet verir.
Blazor WebAssembly uygulaması, Web API çağrılarını veya SignalRkullanarak ağ üzerinden sunucu ile
etkileşime geçebilir.
Şablonlar şunları ele alan blazor. webassembly. js betiğini içerir:
.NET çalışma zamanını, uygulamayı ve uygulamanın bağımlılıklarını indirme.
Uygulamayı çalıştırmak için çalışma zamanının başlatılması.
Blazor WebAssembly barındırma modeli çeşitli avantajlar sunar:
.NET sunucu tarafı bağımlılığı yoktur. Uygulama, istemciye indirildikten sonra tamamen çalışır.
İstemci kaynakları ve yetenekleri tamamen yararlanılabilir.
İş sunucudan istemciye boşaltılır.
Uygulamayı barındırmak için bir ASP.NET Core Web sunucusu gerekli değildir. Sunucusuz dağıtım
senaryoları mümkündür (örneğin, bir CDN 'den uygulama sunma).
WebAssembly barındırma Blazor için aşağı yanlar vardır:
Uygulama tarayıcının özelliklerine kısıtlıdır.
Uyumlu istemci donanımı ve yazılımı (örneğin, WebAssembly desteği) gereklidir.
İndirme boyutu daha büyüktür ve uygulamaların yüklenmesi daha uzun sürer.
.NET çalışma zamanı ve araç desteği daha az olgun. Örneğin, .NET Standard desteğinin ve hata
ayıklamada sınırlamalar mevcuttur.

Blazor Sunucusu
Blazor sunucusu barındırma modeliyle uygulama, sunucuda bir ASP.NET Core uygulamasının içinden
yürütülür. Kullanıcı Arabirimi güncelleştirmeleri, olay işleme ve JavaScript çağrıları SignalR bir bağlantı
üzerinden işlenir.

Blazor sunucusu barındırma modelini kullanarak bir Blazor uygulaması oluşturmak için ASP.NET Core
Blazor Server uygulama şablonunu (DotNet New blazorserver ) kullanın. ASP.NET Core uygulaması Blazor
sunucusu uygulamasını barındırır ve istemcilerin bağlanacağı SignalR uç noktasını oluşturur.
ASP.NET Core uygulama, şu ekleme için uygulamanın Startup sınıfına başvurur:
Sunucu tarafı hizmetler.
İstek işleme işlem hattının uygulaması.
Blazor. Server. js komut dosyası† istemci bağlantısını kurar. Uygulamanın, uygulama durumunu (örneğin,
kayıp ağ bağlantısı durumunda) kalıcı hale getirmek ve geri yüklemek, uygulamanın sorumluluğundadır.
Blazor sunucusu barındırma modeli çeşitli avantajlar sunar:
İndirme boyutu, Blazor WebAssembly uygulamasından önemli ölçüde küçüktür ve uygulama çok daha
hızlı yüklenir.
Uygulama, .NET Core ile uyumlu API 'lerin kullanımı dahil olmak üzere sunucu olanaklarından tam olarak
yararlanır.
Sunucuda .NET Core, uygulamayı çalıştırmak için kullanılır, bu nedenle hata ayıklama gibi mevcut .NET
araçları beklendiği gibi çalışır.
Ölçülü istemciler desteklenir. Örneğin, Blazor Server Apps, WebAssembly ve kaynak kısıtlı cihazlarda
bulunan tarayıcılarla çalışır.
Uygulamanın bileşen kodu da dahilC# olmak üzere, uygulamanın .NET/kod tabanı istemcilere
sunulmuyor.
Sunucu barındırma Blazor için aşağı yanlar vardır:
Daha yüksek gecikme süresi genellikle vardır. Her Kullanıcı etkileşimi bir ağ atmasını içerir.
Çevrimdışı destek yoktur. İstemci bağlantısı başarısız olursa, uygulama çalışmayı durduruyor.
Ölçeklenebilirlik, çok sayıda kullanıcısı olan uygulamalar için zorlayıcı bir uygulamalardır. Sunucunun
birden çok istemci bağlantısını yönetmesi ve istemci durumunu işlemesi gerekir.
Uygulamayı çalıştırmak için bir ASP.NET Core sunucusu gerekir. Sunucusuz dağıtım senaryoları mümkün
değildir (örneğin, bir CDN 'den uygulama sunma).
†blazor. Server. js komut dosyası, ASP.NET Core paylaşılan çerçevesindeki gömülü bir kaynaktan sunulur.
Sunucu tarafından işlenmiş Kullanıcı arabirimine karşılaştırma
Blazor Server uygulamalarını anlamanın bir yolu, Razor görünümlerini veya Razor Pages kullanarak
ASP.NET Core uygulamalarda Kullanıcı arabirimini işlemek için geleneksel modellerden nasıl farklılık gösterir.
Her iki model de, HTML içeriğini anlatmak için Razor dilini kullanır, ancak biçimlendirmenin nasıl işlendiği
konusunda önemli ölçüde farklılık gösterir.
Bir Razor sayfası veya görünüm işlendiğinde, her Razor kodu satırı metin biçiminde HTML yayar.
Oluşturulduktan sonra sunucu, üretilen herhangi bir durum da dahil olmak üzere sayfayı veya görünüm
örneğini ortadan kaldırır. Sayfa için başka bir istek gerçekleştiğinde, örneğin sunucu doğrulaması başarısız
olduğunda ve doğrulama özeti görüntülendiğinde:
Sayfanın tamamı HTML metnine yeniden eklenir.
Sayfa istemciye gönderilir.
Blazor bir uygulama, Bileşenleradlı Kullanıcı arabiriminin yeniden kullanılabilir öğelerinden oluşur. Bir bileşen
kod C# , biçimlendirme ve diğer bileşenleri içerir. Bir bileşen işlendiğinde Blazor, bir HTML veya XML Belge
Nesne Modeli (DOM ) gibi dahil edilen bileşenlerin bir grafiğini üretir. Bu grafik, özelliklerde ve alanlarında
tutulan bileşen durumunu içerir. Blazor, biçimlendirme ikili gösterimini üretmek için bileşen grafiğini
değerlendirir. İkili biçimi şu şekilde olabilir:
HTML metnine açıldı (prerendering sırasında).
Düzenli işleme sırasında biçimlendirmeyi verimli bir şekilde güncelleştirmek için kullanılır.
Blazor bir kullanıcı arabirimi güncelleştirmesi tarafından tetiklenir:
Düğme seçme gibi kullanıcı etkileşimi.
Zamanlayıcı gibi uygulama Tetikleyicileri.
Grafik yeniden tanımlanır ve bir UI farkı (fark) hesaplanır. Bu fark, istemcideki Kullanıcı arabirimini
güncelleştirmek için gereken en küçük DOM düzenlemelerinin kümesidir. Fark istemciye bir ikili biçimde
gönderilir ve tarayıcı tarafından uygulanır.
Kullanıcı, istemci üzerinde bundan uzaklaştığında bir bileşen atılmış olur. Bir Kullanıcı bir bileşenle etkileşim
kurarken, bileşenin durumu (hizmetler, kaynaklar) sunucunun belleğinde tutulmalıdır. Birçok bileşenin
durumu sunucu tarafından eşzamanlı olarak Korunabileceğinden, bellek tükenmesi sorunu ele alınmalıdır.
Sunucu belleğinin en iyi şekilde kullanılmasını sağlamak üzere Blazor sunucu uygulamasının nasıl yazılacağı
hakkında yönergeler için bkz. Güvenli ASP.NET Core Blazor Server uygulamaları.
Uygulanıp
Blazor sunucusu uygulaması ASP.NET Core SignalRüzerine kurulmuştur. Her istemci, bir devreolarak
adlandırılan bir veya daha fazla SignalR bağlantı üzerinden sunucu ile iletişim kurar. Devre, geçici ağ
kesintilerine tolerans sağlayan SignalR bağlantıları üzerinden Blazorsoyutlamasıdır. Blazor istemci SignalR
bağlantısının kesileceğini gördüğünde, yeni bir SignalR bağlantısı kullanarak sunucuya yeniden bağlanmaya
çalışır.
Bir Blazor sunucusu uygulamasına bağlı her tarayıcı ekranı (tarayıcı sekmesi veya IFRAME ) SignalR bir
bağlantı kullanır. Bu, tipik sunucu tarafından işlenmiş uygulamalarla karşılaştırıldığında daha önemli bir ayırım
ifade etmiştir. Sunucu tarafından işlenen bir uygulamada, aynı uygulamayı birden çok tarayıcı ekranında
açmak genellikle sunucuda ek kaynak taleplerine çevirilmez. Blazor sunucusu uygulamasında, her tarayıcı
ekranı, sunucu tarafından yönetilecek ayrı bir devre ve bileşen durumunun ayrı örneklerini gerektirir.
Blazor bir tarayıcı sekmesini kapatmayı veya bir dış URL 'ye gidilmesini göz önünde bulundurur. Düzgün
sonlandırma durumunda, devre ve ilişkili kaynaklar hemen serbest bırakılır. Bir istemci, örneğin bir ağ
kesintisi nedeniyle düzgün şekilde kesilmeyen bir şekilde kesilebilir. Blazor sunucusu, istemcinin yeniden
bağlanmasına izin vermek için, yapılandırılabilir bir Aralık için bağlantısı kesilen devreleri depolar. Daha fazla
bilgi için aynı sunucuya yeniden bağlanma bölümüne bakın.
UI gecikmesi
UI gecikme süresi, başlatılan bir eylemden Kullanıcı arabiriminin güncelleştirildiği zamana kadar geçen
süredir. Bir uygulamanın kullanıcıya yanıt vermesi için kullanıcı ARABIRIMI gecikmesi için daha küçük
değerler zorunludur. Blazor sunucu uygulamasında her bir eylem sunucusuna gönderilir, işlenir ve bir UI farkı
geri gönderilir. Sonuç olarak, UI gecikmesi ağ gecikme süresinin toplamı ve eylemi işlerken sunucu gecikmesi
sayısıdır.
Özel bir kurumsal ağla sınırlı bir iş kolu uygulaması için, ağ gecikmesi nedeniyle kullanıcı gecikmesi algılarını
üzerindeki etki, genellikle çok sayıda CEPSİZ olur. Internet üzerinden dağıtılan bir uygulama için, özellikle de
kullanıcılar coğrafi olarak coğrafi olarak dağıtılmışsa gecikme süresi kullanıcılara karşı farklılık gösterebilir.
Bellek kullanımı ayrıca uygulama gecikme süresine de katkıda bulunabilir. Daha fazla bellek kullanımı, her ikisi
de uygulama performansının düşmesine neden olan ve bu nedenle kullanıcı arabirimi gecikmesini arttığı
diskte sık görülen çöp toplama veya disk belleği belleği Daha fazla bilgi için bkz. Güvenli ASP.NET Core
Blazor Server uygulamaları.
Blazor sunucu uygulamaları, ağ gecikmesini ve bellek kullanımını azaltarak UI gecikmesini en aza indirmek
için iyileştirilmelidir. Ağ gecikmesini ölçmeye yönelik bir yaklaşım için bkz. ASP.NET Core Blazor sunucusu
barındırma ve dağıtma. SignalR ve Blazorhakkında daha fazla bilgi için bkz.
ASP.NET Core Blazor sunucusu barındırma ve dağıtma
Güvenli ASP.NET Core Blazor Server uygulamaları
Sunucuyla bağlantı
Blazor Server uygulamaları sunucuya etkin bir SignalR bağlantısı gerektirir. Bağlantı kaybolursa, uygulama
sunucuya yeniden bağlanmaya çalışır. İstemcinin durumu hala bellekte olduğu sürece, istemci oturumu
durum kaybı olmadan devam eder.
Aynı sunucuya yeniden bağlanma
Sunucu üzerinde kullanıcı arabirimi durumunu ayarlayan ilk istemci isteğine yanıt olarak önceden bir Blazor
sunucusu uygulaması ön ekler. İstemci bir SignalR bağlantısı oluşturmayı denediğinde, istemci aynı sunucuya
yeniden bağlanmalıdır. birden fazla arka uç sunucusu kullanan Blazor Server uygulamalarının SignalR
bağlantıları için yapışkan oturumlar uygulaması gerekir.
Blazor Server uygulamaları için Azure SignalR hizmetini kullanmanızı öneririz. Hizmet, Blazor sunucu
uygulamasının ölçeğini çok sayıda eşzamanlı SignalR bağlantı ile ölçeklendirmeye olanak tanır. Azure SignalR
hizmeti için, hizmetin ServerStickyMode seçeneği veya yapılandırma değeri Required olarak ayarlanarak
yapışkan oturumlar etkinleştirilir. Daha fazla bilgi için bkz. ASP.NET Core Blazor sunucusu barındırma ve
dağıtma.
IIS kullanırken, yapışkan oturumlar uygulama Isteği yönlendirme ile etkinleştirilir. Daha fazla bilgi için bkz.
uygulama Isteği yönlendirme kullanarak HTTP yük dengelemesi.
Kullanıcı arabirimindeki bağlantı durumunu yansıtır
İstemci bağlantının kaybolduğunu algıladığında, istemci yeniden bağlanmayı denediğinde kullanıcıya
varsayılan bir kullanıcı arabirimi görüntülenir. Yeniden bağlantı başarısız olursa, kullanıcıya yeniden deneme
seçeneği sağlanır.
Kullanıcı arabirimini özelleştirmek için _Host. cshtml Razor sayfasının <body> components-reconnect-modal
id bir öğe tanımlayın:

<div id="components-reconnect-modal">
...
</div>

Aşağıdaki tabloda components-reconnect-modal öğesine uygulanan CSS sınıfları açıklanmaktadır.

CSS SINIFI … GÖSTERIR

components-reconnect-show Kayıp bir bağlantı. İstemci yeniden bağlanmaya çalışıyor.


Kalıcı olarak göster.

components-reconnect-hide Etkin bir bağlantı sunucuya yeniden oluşturulur. Kalıcı olarak


gizleyin.

components-reconnect-failed Muhtemelen bir ağ hatasından dolayı yeniden bağlantı


başarısız oldu. Yeniden bağlanmayı denemek için
window.Blazor.reconnect() çağırın.

components-reconnect-rejected Yeniden bağlantı reddedildi. Sunucuya ulaşıldı ancak


bağlantı reddedildi ve kullanıcının sunucudaki durumu
kayboldu. Uygulamayı yeniden yüklemek için
location.reload() çağırın. Bu bağlantı durumu şu
durumlarda oluşabilir:
Sunucu tarafında devre dışı bir kilitlenme oluşur.
Sunucunun kullanıcının durumunu bırakması için
istemcinin bağlantısı yeterince uzun değil.
Kullanıcının etkileşimde bulunduğu bileşenlerin
örnekleri atıldı.
Sunucu yeniden başlatıldı veya uygulamanın çalışan
işlemi geri dönüştürüldü.

Prerendering sonrasında durum bilgisi olan yeniden bağlanma


sunucu bağlantısı kurumadan önce sunucu üzerindeki kullanıcı arabirimine varsayılan olarak, Blazor Server
uygulamaları varsayılan olarak ayarlanır. Bu, _Host. cshtml Razor sayfasında ayarlanır:
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>

<script src="_framework/blazor.server.js"></script>
</body>

<body>
<app>@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))</app>

<script src="_framework/blazor.server.js"></script>
</body>

RenderMode , bileşenin şunları yapıp kullanmadığını yapılandırır:


, Sayfaya ön gönderilir.
, Sayfada statik HTML olarak veya Kullanıcı aracısından bir Blazor uygulamasını önyüklemek için gerekli
bilgileri içeriyorsa.

RENDERMODE AÇIKLAMA

ServerPrerendered Bileşeni statik HTML olarak işler ve Blazor sunucusu


uygulaması için bir işaret içerir. Kullanıcı Aracısı başladığında,
bu işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır.

Server Blazor sunucusu uygulaması için bir işaret oluşturur. Bileşen


çıkışı dahil değildir. Kullanıcı Aracısı başladığında, bu
işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır.

Static Bileşeni statik HTML olarak işler.

RENDERMODE AÇIKLAMA

ServerPrerendered Bileşeni statik HTML olarak işler ve Blazor sunucusu


uygulaması için bir işaret içerir. Kullanıcı Aracısı başladığında,
bu işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır. Parametreler desteklenmiyor.

Server Blazor sunucusu uygulaması için bir işaret oluşturur. Bileşen


çıkışı dahil değildir. Kullanıcı Aracısı başladığında, bu
işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır. Parametreler desteklenmiyor.

Static Bileşeni statik HTML olarak işler. Parametreler destekleniyor.

Statik HTML sayfasından sunucu bileşenleri işleme desteklenmiyor.


RenderMode , bileşen başlangıçta sayfanın bir parçası olarak statik olarak işlenir. Tarayıcı
ServerPrerendered
sunucuya geri bir bağlantı kurduğunda, bileşen yenidenişlenir ve bileşen artık etkileşimli olur. Bileşeni
başlatmak için Onbaşlatılmış {Async} yaşam döngüsü yöntemi varsa, yöntem iki kezyürütülür:
Bileşen statik olarak önceden kullanılırken.
Sunucu bağlantısı kurulduktan sonra.
Bu, bileşen son işlendiğinde Kullanıcı arabiriminde görünen verilerde fark edilebilir bir değişikliğe neden
olabilir.
Blazor sunucu uygulamasında çift işleme senaryosunu önlemek için:
Prerendering sırasında durumu önbelleğe almak için kullanılabilecek bir tanımlayıcı geçirin ve uygulamayı
yeniden başlattıktan sonra durumu alma.
Bileşen durumunu kaydetmek için prerendering sırasında tanımlayıcıyı kullanın.
Önbelleğe alınan durumu almak için prerendering öğesinden sonra tanımlayıcıyı kullanın.
Aşağıdaki kod, Çift işlemeyi engelleyen şablon tabanlı Blazor sunucu uygulamasındaki güncelleştirilmiş bir
WeatherForecastService gösterir:

public class WeatherForecastService


{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

public WeatherForecastService(IMemoryCache memoryCache)


{
MemoryCache = memoryCache;
}

public IMemoryCache MemoryCache { get; }

public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)


{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});

var rng = new Random();

await Task.Delay(TimeSpan.FromSeconds(10));

return Enumerable.Range(1, 5).Select(index => new WeatherForecast


{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
});
}
}

Razor sayfaları ve görünümlerinden durum bilgisi olan etkileşimli bileşenleri işleme


Durum bilgisi olan etkileşimli bileşenler Razor sayfasına veya görünümüne eklenebilir.
Sayfa veya görünüm şunları işler:
Bileşen sayfa veya görünümle birlikte kullanılır.
Prerendering için kullanılan ilk bileşen durumu kayboldu.
SignalR bağlantısı oluşturulduğunda yeni bileşen durumu oluşturulur.
Aşağıdaki Razor sayfası bir Counter bileşeni işler:
<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered"


param-InitialValue="InitialValue" />

@code {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}

<h1>My Razor Page</h1>

@(await Html.RenderComponentAsync<Counter>(RenderMode.ServerPrerendered))

@code {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}

Razor sayfaları ve görünümlerinden etkileşimsiz bileşenleri işleme


Aşağıdaki Razor sayfasında, Counter bileşen bir form kullanılarak belirtilen bir başlangıç değeri ile statik
olarak işlenir:

<h1>My Razor Page</h1>

<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static"


param-InitialValue="InitialValue" />

@code {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}

<h1>My Razor Page</h1>

<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>

@(await Html.RenderComponentAsync<Counter>(RenderMode.Static,
new { InitialValue = InitialValue }))

@code {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}

MyComponent statik olarak işlendiğinde, bileşen etkileşimli olamaz.


Uygulamanın ne zaman prerendering olduğunu Algıla
Blazor sunucu uygulaması prerendering olduğunda, tarayıcıyla bir bağlantı kurulmadığından, JavaScript 'e
çağırma gibi bazı eylemler mümkün değildir. Bileşenler, ön işlenmiş olduğunda farklı şekilde işlenmesi
gerekebilir.
Tarayıcı bağlantısı kurulana kadar JavaScript birlikte çalışma çağrılarını geciktirmek için Onafterrenderasync
bileşen yaşam döngüsü olayınıkullanabilirsiniz. Bu olay yalnızca uygulama tam olarak işlendikten ve istemci
bağlantısı kurulduktan sonra çağırılır.

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div @ref="divElement">Text during render</div>

@code {
private ElementReference divElement;

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync(
"setElementText", divElement, "Text after render");
}
}
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor
Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın. İşlevi IJSRuntime.InvokeVoidAsync
ile çağrılır ve bir değer döndürmez:

<script>
window.setElementText = (element, text) => element.innerText = text;
</script>

WARNING
Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir. JavaScript, Blazor 'in değişiklik
izlemesini kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.

Aşağıdaki bileşen, prerendering ile uyumlu bir şekilde bileşenin başlatma mantığının bir parçası olarak
JavaScript birlikte çalışabilirinin nasıl kullanılacağını göstermektedir. Bileşeni, OnAfterRenderAsync içinden bir
işleme güncelleştirmesi tetiklemenin mümkün olduğunu gösterir. Geliştirici Bu senaryoda sonsuz bir döngü
oluşturmaktan kaçınmalıdır.
JSRuntime.InvokeAsync çağrıldığında, bileşen işlenene kadar hiçbir JavaScript öğesi olmadığından,
ElementRef yalnızca OnAfterRenderAsync için kullanılır ve daha önceki bir yaşam döngüsü yönteminde değil.
JavaScript birlikte çalışma çağrısından alınan yeni durumla birlikte bileşeni yeniden sağlamak için
Statehaschanged çağrılır. StateHasChanged yalnızca infoFromJs null olduğunda çağrıldığı için, kod sonsuz
bir döngü oluşturmaz.
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<p>
Get value via JS interop call:
<strong id="val-get-by-interop">@(infoFromJs ?? "No value yet")</strong>
</p>

Set value via JS interop call:


<div id="val-set-by-interop" @ref="divElement"></div>

@code {
private string infoFromJs;
private ElementReference divElement;

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender && infoFromJs == null)
{
infoFromJs = await JSRuntime.InvokeAsync<string>(
"setElementText", divElement, "Hello from interop call!");

StateHasChanged();
}
}
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor
Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın. İşlevi IJSRuntime.InvokeAsync ile
çağrılır ve bir değer döndürür:

<script>
window.setElementText = (element, text) => {
element.innerText = text;
return text;
};
</script>

WARNING
Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir. JavaScript, Blazor 'in değişiklik
izlemesini kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.

Blazor Server uygulamaları için SignalR istemcisini yapılandırma


Bazen Blazor Server uygulamaları tarafından kullanılan SignalR istemcisini yapılandırmanız gerekir. Örneğin,
bir bağlantı sorununu tanılamak için SignalR istemcisinde günlüğe kaydetmeyi yapılandırmak isteyebilirsiniz.
Pages/_Host. cshtml dosyasında SignalR istemcisini yapılandırmak için:
Blazor. Server. js betiği için <script> etiketine bir autostart="false" özniteliği ekleyin.
Blazor.start çağırın ve SignalR oluşturucuyu belirten bir yapılandırma nesnesini geçirin.
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
Blazor.start({
configureSignalR: function (builder) {
builder.configureLogging("information"); // LogLevel.Information
}
});
</script>

Ek kaynaklar
ASP.NET Core Blazor kullanmaya başlama
ASP.NET Core SignalR giriş
İlk Blazor uygulamanızı oluşturma
9.12.2019 • 12 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Bu öğreticide bir Blazor uygulamasının nasıl oluşturulacağı ve değiştirileceği gösterilmektedir.


Bu öğreticide bir Blazor projesi oluşturmak için ASP.NET Core Blazor kullanmaya başlama makalesindeki
yönergeleri izleyin. Projeyi ToDoListolarak adlandırın.

Derleme bileşenleri
1. Sayfalar klasöründe uygulamanın üç sayfasının her birine gidin: giriş, sayaç ve veri getirme. Bu sayfalar,
Razor bileşen dosyaları dizini. Razor, Counter. Razorve fetchdata. Razortarafından uygulanır.
2. Sayaç sayfasında, bir sayfa yenilemesi olmadan sayacı artırmak için bana tıklama düğmesini seçin. Bir
Web sayfasında normal olarak bir sayacı artırma, JavaScript yazmayı gerektirir. Blazor, bunun yerine
yazabilirsiniz C# .
3. Counter. Razor dosyasındaki Counter bileşeninin uygulamasını inceleyin.
Pages/Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()


{
currentCount++;
}
}

Counter bileşenin kullanıcı arabirimi HTML kullanılarak tanımlanır. Dinamik işleme mantığı (örneğin,
döngüler, koşullar, ifadeler) C# Razoradlı gömülü bir sözdizimi kullanılarak eklenir. HTML biçimlendirme ve
C# işleme mantığı, derleme zamanında bir bileşen sınıfına dönüştürülür. Oluşturulan .NET sınıfının adı
dosya adıyla eşleşir.
Bileşen sınıfının üyeleri bir @code bloğunda tanımlanmıştır. @code bloğunda, bileşen durumu (özellikler,
alanlar) ve yöntemler olay işleme için veya diğer bileşen mantığını tanımlamak için belirtilir. Bu Üyeler daha
sonra bileşenin işleme mantığının bir parçası olarak ve olayları işlemek için kullanılır.
Bana tıklama düğmesi seçildiğinde:
Counterbileşenin kayıtlı onclick işleyicisine ( IncrementCount yöntemi) denir.
Counter bileşeni, işleme ağacını yeniden oluşturur.
Yeni işleme ağacı öncekiyle karşılaştırılır.
Yalnızca Belge Nesne Modeli (DOM ) üzerinde yapılan değişiklikler uygulanır. Görünen sayı
güncelleştirildi.
4. Sayıyı bir C# yerine iki ile artırmak için Counter bileşenin mantığını değiştirin.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()


{
currentCount += 2;
}
}

5. Değişiklikleri görmek için uygulamayı yeniden derleyin ve çalıştırın. Ben tıklama düğmesini seçin. Sayaç iki
olarak artar.

Bileşenleri kullanma
Bir bileşeni, bir HTML söz dizimini kullanarak başka bir bileşene ekleyin.
1. Index bileşenine bir <Counter /> öğesi ekleyerek uygulamanın Index bileşenine Counter bileşenini
ekleyin (Index. Razor).
Bu deneyim için Blazor WebAssembly kullanıyorsanız, Index bileşeni tarafından SurveyPrompt bir bileşen
kullanılır. <SurveyPrompt> öğesini bir <Counter /> öğesiyle değiştirin. Bu deneyim için bir Blazor sunucusu
uygulaması kullanıyorsanız, Index bileşenine <Counter /> öğesini ekleyin:
Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter />

2. Uygulamayı yeniden derleyin ve çalıştırın. Index bileşeni kendi sayacıdır.

Bileşen parametreleri
Bileşenler de parametrelere sahip olabilir. Bileşen parametreleri, bileşen sınıfında [Parameter] özniteliğiyle ortak
özellikler kullanılarak tanımlanır. Biçimlendirme içindeki bir bileşenin bağımsız değişkenlerini belirtmek için
öznitelikleri kullanın.
1. Bileşenin @code C# kodunu güncelleştirin:
[Parameter] özniteliğiyle ortak bir IncrementAmount özelliği ekleyin.
currentCount değerini artırdığınızda IncrementAmount kullanmak için IncrementCount yöntemini
değiştirin.
Pages/Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

[Parameter]
public int IncrementAmount { get; set; } = 1;

private void IncrementCount()


{
currentCount += IncrementAmount;
}
}

1. Özniteliği kullanarak Index bileşeninin <Counter> öğesinde bir IncrementAmount parametresi belirtin.
Sayacı on olarak artırmak için değeri ayarlayın.
Pages/Index. Razor:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter IncrementAmount="10" />

2. Index bileşenini yeniden yükleyin. Beni tıklama düğmesi seçildiğinde sayaç on bir kez artar. Counter
bileşenindeki sayaç bir artış ile devam eder.

Bileşenlere yönlendir
Counter. Razor dosyasının en üstündeki @page yönergesi, Counter bileşeninin bir yönlendirme uç noktası
olduğunu belirtir. Counter bileşeni /counter gönderilen istekleri işler. @page yönergesi olmadan, bileşen
yönlendirilmiş istekleri işlemez, ancak bileşen diğer bileşenler tarafından hala kullanılabilir.

Bağımlılık ekleme
Blazor sunucusu deneyimi
Blazor sunucu uygulamasıyla çalışıyorsanız, WeatherForecastService hizmeti bir tek Startup.ConfigureServices
olarak kaydedilir. Uygulamanın tamamında bağımlılık ekleme (dı)yoluyla hizmetin bir örneği mevcuttur:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}

@inject yönergesi, WeatherForecastService hizmetinin örneğini FetchData bileşenine eklemek için kullanılır.
Pages/FetchData. Razor:

@page "/fetchdata"
@using ToDoList.Data
@inject WeatherForecastService ForecastService

FetchData bileşeni, WeatherForecast nesnelerinin bir dizisini almak için, ForecastService olarak eklenen hizmeti
kullanır:

@code {
private WeatherForecast[] forecasts;

protected override async Task OnInitializedAsync()


{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}

Blazor Weelsembly deneyimi


Blazor WebAssembly uygulamasıyla çalışıyorsanız, Wwwroot/Sample-Data klasöründeki Hava durumu. JSON
dosyasından Hava durumu tahmin verileri almak için HttpClient eklenir.
Pages/FetchData. Razor:

@inject HttpClient Http

...

protected override async Task OnInitializedAsync()


{
forecasts =
await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}

@foreach döngüsü, her tahmin örneğini Hava durumu verileri tablosunda bir satır olarak işlemek için kullanılır:
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>

Yapılacaklar listesi oluşturma


Uygulamaya basit bir yapılacaklar listesi uygulayan yeni bir bileşen ekleyin.
1. Uygulamalar klasörüne Todo. Razor adlı boş bir dosya ekleyin:
2. Bileşen için ilk biçimlendirmeyi belirtin:

@page "/todo"

<h1>Todo</h1>

3. Gezinti çubuğuna Todo bileşenini ekleyin.


NavMenu bileşeni (Shared/NavMenu. Razor) uygulamanın düzeninde kullanılır. Düzenler, uygulamadaki
içeriğin çoğaltılmasını önlemenize olanak sağlayan bileşenlerdir.
Aşağıdaki liste öğesi işaretlemesini paylaşılan/NavMenu. Razor dosyasında var olan liste öğelerinin altına
ekleyerek Todo bileşeni için bir <NavLink> öğesi ekleyin:

<li class="nav-item px-3">


<NavLink class="nav-link" href="todo">
<span class="oi oi-list-rich" aria-hidden="true"></span> Todo
</NavLink>
</li>

4. Uygulamayı yeniden derleyin ve çalıştırın. Todo bileşeni bağlantısının çalıştığından emin olmak için yeni
Todo sayfasını ziyaret edin.
5. Bir Todo öğesini temsil eden bir sınıfı tutmak için projenin köküne bir TodoItem.cs dosyası ekleyin.
TodoItem sınıfı için C# aşağıdaki kodu kullanın:
public class TodoItem
{
public string Title { get; set; }
public bool IsDone { get; set; }
}

6. Todo bileşenine geri dönün (Pages/Todo. Razor):


@code bloğundaki Todo öğeleri için bir alan ekleyin. Todo bileşeni, Todo listesinin durumunu korumak
için bu alanı kullanır.
Her Todo öğesini bir liste öğesi ( <li> ) olarak işlemek için sıralanmamış liste işaretlemesi ve bir foreach
döngüsü ekleyin.

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
}

7. Uygulama, listeye Todo öğeleri eklemek için Kullanıcı arabirimi öğeleri gerektirir. Sıralanmamış listenin (
<ul>...</ul> ) altına bir metin girişi ( <input> ) ve bir düğme ( <button> ) ekleyin:

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

<input placeholder="Something todo" />


<button>Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
}

8. Uygulamayı yeniden derleyin ve çalıştırın. Todo Ekle düğmesi seçildiğinde, bir olay işleyicisi düğmeye
kablolu olmadığı için hiçbir şey olmaz.
9. Todo bileşenine bir AddTodo yöntemi ekleyin ve @onclick özniteliğini kullanarak düğme seçimleri için
kaydedin. Düğme seçildiğinde C# AddTodo yöntemi çağrılır:
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();

private void AddTodo()


{
// Todo: Add the todo
}
}

10. Yeni Todo öğesinin başlığını almak için, @code bloğunun üst kısmına bir newTodo dize alanı ekleyin ve
<input> öğesindeki bind özniteliğini kullanarak metin girişinin değerine bağlayın:

private IList<TodoItem> todos = new List<TodoItem>();


private string newTodo;

<input placeholder="Something todo" @bind="newTodo" />

11. AddTodo yöntemini, belirtilen başlığa sahip TodoItem listeye eklemek için güncelleştirin. newTodo boş bir
dizeye ayarlayarak metin girişinin değerini temizleyin:

@page "/todo"

<h1>Todo</h1>

<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>

<input placeholder="Something todo" @bind="newTodo" />


<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
private string newTodo;

private void AddTodo()


{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}

12. Uygulamayı yeniden derleyin ve çalıştırın. Yeni kodu test etmek için Todo listesine bazı Todo öğeleri ekleyin.
13. Her Todo öğesi için başlık metni düzenlenebilir hale getirilebilir ve bir onay kutusu kullanıcının
tamamlanmış öğeleri izlemesine yardımcı olabilir. Her Todo öğesi için bir onay kutusu girişi ekleyin ve
değerini IsDone özelliğine bağlayın. @todo.Title , @todo.Title bağlantılı <input> bir öğe olarak değiştirin:
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>

14. Bu değerlerin bağlandığını doğrulamak için <h1> üst bilgisini, tamamlanmamış olan Todo öğelerinin
sayısının sayısını gösterecek şekilde güncelleştirin ( IsDone false ).

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

15. Tamamlanan Todo bileşeni (Sayfalar/Todo. Razor):

@page "/todo"

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>

<input placeholder="Something todo" @bind="newTodo" />


<button @onclick="AddTodo">Add todo</button>

@code {
private IList<TodoItem> todos = new List<TodoItem>();
private string newTodo;

private void AddTodo()


{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}

16. Uygulamayı yeniden derleyin ve çalıştırın. Yeni kodu test etmek için Todo öğeleri ekleyin.
ASP.NET Core Razor bileşenleri oluşturma ve kullanma
ASP.NET Core Blazor şablonları
6.12.2019 • 5 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor Framework, Blazor barındırma modellerinin her biri için uygulama geliştirmeye yönelik şablonlar sağlar:
Blazor WebAssembly ( blazorwasm )
Blazor sunucusu ( blazorserver )
Blazorbarındırma modelleri hakkında daha fazla bilgi için bkz. Blazor barındırma modellerini ASP.NET Core.
Şablondan Blazor uygulama oluşturmaya yönelik adım adım yönergeler için, bkz. ASP.NET Core Blazor
kullanmaya başlama.

Blazor proje yapısı


Aşağıdaki dosya ve klasörler, Blazor şablonundan oluşturulan Blazor bir uygulama yapar:
Program.cs ana bilgisayarıASP.NET Core ayarlayan uygulamanın giriş noktasını –. Bu dosyadaki kod,
ASP.NET Core şablonlarından oluşturulan tüm ASP.NET Core uygulamalarda ortaktır.
Startup.cs –, uygulamanın başlangıç mantığını içerir. Startup sınıfı iki yöntemi tanımlar:
ConfigureServices –, uygulamanın bağımlılık ekleme (dı) hizmetlerini yapılandırır. Sunucu
uygulamalarında Blazor, hizmetler AddServerSideBlazorçağırarak eklenir ve WeatherForecastService
örnek FetchData bileşeni tarafından kullanılmak üzere hizmet kapsayıcısına eklenir.
Configure –, uygulamanın istek işleme ardışık düzenini yapılandırır:
Blazor WebAssembly –, uygulamanın kök bileşeni olan App bileşenini ( app DOM öğesi olarak
belirtilen AddComponent yöntemine) ekler.
Blazor Sunucusu
MapBlazorHub, tarayıcıya gerçek zamanlı bağlantı için bir uç nokta ayarlamak üzere
çağırılır. Bağlantı, uygulamalara gerçek zamanlı Web işlevselliği eklemek için bir çerçeveden
SignalRoluşturulur.
Mapfallbacktopage ("/_Host") , uygulamanın kök sayfasını (Pages/_Host. cshtml) ayarlamak
ve gezinmeyi etkinleştirmek için çağırılır.
Wwwroot/index.html (Blazor WebAssembly) bir HTML sayfası olarak uygulanan uygulamanın kök sayfasını
–:
Uygulamanın herhangi bir sayfası başlangıçta istendiğinde, Bu sayfa işlenir ve yanıtta döndürülür.
Bu sayfa, kök App bileşeninin nerede işleneceğini belirtir. App bileşeni (app. Razor) Startup.Configure
içindeki AddComponent metoduna app DOM öğesi olarak belirtilir.
_Framework/Blazor.webassembly.js JavaScript dosyası yüklenir ve şunları yapın:
.NET çalışma zamanını, uygulamayı ve uygulamanın bağımlılıklarını indirir.
Uygulamayı çalıştırmak için çalışma zamanını başlatır.
Pages/_Host. cshtml (Blazor Server), Razor sayfası olarak uygulanan uygulamanın kök sayfasına –:
Uygulamanın herhangi bir sayfası başlangıçta istendiğinde, Bu sayfa işlenir ve yanıtta döndürülür.
Tarayıcı ve sunucu arasındaki gerçek zamanlı SignalR bağlantısını ayarlayan _framework/Blazor.Server.js
JavaScript dosyası yüklenir.
Ana bilgisayar sayfası, kök App bileşeni 'nin (app. Razor) nerede işleneceğini belirtir.
App. razor – Router bileşenini kullanarak istemci tarafı yönlendirmeyi ayarlayan uygulamanın kök
bileşenidir. Router bileşeni tarayıcı gezintisini karşılar ve istenen adresle eşleşen sayfayı işler.
Sayfalar klasörü – Blazor uygulamayı oluşturan yönlendirilebilir bileşenleri/sayfaları ( . Razor) içerir. Her
sayfanın yolu @page yönergesi kullanılarak belirtilir. Şablon aşağıdaki bileşenleri içerir:
Index (Index. Razor) – giriş sayfasını uygular.
Counter ( Counter. Razor) – sayaç sayfasını uygular.
uygulamada işlenmeyen bir özel durum oluştuğunda Error (yalnızcahata. Razor, Blazor sunucu
uygulaması) –.
FetchData (fetchdata. Razor) – verileri getir sayfasını uygular.
Paylaşılan klasör –, uygulama tarafından kullanılan diğer Kullanıcı Arabirimi bileşenlerini ( . Razor) içerir:
MainLayout (mainlayout. Razor) uygulamanın düzen bileşeni –.
NavMenu ( Navmenu. Razor) – kenar çubuğu gezintisini uygular. Diğer Razor bileşenlerine yönelik gezinti
bağlantılarını işleyen navlink bileşenini (NavLink) içerir. NavLink bileşeni, bileşeni yüklendiği zaman
otomatik olarak seçili durumu gösterir ve bu, kullanıcının hangi bileşenin görüntülenmekte olduğunu
anlamasına yardımcı olur.
_Imports. razor –, uygulamanın bileşenlerine ( . Razor) dahil edilecek, ad alanları için @using yönergeleri
gibi ortak Razor yönergelerini içerir.
Veri klasörü (Blazor sunucusu) –, uygulamanın FetchData bileşene örnek Hava durumu verileri sağlayan
WeatherForecastService WeatherForecast sınıfını ve uygulamasını içerir.

Wwwroot , uygulamanın ortak statik varlıklarını Içeren uygulamanın Web kök klasörünü –.
appSettings. JSON (Blazor Server) uygulama için yapılandırma ayarlarını –.
ASP.NET Core Razor bileşenleri oluşturma ve
kullanma
9.12.2019 • 76 minutes to read • Edit Online

, Luke Latham ve Daniel Roth tarafından


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Blazor uygulamalar, bileşenlerikullanılarak oluşturulmuştur. Bir bileşen, bir sayfa, iletişim veya form gibi bir
kullanıcı arabirimi (UI) öbekidir. Bir bileşen, veri eklemek veya UI olaylarına yanıt vermek için gereken HTML
işaretlemesini ve işleme mantığını içerir. Bileşenler esnek ve hafif. Bunlar, iç içe geçmiş, yeniden kullanılabilir ve
projeler arasında paylaşılabilir.

Bileşen sınıfları
Bileşenler, C# ve HTML Işaretlemesi kullanılarak Razor bileşen dosyalarında ( . Razor) uygulanır. Blazor bir
bileşen, bir Razor bileşeniolarak adlandırılır.
Bir bileşenin adı, büyük harfle başlamalıdır. Örneğin, mycoolcomponent. Razor geçerlidir ve mycoolcomponent.
Razor geçersizdir.
Bir bileşen için Kullanıcı arabirimi HTML kullanılarak tanımlanır. Dinamik işleme mantığı (örneğin, döngüler,
koşullar, ifadeler) C# Razoradlı gömülü bir sözdizimi kullanılarak eklenir. Bir uygulama derlendiğinde, HTML
biçimlendirme ve C# işleme mantığı bir bileşen sınıfına dönüştürülür. Oluşturulan sınıfın adı, dosyanın adıyla
eşleşir.
Bileşen sınıfının üyeleri bir @code bloğunda tanımlanmıştır. @code bloğunda, bileşen durumu (özellikler, alanlar)
olay işleme yöntemleriyle veya diğer bileşen mantığını tanımlamaya yönelik yöntemlerle belirtilir. Birden fazla
@code bloğu izin verilir.

NOTE
ASP.NET Core 3,0 ' nin önceki önizlemelerinde, @functions blokları Razor bileşenlerinde @code bloklarında aynı amaçla
kullanılmıştır. @functions blokları Razor bileşenlerinde çalışmaya devam eder, ancak ASP.NET Core 3,0 Preview 6 veya
sonraki bir sürümünde @code bloğunun kullanılmasını öneririz.

Bileşen üyeleri, @ ile başlayan ifadeleri kullanarak C# bileşenin işleme mantığının bir parçası olarak kullanılabilir.
Örneğin bir C# alan, alan adına @ önek olarak işlenerek işlenir. Aşağıdaki örnek değerlendirilir ve işler:
font-style için CSS özellik değerine _headingFontStyle .
<h1> öğesinin içeriğine _headingText .

<h1 style="font-style:@_headingFontStyle">@_headingText</h1>

@code {
private string _headingFontStyle = "italic";
private string _headingText = "Put on your new Blazor!";
}

Bileşen ilk olarak işlendikten sonra, bileşen işleme ağacını olaylara yanıt olarak yeniden oluşturur. Blazor, yeni
işleme ağacını öncekiyle karşılaştırır ve tarayıcının Belge Nesne Modeli (DOM ) üzerinde herhangi bir değişiklik
uygular.
Bileşenler sıradan C# sınıflardır ve bir proje içinde herhangi bir yere yerleştirilebilir. Web sayfalarını üreten
bileşenler genellikle Sayfalar klasöründe bulunur. Sayfa olmayan bileşenler sıklıkla paylaşılan klasöre veya
projeye eklenen özel bir klasöre yerleştirilir. Özel bir klasör kullanmak için, özel klasörün ad alanını üst bileşene ya
da uygulamanın _Imports. Razor dosyasına ekleyin. Örneğin, aşağıdaki ad alanı, uygulamanın kök ad alanı
WebApplication olduğunda Bileşenler klasöründeki bileşenleri kullanılabilir yapar:

@using WebApplication.Components

Bileşenleri Razor Pages ve MVC uygulamalarıyla tümleştirme


Mevcut Razor Pages ve MVC uygulamalarıyla bileşenleri kullanın. Razor bileşenleri kullanmak için mevcut
sayfaları veya görünümleri yeniden yazmanız gerekmez. Sayfa veya görünüm işlendiğinde, bileşenler aynı anda
önceden işlenir.
Bir sayfadan veya görünümden bir bileşeni işlemek için Component etiketi yardımcısını kullanın:

<component type="typeof(Counter)" render-mode="ServerPrerendered"


param-IncrementAmount="10" />

Parametreleri geçirme (örneğin, önceki örnekteki IncrementAmount ) desteklenir.


RenderMode , bileşenin şunları yapıp kullanmadığını yapılandırır:
, Sayfaya ön gönderilir.
, Sayfada statik HTML olarak veya Kullanıcı aracısından bir Blazor uygulamasını önyüklemek için gerekli
bilgileri içeriyorsa.

RENDERMODE AÇIKLAMA

ServerPrerendered Bileşeni statik HTML olarak işler ve Blazor sunucusu


uygulaması için bir işaret içerir. Kullanıcı Aracısı başladığında,
bu işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır.

Server Blazor sunucusu uygulaması için bir işaret oluşturur. Bileşen


çıkışı dahil değildir. Kullanıcı Aracısı başladığında, bu işaretleyici
bir Blazor uygulamasının önyüklemesi için kullanılır.

Static Bileşeni statik HTML olarak işler.

Sayfalar ve görünümler bileşenleri kullanırken, listesiyse doğru değildir. Bileşenler, kısmi görünümler ve bölümler
gibi görüntüleme ve sayfaya özgü senaryolar kullanamaz. Bir bileşende kısmi görünümden mantığı kullanmak
için kısmi görünüm mantığını bir bileşene ayırın.
Statik HTML sayfasından sunucu bileşenleri işleme desteklenmiyor.
Bileşenlerin nasıl işlendiği, bileşen durumu ve Component etiketi Yardımcısı hakkında daha fazla bilgi için bkz.
Blazor barındırma modellerini ASP.NET Core.
Bir sayfadan veya görünümden bir bileşeni işlemek için RenderComponentAsync<TComponent> HTML yardımcı
yöntemini kullanın:
@(await Html.RenderComponentAsync<MyComponent>(RenderMode.ServerPrerendered))

RenderMode , bileşenin şunları yapıp kullanmadığını yapılandırır:


, Sayfaya ön gönderilir.
, Sayfada statik HTML olarak veya Kullanıcı aracısından bir Blazor uygulamasını önyüklemek için gerekli
bilgileri içeriyorsa.

RENDERMODE AÇIKLAMA

ServerPrerendered Bileşeni statik HTML olarak işler ve Blazor sunucusu


uygulaması için bir işaret içerir. Kullanıcı Aracısı başladığında,
bu işaretleyici bir Blazor uygulamasının önyüklemesi için
kullanılır. Parametreler desteklenmiyor.

Server Blazor sunucusu uygulaması için bir işaret oluşturur. Bileşen


çıkışı dahil değildir. Kullanıcı Aracısı başladığında, bu işaretleyici
bir Blazor uygulamasının önyüklemesi için kullanılır.
Parametreler desteklenmiyor.

Static Bileşeni statik HTML olarak işler. Parametreler destekleniyor.

Sayfalar ve görünümler bileşenleri kullanırken, listesiyse doğru değildir. Bileşenler, kısmi görünümler ve bölümler
gibi görüntüleme ve sayfaya özgü senaryolar kullanamaz. Bir bileşende kısmi görünümden mantığı kullanmak
için kısmi görünüm mantığını bir bileşene ayırın.
Statik HTML sayfasından sunucu bileşenleri işleme desteklenmiyor.
Bileşenlerin nasıl işlendiği, bileşen durumu ve RenderComponentAsync HTML Yardımcısı hakkında daha fazla bilgi
için bkz. Blazor barındırma modellerini ASP.NET Core.

Bileşenleri kullanma
Bileşenler, HTML öğesi söz dizimini kullanarak bildirerek diğer bileşenleri içerebilir. Bir bileşeni kullanmak için
biçimlendirme, etiket adının bileşen türü olduğu bir HTML etiketi gibi görünür.
Öznitelik bağlama büyük/küçük harfe duyarlıdır. Örneğin, @bind geçerlidir ve @Bind geçersizdir.
Index. Razor dosyasında aşağıdaki biçimlendirme HeadingComponent örneği işler:

<HeadingComponent />

Bileşenler/HeadingComponent. Razor:
@using System.Globalization
@*
The 'using' directive makes System.Globalization available to
the component. System.Globalization provides a method for
converting a string into title case (capitalizes the first
letter of every word in a string), which is used to convert a
a string into title case for a heading.
*@

@*
Heading text is rendered by evaluating the _headingText field.
The font-style of the heading is rendered by evaluating the
_headingFontStyle field.
*@
<h1 style="font-style:@_headingFontStyle">@_headingText</h1>

<form>
<div>
@*
A check box sets the font style and is bound to the
_italicsCheck field.
*@
<input type="checkbox" id="italicsCheck"
@bind="_italicsCheck" />
<label class="form-check-label"
for="italicsCheck">Use italics</label>
</div>

@*
When the form is submitted, the onclick event executes
the UpdateHeading method.
*@
<button type="button" class="btn btn-primary" @onclick="UpdateHeading">
Update heading
</button>
</form>

@code {
private static TextInfo _tinfo = CultureInfo.CurrentCulture.TextInfo;
private string _headingText =
_tinfo.ToTitleCase("welcome to blazor!");
private string _headingFontStyle = "normal";
private bool _italicsCheck = false;

// When UpdateHeading is executed, _italicsCheck determines


// the value of _headingFontStyle to set the font style of the
// heading.
public void UpdateHeading()
{
_headingFontStyle = _italicsCheck ? "italic" : "normal";
}
}

Bir bileşen bir bileşen adıyla eşleşmeyen büyük harfle yazılmış bir HTML öğesi içeriyorsa, öğenin beklenmeyen
bir adı olduğunu gösteren bir uyarı yayınlanır. Bileşenin ad alanı için @using bir deyimin eklenmesi, bileşenin
kullanılabilir olmasını sağlar ve bu da uyarıyı kaldırır.

Bileşen parametreleri
Bileşenler, bileşen sınıfında [Parameter] özniteliğiyle ortak özellikler kullanılarak tanımlanan bileşen
parametrelerinesahip olabilir. Biçimlendirme içindeki bir bileşenin bağımsız değişkenlerini belirtmek için
öznitelikleri kullanın.
Bileşenler/ChildComponent. Razor:
<div class="panel panel-default">
<div class="panel-heading">@Title</div>
<div class="panel-body">@ChildContent</div>

<button class="btn btn-primary" @onclick="OnClick">


Trigger a Parent component method
</button>
</div>

@code {
[Parameter]
public string Title { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

[Parameter]
public EventCallback<MouseEventArgs> OnClick { get; set; }
}

Örnek uygulamadan aşağıdaki örnekte ParentComponent , ChildComponent``Title özelliğinin değerini ayarlar.


Pages/ParentComponent. Razor:

@page "/ParentComponent"

<h1>Parent-child example</h1>

<ChildComponent Title="Panel Title from Parent"


OnClick="@ShowMessage">
Content of the child component is supplied
by the parent component.
</ChildComponent>

...

Alt içerik
Bileşenler, başka bir bileşenin içeriğini ayarlayabilir. Atama bileşeni, alıcı bileşeni belirten Etiketler arasında içerik
sağlar.
Aşağıdaki örnekte ChildComponent , işlemek için bir kullanıcı arabirimi segmentini temsil eden bir RenderFragment
temsil eden bir ChildContent özelliğine sahiptir. ChildContent değeri bileşenin, içeriğin işlenmesi gereken
biçimlendirmesinde konumlandırılır. ChildContent değeri üst bileşenden alınır ve önyükleme bölmesinin
panel-body içinde işlenir.

Bileşenler/ChildComponent. Razor:
<div class="panel panel-default">
<div class="panel-heading">@Title</div>
<div class="panel-body">@ChildContent</div>

<button class="btn btn-primary" @onclick="OnClick">


Trigger a Parent component method
</button>
</div>

@code {
[Parameter]
public string Title { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

[Parameter]
public EventCallback<MouseEventArgs> OnClick { get; set; }
}

NOTE
RenderFragment içeriği alan özelliğin kurala göre ChildContent olarak adlandırılması gerekir.

Örnek uygulamadaki ParentComponent , içeriği <ChildComponent> etiketlerin içine yerleştirerek ChildComponent


işlemek için içerik sağlayabilir.
Pages/ParentComponent. Razor:

@page "/ParentComponent"

<h1>Parent-child example</h1>

<ChildComponent Title="Panel Title from Parent"


OnClick="@ShowMessage">
Content of the child component is supplied
by the parent component.
</ChildComponent>

...

Öznitelik döndürme ve rastgele parametreler


Bileşenler, bileşen tarafından tanımlanan parametrelere ek olarak ek öznitelikler yakalayabilir ve işleyebilir. Ek
öznitelikler bir sözlükte yakalanabilir ve sonra bileşen @attributes Razor yönergesi kullanılarak işlendiğinde bir
öğe üzerine bırakılabilir . Bu senaryo, çeşitli özelleştirmeleri destekleyen bir işaretleme öğesi üreten bir bileşen
tanımlarken yararlıdır. Örneğin, çok sayıda parametreyi destekleyen bir <input> öznitelikleri ayrı olarak
tanımlamak sıkıcı olabilir.
Aşağıdaki örnekte, ilk <input> öğesi ( id="useIndividualParams" ) bağımsız bileşen parametrelerini kullanır, ancak
ikinci <input> öğesi ( id="useAttributesDict" ) öznitelik sponu kullanır:
<input id="useIndividualParams"
maxlength="@Maxlength"
placeholder="@Placeholder"
required="@Required"
size="@Size" />

<input id="useAttributesDict"
@attributes="InputAttributes" />

@code {
[Parameter]
public string Maxlength { get; set; } = "10";

[Parameter]
public string Placeholder { get; set; } = "Input placeholder text";

[Parameter]
public string Required { get; set; } = "required";

[Parameter]
public string Size { get; set; } = "50";

[Parameter]
public Dictionary<string, object> InputAttributes { get; set; } =
new Dictionary<string, object>()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}

Parametrenin türü dize anahtarlarıyla IEnumerable<KeyValuePair<string, object>> uygulamalıdır.


IReadOnlyDictionary<string, object> kullanmak Bu senaryoda da bir seçenektir.
Her iki yaklaşımın de kullanıldığı işlenen <input> öğeleri aynıdır:

<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">

<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">

Rastgele öznitelikleri kabul etmek için, CaptureUnmatchedValues özelliği true olarak ayarlanan [Parameter]
özniteliğini kullanarak bir bileşen parametresi tanımlayın:

@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> InputAttributes { get; set; }
}

[Parameter] CaptureUnmatchedValues özelliği, parametrenin diğer bir parametreyle eşleşmeyen tüm özniteliklerle
eşleşmesini sağlar. Bir bileşen yalnızca CaptureUnmatchedValues olan tek bir parametre tanımlayabilir.
CaptureUnmatchedValues ile kullanılan özellik türü, Dictionary<string, object> dize anahtarlarıyla atanabilir
olmalıdır. IEnumerable<KeyValuePair<string, object>> veya IReadOnlyDictionary<string, object> Ayrıca bu
senaryodaki seçeneklerdir.
Öğe özniteliklerinin konumuna göre @attributes konumu önemlidir. Öğe üzerinde @attributes , öznitelikler
sağdan sola (son olarak) işlenir. Child bileşeni tüketen bir bileşen için aşağıdaki örneği göz önünde bulundurun:
ParentComponent. Razor:

<ChildComponent extra="10" />

Childcomponent. Razor:

<div @attributes="AdditionalAttributes" extra="5" />

[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }

Child bileşenin extra özniteliği @attributes sağına ayarlanmıştır. Parent bileşenin işlenmiş <div> , öznitelikler
sağdan sola (en son) işlendiği için ek özniteliğiyle geçirildiğinde extra="5" içerir:

<div extra="5" />

Aşağıdaki örnekte, extra ve @attributes sırası Child bileşeninin <div> tersine çevrilir:
ParentComponent. Razor:

<ChildComponent extra="10" />

Childcomponent. Razor:

<div extra="5" @attributes="AdditionalAttributes" />

[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }

Parent bileşenindeki işlenen <div> , ek öznitelik üzerinden geçirildiğinde extra="10" içerir:

<div extra="10" />

Veri bağlama
Hem bileşenlere hem de DOM öğelerine veri bağlama @bind özniteliğiyle gerçekleştirilir. Aşağıdaki örnek, bir
CurrentValue özelliğini metin kutusu değerine bağlar:

<input @bind="CurrentValue" />

@code {
private string CurrentValue { get; set; }
}

Metin kutusu odağı kaybettiğinde, özelliğin değeri güncellenir.


Metin kutusu kullanıcı arabiriminde, özelliğin değerini değiştirme yanıt olarak değil, yalnızca bileşen işlendiğinde
güncelleştirilir. Bileşenler olay işleyicisi kodu yürütüldükten sonra kendilerini oluşturduğundan, özellik
güncelleştirmeleri genellikle olay işleyicisi tetiklendikten hemen sonra Kullanıcı arabirimine yansıtılır.
CurrentValue özelliği ( <input @bind="CurrentValue" /> ) ile @bind kullanmak, temelde aşağıdakilere eşdeğerdir:

<input value="@CurrentValue"
@onchange="@((ChangeEventArgs __e) => CurrentValue =
__e.Value.ToString())" />

@code {
private string CurrentValue { get; set; }
}

Bileşen işlendiğinde, giriş öğesinin value CurrentValue özelliğinden gelir. Kullanıcı metin kutusuna yazdığında
ve öğe odağını değiştirdiğinde, onchange olayı tetiklenir ve CurrentValue özelliği değiştirilen değere ayarlanır.
@bind , tür dönüştürmelerin gerçekleştirildiği durumları işlediği için kod oluşturma daha karmaşıktır. Prensibi
@bind , bir ifadenin geçerli değerini bir value özniteliğiyle ilişkilendirir ve kayıtlı işleyiciyi kullanarak değişiklikleri
işler.
@bind sözdizimiyle onchange olaylarının işlenmesine ek olarak, bir özellik veya alan, event parametreli bir
@bind-value özniteliği belirterek diğer olaylar kullanılarak da bağlanabilir ( @bind-value:event ). Aşağıdaki örnek,
oninput olayı için CurrentValue özelliğini bağlar:

<input @bind-value="CurrentValue" @bind-value:event="oninput" />

@code {
private string CurrentValue { get; set; }
}

onchange aksine, öğe odağı kaybettiğinde harekete geçirilir oninput metin kutusunun değeri değiştiğinde
harekete geçirilir.
Ayrıştırılamayan değerler
Bir Kullanıcı, bir veri sınırlama öğesine ayrıştırılamayan bir değer sağlıyorsa, bağlama olayı tetiklendiğinde,
çözümlenemeyen değer otomatik olarak önceki değerine döndürülür.
Aşağıdaki senaryoyu ele alalım:
Bir <input> öğesi, 123 başlangıçtaki değeri olan bir int türüne bağlanır:

<input @bind="MyProperty" />

@code {
[Parameter]
public int MyProperty { get; set; } = 123;
}

Kullanıcı, öğe değerini sayfada 123.45 olarak güncelleştirir ve öğe odağını değiştirir.

Önceki senaryoda, öğenin değeri 123 olarak geri döndürülür. Değer 123.45 özgün 123 değerinin yararına
reddedildiğinde, Kullanıcı değerinin kabul edilmediğini anlamıştır.
Varsayılan olarak, bağlama öğenin onchange olayına ( @bind="{PROPERTY OR FIELD}" ) uygulanır. Farklı bir olay
ayarlamak için @bind-value="{PROPERTY OR FIELD}" @bind-value:event={EVENT} kullanın. oninput olayı (
@bind-value:event="oninput" ) için yeniden sürüm, ayrıştırılamayan bir değer sunan herhangi bir tuş vuruşu
sonrasında oluşur. oninput olayı int bağlantılı bir türle hedeflenirken, kullanıcının bir . karakteri yazmasının
engellenmiş olması engellenir. . bir karakter hemen kaldırılır, bu nedenle Kullanıcı yalnızca tam sayılara izin
verilen anında geri bildirim alır. oninput olaylarındaki değerin geri döndürülmesi ideal olmayan, örneğin
kullanıcının ayrıştırılamayan <input> bir değeri temizlemeye izin verilmesi gereken senaryolar vardır.
Alternatifler şunlardır:
oninput olayını kullanmayın. Öğe odağı kaybederene kadar geçersiz bir değer geri döndürülmediğinde,
varsayılan onchange olayını ( @bind="{PROPERTY OR FIELD}" ) kullanın.
int? veya string gibi null yapılabilir bir türe bağlayın ve geçersiz girdileri işlemek için özel mantık sağlayın.
InputNumber veya InputDate gibi bir form doğrulama bileşenikullanın. Form doğrulama bileşenlerinde
geçersiz girişleri yönetmek için yerleşik destek vardır. Form doğrulama bileşenleri:
Kullanıcının geçersiz giriş sağlamasına ve ilişkili EditContext doğrulama hataları almasına izin verin.
Kullanıcı ek WebForm verisi girmeye uğramadan doğrulama hatalarını Kullanıcı ARABIRIMINDE
görüntüleyin.
Genelleştirme
@bind değerleri, geçerli kültürün kuralları kullanılarak görüntülenmek üzere biçimlendirilir ve ayrıştırılır.
Geçerli kültüre System.Globalization.CultureInfo.CurrentCulture özelliğinden erişilebilir.
CultureInfo. InvariantCulture aşağıdaki alan türleri için kullanılır ( <input type="{TYPE}" /> ):
date
number

Yukarıdaki alan türleri:


, Uygun tarayıcı tabanlı biçimlendirme kuralları kullanılarak görüntülenir.
Serbest biçimli metin içeremez.
Tarayıcının uygulamasına göre Kullanıcı etkileşimi özellikleri sağlar.
Aşağıdaki alan türleri belirli biçimlendirme gereksinimlerine sahiptir ve şu anda tüm büyük tarayıcılarda
desteklenmediğinden Blazor tarafından desteklenmemektedir:
datetime-local
month
week

@bind , bir değeri ayrıştırmak ve biçimlendirmek için bir System.Globalization.CultureInfo sağlamak üzere
@bind:culture parametresini destekler. date ve number alan türleri kullanılırken bir kültür belirtilmesi
önerilmez. date ve number , gerekli kültürü sağlayan yerleşik Blazor desteğine sahiptir.
Kullanıcının kültürünü ayarlama hakkında daha fazla bilgi için Yerelleştirme bölümüne bakın.
Biçim dizeleri
Veri bağlama @bind:format kullanarak DateTime biçim dizeleriyle birlikte kullanılabilir. Para birimi veya sayı
biçimleri gibi diğer biçim ifadeleri şu anda kullanılamaz.

<input @bind="StartDate" @bind:format="yyyy-MM-dd" />

@code {
[Parameter]
public DateTime StartDate { get; set; } = new DateTime(2020, 1, 1);
}

Yukarıdaki kodda <input> öğenin alan türü ( type ), text varsayılan olarak olur. @bind:format aşağıdaki .NET
türlerini bağlamak için desteklenir:
System.DateTime
System.DateTime?
System.DateTimeOffset
System.DateTimeOffset?
@bind:format özniteliği, <input> öğesinin value uygulanacak tarih biçimini belirtir. Biçim Ayrıca, onchange bir
olay gerçekleştiğinde değeri ayrıştırmak için de kullanılır.
Blazor, tarihleri biçimlendirmek için yerleşik destek içerdiğinden date alanı türü için bir biçim belirtilmesi
önerilmez. Önerinin artma, yyyy-MM-dd tarih biçimini yalnızca date alan türüyle bir biçim sağlanırsa doğru
şekilde çalışacak şekilde kullanın:

<input type="date" @bind="StartDate" @bind:format="yyyy-MM-dd">

Bileşen parametreleri
Bağlama bileşen parametrelerini tanır; burada @bind-{property} , bileşenler arasında bir özellik değeri
bağlayabilirler.
Aşağıdaki alt bileşen ( ChildComponent ) Year bir bileşen parametresine ve geri çağırmaya YearChanged sahiptir:

<h2>Child Component</h2>

<p>Year: @Year</p>

@code {
[Parameter]
public int Year { get; set; }

[Parameter]
public EventCallback<int> YearChanged { get; set; }
}

EventCallback<T> Eventcallback bölümünde açıklanmaktadır.


Aşağıdaki üst bileşen ChildComponent kullanır ve üst öğeden ParentYear parametresini alt bileşendeki Year
parametresine bağlar:
@page "/ParentComponent"

<h1>Parent Component</h1>

<p>ParentYear: @ParentYear</p>

<ChildComponent @bind-Year="ParentYear" />

<button class="btn btn-primary" @onclick="ChangeTheYear">


Change Year to 1986
</button>

@code {
[Parameter]
public int ParentYear { get; set; } = 1978;

private void ChangeTheYear()


{
ParentYear = 1986;
}
}

ParentComponent yüklemek aşağıdaki biçimlendirmeyi üretir:

<h1>Parent Component</h1>

<p>ParentYear: 1978</p>

<h2>Child Component</h2>

<p>Year: 1978</p>

ParentYear özelliğinin değeri ParentComponent düğme seçilerek değiştirilirse, ChildComponent Year özelliği
güncellenir. Year yeni değeri, ParentComponent yeniden eklendiğinde Kullanıcı arabiriminde işlenir:

<h1>Parent Component</h1>

<p>ParentYear: 1986</p>

<h2>Child Component</h2>

<p>Year: 1986</p>

Year parametresi, Year parametresinin türüyle eşleşen bir yardımcı YearChanged olayına sahip olduğundan
bağlanabilir.
Kurala göre <ChildComponent @bind-Year="ParentYear" /> temelde yazmaya eşdeğerdir:

<ChildComponent @bind-Year="ParentYear" @bind-Year:event="YearChanged" />

Genel olarak, bir özellik @bind-property:event özniteliği kullanılarak karşılık gelen bir olay işleyicisine
bağlanabilir. Örneğin, özellik MyProp aşağıdaki iki öznitelik kullanılarak MyEventHandler bağlanabilir:

<MyComponent @bind-MyProp="MyValue" @bind-MyProp:event="MyEventHandler" />

Olay işleme
Razor bileşenleri olay işleme özellikleri sağlar. on{EVENT} adlı bir HTML öğesi özniteliği için (örneğin, onclick ve
onsubmit ), temsilci türü belirtilmiş bir değer ile, Razor bileşenleri özniteliğin değerini bir olay işleyicisi olarak
değerlendirir. Özniteliğin adı her zaman @on{EVENT} biçimlendirilir.
Aşağıdaki kod, Kullanıcı arabiriminde düğme seçildiğinde UpdateHeading yöntemini çağırır:

<button class="btn btn-primary" @onclick="UpdateHeading">


Update heading
</button>

@code {
private void UpdateHeading(MouseEventArgs e)
{
...
}
}

Aşağıdaki kod, Kullanıcı arabiriminde onay kutusu değiştirildiğinde CheckChanged yöntemini çağırır:

<input type="checkbox" class="form-check-input" @onchange="CheckChanged" />

@code {
private void CheckChanged()
{
...
}
}

Olay işleyicileri Ayrıca zaman uyumsuz olabilir ve bir Taskdöndürebilir. Statehaschangedel ile çağırmanız
gerekmez. Özel durumlar oluştuğunda günlüğe kaydedilir.
Aşağıdaki örnekte, düğme seçildiğinde UpdateHeading zaman uyumsuz olarak çağrılır:

<button class="btn btn-primary" @onclick="UpdateHeading">


Update heading
</button>

@code {
private async Task UpdateHeading(MouseEventArgs e)
{
...
}
}

Olay bağımsız değişken türleri


Bazı olaylar için olay bağımsız değişkeni türlerine izin verilir. Bu olay türlerinden birine erişim gerekmiyorsa,
yöntem çağrısında gerekli değildir.
Desteklenen EventArgs aşağıdaki tabloda gösterilmiştir.

OLAY SINIF DOM OLAYLARI VE NOTLARI

Pano ClipboardEventArgs oncut , oncopy , onpaste


OLAY SINIF DOM OLAYLARI VE NOTLARI

Sürükle DragEventArgs ondrag , ondragstart ,


ondragenter , ondragleave ,
ondragover , ondrop , ondragend

DataTransfer ve DataTransferItem
öğe verilerini sürüklemiş tutun.

Hata ErrorEventArgs onerror

Olay EventArgs Genel


onactivate , onbeforeactivate ,
onbeforedeactivate , ondeactivate
, onended , onfullscreenchange ,
onfullscreenerror , onloadeddata ,
onloadedmetadata ,
onpointerlockchange ,
onpointerlockerror ,
onreadystatechange , onscroll

Pano
onbeforecut , onbeforecopy ,
onbeforepaste

Giriş
oninvalid , onreset , onselect ,
onselectionchange , onselectstart
, onsubmit

Medyasını
oncanplay , oncanplaythrough ,
oncuechange , ondurationchange ,
onemptied , onpause , onplay ,
onplaying , onratechange ,
onseeked , onseeking , onstalled ,
onstop , onsuspend , ontimeupdate ,
onvolumechange , onwaiting

Odaklanma FocusEventArgs onfocus , onblur , onfocusin ,


onfocusout

relatedTarget için destek içermez.

Giriş ChangeEventArgs onchange , oninput

Klavye KeyboardEventArgs onkeydown , onkeypress , onkeyup

Fare MouseEventArgs onclick , oncontextmenu ,


ondblclick , onmousedown ,
onmouseup , onmouseover ,
onmousemove , onmouseout
OLAY SINIF DOM OLAYLARI VE NOTLARI

Fare işaretçisi PointerEventArgs onpointerdown , onpointerup ,


onpointercancel , onpointermove ,
onpointerover , onpointerout ,
onpointerenter , onpointerleave ,
ongotpointercapture ,
onlostpointercapture

Fare tekeri WheelEventArgs onwheel , onmousewheel

İlerleme durumu ProgressEventArgs onabort , onload , onloadend ,


onloadstart , onprogress ,
ontimeout

Dokunmatik TouchEventArgs ontouchstart , ontouchend ,


ontouchmove , ontouchenter ,
ontouchleave , ontouchcancel

TouchPoint , dokunmaya duyarlı bir


cihazdaki tek bir iletişim noktasını
temsil eder.

Önceki tablodaki olayların özellikleri ve olay işleme davranışı hakkında bilgi için bkz. başvuru kaynağında
EventArgs sınıfları (ASPNET/AspNetCore Release/3.0 dalı).
Lambda ifadeleri
Lambda ifadeleri de kullanılabilir:

<button @onclick="@(e => Console.WriteLine("Hello, world!"))">Say hello</button>

Genellikle, bir dizi öğe üzerinde yineleme yaparken olduğu gibi ek değerlerin üzerinde kapatılabilir. Aşağıdaki
örnek, her biri Kullanıcı arabiriminde seçildiğinde bir olay bağımsız değişkeni ( MouseEventArgs ) ve düğme
numarası ( buttonNumber ) UpdateHeading çağıran üç düğme oluşturur:

<h2>@message</h2>

@for (var i = 1; i < 4; i++)


{
var buttonNumber = i;

<button class="btn btn-primary"


@onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
}

@code {
private string message = "Select a button to learn its position.";

private void UpdateHeading(MouseEventArgs e, int buttonNumber)


{
message = $"You selected Button #{buttonNumber} at " +
$"mouse position: {e.ClientX} X {e.ClientY}.";
}
}
NOTE
Döngü değişkenini ( i ) doğrudan bir lambda ifadesinde bir for döngüsünde kullanmayın. Aksi halde aynı değişken
tüm lambda ifadeleri tarafından, i değerinin tüm Lambdalar ile aynı olmasına neden olur. Her zaman değerini yerel bir
değişkende (önceki örnekte buttonNumber ) yakalayın ve sonra kullanın.

EventCallback
İç içe bileşenler içeren yaygın bir senaryo, bir alt bileşen olayı gerçekleştiğinde bir üst bileşenin yöntemini
çalıştırma, örneğin, alt öğe içinde bir onclick olayı oluştuğunda—. Olayları bileşenler arasında göstermek için bir
EventCallback kullanın. Bir üst bileşen, bir alt bileşenin EventCallback bir geri çağırma yöntemi atayabilir.

Örnek uygulamadaki ChildComponent (Bileşenler/ChildComponent. Razor), bir düğmenin onclick işleyicisinin,


örneğin ParentComponent bir EventCallback temsilcisini almak üzere nasıl ayarlandığını gösterir. EventCallback ,
bir çevresel cihazdan onclick olayına uygun MouseEventArgs ile yazılır:

<div class="panel panel-default">


<div class="panel-heading">@Title</div>
<div class="panel-body">@ChildContent</div>

<button class="btn btn-primary" @onclick="OnClick">


Trigger a Parent component method
</button>
</div>

@code {
[Parameter]
public string Title { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

[Parameter]
public EventCallback<MouseEventArgs> OnClick { get; set; }
}

ParentComponent , alt öğenin EventCallback<T> ShowMessage yöntemine ayarlar.


Pages/ParentComponent. Razor:

@page "/ParentComponent"

<h1>Parent-child example</h1>

<ChildComponent Title="Panel Title from Parent"


OnClick="@ShowMessage">
Content of the child component is supplied
by the parent component.
</ChildComponent>

<p><b>@messageText</b></p>

@code {
private string messageText;

private void ShowMessage(MouseEventArgs e)


{
messageText = $"Blaze a new trail with Blazor! ({e.ScreenX}, {e.ScreenY})";
}
}
ChildComponent düğme seçildiğinde:
ParentComponent``ShowMessage yöntemi çağrılır. messageText güncellenir ve ParentComponent görüntülenir.
Geri çağırma yönteminde ( ShowMessage ) Statehaschanged çağrısı gerekli değildir. StateHasChanged , alt olaylar,
alt öğe içinde yürütülen olay işleyicilerinde bileşen rerendering tetiklenmesi gibi ParentComponent yeniden
çalıştırmak için otomatik olarak çağrılır.
EventCallback ve EventCallback<T> zaman uyumsuz temsilcilere izin verir. EventCallback<T> kesin bir şekilde
yazılır ve belirli bir bağımsız değişken türü gerektirir. EventCallback zayıf ve bağımsız değişken türüne izin
veriyor.

<p><b>@messageText</b></p>

@{ var message = "Default Text"; }

<ChildComponent
OnClick="@(async () => { await Task.Yield(); messageText = "Blaze It!"; })" />

@code {
private string messageText;
}

InvokeAsync ile bir EventCallback veya EventCallback<T> çağırın ve Taskawait:

await callback.InvokeAsync(arg);

Olay işleme ve bağlama bileşeni parametrelerini EventCallback ve EventCallback<T> kullanın.


EventCallback üzerinde türü kesin belirlenmiş EventCallback<T> tercih edin. EventCallback<T> , bileşenin
kullanıcılarına daha iyi hata geri bildirimi sağlar. Diğer UI olay işleyicileriyle benzer şekilde, olay parametresini
belirtmek isteğe bağlıdır. Geri çağırmaya hiçbir değer geçirilmemişse EventCallback kullanın.
Varsayılan eylemleri engelle
Bir olayın varsayılan eylemini engellemek için @on{EVENT}:preventDefault Directive özniteliğini kullanın.
Giriş cihazında bir anahtar seçildiğinde ve öğe odağı bir metin kutusunda olduğunda, bir tarayıcı normalde metin
kutusunda anahtarın karakterini görüntüler. Aşağıdaki örnekte, @onkeypress:preventDefault Directive özniteliği
belirtilerek varsayılan davranış engellenir. Sayaç artar ve + anahtarı <input> öğenin değerine yakalanmaz:

<input value="@_count" @onkeypress="KeyHandler" @onkeypress:preventDefault />

@code {
private int _count = 0;

private void KeyHandler(KeyboardEventArgs e)


{
if (e.Key == "+")
{
_count++;
}
}
}

@on{EVENT}:preventDefault özniteliğini bir değer olmadan belirtmek @on{EVENT}:preventDefault="true"


eşdeğerdir.
Özniteliğin değeri de bir ifade olabilir. Aşağıdaki örnekte _shouldPreventDefault , true veya false olarak
ayarlanan bir bool alandır:

<input @onkeypress:preventDefault="_shouldPreventDefault" />

Varsayılan eylemi engellemek için bir olay işleyicisi gerekli değildir. Olay işleyicisi ve varsayılan eylem
senaryolarına bağımsız olarak bir şekilde kullanılabilir.
Olay yaymayı durdur
Olay yaymayı durdurmak için @on{EVENT}:stopPropagation Directive özniteliğini kullanın.
Aşağıdaki örnekte, onay kutusunun seçilmesi ikinci alt <div> , üst <div> yaymadan sonraki olayları engeller:

<label>
<input @bind="_stopPropagation" type="checkbox" />
Stop Propagation
</label>

<div @onclick="OnSelectParentDiv">
<h3>Parent div</h3>

<div @onclick="OnSelectChildDiv">
Child div that doesn't stop propagation when selected.
</div>

<div @onclick="OnSelectChildDiv" @onclick:stopPropagation="_stopPropagation">


Child div that stops propagation when selected.
</div>
</div>

@code {
private bool _stopPropagation = false;

private void OnSelectParentDiv() =>


Console.WriteLine($"The parent div was selected. {DateTime.Now}");
private void OnSelectChildDiv() =>
Console.WriteLine($"A child div was selected. {DateTime.Now}");
}

Zincirleme bağlama
Yaygın bir senaryo, bir veri bağlama parametresini bileşen çıkışında bir sayfa öğesine zincirlemesini sağlar. Birden
çok bağlama düzeyi aynı anda gerçekleştiğinden, bu senaryoya zincirleme bağlama denir.
Bir zincir bağlama, sayfanın öğesinde @bind sözdizimiyle uygulanamıyor. Olay işleyicisi ve değeri ayrı olarak
belirtilmelidir. Bununla birlikte, bir üst bileşen, bileşen parametresiyle @bind sözdizimini kullanabilir.
Aşağıdaki PasswordField bileşeni (Passwordfield. Razor):
Bir <input> öğesinin değerini bir Password özelliğine ayarlar.
Password özelliğindeki değişiklikleri, bir Eventcallbackile bir üst bileşene gösterir.
Password:

<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@Password" />

<button class="btn btn-primary" @onclick="ToggleShowPassword">


Show password
</button>

@code {
private bool showPassword;

[Parameter]
public string Password { get; set; }

[Parameter]
public EventCallback<string> PasswordChanged { get; set; }

private Task OnPasswordChanged(ChangeEventArgs e)


{
Password = e.Value.ToString();

return PasswordChanged.InvokeAsync(Password);
}

private void ToggleShowPassword()


{
showPassword = !showPassword;
}
}

PasswordField bileşeni başka bir bileşende kullanılır:

<PasswordField @bind-Password="password" />

@code {
private string password;
}

Önceki örnekteki parolada denetim veya tuzak hataları gerçekleştirmek için:


Password için bir yedekleme alanı oluşturun (Aşağıdaki örnek kodda password ).
Password ayarlayıcısı 'nda denetimleri veya yakalama hatalarını gerçekleştirin.

Aşağıdaki örnek, parolanın değerinde bir boşluk kullanılmışsa kullanıcıya anında geri bildirim sağlar:
Password:

<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@Password" />

<button class="btn btn-primary" @onclick="ToggleShowPassword">


Show password
</button>

<span class="text-danger">@validationMessage</span>

@code {
private bool showPassword;
private string password;
private string validationMessage;

[Parameter]
public string Password
{
get { return password ?? string.Empty; }
set
{
if (password != value)
{
if (value.Contains(' '))
{
validationMessage = "Spaces not allowed!";
}
else
{
password = value;
validationMessage = string.Empty;
}
}
}
}

[Parameter]
public EventCallback<string> PasswordChanged { get; set; }

private Task OnPasswordChanged(ChangeEventArgs e)


{
Password = e.Value.ToString();

return PasswordChanged.InvokeAsync(Password);
}

private void ToggleShowPassword()


{
showPassword = !showPassword;
}
}

Bileşenlere başvuruları yakala


Bileşen başvuruları, bir bileşen örneğine başvurmak için bir yol sağlar, böylece bu örneğe Show veya Reset gibi
komutlar verebilirsiniz. Bir bileşen başvurusunu yakalamak için:
Alt bileşene bir @ref özniteliği ekleyin.
Alt bileşenle aynı türde bir alan tanımlayın.
<MyLoginDialog @ref="loginDialog" ... />

@code {
private MyLoginDialog loginDialog;

private void OnSomething()


{
loginDialog.Show();
}
}

Bileşen işlendiğinde loginDialog alanı MyLoginDialog alt bileşen örneğiyle doldurulur. Daha sonra bileşen
örneğinde .NET yöntemlerini çağırabilirsiniz.

IMPORTANT
loginDialog değişkeni yalnızca bileşen işlendikten sonra ve çıktısı MyLoginDialog öğesini içerdiğinde doldurulur. Bu
noktaya kadar başvurulmasına hiçbir şey yok. Bileşen işlemesini tamamladıktan sonra bileşen başvurularını işlemek için
Onafterrenderasync veya OnAfterRender yöntemlerinikullanın.

Bileşen başvurularını yakalama, öğe başvurularını yakalamakiçin benzer bir sözdizimi kullanın, bir JavaScript
birlikte çalışma özelliği değildir. Bileşen başvuruları yalnızca .NET kodunda kullanıldıkları—JavaScript koduna
aktarılmaz.

NOTE
Alt bileşenlerin durumunu bulunmamalıdır için bileşen başvurularını kullanmayın. Bunun yerine, alt bileşenlere veri
geçirmek için normal bildirime dayalı parametreleri kullanın. Normal bildirime dayalı parametrelerin kullanımı, otomatik
olarak doğru zamanların yeniden yönlendirmesi için alt bileşenlerde oluşur.

Durumu güncelleştirmek için bileşen yöntemlerini dışarıdan çağır


Blazor, yürütmenin tek bir mantıksal iş parçacığını zorlamak için bir SynchronizationContext kullanır. Bir bileşenin
yaşam döngüsü yöntemleri ve Blazor tarafından oluşturulan tüm olay geri çağırmaları bu
SynchronizationContext yürütülür. Bir bileşenin Zamanlayıcı veya diğer bildirimler gibi dış bir olaya göre
güncellenmesi gerekir, Blazor SynchronizationContext dağıtım yapılacak InvokeAsync yöntemini kullanın.
Örneğin, güncelleştirilmiş durumdaki herhangi bir dinleme bileşenine bildirimde bulunan bir bildirim hizmeti
düşünün:

public class NotifierService


{
// Can be called from anywhere
public async Task Update(string key, int value)
{
if (Notify != null)
{
await Notify.Invoke(key, value);
}
}

public event Func<string, int, Task> Notify;


}

Bir bileşeni güncelleştirmek için NotifierService kullanımı:


@page "/"
@inject NotifierService Notifier
@implements IDisposable

<p>Last update: @lastNotification.key = @lastNotification.value</p>

@code {
private (string key, int value) lastNotification;

protected override void OnInitialized()


{
Notifier.Notify += OnNotify;
}

public async Task OnNotify(string key, int value)


{
await InvokeAsync(() =>
{
lastNotification = (key, value);
StateHasChanged();
});
}

public void Dispose()


{
Notifier.Notify -= OnNotify;
}
}

Yukarıdaki örnekte NotifierService bileşenin OnNotify yöntemini Blazor SynchronizationContext dışında çağırır.
InvokeAsync , doğru bağlama geçmek ve bir işlemeyi kuyruğa almak için kullanılır.

Öğelerin ve bileşenlerin korunmasını denetlemek için @anahtarını


kullanın
Bir öğe veya bileşen listesi işlendiğinde ve öğeler ya da bileşenler daha sonra değiştiğinde, Blazoryayılma
algoritması, önceki öğelerin veya bileşenlerin ne zaman tutulacağına ve model nesnelerinin bunlara nasıl
eşleneceğine karar vermelidir. Normalde, bu işlem otomatiktir ve yoksayılabilir, ancak işlemi denetlemek
isteyebileceğiniz durumlar vardır.
Aşağıdaki örnek göz önünde bulundurun:

@foreach (var person in People)


{
<DetailsEditor Details="person.Details" />
}

@code {
[Parameter]
public IEnumerable<Person> People { get; set; }
}

People koleksiyonun içerikleri, ekli, silinmiş veya yeniden sıralanmış girdilerle değişebilir. Bileşen yeniden
oluşturulduğunda <DetailsEditor> bileşeni farklı Details parametre değerleri almak için değişebilir. Bu,
beklenenden daha karmaşık rerendering oluşmasına neden olabilir. Bazı durumlarda rerendering, kayıp öğe
odağı gibi görünür davranış farklılıklarına yol açabilir.
Eşleme işlemi @key Directive özniteliğiyle denetlenebilir. @key , anahtar değerine göre öğelerin veya bileşenlerin
korunmasını güvence altına almak için dağıtılmış algoritmaya neden olur:
@foreach (var person in People)
{
<DetailsEditor @key="person" Details="person.Details" />
}

@code {
[Parameter]
public IEnumerable<Person> People { get; set; }
}

People koleksiyonu değiştiğinde, yayılma algoritması <DetailsEditor> örnekleri ve person örnekleri arasındaki
ilişkilendirmeyi korur:
Bir Person People listesinden silinirse, yalnızca ilgili <DetailsEditor> örneği kullanıcı arabiriminden kaldırılır.
Diğer örnekler değişmeden bırakılır.
Listedeki bir konuma Person eklenirse, ilgili konuma bir yeni <DetailsEditor> örneği eklenir. Diğer örnekler
değişmeden bırakılır.
Person girdileri yeniden sıralandıysanız, karşılık gelen <DetailsEditor> örnekleri korunur ve Kullanıcı
arabiriminde yeniden sıralanır.
Bazı senaryolarda @key kullanımı, rerendering karmaşıklığını en aza indirir ve odak konumu gibi DOM 'ın
durum bilgisi olan kısımlarıyla ilgili olası sorunları önler.

IMPORTANT
Anahtarlar her kapsayıcı öğesi veya bileşeni için yereldir. Anahtarlar belge genelinde küresel olarak karşılaştırılmaz.

@anahtarı ne zaman kullanılır?


Genellikle, bir liste işlendiğinde (örneğin, bir @foreach bloğunda) ve @key tanımlamak için uygun bir değer
olduğunda @key kullanmak mantıklı olur.
Ayrıca, bir nesne değiştiğinde Blazor bir öğeyi veya bileşen alt ağacını @key engellemek için de kullanabilirsiniz:

<div @key="currentPerson">
... content that depends on currentPerson ...
</div>

@currentPerson değişirse @key Attribute yönergesi Blazor <div> ve alt öğelerini atmayı ve yeni öğeler ve
bileşenlerle Kullanıcı arabiriminde alt ağacı yeniden oluşturmayı zorlar. @currentPerson değiştiğinde hiçbir
Kullanıcı arabirimi durumunun korunmayacağını garanti etmeniz gerekirse bu yararlı olabilir.
@anahtar ne zaman kullanılmaz
@key bir performans maliyeti vardır. Performans maliyeti büyük değildir, ancak öğe veya bileşen koruma
kurallarının uygulamanın avantajına göre denetlenmesi durumunda yalnızca @key belirtin.
@key kullanılmasa bile, Blazor alt öğe ve bileşen örneklerini mümkün olduğunca korur. @key kullanmanın
avantajı, model örneklerinin eşlemeyi seçme algoritması yerine, korunan bileşen örneklerine nasıl eşlendiğine
ilişkin denetimdir.
@anahtarı için kullanılacak değerler
Genellikle, @key için aşağıdaki değer türlerinden birini sağlamak mantıklı olur:
Model nesne örnekleri (örneğin, önceki örnekte olduğu gibi Person örneği). Bu, nesne başvurusu eşitliğine
göre koruma sağlar.
Benzersiz tanımlayıcılar (örneğin, int , string veya Guid için birincil anahtar değerleri).

@key için kullanılan değerlerin çakışmayın olduğundan emin olun. Aynı üst öğe içinde çakışan değerler
algılanırsa, eski öğeleri veya bileşenleri yeni öğe veya bileşenlere kesin bir şekilde eşlemediğinden Blazor bir özel
durum oluşturur. Yalnızca nesne örnekleri veya birincil anahtar değerleri gibi farklı değerleri kullanın.

Yönlendirme
Blazor yönlendirme, uygulamadaki her erişilebilir bileşene bir rota şablonu sağlayarak elde edilir.
@page yönergesine sahip bir Razor dosyası derlendiğinde, oluşturulan sınıfa yol şablonunu belirten bir
RouteAttribute verilir. Çalışma zamanında, yönlendirici bileşen sınıflarını bir RouteAttribute arar ve hangi
bileşenin istenen URL ile eşleşen bir rota şablonuna sahip olduğunu işler.
Birden çok yol şablonu, bir bileşene uygulanabilir. Aşağıdaki bileşen /BlazorRoute ve /DifferentBlazorRoute
isteklerine yanıt verir.
Pages/BlazorRoute. Razor:

@page "/BlazorRoute"
@page "/DifferentBlazorRoute"

<h1>Blazor routing</h1>

Rota parametreleri
Bileşenler, @page yönergesinde belirtilen yol şablonundan yol parametreleri alabilir. Yönlendirici, karşılık gelen
bileşen parametrelerini doldurmak için yol parametrelerini kullanır.
Pages/RouteParameter. Razor:

@page "/RouteParameter"
@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

@code {
[Parameter]
public string Text { get; set; }

protected override void OnInitialized()


{
Text = Text ?? "fantastic";
}
}

İsteğe bağlı parametreler desteklenmez, bu nedenle yukarıdaki örnekte iki @page yönergesi uygulanır. İlki, bir
parametre olmadan bileşene gezinmesine izin verir. İkinci @page yönergesi {text} Route parametresini alır ve
değeri Text özelliğine atar.
Catch-all parametre sözdizimi ( * / ** ), birden çok klasör sınırları genelinde yolu yakalayan Razor bileşenlerinde
( . Razor ) desteklenmez.

Kısmi sınıf desteği


Razor bileşenleri kısmi sınıflar olarak oluşturulur. Razor bileşenleri aşağıdaki yaklaşımlardan birini kullanarak
yazılır:
C#kod, tek bir dosyada HTML işaretlemesi ve Razor kodu ile bir @code bloğunda tanımlanmıştır. Blazor
şablonlar, bu yaklaşımı kullanarak Razor bileşenlerini tanımlar.
C#kod, kısmi sınıf olarak tanımlanan bir arka plan kod dosyasına yerleştirilir.
Aşağıdaki örnek, bir Blazor şablonundan oluşturulan bir uygulamada @code bloğu olan varsayılan Counter
bileşenini gösterir. HTML işaretleme, Razor kodu ve C# kod aynı dosyada:
Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
int currentCount = 0;

void IncrementCount()
{
currentCount++;
}
}

Counter bileşeni, kısmi bir sınıf içeren bir arka plan kod dosyası kullanılarak da oluşturulabilir:
Counter. Razor:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

Counter.Razor.cs:

namespace BlazorApp.Pages
{
public partial class Counter
{
int currentCount = 0;

void IncrementCount()
{
currentCount++;
}
}
}

Bir bileşen taban sınıfı belirtin


@inherits yönergesi, bir bileşen için temel sınıf belirtmek üzere kullanılabilir.
Örnek uygulama , bileşenin özelliklerini ve yöntemlerini sağlamak için bir bileşenin BlazorRocksBase temel sınıfı
nasıl devralmasını gösterir.
Pages/BlazorRocks. Razor:

@page "/BlazorRocks"
@inherits BlazorRocksBase

<h1>@BlazorRocksText</h1>

BlazorRocksBase.cs:

using Microsoft.AspNetCore.Components;

namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}

Temel sınıf ComponentBase türetmelidir.

Bileşenleri içeri aktar


Razor ile yazılan bir bileşenin ad alanı temel alınarak belirlenir (öncelik sırasına göre):
Razor dosyası ( . Razor) biçimlendirmesinde @namespace ataması ( @namespace BlazorSample.MyNamespace ).
Projenin proje dosyasında RootNamespace ( <RootNamespace>BlazorSample</RootNamespace> ).
Proje dosyasının dosya adından ( . csproj) ve proje kökünden bileşen yolundan alınan proje adı. Örneğin
Framework, {Project root}/Pages/Index.Razor (BlazorSample. csproj) ad alanına BlazorSample.Pages
çözümleniyor. Bileşenler ad C# bağlama kurallarını izler. Bu örnekteki Index bileşeni için, kapsamdaki
bileşenler tüm bileşenlerdir:
Aynı klasörde, sayfalarda.
Proje kökündeki, açıkça farklı bir ad alanı belirtmeyen bileşenler.
Farklı bir ad alanında tanımlanan bileşenler, Razor 'nin @using yönergesi kullanılarak kapsam içine getirilir.
BlazorSample/Shared/ klasöründe NavMenu.razor başka bir bileşen varsa, bileşen aşağıdaki @using ifadesiyle
Index.razor kullanılabilir:

@using BlazorSample.Shared

This is the Index page.

<NavMenu></NavMenu>

Bileşenlere Ayrıca, @using yönergesini gerektirmeyen tam nitelikli adları kullanılarak başvurulabilir:

This is the Index page.

<BlazorSample.Shared.NavMenu></BlazorSample.Shared.NavMenu>
NOTE
global:: niteleme desteklenmiyor.
Diğer ad using deyimleriyle bileşenleri içeri aktarma (örneğin, @using Foo = Bar ) desteklenmez.
Kısmen nitelenmiş adlar desteklenmez. Örneğin, @using BlazorSample eklemek ve NavMenu.razor başvurmak
<Shared.NavMenu></Shared.NavMenu> desteklenmez.

Koşullu HTML öğesi öznitelikleri


HTML öğesi öznitelikleri, .NET değerine göre koşullu olarak işlenir. Değer false veya null ise, öznitelik
işlenmez. Değer true ise, öznitelik küçültülmüş olarak işlenir.
Aşağıdaki örnekte, checked öğenin biçimlendirmesinde işlenip işlenmeyeceğini IsCompleted belirler:

<input type="checkbox" checked="@IsCompleted" />

@code {
[Parameter]
public bool IsCompleted { get; set; }
}

IsCompleted true , onay kutusu şu şekilde işlenir:

<input type="checkbox" checked />

IsCompleted false , onay kutusu şu şekilde işlenir:

<input type="checkbox" />

Daha fazla bilgi için bkz. ASP.NET Core Razor söz dizimi başvurusu.

WARNING
.NET türü bool olduğunda, Aria-basılangıbı bazı HTML öznitelikleri düzgün şekilde çalışmaz. Bu durumlarda, bool yerine
string türü kullanın.

Ham HTML
Dizeler normalde DOM metin düğümleri kullanılarak işlenir. Bu, içerdikleri tüm biçimlendirmenin yok sayıldığı ve
değişmez değer olarak kabul edildiği anlamına gelir. Ham HTML işlemek için, HTML içeriğini bir MarkupString
değerde sarın. Değer HTML veya SVG olarak ayrıştırılır ve DOM 'a eklenir.

WARNING
Güvenilmeyen bir kaynaktan oluşturulan ham HTML işleme bir güvenlik riskidir ve kaçınılması gerekir!

Aşağıdaki örnek, bir bileşenin işlenmiş çıktısına statik HTML içeriği bloğunu eklemek için MarkupString türünü
kullanmayı gösterir:
@((MarkupString)myMarkup)

@code {
private string myMarkup =
"<p class='markup'>This is a <em>markup string</em>.</p>";
}

Şablonlu bileşenler
Şablonlu bileşenler, bir veya daha fazla UI şablonunu parametre olarak kabul eden bileşenlerdir, daha sonra
bileşen işleme mantığının bir parçası olarak kullanılabilir. Şablonlu bileşenler, normal bileşenlerden daha yeniden
kullanılabilir olan üst düzey bileşenleri yazmanıza izin verir. Birkaç örnek şunlardır:
Kullanıcının tablo üst bilgisi, satırları ve altbilgisi için şablon belirtmesini sağlayan tablo bileşeni.
Bir kullanıcının bir listedeki öğeleri işlemek için şablon belirlemesine izin veren bir liste bileşenidir.
Şablon parametreleri
Şablonlu bir bileşen, RenderFragment veya RenderFragment<T> türünde bir veya daha fazla bileşen parametresi
belirtilerek tanımlanır. Bir işleme parçası, işlenecek Kullanıcı arabiriminin bir kesimini temsil eder.
RenderFragment<T> , işleme parçası çağrıldığında belirtilebildiği bir tür parametresi alır.

TableTemplate bileşeni:

@typeparam TItem

<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr>@RowTemplate(item)</tr>
}
</tbody>
<tfoot>
<tr>@TableFooter</tr>
</tfoot>
</table>

@code {
[Parameter]
public RenderFragment TableHeader { get; set; }

[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; }

[Parameter]
public RenderFragment TableFooter { get; set; }

[Parameter]
public IReadOnlyList<TItem> Items { get; set; }
}

Şablonlu bir bileşen kullanırken, şablon parametreleri parametre adlarıyla eşleşen alt öğeler ( TableHeader ve
aşağıdaki örnekte RowTemplate ) kullanılarak belirtilebilir:
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>

Şablon bağlam parametreleri


Öğe olarak geçirilen RenderFragment<T> bileşen bağımsız değişkenleri context adında örtük bir parametreye
sahiptir (örneğin, yukarıdaki kod örneğinden, @context.PetId ), ancak parametre adını alt öğe üzerindeki Context
özniteliğini kullanarak değiştirebilirsiniz. Aşağıdaki örnekte, RowTemplate öğenin Context özniteliği pet
parametresini belirtir:

<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>

Alternatif olarak, bileşen öğesinde Context özniteliğini de belirtebilirsiniz. Belirtilen Context özniteliği belirtilen
tüm şablon parametreleri için geçerlidir. Bu, örtük alt içerik (herhangi bir sarmalama alt öğesi olmadan) için içerik
parametre adını belirtmek istediğinizde yararlı olabilir. Aşağıdaki örnekte, Context özniteliği TableTemplate
öğesinde görünür ve tüm şablon parametreleri için geçerlidir:

<TableTemplate Items="pets" Context="pet">


<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>

Genel olarak yazılmış bileşenler


Şablonlu bileşenler çoğunlukla genel olarak türdedir. Örneğin, bir genel ListViewTemplate bileşeni
IEnumerable<T> değerlerini işlemek için kullanılabilir. Genel bir bileşen tanımlamak için @typeparam yönergesini
kullanarak tür parametrelerini belirtin:
@typeparam TItem

<ul>
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</ul>

@code {
[Parameter]
public RenderFragment<TItem> ItemTemplate { get; set; }

[Parameter]
public IReadOnlyList<TItem> Items { get; set; }
}

Genel türsüz bileşenleri kullanırken tür parametresi mümkünse algılanır:

<ListViewTemplate Items="pets">
<ItemTemplate Context="pet">
<li>@pet.Name</li>
</ItemTemplate>
</ListViewTemplate>

Aksi halde tür parametresi, tür parametresinin adıyla eşleşen bir öznitelik kullanılarak açıkça belirtilmelidir.
Aşağıdaki örnekte, TItem="Pet" türü belirtir:

<ListViewTemplate Items="pets" TItem="Pet">


<ItemTemplate Context="pet">
<li>@pet.Name</li>
</ItemTemplate>
</ListViewTemplate>

Değerleri ve parametreleri basamaklama


Bazı senaryolarda, özellikle birden çok bileşen katmanı olduğunda, bileşen parametrelerikullanarak bir üst
bileşenden bir alt bileşene veri akışı yapmak uygun değildir. Değerleri ve parametreleri basamaklama, bir üst
bileşenin tüm alt bileşenlerine değer sağlaması için kullanışlı bir yol sağlayarak bu sorunu çözebilir. Basamaklı
değerler ve parametreler, bileşenlerin koordinasyonu için bir yaklaşım sağlar.
Tema örneği
Örnek uygulamadan aşağıdaki örnekte, ThemeInfo sınıfı, uygulamanın belirli bir bölümündeki tüm düğmelerin
aynı stili paylaştığı şekilde bileşen hiyerarşisinin akışını yapmak için tema bilgilerini belirtir.
Uıthemeclasses/Themeınfo. cs:

public class ThemeInfo


{
public string ButtonClass { get; set; }
}

Bir üst bileşen basamaklı değer bileşeni kullanılarak basamaklı bir değer sağlayabilir. CascadingValue bileşeni,
bileşen hiyerarşisinin bir alt ağacını sarmalanmış ve bu alt ağaçta bulunan tüm bileşenlere tek bir değer sağlar.
Örneğin, örnek uygulama, @Body özelliğinin düzen gövdesini oluşturan tüm bileşenler için bir geçişli parametre
olarak uygulamanın düzenlerindeki tema bilgilerini ( ThemeInfo ) belirtir. ButtonClass , düzen bileşeninde
btn-success bir değeri atanır. Tüm alt bileşenler, ThemeInfo basamaklı nesne aracılığıyla bu özelliği kullanabilir.
CascadingValuesParametersLayout bileşeni:

@inherits LayoutComponentBase
@using BlazorSample.UIThemeClasses

<div class="container-fluid">
<div class="row">
<div class="col-sm-3">
<NavMenu />
</div>
<div class="col-sm-9">
<CascadingValue Value="theme">
<div class="content px-4">
@Body
</div>
</CascadingValue>
</div>
</div>
</div>

@code {
private ThemeInfo theme = new ThemeInfo { ButtonClass = "btn-success" };
}

Basamaklı değerleri kullanmak için, bileşenler [CascadingParameter] özniteliği kullanarak Geçişli Parametreler
bildirir. Basamaklı değerler, türe göre basamaklı parametrelere bağlanır.
Örnek uygulamada CascadingValuesParametersTheme bileşeni, ThemeInfo geçişli değeri basamaklı bir parametreye
bağlar. Parametresi, bileşen tarafından görünen düğmelerden birine ait CSS sınıfını ayarlamak için kullanılır.
CascadingValuesParametersTheme bileşeni:
@page "/cascadingvaluesparameterstheme"
@layout CascadingValuesParametersLayout
@using BlazorSample.UIThemeClasses

<h1>Cascading Values & Parameters</h1>

<p>Current count: @currentCount</p>

<p>
<button class="btn" @onclick="IncrementCount">
Increment Counter (Unthemed)
</button>
</p>

<p>
<button class="btn @ThemeInfo.ButtonClass" @onclick="IncrementCount">
Increment Counter (Themed)
</button>
</p>

@code {
private int currentCount = 0;

[CascadingParameter]
protected ThemeInfo ThemeInfo { get; set; }

private void IncrementCount()


{
currentCount++;
}
}

Aynı alt ağaç içindeki aynı türdeki birden çok değeri basamakla, her bir CascadingValue bileşenine ve karşılık
gelen CascadingParameter benzersiz bir Name dizesi sağlayın. Aşağıdaki örnekte, iki CascadingValue bileşeni,
MyCascadingType farklı örneklerini ada göre basamakla:

<CascadingValue Value=@ParentCascadeParameter1 Name="CascadeParam1">


<CascadingValue Value=@ParentCascadeParameter2 Name="CascadeParam2">
...
</CascadingValue>
</CascadingValue>

@code {
private MyCascadingType ParentCascadeParameter1;

[Parameter]
public MyCascadingType ParentCascadeParameter2 { get; set; }

...
}

Alt bileşende, basamaklı parametreler değerlerini, üst bileşendeki ilgili basamaklı değerleri ada göre alır:

...

@code {
[CascadingParameter(Name = "CascadeParam1")]
protected MyCascadingType ChildCascadeParameter1 { get; set; }

[CascadingParameter(Name = "CascadeParam2")]
protected MyCascadingType ChildCascadeParameter2 { get; set; }
}
TabSet örneği
Basamaklı parametreler, bileşenlerin bileşen hiyerarşisinde işbirliği yapmasına de olanak tanır.Örneğin, örnek
uygulamada aşağıdaki Tabset örneğini göz önünde bulundurun.
Örnek uygulama, sekmelerin uygulandığı bir ITab arabirimine sahiptir:

using Microsoft.AspNetCore.Components;

namespace BlazorSample.UIInterfaces
{
public interface ITab
{
RenderFragment ChildContent { get; }
}
}

CascadingValuesParametersTabSet bileşeni, çeşitli Tab bileşenleri içeren TabSet bileşenini kullanır:

<TabSet>
<Tab Title="First tab">
<h4>Greetings from the first tab!</h4>

<label>
<input type="checkbox" @bind="showThirdTab" />
Toggle third tab
</label>
</Tab>
<Tab Title="Second tab">
<h4>The second tab says Hello World!</h4>
</Tab>

@if (showThirdTab)
{
<Tab Title="Third tab">
<h4>Welcome to the disappearing third tab!</h4>
<p>Toggle this tab from the first tab.</p>
</Tab>
}
</TabSet>

Alt Tab bileşenleri, TabSet açıkça parametre olarak geçirilmemektedir. Bunun yerine, alt Tab bileşenleri TabSet
alt içeriğinin bir parçasıdır. Ancak, TabSet üst bilgileri ve etkin sekmeyi işleyebilmesi için, her bir Tab bileşeni
hakkında yine de bilmesi gerekir. Ek kod gerektirmeden bu koordinasyonu etkinleştirmek için, TabSet bileşen
kendisini, alt Tab bileşenleri tarafından çekilen basamaklı bir değer olarak sağlayabilir .
TabSet bileşeni:
@using BlazorSample.UIInterfaces

<!-- Display the tab headers -->


<CascadingValue Value=this>
<ul class="nav nav-tabs">
@ChildContent
</ul>
</CascadingValue>

<!-- Display body for only the active tab -->


<div class="nav-tabs-body p-4">
@ActiveTab?.ChildContent
</div>

@code {
[Parameter]
public RenderFragment ChildContent { get; set; }

public ITab ActiveTab { get; private set; }

public void AddTab(ITab tab)


{
if (ActiveTab == null)
{
SetActivateTab(tab);
}
}

public void RemoveTab(ITab tab)


{
if (ActiveTab == tab)
{
SetActivateTab(null);
}
}

public void SetActivateTab(ITab tab)


{
if (ActiveTab != tab)
{
ActiveTab = tab;
StateHasChanged();
}
}
}

Alt Tab bileşenleri, kapsayan TabSet kendisini basamaklı bir parametre olarak yakalar, bu nedenle Tab
bileşenleri kendilerini TabSet ve bu sekmenin etkin olduğu koordine eder.
Tab bileşeni:
@using BlazorSample.UIInterfaces
@implements ITab

<li>
<a @onclick="Activate" class="nav-link @TitleCssClass" role="button">
@Title
</a>
</li>

@code {
[CascadingParameter]
public TabSet ContainerTabSet { get; set; }

[Parameter]
public string Title { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

private string TitleCssClass => ContainerTabSet.ActiveTab == this ? "active" : null;

protected override void OnInitialized()


{
ContainerTabSet.AddTab(this);
}

private void Activate()


{
ContainerTabSet.SetActivateTab(this);
}
}

Razor şablonları
Oluşturma parçaları Razor şablonu sözdizimi kullanılarak tanımlanabilir. Razor şablonları, bir UI parçacığı
tanımlamak ve aşağıdaki biçimi varsaymak için bir yoldur:

@<{HTML tag}>...</{HTML tag}>

Aşağıdaki örnek, RenderFragment ve RenderFragment<T> değerlerinin nasıl belirtildiğini ve şablonlarının doğrudan


bir bileşende nasıl işleneceğini gösterir. Oluşturma parçaları, şablonlu bileşenlerebağımsız değişken olarak da
geçirilebilir.

@timeTemplate

@petTemplate(new Pet { Name = "Rex" })

@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate =
(pet) => @<p>Your pet's name is @pet.Name.</p>;

private class Pet


{
public string Name { get; set; }
}
}

Önceki kodun işlenmiş çıktısı:


<p>The time is 10/04/2018 01:26:52.</p>

<p>Your pet's name is Rex.</p>

El ile RenderTreeBuilder mantığı


Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder , bileşenleri ve öğeleri işlemek için yöntemler sağlar
ve C# kodu kodda el ile oluşturma dahil.

NOTE
Bileşen oluşturmak için RenderTreeBuilder kullanımı gelişmiş bir senaryodur. Hatalı biçimlendirilmiş bir bileşen (örneğin,
kapatılmamış bir biçimlendirme etiketi) tanımsız davranışa neden olabilir.

Başka bir bileşende el ile yerleşik olarak kullanılabilecek aşağıdaki PetDetails bileşenini göz önünde bulundurun:

<h2>Pet Details Component</h2>

<p>@PetDetailsQuote</p>

@code
{
[Parameter]
public string PetDetailsQuote { get; set; }
}

Aşağıdaki örnekte, CreateComponent yöntemindeki döngü üç PetDetails bileşeni oluşturur. Bileşenleri


oluşturmak için RenderTreeBuilder Yöntemler çağrılırken ( OpenComponent ve AddAttribute ), dizi numaraları
kaynak kodu satır numaralarıdır. Blazor farkı algoritması, ayrı çağrı etkinleştirmeleri değil, farklı kod satırlarına
karşılık gelen sıra numaralarına dayanır. RenderTreeBuilder yöntemlerle bir bileşen oluştururken, dizi numaraları
için bağımsız değişkenleri sabit olarak kodlayın. Sıra numarasını oluşturmak için bir hesaplama veya sayaç
kullanmak kötü performansa neden olabilir. Daha fazla bilgi için bkz. kod satırı numaralarıyla Ilgili sıra
numaraları ve yürütme sırası çalışmıyor bölümü.
BuiltContent bileşeni:
@page "/BuiltContent"

<h1>Build a component</h1>

@CustomRender

<button type="button" @onclick="RenderComponent">


Create three Pet Details components
</button>

@code {
private RenderFragment CustomRender { get; set; }

private RenderFragment CreateComponent() => builder =>


{
for (var i = 0; i < 3; i++)
{
builder.OpenComponent(0, typeof(PetDetails));
builder.AddAttribute(1, "PetDetailsQuote", "Someone's best friend!");
builder.CloseComponent();
}
};

private void RenderComponent()


{
CustomRender = CreateComponent();
}
}

! WARNING Microsoft.AspNetCore.Components.RenderTree türler, işleme işlemlerinin sonuçlarının işlenmesine


izin verir. Bunlar Blazor Framework uygulamasının iç ayrıntılardır. Bu türlerin dengesizleşilmesi ve gelecekteki
sürümlerde değişikliğe tabi olması gerekir.

Sıra numaraları, kod satırı numaralarıyla ilgilidir ve yürütme sırası değildir


Blazor .razor dosyalar her zaman derlenir. Derleme adımı, çalışma zamanında uygulama performansını
geliştiren bilgileri eklemek için kullanılabilir olduğundan, bu büyük olasılıkla .razor için harika bir avantajdır.
Bu geliştirmelerin önemli bir örneği sıra numarasıiçerir. Sıra numaraları, hangi çıkışların ayrı ve sıralı kod
satırlarından geldiğini çalışma zamanına işaret ediyor. Çalışma zamanı, doğrusal bir zamanda, genel ağaç farkı
algoritması için genellikle mümkün olandan çok daha hızlı olan etkili ağaç SLA 'ları oluşturmak için bu bilgileri
kullanır.
Aşağıdaki Razor bileşeni ( . Razor) dosyasını göz önünde bulundurun:

@if (someFlag)
{
<text>First</text>
}

Second

Yukarıdaki kod, aşağıdakine benzer şekilde derlenir:

if (someFlag)
{
builder.AddContent(0, "First");
}

builder.AddContent(1, "Second");
Kod ilk kez yürütüldüğünde, someFlag true , Oluşturucu şunları alır:

SEQUENCE TÜR VERI

0 Metin düğümü Birinci

1. Metin düğümü Saniye

someFlag false hale geldiğini ve biçimlendirmenin yeniden işleneceğini varsayın. Bu kez, Oluşturucu şunları alır:

SEQUENCE TÜR VERI

1. Metin düğümü Saniye

Çalışma zamanı bir fark gerçekleştirdiğinde, sırasıyla 0 öğenin kaldırıldığını görür, bu nedenle aşağıdaki önemsiz
düzenleme betiğinioluşturur:
İlk metin düğümünü kaldırın.
Program aracılığıyla sıra numaraları oluşturursanız ne yanlış gider
Aşağıdaki işleme Ağacı Oluşturucusu mantığını yazmanız yerine düşünün:

var seq = 0;

if (someFlag)
{
builder.AddContent(seq++, "First");
}

builder.AddContent(seq++, "Second");

Şimdi ilk çıktı:

SEQUENCE TÜR VERI

0 Metin düğümü Birinci

1. Metin düğümü Saniye

Bu sonuç önceki bir durum ile aynıdır, bu nedenle olumsuz bir sorun yoktur. someFlag ikinci işleme false ve
çıktı:

SEQUENCE TÜR VERI

0 Metin düğümü Saniye

Bu kez, fark algoritması iki değişikliğin oluştuğunu görür ve algoritma aşağıdaki düzenleme betiğini üretir:
İlk metin düğümünün değerini Second olarak değiştirin.
İkinci metin düğümünü kaldırın.
Sıra numaralarının oluşturulması, özgün kodda if/else dalların ve döngülerin bulunduğu yer hakkındaki tüm
yararlı bilgileri kaybetti. Bu, daha önce olduğu gibi bir fark ile iki kez sonuçlanır.
Bu, önemsiz bir örnektir. Karmaşık ve derin iç içe yapıları ve özellikle döngülerle daha gerçekçi durumlarda
performans maliyeti daha önemlidir. Hangi döngü bloklarının veya dallarının eklendiğini veya kaldırıldığını
hemen belirlemek yerine, fark algoritmasının işleme ağaçlarına katmaları ve genellikle eski ve yeni yapıların nasıl
olduğu hakkında yanlış bir biçimde düzenleme betikleri oluşturması birbirleriyle ilişkilendir.
Kılavuz ve ekibinizle
Sıra numaraları dinamik olarak oluşturulursa uygulama performansı de vardır.
Altyapı, derleme zamanında yakalanmadığı takdirde gerekli bilgiler bulunmadığından, çalışma zamanında
kendi sıra numaralarını otomatik olarak oluşturamaz.
El ile uygulanan RenderTreeBuilder mantığı uzun blokları yazmayın. .razor dosyalarını tercih edin ve
derleyicinin sıra numaralarıyla uğraşmak için izin verin. El ile RenderTreeBuilder mantığın olmaması
durumunda, uzun kod bloklarını OpenRegion / CloseRegion çağrılarına kaydırılmış daha küçük parçalara ayırın.
Her bölge kendi ayrı dizi numaralarına sahiptir, bu nedenle her bölge içinde sıfırdan (veya herhangi bir
rastgele sayıdan) yeniden başlatabilirsiniz.
Dizi numaraları sabit kodluysa, fark algoritması yalnızca değer değerinde sıra numaralarının artırılmasını
gerektirir. İlk değer ve boşluklar ilgisiz. Tek bir seçenek, kod satırı numarasını sıra numarası olarak kullanmak
veya sıfırdan başlayıp bir ya da yüzlerce (ya da tercih edilen aralığa) artırmak için kullanılır.
Blazor sıra numaralarını kullanır, diğer ağaç dağıtma Kullanıcı arabirimi çerçeveleri bunları kullanmaz. Dizi
numaraları kullanıldığında, yayılma çok daha hızlıdır ve Blazor, . Razor dosyaları yazan geliştiriciler için
otomatik olarak sıra numaralarıyla ilgilenen bir derleme adımının avantajına sahiptir.

Yerelleştirme
Blazor Server uygulamaları, Yerelleştirme ara yazılımıkullanılarak yerelleştirilmiştir. Ara yazılım, uygulamadan
kaynak isteyen kullanıcılar için uygun kültürü seçer.
Kültür aşağıdaki yaklaşımlardan biri kullanılarak ayarlanabilir:
Çerezler
Kültürü seçmek için Kullanıcı arabirimi sağlama
Daha fazla bilgi ve örnek için bkz. ASP.NET Core Genelleştirme ve yerelleştirme.
Bağlayıcıyı Uluslararası hale getirme için yapılandırma (Blazor WebAssembly)
Varsayılan olarak, Blazor WebAssembly uygulamaları için Blazorbağlayıcı yapılandırması, açıkça istenen yerel
ayarlar dışında uluslararası duruma getirme bilgilerini kaldırır. Bağlayıcının davranışını denetleme hakkında daha
fazla bilgi ve yönergeler için bkz. ASP.NET Core Blazor için bağlayıcı yapılandırma.
Tanımlama bilgileri
Yerelleştirme kültürü tanımlama bilgisi kullanıcının kültürünü kalıcı hale getirebilirler. Tanımlama bilgisi,
uygulamanın ana bilgisayar sayfasının OnGet yöntemiyle oluşturulur (Pages/Host. cshtml. cs). Yerelleştirme ara
yazılımı, sonraki isteklerde Kullanıcı kültürünü ayarlamak için tanımlama bilgilerini okur.
Tanımlama bilgisinin kullanımı, WebSocket bağlantısının kültürü doğru şekilde yaymasını sağlar. Yerelleştirme
şemaları URL yolunu veya sorgu dizesini temel alıyorsa, düzen WebSockets ile çalışmayabilir, bu nedenle kültürü
kalıcı hale getiremeyebilir. Bu nedenle, yerelleştirme kültürü tanımlama bilgisinin kullanılması önerilen
yaklaşımdır.
Kültür bir yerelleştirme tanımlama bilgisinde kalıcı hale getirilir kültür atamak için herhangi bir teknik
kullanılabilir. Uygulamanın zaten sunucu tarafı ASP.NET Core için bir yerelleştirme şeması varsa, uygulamanın
var olan yerelleştirme altyapısını kullanmaya devam edin ve uygulamanın şeması içinde yerelleştirme kültür
tanımlama bilgisini ayarlayın.
Aşağıdaki örnekte, yerelleştirme ara yazılımı tarafından okunabilen bir tanımlama bilgisinde geçerli kültürün nasıl
ayarlanacağı gösterilmektedir. Blazor Server uygulamasında aşağıdaki içeriklerle bir Pages/Host. cshtml. cs
dosyası oluşturun:
public class HostModel : PageModel
{
public void OnGet()
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
}

Yerelleştirme uygulamada işlenir:


1. Tarayıcı, uygulamaya bir ilk HTTP isteği gönderir.
2. Kültür, yerelleştirme ara yazılımı tarafından atanır.
3. _Host. cshtml. cs içindeki OnGet yöntemi, yanıtın bir parçası olarak bir tanımlama bilgisinde kültürü devam
ettirir.
4. Tarayıcı, etkileşimli bir Blazor sunucusu oturumu oluşturmak için bir WebSocket bağlantısı açar.
5. Yerelleştirme ara yazılımı tanımlama bilgisini okur ve kültürü atar.
6. Blazor Server oturumu doğru kültür ile başlar.
Kültürü seçmek için Kullanıcı arabirimi sağlama
Bir kullanıcının bir kültür seçmesine izin vermek için kullanıcı ARABIRIMI sağlamak üzere bir yeniden
yönlendirme tabanlı yaklaşım önerilir. Bu işlem, bir Kullanıcı bir oturum açma sayfasına yeniden yönlendirildiği
ve ardından özgün kaynağa yeniden yönlendirildiği—bir Kullanıcı güvenli bir kaynağa erişmeyi denediğinde bir
Web uygulamasında gerçekleşmelere benzer.
Uygulama, bir denetleyiciye yeniden yönlendirme yoluyla kullanıcının seçili kültürünü devam ettirir. Denetleyici
kullanıcının seçili kültürünü bir tanımlama bilgisine ayarlar ve kullanıcıyı özgün URI 'ye yeniden yönlendirir.
Bir tanımlama bilgisinde kullanıcının seçili kültürünü ayarlamak ve özgün URI 'ye yeniden yönlendirmeyi
gerçekleştirmek için sunucuda bir HTTP uç noktası oluşturun:

[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult SetCulture(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture)));
}

return LocalRedirect(redirectUri);
}
}

WARNING
Açık yeniden yönlendirme saldırılarını engellemek için LocalRedirect eylemi sonucunu kullanın. Daha fazla bilgi için bkz.
ASP.NET core'da açık yeniden yönlendirme saldırılarını önleme.
Aşağıdaki bileşen, Kullanıcı bir kültür seçtiğinde ilk yeniden yönlendirmenin nasıl gerçekleştirileceği hakkında bir
örnek göstermektedir:

@inject NavigationManager NavigationManager

<h3>Select your language</h3>

<select @onchange="OnSelected">
<option>Select...</option>
<option value="en-US">English</option>
<option value="fr-FR">Français</option>
</select>

@code {
private double textNumber;

private void OnSelected(ChangeEventArgs e)


{
var culture = (string)e.Value;
var uri = new Uri(NavigationManager.Uri())
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var query = $"?culture={Uri.EscapeDataString(culture)}&" +
$"redirectUri={Uri.EscapeDataString(uri)}";

NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);


}
}

Blazor uygulamalarında .NET yerelleştirme senaryolarını kullanma


Blazor uygulamalar içinde, aşağıdaki .NET yerelleştirme ve genelleştirme senaryoları kullanılabilir:
. NET ' in kaynak sistemi
Kültüre özgü sayı ve Tarih biçimlendirmesi
Blazor @bind işlevselliği, kullanıcının geçerli kültürüne göre Genelleştirme gerçekleştirir. Daha fazla bilgi için veri
bağlama bölümüne bakın.
Sınırlı bir ASP.NET Core yerelleştirme senaryosu kümesi şu anda desteklenmektedir:
IStringLocalizer<> Blazor uygulamalarda desteklenir .
IHtmlLocalizer<> , IViewLocalizer<> ve veri ek açıklamaları yerelleştirme ASP.NET Core MVC
senaryolarından ve Blazor uygulamalarında desteklenmez .
Daha fazla bilgi için bkz. ASP.NET Core Genelleştirme ve yerelleştirme.

Ölçeklenebilir vektör grafik (SVG) görüntüleri


Blazor HTML oluşturduğundan, ölçeklenebilir vektör grafik (SVG ) görüntüleri ( . SVG ) dahil olmak üzere
tarayıcıda desteklenen görüntüler <img> etiketi aracılığıyla desteklenir:

<img alt="Example image" src="some-image.svg" />

Benzer şekilde, SVG görüntüleri bir stil sayfası dosyasının ( . css) CSS kurallarında desteklenir:

.my-element {
background-image: url("some-image.svg");
}
Ancak, satır içi SVG işaretlemesi tüm senaryolarda desteklenmez. Bir <svg> etiketini doğrudan bir bileşen
dosyasına ( . Razor) yerleştirirseniz, temel görüntü işleme desteklenir, ancak birçok gelişmiş senaryo
desteklenmemiştir. Örneğin, <use> Etiketler Şu anda dikkate alınamaz ve @bind bazı SVG etiketleriyle
kullanılamaz. Gelecekteki bir sürümde bu sınırlamaları ele almayı bekliyoruz.

Ek kaynaklar
Güvenli ASP.NET Core Blazor Server uygulamaları –, kaynak tükenmesi ile Çekişmek zorunda olan Blazor
sunucu uygulamaları oluşturmaya yönelik yönergeler Içerir.
ASP.NET Core Blazor yaşam döngüsü
9.12.2019 • 6 minutes to read • Edit Online

, Luke Latham ve Daniel Roth tarafından


Blazor Framework zaman uyumlu ve zaman uyumsuz yaşam döngüsü yöntemlerini içerir. Bileşen başlatma ve
işleme sırasında bileşenlerde ek işlemler gerçekleştirmek için yaşam döngüsü yöntemlerini geçersiz kılın.

Yaşam döngüsü yöntemleri


Bileşen başlatma yöntemleri
OnInitializedAsync ve OnInitialized bir bileşeni başlatan kodu yürütün. Bu yöntemlere yalnızca bileşen ilk örneği
oluşturulduğunda bir kez çağırılır.
Zaman uyumsuz bir işlem gerçekleştirmek için işlem üzerinde OnInitializedAsync ve await anahtar sözcüğünü
kullanın:

protected override async Task OnInitializedAsync()


{
await ...
}

NOTE
Bileşen başlatma sırasında zaman uyumsuz çalışma OnInitializedAsync yaşam döngüsü olayında gerçekleşmelidir.

Zaman uyumlu bir işlem için OnInitialized kullanın:

protected override void OnInitialized()


{
...
}

Parametreler ayarlanmadan önce


SetParametersAsync, işleme ağacındaki bileşenin üst öğesi tarafından sağlanan parametreleri ayarlar:

public override async Task SetParametersAsync(ParameterView parameters)


{
await ...

await base.SetParametersAsync(parameters);
}

ParameterView, SetParametersAsync her çağrıldığında parametre değerleri kümesinin tamamını içerir.


SetParametersAsync varsayılan uygulanması her bir özelliğin değerini, ParameterView karşılık gelen bir değere
sahip [Parameter] veya [CascadingParameter] özniteliğiyle ayarlar. ParameterView karşılık gelen bir değere sahip
olmayan parametreler değiştirilmeden bırakılır.
base.SetParametersAync çağrılmazsa, özel kod gelen parametreler değerini gerekli herhangi bir şekilde
yorumlayabilir. Örneğin, sınıftaki özelliklere gelen parametreleri atama gereksinimi yoktur.
Parametreler ayarlandıktan sonra
OnParametersSetAsync ve OnParametersSet bir bileşen üst öğeden parametreleri aldığında ve değerler
özelliklerine atandığında çağrılır. Bu yöntemler bileşen başlatıldıktan sonra ve her yeni parametre değeri
belirtildiğinde yürütülür:

protected override async Task OnParametersSetAsync()


{
await ...
}

NOTE
OnParametersSetAsync yaşam döngüsü olayında parametre ve özellik değerleri uygulanırken zaman uyumsuz iş olması
gerekir.

protected override void OnParametersSet()


{
...
}

Bileşen oluşturulduktan sonra


OnAfterRenderAsync ve OnAfterRender bir bileşen işlemeyi tamamladıktan sonra çağrılır. Öğe ve bileşen
başvuruları bu noktada doldurulur. İşlenmiş DOM öğelerinde çalışan üçüncü taraf JavaScript kitaplıklarını
etkinleştirme gibi, işlenmiş içeriği kullanarak ek başlatma adımları gerçekleştirmek için bu aşamayı kullanın.
OnAfterRenderAsync ve OnAfterRender için firstRender parametresi:
, Bileşen örneği ilk kez işlendiğinde true olarak ayarlanır.
Başlatma işinin yalnızca bir kez gerçekleştirildiğinden emin olmak için kullanılabilir.

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender)
{
await ...
}
}

NOTE
OnAfterRenderAsync yaşam döngüsü olayında, işleme hemen sonra zaman uyumsuz çalışma gerçekleşmelidir.
OnAfterRenderAsync bir Task döndürseniz bile, çerçeve bu görev tamamlandıktan sonra bileşen için başka bir işleme çevrimi
zamanlayamaz. Bu, sonsuz bir işleme döngüsünden kaçınmaktır. Diğer yaşam döngüsü yöntemlerinden farklı olduğundan,
döndürülen görev tamamlandığında daha fazla işleme döngüsü zamanlayabilirsiniz.
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
...
}
}

OnAfterRender ve OnAfterRenderAsync sunucuda prerendering çağrılmaz.


UI yenilemeyi bastır
UI yenilemeyi gizlemek için ShouldRender geçersiz kılın. Uygulama true döndürürse, Kullanıcı arabirimi
yenilenir:

protected override bool ShouldRender()


{
var renderUI = true;

return renderUI;
}

ShouldRender bileşen her işlendiğinde çağrılır.


ShouldRender geçersiz kılınsa bile, bileşen her zaman ilk olarak işlenir.

Durum değişiklikleri
StateHasChanged bileşene durumunu değiştiğini bildirir. Uygun olduğunda, StateHasChanged çağırmak bileşenin
yeniden yönlendirilmesine neden olur.

İşleme sırasında tamamlanmamış zaman uyumsuz eylemleri işle


Yaşam döngüsü olaylarında gerçekleştirilen zaman uyumsuz eylemler, bileşen işlenmeden önce tamamlanmamış
olabilir. Yaşam döngüsü yöntemi yürütülürken nesneler null veya verilerle tamamen doldurulmuş olabilir.
Nesnelerin başlatıldığını onaylamak için işleme mantığı sağlayın. Nesneler null yer tutucu Kullanıcı arabirimi
öğelerini (örneğin, bir yükleme iletisi) işleme.
Blazor şablonlarının FetchData bileşeninde, OnInitializedAsync tahmin verileri alma ( forecasts ) için geçersiz
kılınır. forecasts null olduğunda, kullanıcıya bir yükleme iletisi görüntülenir. OnInitializedAsync
tamamlandığında döndürülen Task , bileşen güncelleştirilmiş durumla yeniden yapılır.
Blazor Server şablonundaki Pages/FetchData. Razor :
@page "/fetchdata"
@using MyBlazorApp.Data
@inject WeatherForecastService ForecastService

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a service.</p>

@if (forecasts == null)


{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<!-- forecast data in table element content -->
</table>
}

@code {
private WeatherForecast[] forecasts;

protected override async Task OnInitializedAsync()


{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}

IDisposable ile bileşen atma


Bir bileşen IDisposableuygularsa, bileşen kullanıcı arabiriminden kaldırıldığında Dispose yöntemi çağırılır.
Aşağıdaki bileşen @implements IDisposable ve Dispose yöntemini kullanır:

@using System
@implements IDisposable

...

@code {
public void Dispose()
{
...
}
}

NOTE
Dispose StateHasChanged çağrısı desteklenmiyor. StateHasChanged oluşturucunun bir parçası olarak çağrılabilir, bu
nedenle bu noktada UI güncelleştirmelerinin kullanılması desteklenmez.

Hataları işleme
Yaşam döngüsü yöntemi yürütme sırasında hataları işleme hakkında bilgi için bkz. ASP.NET Core Blazor
uygulamalarda hataları işleme.
ASP.NET Core Blazor formları ve doğrulama
13.12.2019 • 9 minutes to read • Edit Online

Daniel Roth ve Luke Latham tarafından


Forms ve doğrulama, veri ek açıklamalarıkullanılarak Blazor desteklenir.
Aşağıdaki ExampleModel türü, veri ek açıklamalarını kullanarak doğrulama mantığını tanımlar:

using System.ComponentModel.DataAnnotations;

public class ExampleModel


{
[Required]
[StringLength(10, ErrorMessage = "Name is too long.")]
public string Name { get; set; }
}

Bir form EditForm bileşeni kullanılarak tanımlanır. Aşağıdaki formda tipik öğeler, bileşenler ve Razor kodu
gösterilmektedir:

<EditForm Model="@exampleModel" OnValidSubmit="@HandleValidSubmit">


<DataAnnotationsValidator />
<ValidationSummary />

<InputText id="name" @bind-Value="exampleModel.Name" />

<button type="submit">Submit</button>
</EditForm>

@code {
private ExampleModel exampleModel = new ExampleModel();

private void HandleValidSubmit()


{
Console.WriteLine("OnValidSubmit");
}
}

Form, ExampleModel türünde tanımlanan doğrulamayı kullanarak name alanında Kullanıcı girişini doğrular.
Model, bileşenin @code bloğunda oluşturulur ve özel bir alanda tutulur ( exampleModel ). Alan, <EditForm>
öğesinin Model özniteliğine atanır.
DataAnnotationsValidator bileşeni, veri açıklamalarını kullanarak doğrulama desteğini ekler.
ValidationSummary bileşeni doğrulama iletilerini özetler.
HandleValidSubmit , form başarıyla gönderdiğinde tetiklenir (doğrulamayı geçirir ).

Kullanıcı girişini almak ve doğrulamak için yerleşik bir giriş bileşenleri kümesi vardır. Girişler değiştirildiklerinde ve
bir form gönderildiğinde onaylanır. Kullanılabilir giriş bileşenleri aşağıdaki tabloda gösterilmiştir.

GIRIŞ BILEŞENI … OLARAK IŞLENDI

InputText <input>
GIRIŞ BILEŞENI … OLARAK IŞLENDI

InputTextArea <textarea>

InputSelect <select>

InputNumber <input type="number">

InputCheckbox <input type="checkbox">

InputDate <input type="date">

EditForm dahil olmak üzere tüm giriş bileşenleri, rastgele öznitelikleri destekler. Bir bileşen parametresiyle
eşleşmeyen herhangi bir öznitelik işlenmiş HTML öğesine eklenir.
Giriş bileşenleri, düzenleme sırasında doğrulamak ve CSS sınıfını alan durumunu yansıtacak şekilde değiştirmek
için varsayılan davranışı sağlar. Bazı bileşenler, yararlı ayrıştırma mantığını içerir.Örneğin, InputDate ve
InputNumber , onları doğrulama hatası olarak kaydederek düzeltilemez değerleri düzgün şekilde işleyebilir. Null
değerleri kabul edebilecek türler, hedef alanın null değer alabilme durumunu da destekler (örneğin, int? ).
Aşağıdaki Starship türü, önceki ExampleModel daha büyük bir özellik kümesi ve veri ek açıklamaları kullanarak
doğrulama mantığını tanımlar:

using System;
using System.ComponentModel.DataAnnotations;

public class Starship


{
[Required]
[StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
public string Identifier { get; set; }

public string Description { get; set; }

[Required]
public string Classification { get; set; }

[Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]


public int MaximumAccommodation { get; set; }

[Required]
[Range(typeof(bool), "true", "true",
ErrorMessage = "This form disallows unapproved ships.")]
public bool IsValidatedDesign { get; set; }

[Required]
public DateTime ProductionDate { get; set; }
}

Yukarıdaki örnekte, hiçbir veri ek açıklaması mevcut olmadığından Description isteğe bağlıdır.
Aşağıdaki form, Starship modelinde tanımlanan doğrulamayı kullanarak Kullanıcı girişini doğrular:
@page "/FormsValidation"

<h1>Starfleet Starship Database</h1>

<h2>New Ship Entry Form</h2>

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">


<DataAnnotationsValidator />
<ValidationSummary />

<p>
<label for="identifier">Identifier: </label>
<InputText id="identifier" @bind-Value="starship.Identifier" />
</p>
<p>
<label for="description">Description (optional): </label>
<InputTextArea id="description" @bind-Value="starship.Description" />
</p>
<p>
<label for="classification">Primary Classification: </label>
<InputSelect id="classification" @bind-Value="starship.Classification">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</p>
<p>
<label for="accommodation">Maximum Accommodation: </label>
<InputNumber id="accommodation"
@bind-Value="starship.MaximumAccommodation" />
</p>
<p>
<label for="valid">Engineering Approval: </label>
<InputCheckbox id="valid" @bind-Value="starship.IsValidatedDesign" />
</p>
<p>
<label for="productionDate">Production Date: </label>
<InputDate id="productionDate" @bind-Value="starship.ProductionDate" />
</p>

<button type="submit">Submit</button>

<p>
<a href="http://www.startrek.com/">Star Trek</a>,
&copy;1966-2019 CBS Studios, Inc. and
<a href="https://www.paramount.com">Paramount Pictures</a>
</p>
</EditForm>

@code {
private Starship starship = new Starship();

private void HandleValidSubmit()


{
Console.WriteLine("OnValidSubmit");
}
}

EditForm , hangi alanların değiştirildiği ve geçerli doğrulama iletileri de dahil olmak üzere düzenleme işlemiyle
ilgili meta verileri izleyen basamaklı bir değer olarak EditContext oluşturur. EditForm ayrıca geçerli ve geçersiz
gönderir ( OnValidSubmit , OnInvalidSubmit ) için uygun olaylar sağlar. Alternatif olarak, doğrulamayı tetiklemek ve
alan değerlerini özel doğrulama kodu ile denetlemek için OnSubmit kullanın.
Giriş olayına göre InputText
change olayı yerine input olayını kullanan özel bir bileşen oluşturmak için InputText bileşenini kullanın.
Aşağıdaki biçimlendirmeye sahip bir bileşen oluşturun ve bileşeni tıpkı InputText kullanıldığı gibi kullanın:

@inherits InputText

<input
@attributes="AdditionalAttributes"
class="@CssClass"
value="@CurrentValue"
@oninput="EventCallback.Factory.CreateBinder<string>(
this, __value => CurrentValueAsString = __value, CurrentValueAsString)" />

Doğrulama desteği
DataAnnotationsValidator bileşeni, basamaklı EditContext veri açıklamalarını kullanarak doğrulama desteğini
iliştirir. Veri ek açıklamalarını kullanarak doğrulama desteğinin etkinleştirilmesi bu açık hareketi gerektirir. Veri ek
açıklamalarıyla farklı bir doğrulama sistemi kullanmak için DataAnnotationsValidator özel bir uygulamayla
değiştirin. ASP.NET Core uygulama, başvuru kaynağında İnceleme için kullanılabilir:
Dataannotationsvalidator/Adddataannotationsvalidation.
Blazor iki tür doğrulama gerçekleştirir:
Alan doğrulama , Kullanıcı bir alanın dışına eklendiğinde gerçekleştirilir. Alan doğrulaması sırasında,
DataAnnotationsValidator bileşen bildirilen tüm doğrulama sonuçlarını alanla ilişkilendirir.
Kullanıcı formu gönderdiğinde model doğrulaması gerçekleştirilir. Model doğrulaması sırasında
DataAnnotationsValidator bileşeni, doğrulama sonucunun raporlandığı üye adına göre alanı saptamaya çalışır.
Tek bir üyeyle ilişkilendirilmeyen doğrulama sonuçları, bir alan yerine modeliyle ilişkilendirilir.
Doğrulama özeti ve doğrulama Iletisi bileşenleri
ValidationSummary bileşeni, doğrulama özeti etiketi Yardımcısı'na benzer olan tüm doğrulama iletilerini özetler:

<ValidationSummary />

Model parametresine sahip belirli bir model için çıkış doğrulama iletileri:

<ValidationSummary Model="@starship" />

ValidationMessage bileşeni, doğrulama Iletisi etiketi Yardımcısı'na benzer olan belirli bir alan için doğrulama
iletilerini görüntüler. For özniteliğiyle doğrulama için alanı ve model özelliğini adlandırırken bir lambda ifadesini
belirtin:

<ValidationMessage For="@(() => starship.MaximumAccommodation)" />

ValidationMessageve ValidationSummary bileşenleri rastgele öznitelikleri destekler. Bir bileşen parametresiyle


eşleşmeyen herhangi bir öznitelik, oluşturulan <div> veya <ul> öğesine eklenir.
Özel doğrulama öznitelikleri
Bir doğrulama sonucunun özel bir doğrulama özniteliğikullanılırken bir alanla doğru bir şekilde
ilişkilendirildiğinden emin olmak için, ValidationResultoluştururken doğrulama bağlamının MemberName geçirin:
using System;
using System.ComponentModel.DataAnnotations;

private class MyCustomValidator : ValidationAttribute


{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
...

return new ValidationResult("Validation message to user.",


new[] { validationContext.MemberName });
}
}

Blazor veri ek açıklamaları doğrulama paketi


Microsoft. AspNetCore.Blazor. Dataaçıklamalarda. doğrulama , DataAnnotationsValidator bileşenini kullanarak
doğrulama deneyimini boşlukları dolduran bir pakettir. Paket şu anda deneysel.
[CompareProperty] özniteliği
CompareAttribute DataAnnotationsValidator bileşeniyle iyi çalışmaz. Microsoft. AspNetCore.Blazor. Datareek
açıklamaları. doğrulaması deneysel paketi, bu sınırlamalar etrafında çalıştırılan ComparePropertyAttribute ek bir
doğrulama özniteliği tanıtır. Blazor bir uygulamada, [CompareProperty] [Compare] özniteliğinin doğrudan bir
değiştirme işlemi olur. Daha fazla bilgi için bkz. CompareAttribute Onvalidgönderim EditForm ile yoksayıldı
(ASPNET/AspNetCore #10643).
İç içe modeller, koleksiyon türleri ve karmaşık türler
Blazor, yerleşik DataAnnotationsValidator veri açıklamalarını kullanarak form girişini doğrulamaya yönelik destek
sağlar. Ancak DataAnnotationsValidator , yalnızca koleksiyon veya karmaşık tür özellikleri olmayan forma bağlanan
modelin en üst düzey özelliklerini doğrular.
Koleksiyon ve karmaşık tür özellikleri dahil olmak üzere, bağlantılı modelin tüm nesne grafiğini doğrulamak için,
deneysel Microsoft. aspnetcore.Blazortarafından sunulan ObjectGraphDataAnnotationsValidator kullanın.
Dataaçıklamalarda. doğrulama paketi:

<EditForm Model="@model" OnValidSubmit="@HandleValidSubmit">


<ObjectGraphDataAnnotationsValidator />
...
</EditForm>

Model özelliklerine [ValidateComplexType] ekleyin. Aşağıdaki model sınıflarında, ShipDescription sınıfı model
forma bağlandığında doğrulanacak ek veri açıklamalarını içerir:
Starship.cs:

using System;
using System.ComponentModel.DataAnnotations;

public class Starship


{
...

[ValidateComplexType]
public ShipDescription ShipDescription { get; set; }

...
}
ShipDescription.cs:

using System;
using System.ComponentModel.DataAnnotations;

public class ShipDescription


{
[Required]
[StringLength(40, ErrorMessage = "Description too long (40 char).")]
public string ShortDescription { get; set; }

[Required]
[StringLength(240, ErrorMessage = "Description too long (240 char).")]
public string LongDescription { get; set; }
}

Karmaşık veya koleksiyon türü özelliklerinin doğrulanması


Bir modelin özelliklerine uygulanan doğrulama öznitelikleri, form gönderildiğinde doğrular. Ancak, koleksiyonların
özellikleri veya bir modelin karmaşık veri türleri DataAnnotationsValidator bileşeni tarafından form gönderimi
üzerinde doğrulanmaz. Bu senaryoda iç içe geçmiş doğrulama özniteliklerini kabul etmek için özel bir doğrulama
bileşeni kullanın. Bir örnek için Blazor doğrulama örneğine (ASPNET/Samples)bakın.
ASP.NET Core Razor bileşenleri sınıf kitaplıkları
9.12.2019 • 4 minutes to read • Edit Online

Simon Timms tarafından


Bileşenler, projeler genelinde Razor sınıf kitaplığı 'nda (RCL ) paylaşılabilir. Razor bileşenleri sınıf kitaplığı , şuradan
eklenebilir:
Çözümdeki başka bir proje.
Bir NuGet paketi.
Başvurulan bir .NET kitaplığı.
Bileşenler normal .NET türleri olduğu gibi, bir RCL tarafından sunulan bileşenler normal .NET derlemelerdir.

RCL oluşturma
Ortamınızı Blazoriçin yapılandırmak üzere ASP.NET Core Blazor kullanmaya başlama makalesindeki yönergeleri
izleyin.
Visual Studio
.NET Core CLI
1. Yeni bir proje oluşturun.
2. Razor sınıfı kitaplığı' nı seçin. İleri’yi seçin.
3. Yeni bir Razor sınıf kitaplığı oluştur Iletişim kutusunda Oluştur' u seçin.
4. Proje adı alanında bir proje adı girin veya varsayılan proje adını kabul edin. Bu konudaki örneklerde
MyComponentLib1 proje adı kullanılır. Seçin oluşturma.
5. RCL 'yi bir çözüme ekleyin:
a. Çözüme sağ tıklayın. > var olan projeyi Ekle ' yi seçin.
b. RCL 'nin proje dosyasına gidin.
c. RCL 'nin proje dosyasını ( . csproj) seçin.
6. Uygulamadan RCL 'ye bir başvuru ekleyin:
a. Uygulama projesine sağ tıklayın. > başvuru Ekle ' yi seçin.
b. RCL projesini seçin. Seçin Tamam.

Kitaplık bileşeni kullanma


Başka bir projedeki bir kitaplıkta tanımlanan bileşenleri kullanmak için aşağıdaki yaklaşımlardan birini kullanın:
Ad alanı ile tam tür adını kullanın.
Razor kullanarak Razor @ kullanın. Tek tek bileşenler, ada göre eklenebilir.
Aşağıdaki örneklerde MyComponentLib1 , bir SalesReport bileşeni içeren bir bileşen kitaplığıdır.
SalesReport bileşene, ad alanı ile tam tür adı kullanılarak başvurulabilir:
<h1>Hello, world!</h1>

Welcome to your new app.

<MyComponentLib1.SalesReport />

Ayrıca, kitaplık bir @using yönergesi ile kapsama alınırsa bileşene de başvurulabilir:

@using MyComponentLib1

<h1>Hello, world!</h1>

Welcome to your new app.

<SalesReport />

Kitaplığın bileşenlerini bir projenin tamamına kullanılabilir hale getirmek için en üst düzey _Import. Razor
dosyasına @using MyComponentLib1 yönergesini ekleyin. Ad alanını tek bir sayfaya veya bir klasör içindeki sayfa
kümesine uygulamak için herhangi bir düzeydeki bir _Import. Razor dosyasına yönergesini ekleyin.

NuGet 'i derleyin, paketleyebilir ve iade edin


Bileşen kitaplıkları standart .NET kitaplıkları olduğundan, paketlemeden ve tüm kitaplıkları NuGet 'e dağıtmadan
farklı değildir. Paketleme, bir komut kabuğu 'nda DotNet Pack komutu kullanılarak gerçekleştirilir:

dotnet pack

Bir komut kabuğunda DotNet NuGet Push komutunu kullanarak paketi NuGet 'e yükleyin.

Statik varlıklar ile Razor bileşenleri sınıf kitaplığı oluşturma


RCL statik varlıkları içerebilir. Statik varlıklar, kitaplığı kullanan tüm uygulamalar tarafından kullanılabilir.Daha fazla
bilgi için bkz. ASP.NET Core ile sınıf kitaplıklarında yeniden kullanılabilir Razor Kullanıcı arabirimi.

Ek kaynaklar
ASP.NET Core ile sınıf kitaplıklarında yeniden kullanılabilir Razor Kullanıcı arabirimi
ASP.NET Core Blazor düzenleri
9.12.2019 • 6 minutes to read • Edit Online

Tarafından Rainer Stropek ve Luke Latham


Menüler, telif hakkı iletileri ve şirket logoları gibi bazı uygulama öğeleri genellikle uygulamanın genel düzeninin
parçasıdır ve uygulamadaki her bileşen tarafından kullanılır. Bu öğelerin kodunu bir uygulamanın tüm
bileşenlerine kopyalamak, öğelerden biri bir güncelleştirme gerektirdiğinde her bileşenin güncelleştirilmesi gerekir
—etkili bir yaklaşım değildir. Bu tür çoğaltmaya devam etmek zordur ve zaman içinde tutarsız içeriğe yol açabilir.
Düzenler bu sorunu çözüyor.
Teknik olarak, düzen yalnızca başka bir bileşendir. Bir düzen Razor şablonunda veya C# kodda tanımlanır ve veri
bağlama, bağımlılık eklemeve diğer bileşen senaryolarını kullanabilir.
Bir bileşeni bir düzenedönüştürmek için bileşen:
Düzen içindeki işlenmiş içerik için bir Body özelliği tanımlayan LayoutComponentBase devralır.
İçeriğin işlendiği yerleşim biçimlendirmesinde konumu belirtmek için Razor söz dizimi @Body kullanır.
Aşağıdaki kod örneğinde, mainlayout. Razorolan bir düzen bileşeninin Razor şablonu gösterilmektedir. Düzen
LayoutComponentBase devralır ve gezinti çubuğu ile altbilgi arasındaki @Body ayarlar:

@inherits LayoutComponentBase

<header>
<h1>Doctor Who&trade; Episode Database</h1>
</header>

<nav>
<a href="masterlist">Master Episode List</a>
<a href="search">Search</a>
<a href="new">Add Episode</a>
</nav>

@Body

<footer>
@TrademarkMessage
</footer>

@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}

Blazor uygulama şablonlarından birini temel alan bir uygulamada, MainLayout bileşeni (Mainlayout. Razor)
uygulamanın paylaşılan klasöründedir.

Varsayılan düzen
Uygulamanın app. Razor dosyasındaki Router bileşende varsayılan uygulama yerleşimini belirtin. Varsayılan
Blazor şablonları tarafından sunulan aşağıdaki Router bileşeni, MainLayout bileşenine varsayılan düzeni ayarlar:
<Router AppAssembly="typeof(Startup).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound>
</Router>

NotFound içerik için varsayılan bir düzen sağlamak üzere NotFound içeriği için bir LayoutView belirtin:

<Router AppAssembly="typeof(Startup).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="typeof(MainLayout)">
<h1>Page not found</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

Router bileşeni hakkında daha fazla bilgi için bkz. ASP.NET Core Blazor yönlendirme.
Düzen bir varsayılan düzen olarak belirtildiğinde, bileşen başına veya klasör temelinde geçersiz kılınabileceğinden,
yararlı bir uygulamadır. En genel teknik olduğundan, uygulamanın varsayılan yerleşimini ayarlamak için
yönlendiriciyi kullanmayı tercih edin.

Bir bileşende düzen belirtme


Bir bileşene düzen uygulamak için Razor yönergesini @layout kullanın. Derleyici, @layout bileşen sınıfına
uygulanan bir LayoutAttribute dönüştürür.
Aşağıdaki MasterList bileşenin içeriği, @Body konumundaki MasterLayout eklenir:

@layout MasterLayout
@page "/masterlist"

<h1>Master Episode List</h1>

Düzen doğrudan bir bileşende belirtildiğinde, yönlendiricide ayarlanan varsayılan bir düzen veya _Imports.
Razor'den içeri aktarılan bir @layout yönergesi geçersiz kılınır.

Merkezi düzen seçimi


Bir uygulamanın her klasörü, isteğe bağlı olarak _Imports. Razoradlı bir şablon dosyası içerebilir. Derleyici tüm
Razor şablonlarındaki içeri aktarmalar dosyasında belirtilen yönergeleri aynı klasörde ve özyinelemeli olarak tüm
alt klasörlerinde içerir. Bu nedenle, @layout MyCoolLayout içeren bir _Imports. Razor dosyası, bir klasördeki tüm
bileşenlerin MyCoolLayout kullanmasını sağlar. Klasör ve alt klasörler içindeki tüm . Razor dosyalarına
@layout MyCoolLayout tekrar tekrar eklemeniz gerekmez. @using yönergeler aynı zamanda bileşenlere aynı
şekilde uygulanır.
Aşağıdaki _Imports. Razor dosyası içeri aktarmaları:
MyCoolLayout.
Aynı klasörde ve alt klasörlerde bulunan tüm Razor bileşenleri.
BlazorApp1.Data ad alanı.

@layout MyCoolLayout
@using Microsoft.AspNetCore.Components
@using BlazorApp1.Data

_Imports. Razor dosyası, Razor görünümleri ve sayfaları için _ViewImports. cshtml dosyasına benzer ancak
özellikle Razor bileşen dosyalarına uygulanır.
_Imports bir düzen belirtme . Razor , yönlendiricinin varsayılan düzeniolarak belirtilen bir düzeni geçersiz kılar.

İç içe düzenleri
Uygulamalar iç içe düzenleri içerebilir. Bir bileşen, daha sonra başka bir düzene başvuruda bulunan bir düzene
başvurabilir. Örneğin, iç içe düzenleri çok düzeyli bir menü yapısı oluşturmak için kullanılır.
Aşağıdaki örnek, iç içe düzenleri nasıl kullanacağınızı gösterir. Epısodescomponent. Razor dosyası görüntülenecek
bileşendir. Bileşen MasterListLayout başvurur:

@layout MasterListLayout
@page "/masterlist/episodes"

<h1>Episodes</h1>

Masterlistlayout. Razor dosyası MasterListLayout sağlar. Düzen, MasterLayout başka bir düzene başvuruyor.
EpisodesComponent , @Body göründüğü yerde işlenir:

@layout MasterLayout
@inherits LayoutComponentBase

<nav>
<!-- Menu structure of master list -->
...
</nav>

@Body

Son olarak, Masterlayout. Razor içindeki MasterLayout üstbilgi, ana menü ve alt bilgi gibi en üst düzey düzen
öğelerini içerir. EpisodesComponent MasterListLayout @Body göründüğü yerde işlenir:

@inherits LayoutComponentBase

<header>...</header>
<nav>...</nav>

@Body

<footer>
@TrademarkMessage
</footer>

@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
Ek kaynaklar
ASP.NET Core düzen
ASP.NET Core Blazor bağımlılığı ekleme
9.12.2019 • 9 minutes to read • Edit Online

Rainer Stropek tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor bağımlılık ekleme (dı)işlemini destekler. Uygulamalar, yerleşik hizmetleri ekleme tarafından bileşenlere
kullanabilir. Uygulamalar Ayrıca özel hizmetleri tanımlayabilir ve kaydedebilir ve bu Hizmetleri uygulama
genelinde DI aracılığıyla kullanılabilir hale getirebilirsiniz.
DI, merkezi bir konumda yapılandırılmış hizmetlere erişmek için bir tekniktir. Bu, Blazor uygulamalarda şu şekilde
yararlı olabilir:
Hizmet sınıfının tek bir örneğini tek bir hizmet olarak bilinen birçok bileşen arasında paylaşabilirsiniz.
Başvuru soyutlamalarını kullanarak somut hizmet sınıflarından bileşenleri ayırın. Örneğin, uygulamadaki
verilere erişmek için bir arabirim IDataAccess düşünün. Arabirim somut bir DataAccess sınıfı tarafından
uygulanır ve uygulamanın hizmet kapsayıcısında bir hizmet olarak kaydedilir. Bir bileşen bir IDataAccess
uygulamasını almak için DI kullandığında, bileşen somut tür ile eşleştirilmez. Uygulama, büyük olasılıkla birim
testlerinde bir sahte uygulama için değiştirilebilir.

Varsayılan hizmetler
Varsayılan hizmetler, uygulamanın hizmet koleksiyonuna otomatik olarak eklenir.

HIZMET ÖMÜR AÇIKLAMA

HttpClient Adet HTTP istekleri göndermek ve bir URI


tarafından tanımlanan bir kaynaktan
HTTP yanıtlarını almak için yöntemler
sağlar.

Bir Blazor WebAssembly


uygulamasındaki HttpClient örneği,
arka planda HTTP trafiğini işlemek için
tarayıcıyı kullanır.

Blazor Server uygulamaları, varsayılan


olarak hizmet olarak yapılandırılmış bir
HttpClient içermez. Blazor sunucusu
uygulamasına bir HttpClient
sağlayın.

Daha fazla bilgi için bkz. ASP.NET Core


Blazor bir Web API 'SI çağırma.
HIZMET ÖMÜR AÇIKLAMA

IJSRuntime Adet JavaScript çağrılarının dağıtıldığı bir


JavaScript çalışma zamanının örneğini
temsil eder. Daha fazla bilgi için bkz.
ASP.NET Core Blazor JavaScript birlikte
çalışabilirliği.

NavigationManager Adet URI 'Ler ve gezinme durumu ile


çalışmaya yönelik yardımcıları içerir.
Daha fazla bilgi için bkz. URI ve gezinti
durumu yardımcıları.

Özel bir hizmet sağlayıcı, tabloda listelenen varsayılan Hizmetleri otomatik olarak sağlamaz. Özel bir hizmet
sağlayıcısı kullanır ve tabloda gösterilen hizmetlerden herhangi birini gerekliyse, gerekli hizmetleri yeni hizmet
sağlayıcısına ekleyin.

Uygulamaya hizmet ekleme


Yeni bir uygulama oluşturduktan sonra Startup.ConfigureServices yöntemini inceleyin:

public void ConfigureServices(IServiceCollection services)


{
// Add custom services here
}

ConfigureServices yöntemi, hizmet açıklayıcı nesnelerinin bir listesi olan bir IServiceCollectiongeçirilir
(ServiceDescriptor). Hizmetler, hizmet koleksiyonuna hizmet tanımlayıcıları sağlayarak eklenir. Aşağıdaki örnek,
IDataAccess arabirimiyle kavramı ve somut uygulama DataAccess gösterir:

public void ConfigureServices(IServiceCollection services)


{
services.AddSingleton<IDataAccess, DataAccess>();
}

Hizmetler, aşağıdaki tabloda gösterilen ömürlerle yapılandırılabilir.

ÖMÜR AÇIKLAMA

Scoped Blazor WebAssembly uygulamalarının Şu anda bir dı


kapsamları kavramı yoktur. Scoped kayıtlı hizmetler
Singleton hizmetleri gibi davranır. Ancak, Blazor sunucusu
barındırma modeli Scoped ömrünü destekler. Blazor Server
uygulamalarında, kapsamlı bir hizmet kaydı
bağlantınınkapsamına alınır. Bu nedenle, geçerli amaç
tarayıcıda istemci tarafı çalıştırmak olsa bile, kapsama alınmış
hizmetlerin kullanılması geçerli kullanıcı kapsamında olması
gereken hizmetler için tercih edilir.

Singleton Dı, hizmetin tek bir örneğini oluşturur. Bir Singleton


hizmeti gerektiren tüm bileşenler aynı hizmetin bir örneğini
alır.

Transient Bir bileşen hizmet kapsayıcısından bir Transient hizmeti


örneği aldığında, hizmetin Yeni bir örneğini alır.
Dı sistemi ASP.NET Core içindeki DI sistemini temel alır. Daha fazla bilgi için bkz. ASP.NET Core bağımlılık
ekleme.

Bir bileşende hizmet isteme


Hizmetler hizmet koleksiyonuna eklendikten sonra, @Ekle Razor yönergesini kullanarak hizmetleri bileşenlere
ekleyin. @inject iki parametreye sahiptir:
Eklenecek hizmetin türünü – yazın.
Özelliği, eklenen App Service 'i alan özelliğin adını –. Özelliği el ile oluşturma gerektirmez. Derleyici özelliği
oluşturur.
Daha fazla bilgi için bkz. ASP.NET core'da görünümlere bağımlılık ekleme.
Farklı hizmetler eklemek için birden çok @inject deyimi kullanın.
Aşağıdaki örnek @inject nasıl kullanacağınızı gösterir. Services.IDataAccess uygulayan hizmet bileşenin Özellik
DataRepository eklenir. Kodun yalnızca IDataAccess soyutlamasını nasıl kullandığını aklınızda yapın:

@page "/customer-list"
@using Services
@inject IDataAccess DataRepository

@if (Customers != null)


{
<ul>
@foreach (var customer in Customers)
{
<li>@customer.FirstName @customer.LastName</li>
}
</ul>
}

@code {
private IReadOnlyList<Customer> Customers;

protected override async Task OnInitializedAsync()


{
// The property DataRepository received an implementation
// of IDataAccess through dependency injection. Use
// DataRepository to obtain data from the server.
Customers = await DataRepository.GetAllCustomersAsync();
}
}

Dahili olarak, oluşturulan Özellik ( DataRepository ) InjectAttribute özniteliğini kullanır. Genellikle, bu öznitelik
doğrudan kullanılmaz. Bileşenler için bir temel sınıf gerekliyse ve temel sınıf için eklenen özellikler de gerekliyse,
InjectAttribute el ile ekleyin:

public class ComponentBase : IComponent


{
// DI works even if using the InjectAttribute in a component's base class.
[Inject]
protected IDataAccess DataRepository { get; set; }
...
}

Temel sınıftan türetilmiş bileşenlerde @inject yönergesi gerekli değildir. Temel sınıfın InjectAttribute yeterlidir:
@page "/demo"
@inherits ComponentBase

<h1>Demo Component</h1>

Hizmetler 'de dı kullanma


Karmaşık hizmetler için ek hizmetler gerekebilir. Önceki örnekte, DataAccess HttpClient varsayılan hizmeti
gerektirebilir. @inject (veya InjectAttribute ), hizmetlerde kullanılamaz. Bunun yerine Oluşturucu Ekleme
kullanılmalıdır. Gerekli hizmetler, hizmetin oluşturucusuna parametreler eklenerek eklenir.Dı hizmeti
oluşturduğunda, oluşturucuda gereken hizmetleri algılar ve bunlara göre sağlar.

public class DataAccess : IDataAccess


{
// The constructor receives an HttpClient via dependency
// injection. HttpClient is a default service.
public DataAccess(HttpClient client)
{
...
}
}

Oluşturucu Ekleme önkoşulları:


Bağımsız değişkenlerinin tümü DI tarafından yerine getirilme için tek bir Oluşturucu bulunmalıdır. Varsayılan
değerleri belirttiklerinde, DI tarafından kapsanmayan ek parametrelere izin verilir.
Uygulanabilir Oluşturucu ortakolmalıdır.
Uygulanabilir bir Oluşturucu var olmalıdır. Belirsizlik söz konusu olduğunda, bir özel durum oluşturur.

Bir dı kapsamını yönetmek için yardımcı program temel bileşen sınıfları


ASP.NET Core uygulamalarda, kapsamlı hizmetler genellikle geçerli isteğin kapsamlandırılır. İstek
tamamlandıktan sonra, tüm kapsamlı veya geçici hizmetler dı sistemi tarafından silinir. Blazor Server
uygulamalarında istek kapsamı, istemci bağlantısı süresince sürer ve bu da geçici ve kapsamlı hizmetlerin
beklenenden çok daha uzun sürebileceği anlamına gelir.
Hizmetlerin bir bileşenin kullanım ömrüne göre kapsamını atamak için OwningComponentBase ve
OwningComponentBase<TService> temel sınıfları kullanabilir. Bu temel sınıflar, bileşenin kullanım ömrü kapsamındaki
Hizmetleri çözümlemek IServiceProvider türünde bir ScopedServices özelliğini kullanıma sunar. Razor 'teki bir
taban sınıftan devralan bir bileşeni yazmak için @inherits yönergesini kullanın.

@page "/users"
@attribute [Authorize]
@inherits OwningComponentBase<Data.ApplicationDbContext>

<h1>Users (@Service.Users.Count())</h1>
<ul>
@foreach (var user in Service.Users)
{
<li>@user.UserName</li>
}
</ul>
NOTE
@inject veya InjectAttribute kullanılarak bileşene eklenen hizmetler bileşen kapsamında oluşturulmaz ve istek
kapsamına bağlıdır.

Ek kaynaklar
ASP.NET Core bağımlılık ekleme
ASP.NET core'da görünümlere bağımlılık ekleme
ASP.NET Core Blazor yönlendirme
9.12.2019 • 11 minutes to read • Edit Online

Tarafından Luke Latham

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

İstekleri yönlendirmeyi ve Blazor uygulamalarda gezinti bağlantıları oluşturmak için NavLink bileşenini
kullanmayı öğrenin.

Uç nokta yönlendirme tümleştirmesi ASP.NET Core


Blazor sunucusu ASP.NET Core uç nokta yönlendirmesindetümleşiktir. ASP.NET Core bir uygulama,
Startup.Configure``MapBlazorHub etkileşimli bileşenlere yönelik gelen bağlantıları kabul edecek şekilde
yapılandırılmıştır:

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});

En yaygın yapılandırma, tüm istekleri Razor sayfasına yönlendirmesidir ve bu, Blazor sunucu uygulamasının
sunucu tarafı bölümü için ana bilgisayar görevi görür. Kurala göre, ana bilgisayar sayfası genellikle _Host.
cshtmlolarak adlandırılır. Ana bilgisayar dosyasında belirtilen yol, yol eşleştirilirken düşük bir öncelik ile
çalıştığından bir geri dönüş yolu olarak adlandırılır. Geri dönüş yolu, diğer yollar eşleşmediği zaman kabul edilir.
Bu, uygulamanın Blazor sunucu uygulamasıyla kesintiye uğramadan diğer denetleyicileri ve sayfaları kullanmasına
izin verir.

Rota şablonları
Router bileşeni, belirtilen bir rota ile her bileşene yönlendirmeyi sağlar. Router bileşeni app. Razor dosyasında
görünür:

<Router AppAssembly="typeof(Startup).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound>
</Router>

@page yönergesine sahip bir . Razor dosyası derlendiğinde, oluşturulan sınıf yol şablonunu belirten bir
RouteAttribute sağlanır.
Çalışma zamanında RouteView bileşeni:
Tüm istenen parametrelerle birlikte Router RouteData alır.
Belirtilen parametreleri kullanarak belirtilen bileşeni düzeniyle (veya isteğe bağlı bir varsayılan düzende) işler.
İsteğe bağlı olarak, düzen belirtmeyen bileşenler için kullanılacak düzen sınıfıyla bir DefaultLayout parametresi
belirtebilirsiniz. Varsayılan Blazor şablonları MainLayout bileşenini belirtir. Mainlayout. Razor , şablon projenin
paylaşılan klasöründedir. Düzenler hakkında daha fazla bilgi için bkz. ASP.NET Core Blazor düzenleri.
Birden çok yol şablonu, bir bileşene uygulanabilir. Aşağıdaki bileşen /BlazorRoute ve /DifferentBlazorRoute
isteklerine yanıt verir:

@page "/BlazorRoute"
@page "/DifferentBlazorRoute"

<h1>Blazor routing</h1>

IMPORTANT
URL 'Lerin doğru bir şekilde çözülmesi için, uygulamanın, href özniteliğinde belirtilen uygulama temel yolu ile
Wwwroot/index.html dosyasına (Blazor WebAssembly) veya Pages/_Host. cshtml dosyasına (Blazor Server) bir <base>
etiketi içermesi gerekir ( <base href="/"> ). Daha fazla bilgi için bkz. ASP.NET Core Blazor barındırma ve dağıtma.

İçerik bulunamadığında özel içerik sağla


Router bileşeni, istenen rota için içerik bulunmazsa uygulamanın özel içerik belirtmesini sağlar.
App. Razor dosyasında, Router bileşeninin NotFound Şablon parametresinde özel içerik ayarlayın:

<Router AppAssembly="typeof(Startup).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<h1>Sorry</h1>
<p>Sorry, there's nothing at this address.</p> b
</NotFound>
</Router>

<NotFound> etiketlerinin içeriği, diğer etkileşimli bileşenler gibi rastgele öğeler içerebilir. NotFound içeriğe
varsayılan bir düzen uygulamak için bkz. ASP.NET Core Blazor düzenleri.

Birden çok derlemeden bileşenlere rota


Router bileşenin yönlendirilebilir bileşenleri ararken dikkate alınması için ek derlemeler belirtmek üzere
AdditionalAssemblies parametresini kullanın. Belirtilen derlemeler AppAssembly belirtilen derlemeye ek olarak
değerlendirilir. Aşağıdaki örnekte Component1 , başvurulan bir sınıf kitaplığında tanımlanan yönlendirilebilir bir
bileşendir. Aşağıdaki AdditionalAssemblies örnek, Component1 için yönlendirme desteğiyle sonuçlanır:

<Router
AppAssembly="typeof(Program).Assembly"
AdditionalAssemblies="new[] { typeof(Component1).Assembly }">
...
</Router>
Rota parametreleri
Yönlendirici, karşılık gelen bileşen parametrelerini aynı ada (büyük/küçük harfe duyarsız) doldurmak için yol
parametrelerini kullanır:

@page "/RouteParameter"
@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

@code {
[Parameter]
public string Text { get; set; }

protected override void OnInitialized()


{
Text = Text ?? "fantastic";
}
}

ASP.NET Core 3,0 ' deki Blazor uygulamalar için isteğe bağlı parametreler desteklenmez. Önceki örnekte iki
@page yönergesi uygulanır. İlki, bir parametre olmadan bileşene gezinmesine izin verir. İkinci @page yönergesi
{text} Route parametresini alır ve değeri Text özelliğine atar.

Yol kısıtlamaları
Yol kısıtlaması bir yönlendirme segmentinde bir bileşene tür eşleştirmeyi zorlar.
Aşağıdaki örnekte, Users bileşene olan yol yalnızca şu durumlarda eşleşir:
İstek URL 'sinde bir Id yol kesimi var.
Id segmenti bir tamsayıdır ( int ).

@page "/Users/{Id:int}"

<h1>The user Id is @Id!</h1>

@code {
[Parameter]
public int Id { get; set; }
}

Aşağıdaki tabloda gösterilen yol kısıtlamaları mevcuttur. Sabit kültür ile eşleşen yol kısıtlamaları için daha fazla
bilgi için tablonun altındaki uyarıya bakın.

BILMESI
KÜLTÜR
KISITLAMASI ÖRNEK ÖRNEK EŞLEŞMELER EŞLEŞTIRME

bool {active:bool} true , FALSE Hayır

datetime {dob:datetime} 2016-12-31 , Evet


2016-12-31 7:32pm

decimal {price:decimal} 49.99 , -1,000.01 Evet

double {weight:double} 1.234 , -1,001.01e8 Evet


BILMESI
KÜLTÜR
KISITLAMASI ÖRNEK ÖRNEK EŞLEŞMELER EŞLEŞTIRME

float {weight:float} 1.234 , -1,001.01e8 Evet

guid {id:guid} CD2C1638-1638-72D5- Hayır


1638-DEADBEEF1638
,
{CD2C1638-1638-72D5-
1638-DEADBEEF1638}

int {id:int} 123456789 , -123456789 Evet

long {ticks:long} 123456789 , -123456789 Evet

WARNING
URL 'YI doğrulayan ve bir CLR türüne (örneğin int veya DateTime ) dönüştürülen yol kısıtlamaları her zaman sabit kültürü
kullanır. Bu kısıtlamalar, URL 'nin yerelleştirilemeyen olduğunu varsayar.

Noktalar içeren URL 'lerle yönlendirme


Blazor Server uygulamalarında, _Host. cshtml içindeki varsayılan yol / ( @page "/" ). URL bir dosya isteyecek
şekilde göründüğünden, nokta ( . ) içeren bir istek URL 'SI varsayılan yol tarafından eşleşmiyor. Blazor bir
uygulama, var olmayan bir statik dosya için 404 -Found yanıtı döndürür. Bir nokta içeren yolları kullanmak için,
_Host. cshtml 'yi aşağıdaki yol şablonuyla yapılandırın:

@page "/{**path}"

"/{**path}" şablonu şunları içerir:


Ters eğik çizgi ( / ) kodlaması olmadan birden çok klasör sınırlarındaki yolu yakalamak için çift yıldız catch-all
söz dizimi ( ** ).
path Route parametresi adı.

NOTE
Catch-all parametre sözdizimi ( * / ** ) Razor bileşenlerinde ( . Razor ) desteklenmez.

Daha fazla bilgi için bkz. ASP.NET Core yönlendirme.

Gezinti bağlantısı bileşeni


Gezinti bağlantıları oluştururken, HTML köprü öğelerinin yerine bir NavLink bileşeni kullanın ( <a> ). Bir NavLink
bileşeni, href geçerli URL ile eşleşip eşleşmediğini temel alan active CSS sınıfına geçiş yaparken, bir <a> öğesi
gibi davranır. active sınıfı, bir kullanıcının hangi sayfanın etkin sayfa olduğunu anlamasına yardımcı olan gezinti
bağlantıları.
Aşağıdaki NavMenu bileşeni, NavLink bileşenlerinin nasıl kullanılacağını gösteren bir önyükleme gezinti çubuğu
oluşturur:
<div class="@NavMenuCssClass" @onclick="@ToggleNavMenu">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="MyComponent" Match="NavLinkMatch.Prefix">
<span class="oi oi-plus" aria-hidden="true"></span> My Component
</NavLink>
</li>
</ul>
</div>

<NavLink> öğesinin Match özniteliğine atayabilmeniz için iki NavLinkMatch seçeneği vardır:
NavLinkMatch.All – geçerli URL 'nin tamamı eşleştiğinde etkin NavLink .
NavLinkMatch.Prefix (varsayılan) NavLink geçerli URL 'nin herhangi bir ön ekiyle eşleştiğinde etkin –.

Yukarıdaki örnekte, giriş NavLink href="" giriş URL 'siyle eşleşir ve yalnızca uygulamanın varsayılan temel yol
URL 'sindeki active CSS sınıfını alır (örneğin, https://localhost:5001/ ). İkinci NavLink , Kullanıcı MyComponent
ön ekine sahip herhangi bir URL 'YI ziyaret ettiğinde active sınıfını alır (örneğin,
https://localhost:5001/MyComponent ve https://localhost:5001/MyComponent/AnotherSegment ).

Ek NavLink bileşen öznitelikleri, işlenen tutturucu etiketine geçirilir. Aşağıdaki örnekte NavLink bileşeni target
özniteliğini içerir:

<NavLink href="my-page" target="_blank">My page</NavLink>

Aşağıdaki HTML biçimlendirmesi işlenir:

<a href="my-page" target="_blank" rel="noopener noreferrer">My page</a>

URI ve gezinti durumu yardımcıları


Kod içinde C# , URI 'ler ve gezinme ile çalışmak için Microsoft.AspNetCore.Components.NavigationManager kullanın.
NavigationManager , aşağıdaki tabloda gösterilen olay ve yöntemleri sağlar.

ÜYE AÇIKLAMA

Uri Geçerli mutlak URI 'yi alır.

BaseUri Mutlak bir URI oluşturmak için göreli URI yollarına eklenebilir
olan temel URI 'yi (sondaki eğik çizgiyle birlikte) alır. Genellikle
BaseUri , belgenin Wwwroot/index.html (Blazor
WebAssembly) veya Pages/_Host. cshtml (Blazor Server)
içindeki <base> öğesinde href özniteliğine karşılık gelir.

NavigateTo Belirtilen URI 'ye gider. forceLoad true :


İstemci tarafı yönlendirme atlanır.
Bu tarayıcı, URI 'nin normalde istemci tarafı yönlendirici
tarafından işlenip işlenmediğini sunucudan yeni sayfayı
yüklemeye zorlanır.
ÜYE AÇIKLAMA

LocationChanged Gezinti konumu değiştiğinde harekete gelen bir olay.

ToAbsoluteUri Göreli bir URI 'yi mutlak bir URI 'ye dönüştürür.

ToBaseRelativePath Temel URI (örneğin, daha önce GetBaseUri tarafından


döndürülen bir URI) verildiğinde, mutlak bir URI 'yi taban URI
ön ekine göre bir URI 'ye dönüştürür.

Aşağıdaki bileşen, düğme seçildiğinde uygulamanın Counter bileşenine gider:

@page "/navigate"
@inject NavigationManager NavigationManager

<h1>Navigate in Code Example</h1>

<button class="btn btn-primary" @onclick="NavigateToCounterComponent">


Navigate to the Counter component
</button>

@code {
private void NavigateToCounterComponent()
{
NavigationManager.NavigateTo("counter");
}
}
ASP.NET Core Blazor JavaScript birlikte çalışabilirliği
9.12.2019 • 23 minutes to read • Edit Online

Sağlayan Javier Calvarro Nelson, Daniel Rothve Luke Latham

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor bir uygulama, JavaScript kodundan .NET ve .NET yöntemlerinden JavaScript işlevlerini çağırabilir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

.NET metotlarından JavaScript işlevlerini çağırma


Bir JavaScript işlevini çağırmak için .NET kodunun gerekli olduğu durumlar vardır. Örneğin, JavaScript çağrısı,
tarayıcı özelliklerini veya bir JavaScript kitaplığından uygulamaya yönelik işlevselliği sunabilir. Bu senaryoya
JavaScript birlikte çalışabilirliği (js birlikte çalışma) denir.
.NET 'ten JavaScript 'i çağırmak için IJSRuntime soyutlamasını kullanın. InvokeAsync<T> yöntemi, herhangi bir
sayıda JSON seri hale getirilebilir bağımsız değişkenle birlikte çağırmak istediğiniz JavaScript işlevi için bir
tanımlayıcı alır. İşlev tanımlayıcısı, genel kapsama ( window ) göredir. window.someScope.someFunction çağırmak
isterseniz, tanımlayıcı someScope.someFunction . Çağrılmadan önce işlevi kaydetmeniz gerekmez. Dönüş türü T
ayrıca seri hale getirilebilir JSON olmalıdır. T , döndürülen JSON türüyle en iyi eşleşen .NET türüyle
eşleşmelidir.
Blazor Server uygulamaları için:
Blazor sunucusu uygulaması tarafından birden çok kullanıcı isteği işlenir. JavaScript işlevlerini çağırmak için
bir bileşende JSRuntime.Current çağırmayın.
IJSRuntime soyutlamasını ekler ve bu nesneyi kullanarak JS birlikte çalışma çağrıları verme.
Blazor bir uygulama prerendering olduğunda, tarayıcıyla bir bağlantı kurulmadığından JavaScript 'e çağrı
yapılamaz. Daha fazla bilgi için, Blazor bir uygulamanın ne zaman prerendering olduğunu Algıla bölümüne
bakın.
Aşağıdaki örnek, deneysel bir JavaScript tabanlı kod çözücüsü olan Textdecodertabanlıdır. Örnek, bir C#
yöntemden JavaScript işlevinin nasıl çağrılacağını gösterir. JavaScript işlevi bir C# yöntemden bir bayt dizisi
kabul eder, dizinin kodunu çözer ve görüntülenecek metni bileşene döndürür.
Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesi içinde,
geçirilen bir dizinin kodunu çözmek Için TextDecoder kullanan bir JavaScript işlevi sağlayın ve kodu çözülen
değeri döndürün:
<script>
window.convertArray = (win1251Array) => {
var win1251decoder = new TextDecoder('windows-1251');
var bytes = new Uint8Array(win1251Array);
var decodedArray = win1251decoder.decode(bytes);
console.log(decodedArray);
return decodedArray;
};
</script>

Önceki örnekte gösterilen kod gibi JavaScript kodu, betik dosyasına yönelik bir başvuruya sahip bir JavaScript
dosyasından ( . js) de yüklenebilir:

<script src="exampleJsInterop.js"></script>

Aşağıdaki bileşen:
Bir bileşen düğmesi (diziyi Dönüştür) seçildiğinde JSRuntime kullanarak convertArray JavaScript işlevini
çağırır.
JavaScript işlevi çağrıldıktan sonra, geçirilen dizi bir dizeye dönüştürülür. Dize, görüntüleme için bileşene
döndürülür.
@page "/call-js-example"
@inject IJSRuntime JSRuntime;

<h1>Call JavaScript Function Example</h1>

<button type="button" class="btn btn-primary" @onclick="ConvertArray">


Convert Array
</button>

<p class="mt-2" style="font-size:1.6em">


<span class="badge badge-success">
@ConvertedText
</span>
</p>

@code {
// Quote (c)2005 Universal Pictures: Serenity
// https://www.uphe.com/movies/serenity
// David Krumholtz on IMDB: https://www.imdb.com/name/nm0472710/

private MarkupString ConvertedText =


new MarkupString("Select the <b>Convert Array</b> button.");

private uint[] QuoteArray = new uint[]


{
60, 101, 109, 62, 67, 97, 110, 39, 116, 32, 115, 116, 111, 112, 32,
116, 104, 101, 32, 115, 105, 103, 110, 97, 108, 44, 32, 77, 97,
108, 46, 60, 47, 101, 109, 62, 32, 45, 32, 77, 114, 46, 32, 85, 110,
105, 118, 101, 114, 115, 101, 10, 10,
};

private async Task ConvertArray()


{
var text =
await JSRuntime.InvokeAsync<string>("convertArray", QuoteArray);

ConvertedText = new MarkupString(text);

StateHasChanged();
}
}

IJSRuntime kullanımı
IJSRuntime soyutlamasını kullanmak için aşağıdaki yaklaşımlardan birini benimseyin:
IJSRuntime soyutlama Razor bileşenine ( . Razor) ekleme:

@inject IJSRuntime JSRuntime

@code {
protected override void OnInitialized()
{
StocksService.OnStockTickerUpdated += stockUpdate =>
{
JSRuntime.InvokeVoidAsync("handleTickerChanged",
stockUpdate.symbol, stockUpdate.price);
};
}
}

Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesinin
Içinde, bir handleTickerChanged JavaScript işlevi sağlayın. İşlevi IJSRuntime.InvokeVoidAsync ile çağrılır ve
bir değer döndürmez:

<script>
window.handleTickerChanged = (symbol, price) => {
// ... client-side processing/display code ...
};
</script>

IJSRuntime soyutlamasını bir sınıfa ( . cs) Ekle:

public class JsInteropClasses


{
private readonly IJSRuntime _jsRuntime;

public JsInteropClasses(IJSRuntime jsRuntime)


{
_jsRuntime = jsRuntime;
}

public ValueTask<string> TickerChanged(string data)


{
return _jsRuntime.InvokeAsync<string>(
"handleTickerChanged",
stockUpdate.symbol,
stockUpdate.price);
}
}

Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor Server) <head> öğesinin
Içinde, bir handleTickerChanged JavaScript işlevi sağlayın. İşlevi JSRuntime.InvokeAsync ile çağrılır ve bir
değer döndürür:

<script>
window.handleTickerChanged = (symbol, price) => {
// ... client-side processing/display code ...
return 'Done!';
};
</script>

Buildrendertreeile dinamik içerik oluşturma için [Inject] özniteliğini kullanın:

[Inject]
IJSRuntime JSRuntime { get; set; }

Bu konuya eşlik eden istemci tarafı örnek uygulamada, Kullanıcı girişi almak ve bir hoş geldiniz iletisi göstermek
üzere DOM ile etkileşime geçen uygulama için iki JavaScript işlevi mevcuttur:
showPrompt – Kullanıcı girişini kabul etmek için bir istem üretir (kullanıcının adı) ve çağıranın adını döndürür.
displayWelcome –, çağıran bir id welcome bir DOM nesnesine bir hoş geldiniz iletisi atar.

Wwwroot/Examplejsınterop. js:
window.exampleJsFunctions = {
showPrompt: function (text) {
return prompt(text, 'Type your name here');
},
displayWelcome: function (welcomeMessage) {
document.getElementById('welcome').innerText = welcomeMessage;
},
returnArrayAsyncJs: function () {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
data.push(4);
console.log(data);
});
},
sayHello: function (dotnetHelper) {
return dotnetHelper.invokeMethodAsync('SayHello')
.then(r => console.log(r));
}
};

JavaScript dosyasına başvuran <script> etiketini Wwwroot/index.html dosyasında (Blazor WebAssembly) veya
Pages/_Host. cshtml dosyasında (Blazor Server) yerleştirin.
Wwwroot/index.html (Blazor WebAssembly):

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Blazor WebAssembly Sample</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/site.css" rel="stylesheet" />
</head>

<body>
<app>Loading...</app>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss"> </a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="exampleJsInterop.js"></script>
</body>

</html>

Pages/_Host. cshtml (Blazor sunucusu):


@page "/"
@namespace BlazorSample.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Blazor Server Sample</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</app>

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss"> </a>
</div>

<script src="_framework/blazor.server.js"></script>
<script src="exampleJsInterop.js"></script>
</body>
</html>

<script> etiketi dinamik olarak güncelleştirilemediğinden bir <script> etiketini bileşen dosyasına
yerleştirmeyin.
.NET yöntemleri, IJSRuntime.InvokeAsync<T> çağırarak Examplejsınterop. js dosyasında JavaScript işlevleriyle
birlikte çalışır.
IJSRuntime soyutlama, Blazor sunucu senaryolarına izin vermek için zaman uyumsuzdur. Uygulama bir Blazor
Weelsembly uygulaması ise ve bir JavaScript işlevini zaman uyumlu olarak çağırmak istiyorsanız,
IJSInProcessRuntime ve bunun yerine Invoke<T> çağırın. Çoğu JS birlikte çalışma kitaplıklarının, kitaplıkların
tüm senaryolarda kullanılabilir olmasını sağlamak için zaman uyumsuz API 'Leri kullanmasını öneririz.
Örnek uygulama, JS birlikte çalışabilirliği göstermek için bir bileşeni içerir. Bileşen:
Bir JavaScript istemi aracılığıyla Kullanıcı girişini alır.
İşlemek için bileşene metni döndürür.
Bir hoş geldiniz iletisini göstermek için DOM ile etkileşime sahip ikinci bir JavaScript işlevini çağırır.
Pages/Jsınterop. Razor:
@page "/JSInterop"
@using BlazorSample.JsInteropClasses
@inject IJSRuntime JSRuntime

<h1>JavaScript Interop</h1>

<h2>Invoke JavaScript functions from .NET methods</h2>

<button type="button" class="btn btn-primary" @onclick="TriggerJsPrompt">


Trigger JavaScript Prompt
</button>

<h3 id="welcome" style="color:green;font-style:italic"></h3>

@code {
public async Task TriggerJsPrompt()
{
// showPrompt is implemented in wwwroot/exampleJsInterop.js
var name = await JSRuntime.InvokeAsync<string>(
"exampleJsFunctions.showPrompt",
"What's your name?");
// displayWelcome is implemented in wwwroot/exampleJsInterop.js
await JSRuntime.InvokeVoidAsync(
"exampleJsFunctions.displayWelcome",
$"Hello {name}! Welcome to Blazor!");
}
}

1. TriggerJsPrompt , bileşenin tetikleyicisi JavaScript istem düğmesi seçilerek yürütüldüğünde,


Wwwroot/Examplejsınterop. js dosyasında verilen JavaScript showPrompt işlevi çağırılır.
2. showPrompt işlevi, HTML kodlu ve bileşene döndürülen kullanıcı girişini (kullanıcının adı) kabul eder. Bileşen,
kullanıcının adını name yerel bir değişkende depolar.
3. name depolanan dize, hoş geldiniz iletisini bir başlık etiketine işleyen displayWelcome bir JavaScript işlevine
iletilen bir hoş geldiniz iletisine dahil edilir.

Void JavaScript işlevini çağırın


Void (0)/void 0 veya undefined döndüren JavaScript işlevleri IJSRuntime.InvokeVoidAsync ile çağırılır.

Blazor bir uygulamanın ne zaman prerendering olduğunu Algıla


Blazor sunucu uygulaması prerendering olduğunda, tarayıcıyla bir bağlantı kurulmadığından, JavaScript 'e
çağırma gibi bazı eylemler mümkün değildir. Bileşenler, ön işlenmiş olduğunda farklı şekilde işlenmesi
gerekebilir.
Tarayıcı bağlantısı kurulana kadar JavaScript birlikte çalışma çağrılarını geciktirmek için Onafterrenderasync
bileşen yaşam döngüsü olayınıkullanabilirsiniz. Bu olay yalnızca uygulama tam olarak işlendikten ve istemci
bağlantısı kurulduktan sonra çağırılır.
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div @ref="divElement">Text during render</div>

@code {
private ElementReference divElement;

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync(
"setElementText", divElement, "Text after render");
}
}
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor
Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın. İşlevi IJSRuntime.InvokeVoidAsync ile
çağrılır ve bir değer döndürmez:

<script>
window.setElementText = (element, text) => element.innerText = text;
</script>

WARNING
Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir. JavaScript, Blazor 'in değişiklik izlemesini
kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.

Aşağıdaki bileşen, prerendering ile uyumlu bir şekilde bileşenin başlatma mantığının bir parçası olarak
JavaScript birlikte çalışabilirinin nasıl kullanılacağını göstermektedir. Bileşeni, OnAfterRenderAsync içinden bir
işleme güncelleştirmesi tetiklemenin mümkün olduğunu gösterir. Geliştirici Bu senaryoda sonsuz bir döngü
oluşturmaktan kaçınmalıdır.
JSRuntime.InvokeAsync çağrıldığında, bileşen işlenene kadar hiçbir JavaScript öğesi olmadığından, ElementRef
yalnızca OnAfterRenderAsync için kullanılır ve daha önceki bir yaşam döngüsü yönteminde değil.
JavaScript birlikte çalışma çağrısından alınan yeni durumla birlikte bileşeni yeniden sağlamak için
Statehaschanged çağrılır. StateHasChanged yalnızca infoFromJs null olduğunda çağrıldığı için, kod sonsuz bir
döngü oluşturmaz.
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<p>
Get value via JS interop call:
<strong id="val-get-by-interop">@(infoFromJs ?? "No value yet")</strong>
</p>

Set value via JS interop call:


<div id="val-set-by-interop" @ref="divElement"></div>

@code {
private string infoFromJs;
private ElementReference divElement;

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender && infoFromJs == null)
{
infoFromJs = await JSRuntime.InvokeAsync<string>(
"setElementText", divElement, "Hello from interop call!");

StateHasChanged();
}
}
}

Yukarıdaki örnek kod için, Wwwroot/index.html (Blazor WebAssembly) veya Pages/_Host. cshtml (Blazor
Server) <head> öğesi içinde bir setElementText JavaScript işlevi sağlayın. İşlevi IJSRuntime.InvokeAsync ile
çağrılır ve bir değer döndürür:

<script>
window.setElementText = (element, text) => {
element.innerText = text;
return text;
};
</script>

WARNING
Yukarıdaki örnek yalnızca tanıtım amacıyla Belge Nesne Modeli (DOM) değiştirir. JavaScript, Blazor 'in değişiklik izlemesini
kesintiye uğradığı için çoğu senaryoda, JavaScript ile DOM 'ı doğrudan değiştirme önerilmez.

Öğelere başvuruları yakala


Bazı JS birlikte çalışma senaryoları HTML öğelerine başvurular gerektirir. Örneğin, bir kullanıcı arabirimi
kitaplığı başlatma için bir öğe başvurusu gerektirebilir veya focus veya play gibi bir öğe üzerinde komut
benzeri API 'Ler çağırmanız gerekebilir.
Aşağıdaki yaklaşımı kullanarak bir bileşen içindeki HTML öğelerine başvuruları yakalayın:
HTML öğesine bir @ref özniteliği ekleyin.
Adı @ref özniteliği değeri ile eşleşen ElementReference türünde bir alan tanımlayın.
Aşağıdaki örnek, username <input> öğesine bir başvuru yakalama göstermektedir:
<input @ref="username" ... />

@code {
ElementReference username;
}

WARNING
Yalnızca Blazoretkileşimde bulunmayan boş bir öğenin içeriğini bulunmamalıdır için bir öğe başvurusu kullanın. Bu senaryo,
bir 3. taraf API 'SI öğeye içerik sağladığı zaman yararlıdır. Blazor öğesiyle etkileşmediği için, Blazoröğesi ve DOM gösterimi
arasında bir çakışma olabilir.
Aşağıdaki örnekte, Blazor, bu öğenin liste öğelerini ( <li> ) doldurmak üzere DOM ile etkileşimde bulunduğundan,
sıralanmamış listenin ( ul ) içeriğini () zaman zaman aşmaktır .

<ul ref="MyList">
@foreach (var item in Todos)
{
<li>@item.Text</li>
}
</ul>

JS birlikte çalışma öğesi, öğe MyList içeriğini değiştiriyorsa ve Blazor SLA 'ya uygulamaya çalışırsa, diffler DOM ile
eşleşmez.

.NET kodu açısından düşünüldüğünde, ElementReference donuk bir tanıtıcıdır. ElementReference ile
yapabileceğiniz tek şey, JS birlikte çalışma yoluyla JavaScript koduna geçiş yapar. Bunu yaptığınızda, JavaScript
tarafı kodu normal DOM API 'Leri ile kullanılabilecek bir HTMLElement örneğini alır.
Örneğin, aşağıdaki kod bir öğe üzerinde odağı ayarlamaya izin veren bir .NET genişletme yöntemi tanımlar:
Examplejsınterop. js:

window.exampleJsFunctions = {
focusElement : function (element) {
element.focus();
}
}

Değer döndürmeyen bir JavaScript işlevini çağırmak için IJSRuntime.InvokeVoidAsync kullanın. Aşağıdaki kod,
yakalanan ElementReference önceki JavaScript işlevini çağırarak Kullanıcı adı girişi üzerinde odağı ayarlar:

@inject IJSRuntime JSRuntime

<input @ref="username" />


<button @onclick="SetFocus">Set focus on username</button>

@code {
private ElementReference username;

public async Task SetFocus()


{
await JSRuntime.InvokeVoidAsync(
"exampleJsFunctions.focusElement", username);
}
}

Bir genişletme yöntemi kullanmak için IJSRuntime örneğini alan bir statik genişletme yöntemi oluşturun:
public static async Task Focus(this ElementReference elementRef, IJSRuntime jsRuntime)
{
await jsRuntime.InvokeVoidAsync(
"exampleJsFunctions.focusElement", elementRef);
}

Focus yöntemi doğrudan nesne üzerinde çağrılır. Aşağıdaki örnek, Focus yönteminin JsInteropClasses ad
alanından kullanılabildiğini varsayar:

@inject IJSRuntime JSRuntime


@using JsInteropClasses

<input @ref="username" />


<button @onclick="SetFocus">Set focus on username</button>

@code {
private ElementReference username;

public async Task SetFocus()


{
await username.Focus(JSRuntime);
}
}

IMPORTANT
username değişkeni yalnızca bileşen işlendikten sonra doldurulur. Doldurulmamış bir ElementReference JavaScript
koduna geçirilirse, JavaScript kodu bir null değeri alır. Bileşen işlemeyi tamamladıktan sonra öğe başvurularını
değiştirmek için (bir öğe üzerinde ilk odağı ayarlamak için) Onafterrenderasync veya OnAfterRender bileşen yaşam
döngüsü yöntemlerinikullanın.

Genel türlerle çalışırken ve bir değer döndürürken, Valuetask<t >kullanın:

public static ValueTask<T> GenericMethod<T>(this ElementReference elementRef,


IJSRuntime jsRuntime)
{
return jsRuntime.InvokeAsync<T>(
"exampleJsFunctions.doSomethingGeneric", elementRef);
}

GenericMethod doğrudan nesne üzerinde bir tür ile çağırılır. Aşağıdaki örnek, GenericMethod JsInteropClasses
ad alanından kullanılabilir olduğunu varsayar:
@inject IJSRuntime JSRuntime
@using JsInteropClasses

<input @ref="username" />


<button @onclick="OnClick">Do something generic</button>

<p>
returnValue: @returnValue
</p>

@code {
private ElementReference username;
private string returnValue;

private async Task OnClick()


{
returnValue = await username.GenericMethod<string>(JSRuntime);
}
}

JavaScript işlevlerinden .NET yöntemlerini çağır


Statik .NET yöntemi çağrısı
JavaScript 'ten statik bir .NET yöntemi çağırmak için DotNet.invokeMethod veya DotNet.invokeMethodAsync
işlevlerini kullanın. Çağırmak istediğiniz statik metodun tanımlayıcısını, işlevi içeren derlemenin adını ve tüm
bağımsız değişkenleri geçirin. Blazor sunucu senaryolarını desteklemek için zaman uyumsuz sürüm tercih edilir.
JavaScript 'ten bir .NET yöntemi çağırmak için, .NET yönteminin public, static ve [JSInvokable] özniteliğine
sahip olması gerekir. Varsayılan olarak, yöntem tanımlayıcısı yöntem adıdır, ancak JSInvokableAttribute
oluşturucusunu kullanarak farklı bir tanımlayıcı belirtebilirsiniz. Açık genel yöntemlerin çağrılması Şu anda
desteklenmiyor.
Örnek uygulama, int s C# dizisini döndürmek için bir yöntem içerir. JSInvokable özniteliği yöntemine
uygulanır.
Pages/Jsınterop. Razor:

<button type="button" class="btn btn-primary"


onclick="exampleJsFunctions.returnArrayAsyncJs()">
Trigger .NET static method ReturnArrayAsync
</button>

@code {
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}
}

İstemciye sunulan JavaScript, C# .net yöntemini çağırır.


Wwwroot/Examplejsınterop. js:
window.exampleJsFunctions = {
showPrompt: function (text) {
return prompt(text, 'Type your name here');
},
displayWelcome: function (welcomeMessage) {
document.getElementById('welcome').innerText = welcomeMessage;
},
returnArrayAsyncJs: function () {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
data.push(4);
console.log(data);
});
},
sayHello: function (dotnetHelper) {
return dotnetHelper.invokeMethodAsync('SayHello')
.then(r => console.log(r));
}
};

Tetikleyici .net static yöntemi ReturnArrayAsync düğmesi seçildiğinde, tarayıcının Web geliştirici
araçlarında konsol çıkışını inceleyin.
Konsol çıktısı:

Array(4) [ 1, 2, 3, 4 ]

Dördüncü dizi değeri, ReturnArrayAsync tarafından döndürülen diziye ( data.push(4); ) gönderilir.


Örnek yöntem çağrısı
JavaScript 'ten de .NET örnek yöntemlerini çağırabilirsiniz. JavaScript 'ten bir .NET örnek yöntemi çağırmak için:
.NET örneğini bir DotNetObjectReference örneğine sarmalayarak JavaScript 'e geçirin. .NET örneği,
JavaScript 'e başvuruya göre geçirilir.
invokeMethod veya invokeMethodAsync işlevlerini kullanarak örnekte .NET örnek yöntemlerini çağırın. .NET
örneği, JavaScript 'ten başka .NET yöntemleri çağrılırken bir bağımsız değişken olarak da geçirilebilir.

NOTE
Örnek uygulama, iletileri istemci tarafı konsoluna kaydeder. Örnek uygulama tarafından gösterilen aşağıdaki örnekler için
tarayıcının geliştirici araçlarında tarayıcının konsol çıkışını inceleyin.

Tetikleyici .NET örnek yöntemi HelloHelper. SayHello düğmesi seçildiğinde,


ExampleJsInterop.CallHelloHelperSayHello çağrılır ve Blazor bir adı yöntemine geçirir.

Pages/Jsınterop. Razor:

<button type="button" class="btn btn-primary" @onclick="TriggerNetInstanceMethod">


Trigger .NET instance method HelloHelper.SayHello
</button>

@code {
public async Task TriggerNetInstanceMethod()
{
var exampleJsInterop = new ExampleJsInterop(JSRuntime);
await exampleJsInterop.CallHelloHelperSayHello("Blazor");
}
}
CallHelloHelperSayHello , JavaScript işlevini sayHello yeni bir HelloHelper örneğiyle çağırır.
JsInteropClasses/Examplejsınterop. cs:

public class ExampleJsInterop


{
private readonly IJSRuntime _jsRuntime;

public ExampleJsInterop(IJSRuntime jsRuntime)


{
_jsRuntime = jsRuntime;
}

public ValueTask<string> CallHelloHelperSayHello(string name)


{
// sayHello is implemented in wwwroot/exampleJsInterop.js
return _jsRuntime.InvokeAsync<string>(
"exampleJsFunctions.sayHello",
DotNetObjectReference.Create(new HelloHelper(name)));
}
}

Wwwroot/Examplejsınterop. js:

window.exampleJsFunctions = {
showPrompt: function (text) {
return prompt(text, 'Type your name here');
},
displayWelcome: function (welcomeMessage) {
document.getElementById('welcome').innerText = welcomeMessage;
},
returnArrayAsyncJs: function () {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
data.push(4);
console.log(data);
});
},
sayHello: function (dotnetHelper) {
return dotnetHelper.invokeMethodAsync('SayHello')
.then(r => console.log(r));
}
};

Ad, HelloHelper.Name özelliğini ayarlayan HelloHelper oluşturucusuna geçirilir. JavaScript işlevi sayHello
yürütüldüğünde, HelloHelper.SayHello JavaScript işlevi tarafından konsola yazılan Hello, {Name}! iletisi
döndürür.
JsInteropClasses/HelloHelper. cs:

public class HelloHelper


{
public HelloHelper(string name)
{
Name = name;
}

public string Name { get; set; }

[JSInvokable]
public string SayHello() => $"Hello, {Name}!";
}
Tarayıcının Web geliştirici araçlarında konsol çıkışı:

Hello, Blazor!

Birlikte çalışma kodunu bir sınıf kitaplığında paylaşma


JS birlikte çalışma kodu bir NuGet paketindeki kodu paylaşmanıza olanak sağlayan bir sınıf kitaplığına dahil
edilebilir.
Sınıf kitaplığı, yerleşik derlemede JavaScript kaynaklarını katıştırmayı işler. JavaScript dosyaları Wwwroot
klasörüne yerleştirilir. Araç, kitaplık oluşturulduğunda kaynakları katıştırmaya önem kazanır.
Oluşturulan NuGet paketine, uygulamanın proje dosyasında herhangi bir NuGet paketiyle aynı şekilde
başvurulur. Paket geri yüklendikten sonra, uygulama kodu JavaScript 'e, gibi çağrı yapabilir C#.
Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenleri sınıf kitaplıkları.

Harden JS birlikte çalışma çağrıları


JS birlikte çalışması, ağ hataları nedeniyle başarısız olabilir ve güvenilmez olarak değerlendirilmelidir. Varsayılan
olarak, bir Blazor sunucusu uygulaması, bir dakika sonra sunucu üzerinde JS birlikte çalışabilirlik çağrılarını
zaman aşımına uğrar. Bir uygulama, 10 saniye gibi daha agresif zaman aşımına uğrayedebilmesine, aşağıdaki
yaklaşımlardan birini kullanarak zaman aşımını ayarlayın:
Startup.ConfigureServices genel olarak, zaman aşımını belirtin:

services.AddServerSideBlazor(
options => options.JSInteropDefaultCallTimeout = TimeSpan.FromSeconds({SECONDS}));

Bileşen kodunda çağrı başına, tek bir çağrı zaman aşımını belirtebilir:

var result = await JSRuntime.InvokeAsync<string>("MyJSOperation",


TimeSpan.FromSeconds({SECONDS}), new[] { "Arg1" });

Kaynak tükenmesi hakkında daha fazla bilgi için bkz. Güvenli ASP.NET Core Blazor Server uygulamaları.

Ek kaynaklar
InteropComponent. Razor örneği (ASPNET/AspNetCore GitHub deposu, 3,0 yayın dalı)
ASP.NET Core Blazor kimlik doğrulaması ve
yetkilendirme
9.12.2019 • 18 minutes to read • Edit Online

Steve Sanderson tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

ASP.NET Core, Blazor uygulamalardaki güvenlik yapılandırmasını ve yönetimini destekler.


Güvenlik senaryoları Blazor Server ve WebAssembly Apps Blazor farklıdır. Blazor sunucu uygulamaları sunucuda
çalıştığından, yetkilendirme denetimleri şunları tespit edebilir:
Kullanıcıya sunulan kullanıcı ARABIRIMI seçenekleri (örneğin, bir kullanıcı için hangi menü girişlerinin
kullanılabildiği).
Uygulama ve bileşenlerin bölgeleri için erişim kuralları.
Blazor WebAssembly uygulamaları istemcide çalışır. Yetkilendirme yalnızca hangi kullanıcı arabirimi seçeneklerinin
gösterileceğini belirlemede kullanılır. İstemci tarafı denetimleri bir kullanıcı tarafından değiştirililerek veya
atlandığından, bir Blazor WebAssembly uygulaması yetkilendirme erişim kurallarını zorunlu kılamaz.

Kimlik Doğrulama
Blazor, kullanıcının kimliğini kurmak için mevcut ASP.NET Core kimlik doğrulama mekanizmalarını kullanır. Tam
mekanizma Blazor uygulamasının nasıl barındırıldığını, Blazor sunucunun veya Blazor WebAssembly ' ne bağlıdır.
Blazor sunucusu kimlik doğrulaması
Blazor Server Apps, SignalRkullanılarak oluşturulan gerçek zamanlı bir bağlantı üzerinden çalışır. SignalRtabanlı
uygulamalarda kimlik doğrulaması , bağlantı oluşturulduğunda işlenir. Kimlik doğrulaması, bir tanımlama bilgisine
veya başka bir taşıyıcı belirtecine dayalı olabilir.
Blazor sunucusu proje şablonu, proje oluşturulduğunda kimlik doğrulamasını sizin için ayarlayabilir.
Visual Studio
Visual Studio Code
Kimlik doğrulama mekanizmasına sahip yeni bir Blazor sunucu projesi oluşturmak için ASP.NET Core Blazor
kullanmaya başlama makalesindeki Visual Studio kılavuzunu izleyin.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda Blazor sunucusu uygulama şablonunu
seçtikten sonra, kimlik doğrulamasıaltında Değiştir ' i seçin.
Diğer ASP.NET Core projelerine yönelik aynı kimlik doğrulama mekanizması kümesini sunmak için bir iletişim
kutusu açılır:
Kimlik doğrulaması yok
Kullanıcı hesaplarının – bireysel kullanıcı hesapları depolanabilir:
ASP.NET Core kimlik sistemini kullanarak uygulama içinde.
Azure AD B2C.
İş veya okul hesapları
Windows Kimlik Doğrulaması
Blazor WebAssembly kimlik doğrulaması
Blazor WebAssembly uygulamalarında, tüm istemci tarafı kodlar kullanıcılar tarafından değiştirilemediği için kimlik
doğrulama denetimleri atlanabilir. Aynı, JavaScript SPA çerçeveleri veya herhangi bir işletim sistemi için yerel
uygulamalar dahil olmak üzere tüm istemci tarafı uygulama teknolojileri için de geçerlidir.
Uygulamanın proje dosyasına Microsoft. AspNetCore. components. Authorization için bir paket başvurusu ekleyin.
Blazor WebAssembly uygulamaları için özel bir AuthenticationStateProvider hizmeti uygulaması aşağıdaki
bölümlerde ele alınmıştır.

AuthenticationStateProvider hizmeti
Blazor Server uygulamaları ASP.NET Core HttpContext.User kimlik doğrulama durumu verilerini alan yerleşik bir
AuthenticationStateProvider hizmeti içerir. Kimlik doğrulama durumu, mevcut ASP.NET Core sunucu tarafı kimlik
doğrulama mekanizmalarıyla tümleştirilir.
AuthenticationStateProvider , kimlik doğrulama durumunu almak için AuthorizeView bileşeni ve
CascadingAuthenticationState bileşeni tarafından kullanılan temel hizmettir.

Genellikle AuthenticationStateProvider doğrudan kullanmazsınız. Bu makalenin ilerleyen kısımlarında açıklanan


Authorizeview bileşenini veya görev yaklaşımlarını kullanın. AuthenticationStateProvider doğrudan kullanmanın
ana dezavantajı, temeldeki kimlik doğrulama durumu verileri değişirse bileşen tarafından otomatik olarak
bildirilmemektedir.
AuthenticationStateProvider hizmeti, aşağıdaki örnekte gösterildiği gibi geçerli kullanıcının ClaimsPrincipal
verilerini sağlayabilir:

@page "/"
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<button @onclick="@LogUsername">Write user info to console</button>

@code {
private async Task LogUsername()
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;

if (user.Identity.IsAuthenticated)
{
Console.WriteLine($"{user.Identity.Name} is authenticated.");
}
else
{
Console.WriteLine("The user is NOT authenticated.");
}
}
}

user.Identity.IsAuthenticated true ve Kullanıcı bir ClaimsPrincipalolduğundan, talepler, değerlendirilen rollerde


numaralandırılabilir ve üyelik yapılabilir.
Bağımlılık ekleme (dı) ve hizmetleri hakkında daha fazla bilgi için bkz. ASP.NET Core Blazor bağımlılığı ekleme ve
ASP.NET Core bağımlılık ekleme.
Özel bir AuthenticationStateProvider uygulama
Blazor WebAssembly uygulaması oluşturuyorsanız veya uygulamanızın belirtimi kesinlikle özel bir sağlayıcı
gerektiriyorsa, bir sağlayıcı uygulayın ve GetAuthenticationStateAsync geçersiz kılın:

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;

namespace BlazorSample.Services
{
public class CustomAuthStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "mrfibuli"),
}, "Fake authentication type");

var user = new ClaimsPrincipal(identity);

return Task.FromResult(new AuthenticationState(user));


}
}
}

CustomAuthStateProvider hizmeti Startup.ConfigureServices kaydedilir:

// using Microsoft.AspNetCore.Components.Authorization;
// using BlazorSample.Services;

services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();

CustomAuthStateProvider kullanarak, tüm kullanıcıların Kullanıcı adı mrfibuli kimlik doğrulaması yapılır.

Kimlik doğrulama durumunu basamaklı bir parametre olarak kullanıma


sunma
Kullanıcı tarafından tetiklenen bir eylem gerçekleştirirken olduğu gibi, yordamsal mantık için kimlik doğrulama
durumu verileri gerekliyse, Task<AuthenticationState> türünde bir geçişli parametre tanımlayarak kimlik doğrulama
durumu verilerini alın:
@page "/"

<button @onclick="@LogUsername">Log username</button>

@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }

private async Task LogUsername()


{
var authState = await authenticationStateTask;
var user = authState.User;

if (user.Identity.IsAuthenticated)
{
Console.WriteLine($"{user.Identity.Name} is authenticated.");
}
else
{
Console.WriteLine("The user is NOT authenticated.");
}
}
}

NOTE
Blazor WebAssembly uygulama bileşeninde, Microsoft.AspNetCore.Components.Authorization ad alanını (
@using Microsoft.AspNetCore.Components.Authorization ) ekleyin.

user.Identity.IsAuthenticated true , talepler numaralandırılabilir ve değerlendirilen rollerde üyeliğe eklenebilir.


App. Razor dosyasındaki AuthorizeRouteView ve CascadingAuthenticationState bileşenlerini kullanarak
Task<AuthenticationState> geçişli parametreyi ayarlayın:

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>

Yetkilendirme
Bir kullanıcının kimliği doğrulandıktan sonra, kullanıcının neler yapabileceğini denetlemek için Yetkilendirme
kuralları uygulanır.
Erişim, genellikle aşağıdakileri yapıp verilmeksizin verilir veya reddedilir:
Bir kullanıcının kimliği doğrulanır (oturum açıldı).
Bir Kullanıcı bir roldür.
Bir kullanıcının talebivardır.
Bir ilke karşılandı.
Bu kavramların her biri, ASP.NET Core MVC veya Razor Pages uygulamasındaki ile aynıdır. ASP.NET Core
güvenliği hakkında daha fazla bilgi için, ASP.NET Core güvenlik ve kimlik' in altındaki makalelere bakın.

AuthorizeView bileşeni
AuthorizeView bileşeni, kullanıcının onu görme yetkisine sahip olup olmadığına bağlı olarak Kullanıcı
ARABIRIMINI seçmeli olarak görüntüler. Bu yaklaşım yalnızca Kullanıcı için veri görüntülemesi gerektiğinde ve
Kullanıcı kimliğini yordamsal mantığda kullanmanıza gerek olmadığında yararlıdır.
Bileşeni, oturum açmış kullanıcıyla ilgili bilgilere erişmek için kullanabileceğiniz AuthenticationState türünde bir
context değişkeni kullanıma sunar:

<AuthorizeView>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

Kullanıcının kimliği doğrulanmadıysa, görüntülenmek üzere farklı içerikler de sağlayabilirsiniz:

<AuthorizeView>
<Authorized>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you're authenticated.</p>
</Authorized>
<NotAuthorized>
<h1>Authentication Failure!</h1>
<p>You're not signed in.</p>
</NotAuthorized>
</AuthorizeView>

<Authorized> ve <NotAuthorized> etiketlerinin içeriği, diğer etkileşimli bileşenler gibi rastgele öğeler içerebilir.
Kullanıcı arabirimi seçeneklerini veya erişimini denetleyen roller veya ilkeler gibi yetkilendirme koşulları,
Yetkilendirme bölümünde ele alınmıştır.
Yetkilendirme koşulları belirtilmemişse, AuthorizeView varsayılan bir ilke kullanır ve şu şekilde davranır:
Kimliği doğrulanmış (oturum açmış) kullanıcılar yetkili olarak.
Kimliği doğrulanmamış (oturumu açılmış) kullanıcılar yetkilendirilmemiş.
Rol tabanlı ve ilke tabanlı yetkilendirme
AuthorizeView bileşeni rol tabanlı veya ilke tabanlı yetkilendirmeyi destekler.

Rol tabanlı yetkilendirme için Roles parametresini kullanın:

<AuthorizeView Roles="admin, superuser">


<p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

Daha fazla bilgi için bkz. ASP.NET Core rol tabanlı yetkilendirme.
İlke tabanlı yetkilendirme için Policy parametresini kullanın:

<AuthorizeView Policy="content-editor">
<p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>
Talep tabanlı yetkilendirme, ilke tabanlı yetkilendirme için özel bir durumdur. Örneğin, kullanıcıların belirli bir talebe
sahip olmasını gerektiren bir ilke tanımlayabilirsiniz. Daha fazla bilgi için bkz. ASP.NET Core ilke tabanlı
yetkilendirme.
Bu API 'Ler Blazor sunucuda Blazor ya da WebAssembly uygulamalarında kullanılabilir.
Ne Roles ne de Policy belirtilmemişse, AuthorizeView varsayılan ilkeyi kullanır.
Zaman uyumsuz kimlik doğrulaması sırasında görünen içerik
Blazor, kimlik doğrulaması durumunun zaman uyumsuzolarak belirlenmesine izin verir. Bu yaklaşım için birincil
senaryo, kimlik doğrulaması için bir dış uç noktaya istek yapan Blazor WebAssembly Apps ' dedir.
Kimlik doğrulaması devam ederken, AuthorizeView varsayılan olarak içerik görüntülemez. Kimlik doğrulama
gerçekleştiğinde içeriği göstermek için <Authorizing> öğesini kullanın:

<AuthorizeView>
<Authorized>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you're authenticated.</p>
</Authorized>
<Authorizing>
<h1>Authentication in progress</h1>
<p>You can only see this content while authentication is in progress.</p>
</Authorizing>
</AuthorizeView>

Bu yaklaşım normalde Blazor Server uygulamaları için geçerli değildir. Blazor sunucu uygulamaları, durum
oluşturulur almaz kimlik doğrulama durumunu bilir. Authorizing içerik Blazor sunucu uygulamasının
AuthorizeView bileşeninde bulunabilir, ancak içerik hiçbir şekilde gösterilmez.

[Yetkilendir] özniteliği
[Authorize] özniteliği Razor bileşenlerinde kullanılabilir:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

NOTE
Blazor WebAssembly uygulama bileşeninde, bu bölümdeki örneklere Microsoft.AspNetCore.Authorization ad alanını (
@using Microsoft.AspNetCore.Authorization ) ekleyin.

IMPORTANT
Yalnızca Blazor yönlendirici üzerinden ulaşılan @page bileşenlerinde [Authorize] kullanın. Yetkilendirme yalnızca, bir sayfada
işlenen alt bileşenler için değil , yönlendirmenin bir yönü olarak gerçekleştirilir. Bir sayfa içindeki belirli parçaların
görüntülenmesini yetkilendirmek için, bunun yerine AuthorizeView kullanın.

[Authorize] özniteliği rol tabanlı veya ilke tabanlı yetkilendirmeyi de destekler. Rol tabanlı yetkilendirme için
Roles parametresini kullanın:
@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

İlke tabanlı yetkilendirme için Policy parametresini kullanın:

@page "/"
@attribute [Authorize(Policy = "content-editor")]

<p>You can only see this if you satisfy the 'content-editor' policy.</p>

Ne Roles ne de Policy belirtilmemişse, [Authorize] varsayılan ilkeyi kullanır, bu varsayılan olarak kabul edilir:
Kimliği doğrulanmış (oturum açmış) kullanıcılar yetkili olarak.
Kimliği doğrulanmamış (oturumu açılmış) kullanıcılar yetkilendirilmemiş.

Yönlendirici bileşeniyle yetkisiz içeriği özelleştirme


AuthorizeRouteView bileşeniyle birlikte Router bileşeni, uygulamanın şu durumlarda özel içerik belirlemesine izin
verir:
İçerik bulunamadı.
Kullanıcı, bileşene uygulanan bir [Authorize] koşulunu başarısız olur. [Authorize] özniteliği [Authorize]
öznitelik bölümünde ele alınmıştır.
Zaman uyumsuz kimlik doğrulama devam ediyor.
Varsayılan Blazor sunucusu proje şablonunda, app. Razor dosyası nasıl özel içerik ayarlanacağını gösterir:

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<h1>Sorry</h1>
<p>You're not authorized to reach this page.</p>
<p>You may need to log in as a different user.</p>
</NotAuthorized>
<Authorizing>
<h1>Authentication in progress</h1>
<p>Only visible while authentication is in progress.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<h1>Sorry</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>

<NotFound> , <NotAuthorized> ve <Authorizing> etiketlerinin içeriği, diğer etkileşimli bileşenler gibi rastgele öğeler
içerebilir.
<NotAuthorized> öğesi belirtilmemişse, AuthorizeRouteView aşağıdaki geri dönüş iletisini kullanır:
Not authorized.

Kimlik doğrulama durumu değişiklikleri hakkında bildirim


Uygulama, temeldeki kimlik doğrulama durumu verilerinin değiştiğini belirlerse (örneğin, Kullanıcı oturumu
kapattığından veya başka bir kullanıcı rollerini değiştirse), özel bir AuthenticationStateProvider isteğe bağlı olarak
AuthenticationStateProvider temel sınıfında yöntemi NotifyAuthenticationStateChanged çağırabilir. Bu, yeni verileri
kullanarak yeniden kimlik doğrulama durumu verilerini (örneğin, AuthorizeView ) tüketicilere bildirir.

Yordamsal mantık
Uygulama, yordamsal mantığın bir parçası olarak yetkilendirme kurallarını denetmek için gerekliyse, kullanıcının
ClaimsPrincipalalmak için Task<AuthenticationState> türünde basamaklı bir parametre kullanın.
Task<AuthenticationState> , ilkeleri değerlendirmek için IAuthorizationService gibi diğer hizmetlerle birleştirilebilir.

@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }

private async Task DoSomething()


{
var user = (await authenticationStateTask).User;

if (user.Identity.IsAuthenticated)
{
// Perform an action only available to authenticated (signed-in) users.
}

if (user.IsInRole("admin"))
{
// Perform an action only available to users in the 'admin' role.
}

if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))


.Succeeded)
{
// Perform an action only available to users satisfying the
// 'content-editor' policy.
}
}
}

NOTE
Blazor WebAssembly uygulama bileşeninde, Microsoft.AspNetCore.Authorization ve
Microsoft.AspNetCore.Components.Authorization ad alanlarını ekleyin:

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

Blazor WebAssembly uygulamalarında yetkilendirme


Blazor WebAssembly uygulamalarında, tüm istemci tarafı kodlar kullanıcılar tarafından değiştirilemediği için
yetkilendirme denetimleri atlanabilir. Aynı, JavaScript SPA çerçeveleri veya herhangi bir işletim sistemi için yerel
uygulamalar dahil olmak üzere tüm istemci tarafı uygulama teknolojileri için de geçerlidir.
İstemci tarafı uygulamanız tarafından erişilen tüm API uç noktalarında sunucuda her zaman
yetkilendirme denetimleri gerçekleştirin.

Sorun giderme hataları


Yaygın hatalar:
Yetkilendirme, görev<AuthenticationState > türünde bir geçişli parametre gerektirir. Bunu
sağlamak için basamaklı Dingauthenticationstate kullanmayı göz önünde bulundurun.
null değer authenticationStateTask alındı

Projenin kimlik doğrulaması etkin bir Blazor sunucu şablonu kullanılarak oluşturulmamış olması olasıdır.
<CascadingAuthenticationState> UI ağacının bir parçası etrafında sarmalayın, örneğin, app. Razor içinde aşağıdaki
gibi:

<CascadingAuthenticationState>
<Router AppAssembly="typeof(Startup).Assembly">
...
</Router>
</CascadingAuthenticationState>

CascadingAuthenticationState , Task<AuthenticationState> basamaklı parametresini sağlar ve bu, temel alınan


AuthenticationStateProvider DI hizmetinden alır.

Ek kaynaklar
ASP.NET Core güvenliğine genel bakış
Güvenli ASP.NET Core Blazor Server uygulamaları
ASP.NET Core Windows kimlik doğrulamasını yapılandırma
Güvenli ASP.NET Core Blazor Server uygulamaları
9.12.2019 • 36 minutes to read • Edit Online

Sağlayan Javier Calvarro Nelson


sunucu uygulamaları Blazor sunucu ve istemcinin uzun süreli bir ilişki korumasını gerektiren, durum bilgisi olan bir
veri işleme modelini benimseyin. Kalıcı durum, büyük olasılıkla uzun süreli bağlantılara yayılabilen bir
devretarafından korunur.
Bir Kullanıcı Blazor sunucu sitesi ziyaret ettiğinde sunucu, sunucunun belleğinde bir devre oluşturur. Devre,
kullanıcının Kullanıcı ARABIRIMINDE bir düğme seçtiğinde olduğu gibi olaylara hangi içeriğin işleneceğini ve yanıt
verdiğini tarayıcıya gösterir. Bu işlemleri gerçekleştirmek için, devre bir bağlantı, kullanıcının tarayıcısında ve .NET
yöntemlerinde JavaScript işlevlerini çağırır. Bu iki yönlü JavaScript tabanlı etkileşim, JavaScript birlikte çalışma (js
birlikte çalışma)olarak adlandırılır.
JS birlikte çalışması Internet üzerinden yapıldığından ve istemci uzak bir tarayıcı kullandığından Blazor sunucu
uygulamaları çoğu Web uygulaması güvenlik kaygılarını paylaşır. Bu konu, sunucu uygulamalarına Blazor yönelik
yaygın tehditleri açıklar ve Internet 'e yönelik uygulamalara odaklanmış tehdit azaltma kılavuzu sağlar.
Şirket ağları veya intranetleri gibi kısıtlı ortamlarda, azaltma yönerglarından bazıları şunlardır:
Kısıtlanmış ortamda uygulanmaz.
Güvenlik riski kısıtlı bir ortamda azaldığından, uygulama maliyeti değer değildir.

Kaynak tükenmesi
İstemci sunucuyla etkileşime geçtiğinde kaynak tükenmesi gerçekleşebilir ve sunucunun aşırı kaynak kullanmasına
neden olur. Aşırı kaynak tüketimi öncelikle şunları etkiler:
CPU
Bellek
İstemci bağlantıları
Hizmet reddi (DoS ) saldırıları genellikle bir uygulamanın veya sunucunun kaynaklarını tüketme konusunda arama
yapılır. Ancak, kaynak tükenmesi sistem üzerinde bir saldırının sonucu değildir. Örneğin, yüksek Kullanıcı talebi
nedeniyle sınırlı kaynaklar tükenebilir. DoS, hizmet reddi (DOS ) saldırıları bölümünde daha fazla ele alınmıştır.
Veritabanları ve dosya tutamaçları (dosyaları okumak ve yazmak için kullanılır) gibi Blazor Framework harici
kaynakları kaynak tükenmesi de yaşayabilir. Daha fazla bilgi için bkz. ASP.NET Core performans En Iyi yöntemleri.
CPU
Bir veya daha fazla istemci, yoğun CPU işi gerçekleştirmeye çalışan bir veya daha fazla istemci tarafından meydana
gelebilir.
Örneğin, Fibonnacci numarasınıhesaplayan bir Blazor sunucusu uygulaması düşünün. Bir Fibonnacci numarası,
dizideki her bir sayının önceki iki sayının toplamı olduğu bir Fibonnacci sırasından oluşturulur. Yanıta ulaşmak için
gereken iş miktarı, sıranın uzunluğuna ve ilk değerin boyutuna bağlıdır. Uygulama bir istemcinin isteğine sınır
yerleştirmezse, CPU yoğunluklu hesaplamalar CPU 'nun süresini ayırt edebilir ve diğer görevlerin performansını
azalrlar. Aşırı kaynak tüketimi, kullanılabilirliği etkileyen bir güvenlik konusudur.
CPU tükenmesi, herkese açık olan tüm uygulamalar için bir sorun teşkil etmez. Normal Web uygulamalarında,
istekler ve bağlantılar bir güvenlik önlemi olarak zaman aşımına uğrar, ancak Blazor Server uygulamaları aynı
korumaları sağlamaz. Blazor Server uygulamaları, CPU yoğun olabilecek işleri gerçekleştirmeden önce uygun
denetimleri ve limitleri içermelidir.
Bellek
Bir veya daha fazla istemci, sunucuyu büyük miktarda bellek kullanmaya zorlmaya zorlarsanız bellek tükenmesi
meydana gelebilir.
Örneğin, öğelerin listesini kabul eden ve görüntüleyen bir bileşen ile Blazorsunucu tarafı uygulamasını düşünün.
Blazor uygulama, izin verilen öğe sayısı veya istemciye geri işlenen öğe sayısı için sınır yerleştirmezse, bellek yoğun
işleme ve işleme sunucu belleğini sunucunun performansının bulunduğu noktaya göre olumsuz etkileyebilir.
Sunucu kilitlenmişse veya çöktüğünde göründüğü noktadan yavaş olabilir.
Sunucuda olası bir bellek tükenmesi senaryosuna ait öğelerin listesini sürdürmek ve görüntülemek için aşağıdaki
senaryoyu göz önünde bulundurun:
Bir List<MyItem> özellik veya alanındaki öğeler, sunucunun belleğini kullanır. Uygulama, öğelerin listesinin
sınırsız olarak büyümesine izin veriyorsa, sunucunun belleği tükenmeye karşı bir risk vardır. Belleğin
tükenmesinin geçerli oturum sonlandırmasına (kilitlenme) ve bu sunucu örneğindeki tüm eşzamanlı oturumlara
bir bellek dışı özel durum almasına neden olur. Bu senaryonun oluşmasını önlemek için, uygulamanın eşzamanlı
kullanıcılara bir öğe sınırı uygulayan bir veri yapısı kullanması gerekir.
Bir sayfalama şeması işleme için kullanılmazsa, sunucu Kullanıcı arabiriminde görünmeyen nesneler için ek
bellek kullanır. Öğe sayısı sınırı olmadan, bellek talepleri kullanılabilir sunucu belleğini tüketebilir. Bu senaryoyu
engellemek için aşağıdaki yaklaşımlardan birini kullanın:
İşleme sırasında sayfalandırılmış listeler kullanın.
Yalnızca ilk 100 ' i 1.000 öğeyi görüntüleyin ve kullanıcının görüntülenen öğelerin ötesinde öğeleri
bulmak için arama ölçütü girmesini gerektirir.
Daha gelişmiş bir işleme senaryosu için sanallaştırmayıdestekleyen listeler veya kılavuzlar uygulayın.
Sanallaştırma kullanarak, listeler yalnızca kullanıcıya şu anda görünür olan öğelerin bir alt kümesini işler.
Kullanıcı ARABIRIMDEKI ScrollBar ile etkileşime geçtiğinde, bileşen yalnızca görüntüleme için gereken
öğeleri işler. Şu anda görüntülenmek üzere gerekli olmayan öğeler, en ideal yaklaşım olan ikincil
depolamada tutulabilir. Görüntülenmezler olmayan öğeler bellekte tutulabilir ve bu da daha az idealdir.
Blazor Server Apps, WPF, Windows Forms veya Blazor WebAssembly gibi durum bilgisi olan uygulamalar için
diğer kullanıcı arabirimi çerçevelerine benzer bir programlama modeli sunar. Ana fark, uygulama tarafından
tüketilen belleğin, istemciye ait olduğu ve yalnızca o tek istemciyi etkilediği bazı Kullanıcı arabirimi çerçevelerinden
biridir. Örneğin, bir Blazor WebAssembly uygulaması tamamen istemcide çalışır ve yalnızca istemci bellek
kaynaklarını kullanır. Blazor sunucusu senaryosunda, uygulama tarafından tüketilen bellek sunucuya aittir ve
sunucu örneğindeki istemciler arasında paylaşılır.
Sunucu tarafı bellek talepleri tüm Blazor sunucu uygulamaları için bir noktadır. Ancak, çoğu Web uygulaması
durum bilgisiz olur ve bir isteği işlerken kullanılan bellek, yanıt döndürüldüğünde serbest bırakılır. Genel bir öneri
olarak, istemcilerin, istemci bağlantılarını devam eden diğer tüm sunucu tarafı uygulamalarda olduğu gibi ilişkisiz
miktarda bellek ayırmasına izin vermez. Bir Blazor sunucusu uygulaması tarafından tüketilen bellek, tek bir istekten
daha uzun bir süre devam ettirir.

NOTE
Geliştirme sırasında, bir profil oluşturucu kullanılabilir veya istemci bellek taleplerini değerlendirmek için yakalanan bir izleme
olabilir. Profil Oluşturucu veya izleme, belirli bir istemciye ayrılan belleği yakalamaz. Geliştirme sırasında belirli bir istemcinin
bellek kullanımını yakalamak için, bir döküm yakalayın ve Kullanıcı devresi içinde kök olan tüm nesnelerin bellek talebini
inceleyin.

İstemci bağlantıları
Bir veya daha fazla istemci sunucuya çok fazla eş zamanlı bağlantı açtıklarında, diğer istemcilerin yeni bağlantı
kurmasını engellediğinden bağlantı tükenmesi meydana gelebilir.
Blazor istemcileri, oturum başına tek bir bağlantı kurar ve tarayıcı penceresi açık olduğu sürece bağlantıyı açık halde
tutar. Tüm bağlantıları koruma sunucusundaki talepler Blazor uygulamalarına özgü değildir. Bağlantıların kalıcı
doğası ve Blazor Server uygulamalarının durum bilgisi olan doğası göz önüne alındığında, bağlantı tükenmesi
uygulamanın kullanılabilirliğine daha fazla risk taşır.
Varsayılan olarak, bir Blazor sunucusu uygulaması için Kullanıcı başına bağlantı sayısı sınırı yoktur. Uygulama bir
bağlantı sınırı gerektiriyorsa aşağıdaki yaklaşımlardan birini veya daha fazlasını yapın:
Yetkisiz kullanıcıların uygulamaya bağlanma yeteneğini doğal olarak sınırlayan kimlik doğrulaması gerektir. Bu
senaryonun etkili olabilmesi için kullanıcıların, ' de Yeni Kullanıcı sağlaması engellenmelidir.
Kullanıcı başına bağlantı sayısını sınırlayın. Bağlantıları sınırlandırma, aşağıdaki yaklaşımlar aracılığıyla
gerçekleştirilebilir. Meşru kullanıcıların uygulamaya erişmesine izin vermeye özen gösterin (örneğin, istemcinin
IP adresine göre bir bağlantı sınırı oluşturulduğunda).
Uygulama düzeyinde:
Uç nokta yönlendirme genişletilebilirliği.
Uygulamaya bağlanmak ve Kullanıcı başına etkin oturumları izlemek için kimlik doğrulaması
gerektir.
Sınıra ulaştıktan sonra yeni oturumları reddedin.
İstemcilerden bir uygulamaya bağlantıları oluşturan Azure SignalR hizmeti gibi bir ara sunucu
aracılığıyla uygulamaya yönelik proxy WebSocket bağlantıları. Bu, tek bir istemcinin
yapabileceğinden daha fazla bağlantı kapasitesine sahip bir uygulama sağlar ve istemcinin sunucu
bağlantılarını tüketmesini önler.
Sunucu düzeyinde: uygulamanın önünde bir proxy/ağ geçidi kullanın. Örneğin, Azure ön kapısı , Web
trafiğinin bir uygulamaya küresel olarak yönlendirilmesini tanımlamanıza, yönetmenize ve izlemenize
olanak sağlar.

Hizmet reddi (DoS) saldırıları


Hizmet reddi (DoS ) saldırıları, istemcinin bir veya daha fazla kaynağın bir veya daha fazla uygulamayı tüketmesine
neden olan bir istemciyi içerir. Blazor Server uygulamaları, bazı varsayılan limitleri içerir ve DoS saldırılarına karşı
koruma sağlamak için diğer ASP.NET Core ve SignalR limitlerini kullanır:

BLAZOR SUNUCUSU UYGULAMA SINIRI AÇIKLAMA VARSAYILAN

Belirli bir sunucunun bellekte tek seferde


CircuitOptions.DisconnectedCircuitMaxRetained 100
tuttuğu bağlantı kesilen en fazla
bağlantı sayısı.

Bağlantısı kesilmiş bir devre dışı


CircuitOptions.DisconnectedCircuitRetentionPeriod 3 dakika
bırakılmadan önce bellekte tutulan en
fazla süre.

Zaman uyumsuz bir


CircuitOptions.JSInteropDefaultCallTimeout JavaScript işlev 1 dakika
çağrısını zaman aşımına uğramadan
önce sunucunun bekleyeceği en fazla
süre.

En fazla bildirilmemiş işleme toplu işi


CircuitOptions.MaxBufferedUnacknowledgedRenderBatches 10
sayısı sunucu, güçlü yeniden bağlanmayı
desteklemek için belirli bir zamanda her
bir devreye göre bellekte kalır. Sınıra
ulaştıktan sonra sunucu, bir veya daha
fazla toplu iş istemci tarafından
onaylanana kadar yeni oluşturma toplu
işleri oluşturmayı durduruyor.
SIGNALR VE ASP.NET CORE SINIRI AÇIKLAMA VARSAYILAN

Tek bir ileti için ileti boyutu.


CircuitOptions.MaximumReceiveMessageSize 32 KB

Tarayıcıyla etkileşimler (istemci)


İstemci, JS birlikte çalışma olayı gönderme ve işleme tamamlama aracılığıyla sunucuyla etkileşime girer. JS birlikte
çalışma iletişimi, JavaScript ve .NET arasında her iki yolla da geçer:
Tarayıcı olayları istemciden sunucuya zaman uyumsuz biçimde gönderilir.
Sunucu, gerektiği şekilde kullanıcı arabiriminden zaman uyumsuz olarak rerendering.
.NET 'ten çağrılan JavaScript işlevleri
.NET yöntemlerinden JavaScript 'e yapılan çağrılar için:
Tüm etkinleştirmeleri, başarısız olduktan sonra, çağırana bir OperationCanceledException döndüren
yapılandırılabilir bir zaman aşımı sağlar.
Bir dakikalık çağrılar ( CircuitOptions.JSInteropDefaultCallTimeout ) için varsayılan bir zaman aşımı vardır.
Bu sınırı yapılandırmak için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği.
İptal belirtecini çağrı başına temelinde denetlemek için bir iptal belirteci sağlayabilirsiniz. Bir iptal belirteci
sağlandıysa, mümkün olan ve istemciye yapılan tüm çağrıların zaman içinde sağlandığı varsayılan çağrı
zaman aşımını kullanır.
JavaScript çağrısının sonucu güvenilir olamaz. Tarayıcıda çalışan Blazor uygulama istemcisi çağırmak için
JavaScript işlevini arar. İşlev çağrılır ve sonuç ya da bir hata oluşturulur. Kötü amaçlı bir istemci şunları
gerçekleştirmeye çalışabilir:
JavaScript işlevinden bir hata döndürerek uygulamada sorun oluşmasına neden olur.
JavaScript işlevinden beklenmeyen bir sonuç döndürerek sunucuda istemeden bir davranış alır.
Yukarıdaki senaryolara karşı koruma için aşağıdaki önlemleri alın:
Try-catch DEYIMLERI içindeki js birlikte çalışabilirlik çağrılarını, çağırma sırasında oluşabilecek hataları hesaba
eklemek için kaydırın. Daha fazla bilgi için bkz. ASP.NET Core Blazor uygulamalarda hataları işleme.
Herhangi bir işlem yapmadan önce, hata iletileri de dahil olmak üzere JS birlikte çalışma çağırmaları tarafından
döndürülen verileri doğrulayın.
Tarayıcıdan çağrılan .NET yöntemleri
JavaScript 'e yönelik çağrılara .NET yöntemlerine güvenmeyin. JavaScript 'e bir .NET yöntemi sunulduğunda, .NET
yönteminin nasıl çağrılacağını göz önünde bulundurun:
Uygulamaya genel bir uç nokta gibi, JavaScript 'e sunulan tüm .NET metodunu değerlendirin.
Girişi doğrula.
Değerlerin beklenen aralıklar içinde olduğundan emin olun.
Kullanıcının istenen eylemi gerçekleştirme izni olduğundan emin olun.
.NET Yöntem çağırma kapsamında aşırı miktarda kaynak ayırmayın. Örneğin, denetim gerçekleştirin ve
CPU ve bellek kullanımı için sınır koyun.
Statik ve örnek yöntemlerinin JavaScript istemcilerine sunutabileceğiniz hesaba sahip olun. Tasarım,
uygun kısıtlamalarla durum paylaşma için çağrı yaptığı müddetçe, oturumlar arasında durum
paylaşmaktan kaçının.
İlk olarak bağımlılık ekleme (DI) aracılığıyla oluşturulan DotNetReference nesneleri aracılığıyla
kullanıma sunulan örnek yöntemleri için nesnelerin kapsamlı nesneler olarak kaydedilmesi gerekir.
Bu, Blazor sunucu uygulamasının kullandığı tüm DI Hizmetleri için geçerlidir.
Statik yöntemler için, uygulama bir sunucu örneğindeki tüm kullanıcılar genelinde durum
tasarımını özel olarak paylaşmadığı müddetçe, istemciye kapsamdaki durumu oluşturmaktan
kaçının.
Parametrelerde Kullanıcı tarafından sağlanan verileri JavaScript çağrılarına geçirmekten kaçının.
Parametrelerde veri geçirilmesi kesinlikle gerekliyse, JavaScript kodunun, siteler arası betik oluşturma
(XSS ) güvenlik açıklarına gerek kalmadan verileri geçirmeyi işlediğinden emin olun. Örneğin, bir öğenin
innerHTML özelliğini ayarlayarak Belge Nesne Modeli ( DOM ) Kullanıcı tarafından sağlanan verileri
yazma. eval ve diğer güvenli olmayan JavaScript temel öğelerini devre dışı bırakmak için Içerik güvenlik
ilkesi (CSP ) kullanmayı düşünün.
Framework 'ün gönderme uygulamasının en üstünde .NET etkinleştirmeleri için özel bir dağıtma uygulamaktan
kaçının. .NET yöntemlerini tarayıcıya sunma, genel Blazor geliştirme için önerilmeyen gelişmiş bir senaryodur.
Olaylar
Olaylar Blazor sunucusu uygulamasına bir giriş noktası sağlar. Web Apps 'teki uç noktaları koruma için aynı kurallar,
Blazor Server uygulamalarındaki olay işleme için geçerlidir. Kötü amaçlı bir istemci, istediği verileri bir olay için yük
olarak gönderebilirler.
Örneğin:
Bir <select> için değişiklik olayı, uygulamanın istemciye sunulan seçenekler içinde olmayan bir değer
gönderebilir.
<input> , istemci tarafı doğrulamayı atlayarak herhangi bir metin verisini sunucuya gönderebilir.

Uygulamanın, uygulamanın işlediği herhangi bir olay için verileri doğrulaması gerekir. Blazor Framework Forms
bileşenleri temel doğrulamaları gerçekleştirir. Uygulama özel form bileşenleri kullanıyorsa, olay verilerinin uygun
şekilde doğrulanması için özel kodun yazılması gerekir.
Blazor sunucu olayları zaman uyumsuzdur, bu nedenle uygulamanın yeni bir işleme üreten bir işleme süresi
geçmeden önce sunucuya birden çok olay gönderilebilir. Göz önünde bulundurulması gereken bazı güvenlik etkileri
vardır. Uygulamadaki istemci eylemlerinin sınırlandırmasının, olay işleyicileri içinde gerçekleştirilmesi ve geçerli
işlenen görünüm durumuna bağlı olmaması gerekir.
Bir kullanıcının bir sayacı en fazla üç kez artmasını sağlayan bir sayaç bileşeni düşünün. Sayacı artırma düğmesi,
count değerine göre koşullu olarak belirlenir:

<p>Count: @count<p>

@if (count < 3)


{
<button @onclick="IncrementCount" value="Increment count" />
}

@code
{
private int count = 0;

private void IncrementCount()


{
count++;
}
}

Bir istemci, çerçeve bu bileşenin yeni bir işlemesini oluşturmadan önce bir veya daha fazla artış olayı gönderebilir.
Bu, düğme kullanıcı ARABIRIMI tarafından yeterince hızlı bir şekilde kaldırılmadığı için count , Kullanıcı tarafından
üç kez artılabildiğinden oluşur. Üç count artımlarının sınırına ulaşmak için doğru yol aşağıdaki örnekte
gösterilmiştir:
<p>Count: @count<p>

@if (count < 3)


{
<button @onclick="IncrementCount" value="Increment count" />
}

@code
{
private int count = 0;

private void IncrementCount()


{
if (count < 3)
{
count++;
}
}
}

İşleyicinin içindeki if (count < 3) { ... } denetimini ekleyerek, count artırma kararı geçerli uygulama durumuna
göre belirlenir. Bu karar, önceki örnekte olduğu gibi Kullanıcı arabiriminin durumunu temel değildir ve bu da geçici
olarak eski olabilir.
Birden çok gönderine karşı koruma
Bir olay geri çağırması, bir dış hizmetten veya veritabanından veri getirme gibi uzun süren bir işlemi çağıralıyorsa,
bir koruyucu kullanmayı düşünün. Koruyucu, bir işlem görsel geri bildirimde çalışırken, kullanıcının birden çok
işlemi sıraya almasını önleyebilir. Aşağıdaki bileşen kodu, GetForecastAsync verileri sunucudan alırken true
isLoading ayarlar. isLoading true , bu düğme Kullanıcı arabiriminde devre dışı bırakılır:

@page "/fetchdata"
@using BlazorServerSample.Data
@inject WeatherForecastService ForecastService

<button disabled="@isLoading" @onclick="UpdateForecasts">Update</button>

@code {
private bool isLoading;
private WeatherForecast[] forecasts;

private async Task UpdateForecasts()


{
if (!isLoading)
{
isLoading = true;
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
isLoading = false;
}
}
}

Erken iptali yapın ve bir-After-Dispose kullanmaktan kaçının


Birden çok gönderenlere karşı koruma bölümünde açıklandığı gibi bir koruyucu kullanmanın yanı sıra, bileşen
bırakıldığında uzun süreli işlemleri iptal etmek için bir CancellationToken kullanmayı düşünün. Bu yaklaşımda,
bileşenlerden sonra kullanım -sonrasında Dispose özelliğinden kaçınmanın sağladığı avantaj vardır:
@implements IDisposable

...

@code {
private readonly CancellationTokenSource TokenSource =
new CancellationTokenSource();

private async Task UpdateForecasts()


{
...

forecasts = await ForecastService.GetForecastAsync(DateTime.Now,


TokenSource.Token);

if (TokenSource.Token.IsCancellationRequested)
{
return;
}

...
}

public void Dispose()


{
CancellationTokenSource.Cancel();
}
}

Büyük miktarlarda veri üreten olaylardan kaçının


oninput veya onscroll gibi bazı DOM olayları, büyük miktarda veri üretebilir. Bu olayları Blazor Server
uygulamalarında kullanmaktan kaçının.

Ek güvenlik kılavuzu
ASP.NET Core uygulamalarının güvenliğini sağlama kılavuzu Blazor sunucu uygulamalarına uygulanır ve aşağıdaki
bölümlerde ele alınmıştır:
Günlüğe kaydetme ve hassas veriler
HTTPS ile yoldaki bilgileri koruma
Siteler arası betik oluşturma (XSS ))
Çapraz kaynak koruması
Tıklama-Jacking
Yeniden yönlendirmeleri aç
Günlüğe kaydetme ve hassas veriler
İstemci ve sunucu arasındaki JS birlikte çalışma etkileşimleri, ILogger örneklerle sunucu günlüklerine kaydedilir.
Blazor, gerçek olaylar veya JS birlikte çalışma girişleri ve çıkışları gibi hassas bilgilerin günlüğe kaydedilmesini
önler.
Sunucuda bir hata oluştuğunda, çerçeve istemciye bildirir ve oturumu kapatır. Varsayılan olarak, istemci tarayıcının
geliştirici araçlarında görünebileceğini belirten genel bir hata iletisi alır.
İstemci tarafı hatası, çağrı yığınını içermez ve hatanın nedeni hakkında ayrıntı sağlamaz, ancak sunucu günlükleri bu
gibi bilgileri içerir. Geliştirme amacıyla, önemli hata bilgileri, ayrıntılı hataları etkinleştirerek istemciye kullanılabilir
hale getirilebilir.
İle ilgili ayrıntılı hataları etkinleştir:
CircuitOptions.DetailedErrors .
yapılandırma anahtarı DetailedErrors . Örneğin, ASPNETCORE_DETAILEDERRORS ortam değişkenini true değerine
ayarlayın.

WARNING
Internet 'teki istemcilere hata bilgilerini ortaya çıkarmak her zaman kaçınılması gereken bir güvenlik riskidir.

HTTPS ile yoldaki bilgileri koruma


Blazor sunucusu, istemci ve sunucu arasındaki iletişim için SignalR kullanır. Blazor sunucusu normalde SignalR
üzerinde görüşür, genellikle WebSockets olan aktarımı kullanır.
Blazor sunucusu, sunucu ve istemci arasında gönderilen verilerin bütünlüğünü ve gizliliğini garanti etmez. Her
zaman HTTPS kullanın.
Siteler arası betik oluşturma (XSS )
Siteler arası betik oluşturma (XSS ), yetkisiz bir tarafın tarayıcı bağlamında rastgele mantık yürütmesine olanak
sağlar. Güvenliği aşılmış bir uygulama, istemcide rastgele kod çalıştırabilir. Güvenlik açığı, sunucuda büyük olasılıkla
çok sayıda kötü amaçlı eylem gerçekleştirmek için kullanılabilir:
Sahte/geçersiz olayları sunucuya gönderme.
Dağıtım başarısız/geçersiz işleme tamamlama.
İşleme tamamlamamasını gönderdikten kaçının.
JavaScript 'ten .NET 'e birlikte çalışma çağrıları gönderme.
.NET 'ten JavaScript 'e birlikte çalışma çağrılarının yanıtını değiştirme.
.NET ile JS birlikte çalışma sonuçlarına dağıtma kullanmaktan kaçının.
Blazor Server Framework, önceki tehditlere karşı korumak için gereken adımları gerçekleştirir:
İstemci, işleme toplu işlerini bildirmeden, yeni UI güncellemeleri oluşturmayı durduruyor.
CircuitOptions.MaxBufferedUnacknowledgedRenderBatches ile yapılandırılır.
İstemciden bir yanıt almadan bir dakikadan sonra herhangi bir .NET için JavaScript çağrısı süresi.
CircuitOptions.JSInteropDefaultCallTimeout ile yapılandırılır.
JS birlikte çalışması sırasında tarayıcıdan gelen tüm girişte temel doğrulama gerçekleştirir:
.NET başvuruları geçerli ve .NET yöntemi tarafından beklenen türde.
Veriler hatalı biçimlendirilmemiş.
Yöntem için doğru sayıda bağımsız değişken, yükte bulunur.
Yöntemi çağırmadan önce bağımsız değişkenler veya sonuç doğru şekilde seri durumdan çıkarılmış
olabilir.
Tarayıcıdan gönderilen olaylardan gelen tüm girişte temel doğrulama gerçekleştirir:
Olayın geçerli bir türü vardır.
Olay verilerinin serisi kaldırılamaz.
Olayla ilişkili bir olay işleyicisi var.
Framework 'ün uyguladığı korumalarına ek olarak, tehditlere karşı korumak ve uygun işlemleri gerçekleştirmek için
uygulamanın geliştirici tarafından kodlanmış olması gerekir:
Olayları işlerken her zaman verileri doğrulayın.
Geçersiz veri aldıktan sonra uygun eylemi gerçekleştirin:
Verileri yoksayın ve döndürün. Bu, uygulamanın istekleri işlemeye devam etmesine izin verir.
Uygulama girişin meşru olduğunu belirlerse ve meşru istemci tarafından üretilemeyecek bir özel durum
oluşturun. Bir özel durum oluşturmak devre dışı olarak oturum kapatır ve oturumu sonlandırır.
Günlüklere dahil olan işleme toplu işlemleri tarafından sağlanan hata iletisine güvenmeyin. Hata istemci
tarafından sağlanır ve istemcinin güvenliği tehlikeye aşmış olabileceğinden genellikle güvenilemez.
JS birlikte çalışma çağrılarında, JavaScript ve .NET yöntemleri arasında her iki yönde de girişe güvenmeyin.
Bağımsız değişkenlerin veya sonuçların doğru şekilde seri durumdan çıkarılsa bile, uygulama bağımsız
değişkenlerin ve sonuçların içeriğinin geçerli olduğunu doğrulamaktan sorumludur.
Bir XSS Güvenlik açığının mevcut olması için, uygulamanın işlenen sayfada Kullanıcı girişini içermesi gerekir. Blazor
Server bileşenleri, bir . Razor dosyasındaki biçimlendirmenin yordamsal C# mantığa dönüştürülebileceği bir
derleme zamanı adımı yürütür. Çalışma zamanında, C# Logic öðeleri, metinleri ve alt bileşenleri açıklayan bir işleme
ağacı oluşturur. Bu, tarayıcı DOM 'a bir JavaScript yönergeleri dizisi aracılığıyla uygulanır (veya prerendering
durumunda HTML olarak serileştirilir):
Normal Razor söz dizimi (örneğin, @someStringValue ) ile işlenen Kullanıcı girişi, Razor söz dizimi DOM 'a
yalnızca metin yazabileceğiniz komutlar aracılığıyla eklendiğinden bir XSS Güvenlik Açığı sunmaz. Değer HTML
biçimlendirmesi içerse bile, değer statik metin olarak görüntülenir. Prerendering olduğunda çıktı HTML
kodlamalı olur ve bu da içeriği statik metin olarak görüntüler.
Betik etiketlerine izin verilmez ve uygulamanın bileşen işleme ağacına dahil edilmemelidir. Bir komut dosyası
etiketi bir bileşenin biçimlendirmesinde yer alıyorsa, derleme zamanı hatası oluşturulur.
Bileşen yazarları, Razor kullanmadan bileşenleri C# içinde yazar. Bileşen yazarı, çıkış yayırken doğru API 'Leri
kullanmaktan sorumludur. Örneğin, builder.AddContent(0, someUserSuppliedString) , ikincisi bir XSS Güvenlik
Açığı oluşturmasından builder.AddMarkupContent(0, someUserSuppliedString) değil ' i kullanın.
XSS saldırılarına karşı koruma kapsamında, Içerik güvenlik ilkesi (CSP )gibi XSS azaltmalarını gerçekleştirmeyi
düşünün.
Daha fazla bilgi için bkz. Siteler arası betik kullanmayı (XSS ) ASP.NET core'da engelle.
Çapraz kaynak koruması
Çapraz kaynak saldırıları, sunucuya yönelik bir eylem gerçekleştiren farklı bir kaynaktan gelen bir istemciyi içerir.
Kötü amaçlı eylem, genellikle bir GET isteği veya bir form GÖNDERISINI (siteler arası Istek sahteciliği, CSRF ),
ancak kötü amaçlı bir WebSocket açmak da mümkündür. Blazor sunucu uygulamaları, hub protokolünü kullanan
diğer SignalR uygulamaların aynısınısunar:
Blazor sunucu uygulamalarına ek ölçüler alınana kadar, kaynak dışı erişilebilir. Çapraz kaynak erişimini devre dışı
bırakmak için, işlem hattında CORS ana hattını ekleyerek ve Blazor uç nokta meta verilerine ekleyerek
DisableCorsAttribute izin verilen çıkış noktaları kümesini, çıkış noktaları arası kaynak paylaşımı için SignalR
yapılandırarakbir süre sonu devre dışı bırakın.
CORS etkinse, CORS yapılandırmasına bağlı olarak uygulamayı korumak için ek adımlar gerekebilir. CORS
genel olarak etkinleştirilmişse, hub.MapBlazorHub() çağrıldıktan sonra uç nokta meta verilerine
DisableCorsAttribute meta verileri eklenerek Blazor sunucu hub 'ı için CORS devre dışı bırakılabilir.

Daha fazla bilgi için bkz. ASP.NET Core siteler arası Istek sahteciliği (XSRF/CSRF ) saldırılarını önle.
Tıklama-Jacking
Tıklama-Jacking, kullanıcıyı saldırı altında sitede eylemler gerçekleştirmeye ikna etmek için bir sitenin farklı bir
kaynaktan bir <iframe> olarak işlenmesini içerir.
Bir uygulamanın bir <iframe> içinde işlemesini korumak için Içerik güvenlik ilkesi (CSP ) ve X-Frame-Options üst
bilgisini kullanın. Daha fazla bilgi için bkz. MDN Web belgeleri: X-Frame-Options.
Yeniden yönlendirmeleri aç
Bir Blazor sunucusu uygulaması oturumu başladığında, sunucu, oturum başlatma işleminin bir parçası olarak
gönderilen URL 'lerin temel doğrulamasını gerçekleştirir. Framework, devre oluşturmadan önce temel URL 'nin
geçerli URL 'nin bir üst olduğunu denetler. Framework tarafından başka denetim yapılmaz.
Kullanıcı istemcide bir bağlantı seçtiğinde, bağlantının URL 'SI sunucuya gönderilir ve bu işlem gerçekleştirilecek
eylemi belirler. Örneğin, uygulama bir istemci tarafı gezintisi gerçekleştirebilir veya tarayıcıya yeni konuma
gidemeyeceğini belirtebilir.
Bileşenler, NavigationManager kullanımı aracılığıyla program aracılığıyla gezinme isteklerini de tetikleyebilirler. Bu
tür senaryolarda, uygulama bir istemci tarafı gezintisi gerçekleştirebilir veya tarayıcıya yeni konuma gidebileceğini
gösterebilir.
Bileşenler:
Gezinti çağrısı bağımsız değişkenlerinin bir parçası olarak Kullanıcı girişini kullanmaktan kaçının.
Hedefin uygulama tarafından izin verildiğinden emin olmak için bağımsız değişkenleri doğrulayın.
Aksi takdirde, kötü niyetli bir kullanıcı tarayıcıyı saldırgan tarafından denetlenen bir siteye gitmesini zorlayabilir. Bu
senaryoda, saldırgan uygulamayı NavigationManager.Navigate yöntemi çağrısının bir parçası olarak bazı kullanıcı
girişlerini kullanarak ' ye püf ediyor.
Bu öneri, uygulamanın bir parçası olarak bağlantılar işlenirken de geçerlidir:
Mümkünse, göreli bağlantıları kullanın.
Mutlak bağlantı hedeflerinin bir sayfaya dahil etmeden önce geçerli olduğunu doğrulayın.
Daha fazla bilgi için bkz. ASP.NET core'da açık yeniden yönlendirme saldırılarını önleme.

Kimlik doğrulaması ve yetkilendirme


Kimlik doğrulama ve yetkilendirme hakkında yönergeler için bkz. ASP.NET Core Blazor kimlik doğrulaması ve
yetkilendirme.

Güvenlik denetim listesi


Aşağıdaki güvenlik konuları listesi ayrıntılı değildir:
Etkinliklerden bağımsız değişkenleri doğrulayın.
Giriş ve, JS birlikte çalışma çağrılarındaki sonuçları doğrulayın.
.NET için JS birlikte çalışabilirlik çağrılarına yönelik kullanıcı girişini kullanmaktan (veya önceden doğrulama)
kaçının.
İstemcinin ilişkisiz miktarda bellek ayırmasını engelleyin.
Bileşen içindeki veriler.
istemciye döndürülen başvuruları DotNetObject .
Birden çok gönderine karşı koruma.
Bileşen atıldığı zaman uzun süre çalışan işlemleri iptal edin.
Büyük miktarlarda veri üreten olaylardan kaçının.
NavigationManager.Navigate yapılan çağrıların bir parçası olarak Kullanıcı girişini kullanmaktan kaçının ve URL
'Ler için Kullanıcı girişini, bir izin verilen kaynaklar kümesine göre doğrulama, önce kaçınılmaz.
Kullanıcı arabiriminin durumuna göre yetkilendirme kararları yapmayın, ancak yalnızca bileşen durumudur.
XSS saldırılarına karşı korunmak için Içerik güvenlik ilkesi 'ni (CSP ) kullanmayı düşünün.
Tıklama-Jacking 'e karşı korumak için CSP ve X çerçeve seçeneklerini kullanmayı düşünün.
CORS 'yi etkinleştirirken veya Blazor uygulamaları için doğrudan CORS 'yi devre dışı bırakrken CORS
ayarlarının uygun olduğundan emin olun.
Blazor uygulamasına yönelik sunucu tarafı sınırlarının kabul edilemez bir risk düzeyi olmadan kabul edilebilir bir
kullanıcı deneyimi sağlamasına emin olmak için test edin.
ASP.NET Core Blazor durum yönetimi
9.12.2019 • 21 minutes to read • Edit Online

Steve Sanderson tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor sunucusu, durum bilgisi olan bir uygulama çerçevesidir. Çoğu zaman, uygulama sunucuya devam eden bir
bağlantı sağlar. Kullanıcının durumu, sunucu belleğinde bir devrendetutulur.
Bir kullanıcının devresi için durum tutulan örnekler şunlardır:
İşlenmiş Kullanıcı arabirimi, bileşen örneklerinin hiyerarşisini ve en son işleme çıktılarının—.
Bileşen örneklerinde alanların ve özelliklerin değerleri.
Devre kapsamına alınan bağımlılık ekleme (dı) hizmet örneklerinde tutulan veriler.

NOTE
Bu makale Blazor Server uygulamalarındaki durum kalıcılığını ele alınmaktadır. Blazor WebAssembly Apps, Tarayıcıda istemci
tarafı durum kalıcılığından yararlanabilir, ancak bu makalenin kapsamı dışında özel çözümler veya üçüncü taraf paketleri
gerektirebilir.

Blazor devreler
Bir Kullanıcı geçici bir ağ bağlantısı kaybıyla karşılaşıyorsa, uygulamayı kullanmaya devam edebilmek için
kullanıcıyı özgün devresine yeniden bağlamaya çalışır Blazor. Ancak, bir kullanıcıyı sunucunun belleğindeki özgün
devresine yeniden bağlamak her zaman mümkün değildir:
Sunucu, bağlantısı kesilen bir devreni süresiz olarak sürdüremez. Sunucu, bir zaman aşımından sonra veya
sunucu bellek baskısı altında olduğunda, bağlantısı kesilen bir bağlantı hattını serbest bırakmalıdır.
Çoklu sunucu, yük dengeli dağıtım ortamlarında, herhangi bir zamanda herhangi bir sunucu işleme isteği
kullanılamaz hale gelebilir. Tek tek sunucular, tüm istek hacmini işlemek için artık gerekli olmadığında veya
otomatik olarak kaldırılabilir. Kullanıcı yeniden bağlanmaya çalıştığında, özgün sunucu kullanılamayabilir.
Kullanıcı tarayıcıyı kapatabilir ve yeniden açabilir veya sayfayı yeniden yükleyerek tarayıcı belleğinde tutulan
tüm durumları kaldırır. Örneğin, JavaScript birlikte çalışabilirlik çağrıları aracılığıyla ayarlanan değerler
kaybolur.
Kullanıcı özgün devresine yeniden bağlanalınmayacaksa, Kullanıcı boş duruma sahip yeni bir devre alır. Bu, bir
masaüstü uygulamasını kapatıp yeniden açmaya eşdeğerdir.

Devreler arasında durumu koru


Bazı senaryolarda, devre genelinde durum koruma istenebilir. Bir uygulama, şu durumlarda bir kullanıcı için
önemli verileri koruyabilir:
Web sunucusu kullanılamaz hale gelir.
Kullanıcının tarayıcısı yeni bir Web sunucusuyla yeni bir devre başlatmaya zorlanır.
Genel olarak, devrelerde durumu korumak, kullanıcıların zaten var olan verileri okurken değil, etkin bir şekilde veri
oluşturmakta olduğu senaryolar için geçerlidir.
Tek bir devrenin ötesinde durumu korumak için, verileri yalnızca sunucunun belleğine depolamayın. Uygulama,
verileri başka bir depolama konumuna kalıcı hale vermelidir. Durum kalıcılığı otomatik değil—durum bilgisi olan
veri kalıcılığını uygulamak üzere uygulamayı geliştirirken adımları uygulamanız gerekir.
Veri kalıcılığı genellikle yalnızca kullanıcıların oluşturma çabasında olduğu yüksek değerli durum için gereklidir.
Aşağıdaki örneklerde, kalıcı durum ticari etkinliklerdeki zaman veya yardımlarını kaydeder:
Çok adımlı WebForm –, bir kullanıcının, durumları kaybedilmişse, çok adımlı bir işlemin birkaç tamamlanmış
adımı için verileri yeniden girmesi için zaman alan bir işlemdir. Kullanıcı, çok adımlı formdan uzaklaştıklarında
ve daha sonra forma geri döndüğünüzde bu senaryodaki durumu kaybeder.
Alışveriş sepeti, olası geliri temsil eden bir uygulamanın ticari olarak önemli bir bileşeni –. Durumlarını
kaybettikleri bir Kullanıcı ve bu nedenle alışveriş sepeti, siteye daha sonra geri döntiklerinde daha az ürün veya
hizmet satın alabilir.
Genellikle, gönderilmemiş bir oturum açma iletişim kutusuna girilen Kullanıcı adı gibi, kolayca yeniden
oluşturulmuş durumu korumak gerekli değildir.

IMPORTANT
Uygulama, uygulama durumunuyalnızca kalıcı hale getirebilirler. Usıs, bileşen örnekleri ve bunların işleme ağaçları gibi kalıcı
hale getirilir. Bileşenler ve işleme ağaçları genellikle seri hale getirilebilir değildir. Bir TreeView 'un genişletilmiş düğümleri gibi
kullanıcı arabirimi durumuna benzer bir şeyi sürdürmek için, uygulamanın davranışı seri hale getirilebilir uygulama durumu
olarak modelleyeceği özel kodu olmalıdır.

Durumun nerede kalıcı olduğu


Blazor sunucu uygulamasındaki kalıcı durum için üç ortak konum vardır. Her yaklaşım farklı senaryolara en iyi
şekilde uygundur ve farklı uyarılar içerir:
Veritabanında sunucu tarafı
URL
Tarayıcıda istemci tarafı
Veritabanında sunucu tarafı
Kalıcı veri kalıcılığı veya birden çok kullanıcı veya cihaza yayılması gereken veriler için, bağımsız bir sunucu tarafı
veritabanı neredeyse en iyi seçenektir. Şu seçenekler mevcuttur:
İlişkisel SQL veritabanı
Anahtar değeri deposu
Blob deposu
Tablo deposu
Veriler veritabanına kaydedildikten sonra, bir kullanıcı tarafından herhangi bir zamanda yeni bir devre başlatılabilir.
Kullanıcının verileri korunur ve yeni bir devrede kullanılabilir.
Azure veri depolama seçenekleri hakkında daha fazla bilgi için bkz. Azure depolama belgeleri ve Azure
veritabanları.
{1>URL<1}
Gezinti durumunu temsil eden geçici veriler için, verileri URL 'nin bir parçası olarak modelleyin. URL 'de
modellenen durum örnekleri şunları içerir:
Görüntülenen varlığın KIMLIĞI.
Disk belleğine alınmış bir kılavuzdaki geçerli sayfa numarası.
Tarayıcının adres çubuğunun içeriği korunur:
Kullanıcı sayfayı el ile yeniden yükler.
Web sunucusu kullanılamaz hale gelirse—Kullanıcı farklı bir sunucuya bağlanmak için sayfayı yeniden
yüklemeye zorlanır.
@page yönergesi ile URL desenleri tanımlama hakkında bilgi için bkz. ASP.NET Core Blazor yönlendirme.
Tarayıcıda istemci tarafı
Kullanıcının etkin şekilde oluşturmakta olduğu geçici veriler için, yaygın bir yedekleme deposu tarayıcının
localStorage ve sessionStorage koleksiyonlarıdır. Devre dışı bırakılırsa, sunucu tarafı depolama alanının
avantajlarından yararlanan uygulama, saklı durumu yönetmek veya temizlemek için gerekli değildir.

NOTE
Bu bölümdeki "istemci tarafı", Blazor WebAssembly barındırma modeliyledeğil, tarayıcıdaki istemci tarafı senaryolarına
başvurur. localStorage ve sessionStorage Blazor WebAssembly uygulamalarında kullanılabilir, ancak yalnızca özel kod
yazarak veya 3. taraf paketini kullanarak kullanılabilir.

localStorage ve sessionStorage aşağıdaki gibi farklılık gösterir:


localStorage kullanıcının tarayıcısına kapsamlandırılır. Kullanıcı sayfayı yeniden yüklediğinde veya tarayıcıyı
kapatıp yeniden açarsa durum devam ettirir. Kullanıcı birden çok tarayıcı sekmesi açarsa, durum sekmeler
arasında paylaşılır. Veriler açık olarak temizlenene kadar localStorage devam ettirir.
sessionStorage , kullanıcının tarayıcı sekmesinin kapsamına alınır. Kullanıcı sekmeyi yeniden yüklediğinde
durum devam ettirir. Kullanıcı sekmeyi veya tarayıcıyı kapatırsa durum kaybedilir. Kullanıcı birden çok tarayıcı
sekmesi açarsa, her sekmenin kendi bağımsız bir veri sürümü vardır.
Genellikle, sessionStorage kullanımı daha güvenlidir. sessionStorage , kullanıcının birden çok sekme açmasını ve
aşağıdaki gibi karşılaştığı riskleri önler:
Sekmelerde durum depolamadaki hatalar.
Sekme diğer sekmelerin durumunun üzerine yazdığınızda kafa karıştırıcı davranışı.
localStorage , uygulamanın kapatma ve tarayıcıyı yeniden açma genelinde durumu kalıcı olması gerekiyorsa daha
iyi bir seçenektir.
Tarayıcı depolamayı kullanmaya yönelik uyarılar:
Sunucu tarafı veritabanının kullanımına benzer şekilde veri yükleme ve kaydetme zaman uyumsuzdur.
Sunucu tarafı veritabanının aksine, istenen sayfa prerendering aşamasında tarayıcıda bulunmadığından,
depolama alanı prerendering sırasında kullanılamaz.
Birkaç kilobayt veri depolaması Blazor sunucu uygulamalarında kalıcı hale getiriyoruz. Birkaç kilobayt dışında,
veriler ağ üzerinden yüklenip kaydedildiğinden performans etkilerini göz önünde bulundurmanız gerekir.
Kullanıcılar verileri görüntüleyebilir veya bunlarla karşılaşabilir. ASP.NET Core veri koruma riski azaltabilirler.

Üçüncü taraf tarayıcı depolama çözümleri


Üçüncü taraf NuGet paketleri localStorage ve sessionStorage çalışmaya yönelik API 'Ler sağlar.
ASP.NET Core veri korumasınısaydam olarak kullanan bir paket seçmeyi düşünülüyor. ASP.NET Core veri
koruma, depolanan verileri şifreler ve depolanan verilerle yapılan değişikliklere karşı olası riskleri azaltır. JSON seri
hale getirilmiş veriler düz metin halinde depolanıyorsa, kullanıcılar tarayıcı geliştirici araçlarını kullanarak verileri
görebilir ve depolanan verileri de değiştirebilir. Verilerin güvenliğini sağlamak her zaman bir sorun değildir çünkü
veriler önemsiz olarak olabilir. Örneğin, bir kullanıcı ARABIRIMI öğesinin saklı rengini okumak veya değiştirmek,
Kullanıcı veya kuruluş için önemli bir güvenlik riski değildir. Kullanıcıların hassas verileriincelemesine veya
değiştirmesine izin vermeyi önleyin.

Korumalı tarayıcı depolaması deneysel paket


localStorage ve sessionStorage için veri koruması sağlayan bir NuGet paketi örneği Microsoft. Aspnetcore.
protectedbrowserstorage' dır.

WARNING
Microsoft.AspNetCore.ProtectedBrowserStorage , şu anda üretim kullanımı için uygun olmayan, desteklenmeyen bir
deneysel pakettir.

Yükleme
Microsoft.AspNetCore.ProtectedBrowserStorage paketini yüklemek için:
1. Blazor Server App projesinde, Microsoft. AspNetCore. ProtectedBrowserStorageöğesine bir paket
başvurusu ekleyin.
2. Üst düzey HTML 'de (örneğin, varsayılan Proje şablonundaki Pages/_Host. cshtml dosyasında) aşağıdaki
<script> etiketini ekleyin:

<script src="_content/Microsoft.AspNetCore.ProtectedBrowserStorage/protectedBrowserStorage.js">
</script>

3. Startup.ConfigureServices yönteminde, hizmet koleksiyonuna localStorage ve sessionStorage hizmetleri


eklemek için AddProtectedBrowserStorage çağırın:

services.AddProtectedBrowserStorage();

Bir bileşen içindeki verileri kaydetme ve yükleme


Tarayıcı depolamaya veri yüklemeyi veya kaydetmeyi gerektiren herhangi bir bileşende, aşağıdakilerden birinin bir
örneğini eklemek için @inject kullanın:
ProtectedLocalStorage
ProtectedSessionStorage

Seçim, hangi yedekleme deposunu kullanmak istediğinize bağlıdır. Aşağıdaki örnekte sessionStorage kullanılır:

@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore

@using deyimin bileşen yerine bir _Imports. Razor dosyasına yerleştirilmesi olabilir. _Imports. Razor dosyası
kullanımı, ad alanını uygulamanın daha büyük kesimlerine veya uygulamanın tamamına kullanılabilir hale getirir.
Proje şablonunun Counter bileşenindeki currentCount değerini kalıcı hale getirmek için IncrementCount
yöntemini ProtectedSessionStore.SetAsync kullanılacak şekilde değiştirin:
private async Task IncrementCount()
{
currentCount++;
await ProtectedSessionStore.SetAsync("count", currentCount);
}

Daha büyük, daha gerçekçi uygulamalar, tek tek alanların depolanması ise olası bir senaryodur. Uygulamalar
karmaşık durum içeren tüm model nesnelerini depolamaya daha olasıdır. ProtectedSessionStore JSON verilerini
otomatik olarak serileştirir ve seri hale getirir.
Yukarıdaki kod örneğinde, currentCount verileri kullanıcının tarayıcısında sessionStorage['count'] olarak
depolanır. Veriler düz metin biçiminde depolanmaz, bunun yerine ASP.NET Core veri korumakullanılarak korunur.
Şifrelenmiş veriler, sessionStorage['count'] tarayıcının geliştirici konsolunda değerlendirildiğinde görülebilir.
Kullanıcı Counter bileşene daha sonra geri dönerse currentCount verileri kurtarmak için (tamamen yeni bir
devreye açık olanlar dahil), ProtectedSessionStore.GetAsync kullanın:

protected override async Task OnInitializedAsync()


{
currentCount = await ProtectedSessionStore.GetAsync<int>("count");
}

Bileşenin parametreleri gezinti durumu içeriyorsa, ProtectedSessionStore.GetAsync çağırın ve sonucu


OnInitializedAsync değil OnParametersSetAsync atayın. OnInitializedAsync , bileşen ilk kez oluşturulduğunda
yalnızca bir kez çağırılır. OnInitializedAsync , Kullanıcı aynı sayfada kaldığında farklı bir URL 'ye gittiğinde daha
sonra yeniden çağrılmaz. Daha fazla bilgi için bkz. ASP.NET Core Blazor yaşam döngüsü.

WARNING
Bu bölümdeki örnekler yalnızca sunucuda prerendering etkinleştirilmemişse çalışır. Prerendering etkinken şuna benzer bir
hata oluşturulur:

JavaScript birlikte çalışabilirlik çağrıları şu an için verilemez. Bunun nedeni, bileşenin ön işlenmiş olmasından kaynaklanır.

Prerendering 'ı devre dışı bırakın ya da prerendering ile çalışmak için ek kod ekleyin. Prerendering ile birlikte çalışarak kodu
yazma hakkında daha fazla bilgi için bkz. Handle prerendering bölümü.

Yükleme durumunu işle


Tarayıcı depolaması zaman uyumsuz olduğundan (bir ağ bağlantısı üzerinden erişilir), veriler yüklenmeden ve bir
bileşen tarafından kullanıma sunulmadan önce her zaman bir zaman dilimi vardır. En iyi sonuçlar için, yükleme
sırasında, boş veya varsayılan verileri görüntülemek yerine bir yükleme durumu iletisi işleme devam ediyor.
Bir yaklaşım, verilerin null (hala yükleme) olup olmadığını izlemedir. Varsayılan Counter bileşende, sayı bir int
tutulur. Türe bir soru işareti ( ? ) ekleyerek currentCount null yapılabilir yapın ( int ):

private int? currentCount;

Sayı ve artış düğmesini koşullu olarak görüntülemediğinizden, bu öğeleri yalnızca veriler yüklenmişse
görüntülemeyi seçin:
@if (currentCount.HasValue)
{
<p>Current count: <strong>@currentCount</strong></p>

<button @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}

Tanıtıcı prerendering
Prerendering sırasında:
Kullanıcının tarayıcısına etkileşimli bir bağlantı yok.
Tarayıcıda, JavaScript kodunu çalıştırabildiği bir sayfa yok.
localStorage veya sessionStorage prerendering sırasında kullanılamaz. Bileşen depolama ile etkileşim kurmayı
denerse şuna benzer bir hata oluşturulur:

JavaScript birlikte çalışabilirlik çağrıları şu an için verilemez. Bunun nedeni, bileşenin ön işlenmiş olmasından
kaynaklanır.

Hatayı çözmek için bir yol prerendering devre dışı bırakılır. Bu genellikle uygulama tarayıcı tabanlı depolamanın
yoğun bir şekilde kullanımını yapıyorsa en iyi seçenektir. Prerendering karmaşıklık ekler ve localStorage veya
sessionStorage kullanılabilir olana kadar uygulama yararlı bir içeriğe gidemez.

Prerendering 'yi devre dışı bırakmak için, Pages/_Host. cshtml dosyasını açın ve Component etiketi Yardımcısı
render-mode çağrısını Server olarak değiştirin.

Prerendering 'yi devre dışı bırakmak için, Pages/_Host. cshtml dosyasını açın ve
Html.RenderComponentAsync<App>(RenderMode.Server) çağrısını değiştirin.

Prerendering, localStorage veya sessionStorage kullanmayan diğer sayfalar için yararlı olabilir. Prerendering
etkin tutmak için, tarayıcı devreye bağlanana kadar yükleme işlemini erteleyin. Aşağıda, bir sayaç değeri
depolamak için bir örnek verilmiştir:
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedLocalStorage ProtectedLocalStore

... rendering code goes here ...

@code {
private int? currentCount;
private bool isConnected = false;

protected override async Task OnAfterRenderAsync(bool firstRender)


{
if (firstRender)
{
// When execution reaches this point, the first *interactive* render
// is complete. The component has an active connection to the browser.
isConnected = true;
await LoadStateAsync();
StateHasChanged();
}
}

private async Task LoadStateAsync()


{
currentCount = await ProtectedLocalStore.GetAsync<int>("prerenderedCount");
}

private async Task IncrementCount()


{
currentCount++;
await ProtectedSessionStore.SetAsync("count", currentCount);
}
}

Durum korumasını ortak bir konuma ayırın


Birçok bileşen tarayıcı tabanlı depolamaya güveniyorsa, durum sağlayıcısı kodu birçok kez yeniden uygulama kod
yinelemesi oluşturur. Kod çoğaltmaktan kaçınmanın bir seçeneği, durum sağlayıcısı mantığını kapsülleyen bir
durum sağlayıcısı ana bileşeni oluşturmaktır. Alt bileşenler, durum kalıcılığı mekanizmasına bakılmaksızın kalıcı
verilerle çalışabilir.
Aşağıdaki bir CounterStateProvider bileşeni örneğinde, sayaç verileri kalıcıdır:
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore

@if (hasLoaded)
{
<CascadingValue Value="@this">
@ChildContent
</CascadingValue>
}
else
{
<p>Loading...</p>
}

@code {
private bool hasLoaded;

[Parameter]
public RenderFragment ChildContent { get; set; }

public int CurrentCount { get; set; }

protected override async Task OnInitializedAsync()


{
CurrentCount = await ProtectedSessionStore.GetAsync<int>("count");
hasLoaded = true;
}

public async Task SaveChangesAsync()


{
await ProtectedSessionStore.SetAsync("count", CurrentCount);
}
}

CounterStateProvider bileşeni, yükleme tamamlanana kadar alt içeriğini işlemeden Yükleme aşamasını işler.
CounterStateProvider bileşenini kullanmak için, bileşenin bir örneğini sayaç durumuna erişimi gerektiren diğer
tüm bileşenler etrafında sarmalayın. Bir uygulamadaki tüm bileşenlerin durumunu erişilebilir hale getirmek için,
CounterStateProvider bileşenini App bileşenindeki Router etrafında sarmalayın (app. Razor):

<CounterStateProvider>
<Router AppAssembly="typeof(Startup).Assembly">
...
</Router>
</CounterStateProvider>

Sarmalanan bileşenler, kalıcı sayaç durumunu alır ve değiştirebilir.Aşağıdaki Counter bileşeni, bu kalıbı uygular:
@page "/counter"

<p>Current count: <strong>@CounterStateProvider.CurrentCount</strong></p>

<button @onclick="IncrementCount">Increment</button>

@code {
[CascadingParameter]
private CounterStateProvider CounterStateProvider { get; set; }

private async Task IncrementCount()


{
CounterStateProvider.CurrentCount++;
await CounterStateProvider.SaveChangesAsync();
}
}

Yukarıdaki bileşen ProtectedBrowserStorage etkileşimde bulunmak veya bir "yükleme" aşaması ile uğraşmak için
gerekli değildir.
Daha önce açıklandığı gibi prerendering ile başa çıkmak için CounterStateProvider , sayaç verilerini kullanan tüm
bileşenlerin prerendering ile otomatik olarak çalışmasını sağlayacak şekilde değiştirilebilir. Ayrıntılar için bkz.
Handle prerendering bölümü.
Genel olarak, durum sağlayıcısı üst bileşen deseninin kullanılması önerilir:
Diğer birçok bileşenin durumunu kullanmak için.
Kalıcı olacak yalnızca bir üst düzey durum nesnesi varsa.
Birçok farklı durum nesnesini kalıcı hale getirmek ve farklı yerlerde nesnelerin farklı alt kümelerini kullanmak için,
durumu küresel olarak yükleme ve kaydetme işlemlerini yapmaktan kaçınmak daha iyidir.
ASP.NET Core Blazor uygulamalarda hataları işleme
9.12.2019 • 22 minutes to read • Edit Online

Steve Sanderson tarafından


Bu makalede, işlenmemiş özel durumları Blazor nasıl yönettiği ve hataları algılayan ve işleyen uygulamalar
geliştirileceği açıklanır.

Geliştirme sırasında ayrıntılı hatalar


Geliştirme sırasında Blazor bir uygulama düzgün bir şekilde çalışmadığı zaman, uygulamanın ayrıntılı hata
bilgilerinin alınması sorunu gidermeye ve sorunun giderilmesine yardımcı olur. Bir hata oluştuğunda, Blazor
uygulamalar ekranın alt kısmında altın bir çubuk görüntüler:
Geliştirme sırasında altın çubuk, özel durumu görebileceğiniz tarayıcı konsoluna yönlendirir.
Üretimde, altın çubuk kullanıcıya bir hata oluştuğunu bildirir ve tarayıcıyı yenilemeyi önerir.
Bu hata işleme deneyimi için Kullanıcı arabirimi Blazor projesi şablonlarının bir parçasıdır. Blazor WebAssembly
uygulamasında, Wwwroot/index.html dosyasındaki deneyimi özelleştirin:

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss"> </a>
</div>

Blazor sunucu uygulamasında, Pages/_Host. cshtml dosyasındaki deneyimi özelleştirin:

<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss"> </a>
</div>

blazor-error-ui öğesi Blazor şablonlarına eklenen stillerle gizlenir ve bir hata oluştuğunda gösterilir.

Blazor Framework işlenmemiş özel durumlara nasıl yeniden davranır


Blazor sunucusu durum bilgisi olan bir çerçevedir. Kullanıcılar bir uygulamayla etkileşim kurarken, devreolarak
bilinen sunucuya bir bağlantı sağlar. Devre, etkin bileşen örneklerini ve diğer birçok durum düzeyini barındırır;
örneğin:
Bileşenlerin en son işlenmiş çıktısı.
İstemci tarafı olayları tarafından tetiklenebilecek geçerli olay işleme temsilcileri kümesi.
Bir Kullanıcı uygulamayı birden çok tarayıcı sekmelerinde açarsa, birden çok bağımsız devreler vardır.
Blazor, işlenmemiş özel durumların çoğunu gerçekleştiği devreyi önemli olarak değerlendirir. İşlenmeyen bir özel
durum nedeniyle devre sonlandırılırsa, Kullanıcı yalnızca yeni bir bağlantı oluşturmak için sayfayı yeniden
yükleyerek uygulamayla etkileşime geçerek devam edebilir. Diğer kullanıcılar veya diğer tarayıcı sekmeleri için
devre dışı bırakılmış olan Sonlandırıcı dışındaki devreleri etkilenmez. Bu senaryo, kilitlenen uygulamanın yeniden
başlatılması gereken—, ancak diğer uygulamaların etkilenmemesi gerektiğini engelleyen bir masaüstü
uygulamasına benzerdir.
Aşağıdaki nedenlerden dolayı işlenmeyen bir özel durum oluştuğunda devre sonlandırılır:
İşlenmeyen bir özel durum, genellikle devre dışı bir durumda bırakır.
İşlenmemiş bir özel durumdan sonra uygulamanın normal işlemi garanti edilemez.
Devre devam ederse uygulamada güvenlik açıkları görünebilir.

Geliştirici kodundaki işlenmemiş özel durumları yönetme


Bir uygulamanın bir hatadan sonra devam edebilmesi için, uygulamanın hata işleme mantığı olması gerekir. Bu
makalenin sonraki bölümlerinde işlenmemiş özel durumların olası kaynakları açıklanır.
Üretimde, çerçeve özel durum iletilerini veya yığın izlemelerini Kullanıcı arabiriminde işlemez. Özel durum iletilerini
veya yığın izlemelerini işleme şu şekilde olabilir:
Hassas bilgileri son kullanıcılara açıklayın.
Kötü niyetli bir kullanıcının uygulama, sunucu veya ağ güvenliğini tehlikeye atabilecek bir uygulamada zayıf
yanları bulmasına yardımcı olun.

Kalıcı bir sağlayıcıyla hataları günlüğe kaydet


İşlenmeyen bir özel durum oluşursa, özel durum hizmet kapsayıcısında yapılandırılmış ILogger örneklerine
kaydedilir. Varsayılan olarak, Blazor uygulamalar konsol günlüğü sağlayıcısı ile konsol çıktısına kaydedilir. Günlük
boyutunu ve günlük döndürmesini yöneten bir sağlayıcı ile daha kalıcı bir konuma oturum açmayı düşünün. Daha
fazla bilgi için bkz. .NET Core ve ASP.NET Core oturum açma.
Geliştirme sırasında, Blazor hata ayıklamaya yardımcı olması için genellikle özel durumların tüm ayrıntılarını
tarayıcı konsoluna gönderir. Üretimde, tarayıcı konsolundaki ayrıntılı hatalar varsayılan olarak devre dışıdır. Bu,
hataların istemcilere gönderilmediği, ancak özel durumun tam ayrıntılarının hala sunucu tarafında günlüğe
kaydedildiği anlamına gelir. Daha fazla bilgi için bkz. ASP.NET Core hataları işleme.
Hangi olayların günlüğe kaydedileceğini ve günlüğe kaydedilen olayların önem düzeyi düzeyini karar vermelisiniz.
Saldırgan kullanıcılar hataları kasıtlı olarak tetikleyebiliyor olabilir. Örneğin, ürün ayrıntılarını görüntüleyen bir
bileşenin URL 'sinde bilinmeyen bir ProductId sağlandığı bir hatadan olay günlüğe kaydetme. Tüm hatalar
günlüğe kaydetme için yüksek önem derecesine sahip olaylar olarak değerlendirilmemelidir.

Hataların gerçekleşebileceği yerleri


Çerçeve ve uygulama kodu aşağıdaki konumlardan herhangi birinde işlenmeyen özel durumları tetikleyebiliriz:
Bileşen örneği oluşturma
Yaşam döngüsü yöntemleri
İşleme mantığı
Olay işleyicileri
Bileşen elden çıkarma
JavaScript birlikte çalışma
Devre işleyicileri
Devre elden çıkarma
Prerendering
Önceki işlenmemiş özel durumlar, bu makalenin aşağıdaki bölümlerinde açıklanmıştır.
Bileşen örneği oluşturma
Blazor bir bileşenin örneğini oluşturduğunda:
Bileşenin Oluşturucusu çağrılır.
@inject yönergesi veya [Inject] özniteliği aracılığıyla bileşen oluşturucusuna sağlanan Singleton olmayan
her türlü hizmeti Oluşturucu.
Herhangi bir [Inject] özelliği için yürütülen bir Oluşturucu veya ayarlayıcı işlenmeyen bir özel durum
oluşturduğunda devre dışı olur. Framework bileşeni örneklemediğinden özel durum önemlidir. Oluşturucu mantığı
özel durumlar oluşturmayabilir, uygulama hata işleme ve günlüğe kaydetme ile try-catch ifadesini kullanarak özel
durumları yakalemelidir.
Yaşam döngüsü yöntemleri
Bir bileşenin kullanım ömrü boyunca Blazor aşağıdaki yaşam döngüsü yöntemleriniçağırır:
OnInitialized / OnInitializedAsync
OnParametersSet / OnParametersSetAsync
ShouldRender / ShouldRenderAsync
OnAfterRender / OnAfterRenderAsync

Herhangi bir yaşam döngüsü yöntemi, zaman uyumlu veya zaman uyumsuz olarak bir özel durum oluşturursa, özel
durum devre dışı olur. Bileşenler için yaşam döngüsü yöntemlerinde hatalarla başa çıkmak için hata işleme mantığı
ekleyin.
Aşağıdaki örnekte OnParametersSetAsync bir ürünü almak için bir yöntemi çağırır:
ProductRepository.GetProductByIdAsync yönteminde oluşan bir özel durum try-catch ifadesiyle işlenir.
catch bloğu yürütüldüğünde:
loadFailed , kullanıcıya bir hata iletisi göstermek için kullanılan true olarak ayarlanır.
Hata günlüğe kaydedilir.
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject IProductRepository ProductRepository
@inject ILogger<ProductDetails> Logger

@if (details != null)


{
<h1>@details.ProductName</h1>
<p>@details.Description</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}

@code {
private ProductDetails details;
private bool loadFailed;

[Parameter]
public int ProductId { get; set; }

protected override async Task OnParametersSetAsync()


{
try
{
loadFailed = false;
details = await ProductRepository.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
}

İşleme mantığı
.razor bileşen dosyasındaki bildirim temelli biçimlendirme BuildRenderTree adlı bir C# yönteme derlenir. Bir
bileşen işlendiğinde BuildRenderTree yürütülür ve işlenmiş bileşenin öğelerini, metnini ve alt bileşenlerini açıklayan
bir veri yapısı oluşturur.
İşleme mantığı bir özel durum oluşturabilir. @someObject.PropertyName değerlendiriliyorsa ancak @someObject null
bu senaryoya bir örnek oluşur. İşleme mantığı tarafından oluşturulan işlenmeyen bir özel durum, devre için önemli
bir durumdur.
Oluşturma mantığındaki null başvuru özel durumunu engellemek için, üyelerine erişmeden önce bir null
nesnesini denetleyin. Aşağıdaki örnekte, person.Address null``person.Address özelliklere erişilmez:

@if (person.Address != null)


{
<div>@person.Address.Line1</div>
<div>@person.Address.Line2</div>
<div>@person.Address.City</div>
<div>@person.Address.Country</div>
}

Yukarıdaki kod, person null olmadığını varsayar. Genellikle, kodun yapısı, bileşenin işlendiği sırada bir nesnenin
var olmasını garanti eder. Bu durumlarda, işleme mantığındaki null denetlemek gerekli değildir. Önceki örnekte,
bileşen örneği oluşturulduğunda person oluşturulduğu için person olması garanti edilebilir.
Olay işleyicileri
İstemci tarafı kod, kullanarak olay işleyicileri C# oluşturulduğunda kodun çağırmaları tetikler:
@onclick
@onchange
Diğer @on... öznitelikleri
@bind

Olay işleyici kodu, bu senaryolarda işlenmeyen bir özel durum oluşturabilir.


Bir olay işleyicisi işlenmeyen bir özel durum oluşturursa (örneğin, bir veritabanı sorgusu başarısız olursa), özel
durum devre dışı olarak önemli olur. Uygulama, dış nedenlerle başarısız olabilecek kodu çağırırsa, hata işleme ve
günlüğe kaydetme ile try-catch ifadesini kullanarak özel durumlar yakalayın.
Kullanıcı kodu yakalanmazsa ve özel durumu işlemezse çerçeve özel durumu günlüğe kaydeder ve devre
sonlandırır.
Bileşen elden çıkarma
Örneğin, Kullanıcı başka bir sayfaya gezindiği için, bir bileşen kullanıcı arabiriminden kaldırılabilir.
System.IDisposable uygulayan bir bileşen kullanıcı arabiriminden kaldırıldığında, çerçeve bileşenin Dispose
yöntemini çağırır.
Bileşenin Dispose yöntemi işlenmeyen bir özel durum oluşturursa, bu özel durum devre dışı olarak önemli olur.
Çıkarma mantığı özel durumlar oluşturmayabilir, uygulama hata işleme ve günlüğe kaydetme ile try-catch ifadesini
kullanarak özel durumları yakalemelidir.
Bileşen aktiften çıkarma hakkında daha fazla bilgi için bkz. ASP.NET Core Blazor yaşam döngüsü.
JavaScript ile birlikte çalışma
IJSRuntime.InvokeAsync<T> , .NET kodunun Kullanıcı tarayıcısındaki JavaScript çalışma zamanına zaman uyumsuz
çağrılar yapmasına izin verir.
InvokeAsync<T> ile ilgili hata işleme için aşağıdaki koşullar geçerlidir:
InvokeAsync<T> çağrısı eşzamanlı olarak başarısız olursa, .NET özel durumu oluşur. InvokeAsync<T> çağrısı
başarısız olabilir, örneğin, sağlanan bağımsız değişkenler serileştirilemiyor. Geliştirici kodu özel durumu
yakalamalı. Bir olay işleyicisindeki veya bileşen yaşam döngüsü yöntemindeki uygulama kodu bir özel durumu
işlemezse, ortaya çıkan özel durum devre dışı olur.
InvokeAsync<T> çağrısı zaman uyumsuz olarak başarısız olursa, .NET Task başarısız olur. Örneğin, JavaScript
tarafı kodu bir özel durum oluşturduğundan veya rejected olarak tamamlanan bir Promise döndürdüğünden
InvokeAsync<T> çağrısı başarısız olabilir. Geliştirici kodu özel durumu yakalamalı. Await işleci kullanılıyorsa,
yöntem çağrısını hata işleme ve günlüğe kaydetme ile try-catch ifadesinde sarmalamalı olarak düşünün. Aksi
takdirde, başarısız kod, devre için önemli olan işlenmemiş bir özel durumla sonuçlanır.
Varsayılan olarak, InvokeAsync<T> çağrıları belirli bir süre içinde tamamlanmalıdır veya çağrı zaman aşımına
uğrar. Varsayılan zaman aşımı süresi bir dakikadır. Zaman aşımı, kodu ağ bağlantısında veya hiçbir zaman bir
tamamlanma iletisi göndermeme JavaScript kodundaki bir kaybına karşı korur. Çağrı zaman aşımına uğrarsa,
elde edilen Task bir OperationCanceledExceptionbaşarısız olur. Günlüğe kaydetme ile özel durumu yakalar ve
işleyin.
Benzer şekilde, JavaScript kodu [JSInvokable] özniteliği tarafından belirtilen .net yöntemlerine çağrı başlatabilir.
Bu .NET yöntemleri işlenmeyen bir özel durum oluşturur:
Özel durum devre için önemli olarak değerlendirilmez.
JavaScript tarafı Promise reddedilir.
.NET tarafında ya da yöntem çağrısının JavaScript tarafında hata işleme kodu kullanma seçeneğiniz vardır.
Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği.
Devre işleyicileri
Blazor, bir kullanıcının devresi durumu değiştiğinde bildirimleri alan bir devre işleyicisitanımlamasına olanak tanır.
Aşağıdaki durumlar kullanılır:
initialized
connected
disconnected
disposed

Bildirimler, CircuitHandler soyut temel sınıfından devralan bir DI hizmeti kaydedilerek yönetilir.
Özel bir devre işleyicisindeki Yöntemler işlenmeyen bir özel durum oluşturuyorsam, özel durum devre için önemli
olur. Bir işleyicinin kodundaki veya yöntemleri çağrılan özel durumlara tolerans sağlamak için kodu bir veya daha
fazla try-catch deyiminde hata işleme ve günlüğe kaydetme ile sarın.
Devre elden çıkarma
Bir kullanıcının bağlantısı kesilmediği ve Framework devre durumunu temizlemede bir devre dışı bırakıldığında,
çerçeve devre dışı bırakıldı. Kapsamı elden atılırken, System.IDisposableuygulayan hiçbir devre kapsamlı DI hizmeti
yok. Herhangi bir DI hizmeti, elden çıkarma sırasında işlenmeyen bir özel durum oluşturursa, çerçeve özel durumu
günlüğe kaydeder.
Prerendering
Blazor bileşenleri, Component etiketi Yardımcısı kullanılarak, işlenmiş HTML biçimlendirmesinin kullanıcının ilk
HTTP isteğinin bir parçası olarak döndürülmesi için önceden kullanılabilir. Bu şu şekilde geçerlidir:
Aynı sayfanın parçası olan tüm ön işlenmiş bileşenler için yeni bir devre oluşturma.
İlk HTML oluşturuluyor.
Kullanıcı tarayıcısının aynı sunucuya geri SignalR bir bağlantı kuruncaya kadar devreyi disconnected olarak
kabul edin. Bağlantı oluşturulduğunda, devre üzerindeki etkileşim sürdürülür ve bileşenlerin HTML işaretlemesi
güncelleştirilir.
Herhangi bir bileşen prerendering sırasında, örneğin bir yaşam döngüsü yöntemi veya işleme mantığı sırasında
işlenmeyen bir özel durum oluşturursa:
Bu, devre için önemli bir durumdur.
Özel durum, Component Tag Yardımcısı 'ndan çağrı yığınını ortaya atılır. Bu nedenle, özel durum geliştirici kodu
tarafından açıkça yakalanmadığı takdirde tüm HTTP isteği başarısız olur.
Normal koşullarda, prerendering başarısız olduğunda bileşeni oluşturma ve işleme devam etmek, çalışan bir
bileşen işlenemediği için mantıklı değildir.
Prerendering sırasında oluşabilecek hatalara tolerans sağlamak için hata işleme mantığı özel durum oluşturabilecek
bir bileşenin içine yerleştirilmelidir. Try-catch deyimlerini hata işleme ve günlüğe kaydetme ile kullanın. Bir
try-catch bildiriminde Component etiketi yardımcısını sarmalama yerine, Component etiketi Yardımcısı tarafından
işlenen bileşene hata işleme mantığını koyun.
Blazor bileşenleri, işlenmiş HTML işaretlemesi kullanıcının ilk HTTP isteğinin bir parçası olarak döndürüldüğünden
Html.RenderComponentAsync kullanılarak önceden uygulanabilir. Bu şu şekilde geçerlidir:

Aynı sayfanın parçası olan tüm ön işlenmiş bileşenler için yeni bir devre oluşturma.
İlk HTML oluşturuluyor.
Kullanıcı tarayıcısının aynı sunucuya geri SignalR bir bağlantı kuruncaya kadar devreyi disconnected olarak
kabul edin. Bağlantı oluşturulduğunda, devre üzerindeki etkileşim sürdürülür ve bileşenlerin HTML işaretlemesi
güncelleştirilir.
Herhangi bir bileşen prerendering sırasında, örneğin bir yaşam döngüsü yöntemi veya işleme mantığı sırasında
işlenmeyen bir özel durum oluşturursa:
Bu, devre için önemli bir durumdur.
Özel durum, Html.RenderComponentAsync çağrısından çağrı yığınını ortaya atılır. Bu nedenle, özel durum geliştirici
kodu tarafından açıkça yakalanmadığı takdirde tüm HTTP isteği başarısız olur.
Normal koşullarda, prerendering başarısız olduğunda bileşeni oluşturma ve işleme devam etmek, çalışan bir
bileşen işlenemediği için mantıklı değildir.
Prerendering sırasında oluşabilecek hatalara tolerans sağlamak için hata işleme mantığı özel durum oluşturabilecek
bir bileşenin içine yerleştirilmelidir. Try-catch deyimlerini hata işleme ve günlüğe kaydetme ile kullanın. try-catch
bildiriminde RenderComponentAsync çağrısını sarmalama yerine, RenderComponentAsync tarafından işlenen bileşene
hata işleme mantığını koyun.

Gelişmiş senaryolar
Özyinelemeli işleme
Bileşenler yinelemeli olarak iç içe olabilir. Bu, özyinelemeli veri yapılarını temsil etmek için kullanışlıdır. Örneğin, bir
TreeNode bileşeni, düğüm alt öğelerinin her biri için daha fazla TreeNode bileşeni işleyebilir.

Yinelemeli olarak işlenirken, sonsuz özyineleme sonucu veren kodlama desenlerinden kaçının:
Bir döngüyü içeren bir veri yapısını yinelemeli olarak işlemez. Örneğin, alt öğeleri içeren bir ağaç düğümünü
işlemez.
Bir döngüyü içeren bir düzen zinciri oluşturmayın. Örneğin, düzeni kendisi olan bir düzen oluşturmayın.
Son kullanıcının, kötü amaçlı veri girişi veya JavaScript birlikte çalışabilirlik çağrıları aracılığıyla
özyineleme/varyantları (kurallar) ihlal etmemenizi izin verme.
Oluşturma sırasında sonsuz döngüler:
İşleme işleminin süresiz olarak devam etmesine neden olur.
Sonlandırılmamış bir döngü oluşturmaya eşdeğerdir.
Bu senaryolarda, etkilenen devre askıda kalır ve iş parçacığı genellikle şunları yapmayı dener:
Süresiz olarak işletim sisteminin izin verdiği CPU süresini çok fazla kullanın.
Sınırsız miktarda sunucu belleği tükettin. Sınırsız bellek tüketme, Sonlandırılmamış bir döngünün her
yinelemede bir koleksiyona giriş eklediği senaryoya eşdeğerdir.
Sonsuz özyineleme desenlerinin önüne geçmek için, özyinelemeli işleme kodunun uygun durdurma koşullarını
içerdiğinden emin olun.
Özel işleme ağacı mantığı
Çoğu Blazor bileşen . Razor dosyaları olarak uygulanır ve çıktılarını oluşturmak için RenderTreeBuilder üzerinde
çalışan Logic üretmek için derlenir. Bir geliştirici, yordamsal C# kodu kullanarak RenderTreeBuilder mantığını el ile
uygulayabilir. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenleri oluşturma ve kullanma.
WARNING
El ile işleme ağacı Oluşturucu mantığının kullanımı, genel bileşen geliştirme için önerilmeyen gelişmiş ve güvenli olmayan bir
senaryo olarak değerlendirilir.

RenderTreeBuilder kod yazılmışsa, geliştirici kodun doğruluğunu garanti etmelidir. Örneğin, geliştirici şunları
sağlamalıdır:
OpenElement ve CloseElement çağrıları doğru dengelenir.
Öznitelikler yalnızca doğru yerlere eklenir.
Hatalı elle işleme ağacı Oluşturucu mantığı kilitlenmeler, sunucu askıda kalma ve güvenlik açıkları dahil rastgele
tanımsız davranışa neden olabilir.
El ile işleme ağacı Oluşturucu mantığını aynı karmaşıklık düzeyinde ve aynı tehlike düzeyiyle, el ile derleme kodu
veya MSIL yönergeleri yazarak değerlendirin.
Hata ayıklama ASP.NET Core Blazor
13.11.2019 • 5 minutes to read • Edit Online

Daniel Roth

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Chrome 'da WebAssembly üzerinde çalışan Blazor WebAssembly uygulamalarında hata ayıklama için erken destek
bulunur.
Hata ayıklayıcı özellikleri sınırlıdır. Kullanılabilir senaryolar şunlardır:
Kesme noktaları ayarlayın ve kaldırın.
Kod veya özgeçmişden ( F8 ) kod yürütme aracılığıyla tek adımlı ( F10 ).
Yereller görünümü ' nde, int , string ve bool türündeki tüm yerel değişkenlerin değerlerini gözlemleyin.
JavaScript 'ten .NET 'e ve .NET 'ten JavaScript 'e gidecek çağrı zincirleri dahil olmak üzere çağrı yığınına bakın.
Şunları yapamazsınız:
int, string veya bool olmayan herhangi bir yerelin değerlerini gözlemleyin.
Herhangi bir sınıf özelliklerinin veya alanının değerlerini gözlemleyin.
Değerlerini görmek için değişkenlerin üzerine gelin.
Konsolunda ifadeleri değerlendirin.
Zaman uyumsuz çağrılar arasında adımla.
Diğer birçok sıradan hata ayıklama senaryosunu gerçekleştirin.
Daha fazla hata ayıklama senaryosu geliştirmesi, mühendislik ekibinin bir odadır.

Prerequisites
Hata ayıklama aşağıdaki tarayıcılardan birini gerektirir:
Google Chrome (sürüm 70 veya üzeri)
Microsoft Edge Önizlemesi (Edge geliştirme kanalı)

Yordam
1. Debug yapılandırmasında bir Blazor WebAssembly uygulaması çalıştırın. --configuration Debug seçeneğini
DotNet Run komutuna geçirin: dotnet run --configuration Debug .
2. Uygulamaya tarayıcıda erişin.
3. Klavye odağını geliştirici araçları paneline değil uygulamaya yerleştirin. Hata ayıklama başlatıldığında geliştirici
araçları paneli kapatılabilir.
4. Aşağıdaki Blazorözgü klavye kısayolunu seçin:
Windows/Linux üzerinde Shift+Alt+D
macOS üzerinde Shift+Cmd+D
5. Uzaktan hata ayıklama etkinken tarayıcıyı yeniden başlatmak için ekranda listelenen adımları izleyin.
6. Hata ayıklama oturumu başlatmak için aşağıdaki Blazorözgü klavye kısayolunu bir kez daha seçin:
Windows/Linux üzerinde Shift+Alt+D
macOS üzerinde Shift+Cmd+D

Uzaktan hata ayıklamayı etkinleştir


Uzaktan hata ayıklama devre dışıysa, hata ayıklanabilir Browser sekmesi hata sayfası Chrome tarafından
oluşturulur. Hata sayfası, hata ayıklama proxy 'sinin uygulamaya bağlanabilmesi için hata ayıklama bağlantı noktası
Blazor açıkken Chrome çalıştırmaya yönelik yönergeler içerir. Tüm Chrome örneklerini kapatın ve belirtildiği
şekilde Chrome 'u yeniden başlatın.

Uygulamada hata ayıklama


Uzaktan hata ayıklama etkinken Chrome çalışmaya başladıktan sonra hata ayıklama klavye kısayolu yeni bir hata
ayıklayıcı sekmesi açar. Bir süre sonra, kaynaklar sekmesi uygulamadaki .net derlemelerinin listesini gösterir. Her
bir derlemeyi genişletin ve hata ayıklama için kullanılabilen . cs/ . Razor kaynak dosyalarını bulun. Kesme noktaları
ayarlayın, uygulamanın sekmesine geri dönün ve kod yürütüldüğünde kesme noktaları isabet edilir. Kesme noktası
isabet ettikten sonra, kod veya özgeçmişden ( F8 ) kod yürütme işlemi normal şekilde tek adımlı ( F10 ).
Blazor, Chrome DevTools protokolünü uygulayan ve protokolünü ile genişletgetiren bir hata ayıklama proxy 'si
sağlar. NET 'e özgü bilgiler. Klavye kısayolunun hata ayıklaması basıldığında Blazor, ara sunucu üzerindeki Chrome
DevTools 'u gösterir. Proxy, hata ayıklama işlemini Aradığınız tarayıcı penceresine bağlanır (Bu nedenle, uzaktan
hata ayıklamayı etkinleştirmeniz gerekir).

Tarayıcı kaynağı eşlemeleri


Tarayıcı kaynak haritaları tarayıcının derlenmiş dosyaları özgün kaynak dosyalarına geri eşlemesine ve istemci tarafı
hata ayıklama için yaygın olarak kullanılmasına izin verir. Ancak, Blazor Şu anda doğrudan C# JavaScript/, ile
eşlenmiyor. Bunun yerine, Blazor, kaynak haritaları ilgili değil, tarayıcı içinde Il yorumu yapar.

Sorun giderme ipucu


Hatalar halinde çalıştırıyorsanız, aşağıdaki ipucu yardımcı olabilir:
Hata ayıklayıcı sekmesinde, tarayıcınızda Geliştirici Araçları ' nı açın. Konsolunda, tüm kesme noktalarını
kaldırmak için localStorage.clear() yürütün.
ASP.NET Core Blazor bir Web API 'SI çağırma
9.12.2019 • 8 minutes to read • Edit Online

Luke Latham, Daniel Rothve Juan de la Cruz tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor WebAssembly Apps, önceden yapılandırılmış bir HttpClient hizmetini kullanarak Web API 'lerini çağırır.
Blazor JSON yardımcıları veya HttpRequestMessagekullanarak JavaScript getirme API 'si seçeneklerini içerebilen
oluşturma istekleri.
Blazor Server Apps, genellikle IHttpClientFactorykullanılarak oluşturulan HttpClient örneklerini kullanarak Web
API 'lerini çağırır. Daha fazla bilgi için bkz. ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP istekleri yapın.
Örnek kodu görüntüleyin veya indirin (nasıl Indirilir) – BlazorWebAssemblySample uygulamasını seçin.
BlazorWebAssemblySample örnek uygulamasında aşağıdaki bileşenlere bakın:
Web API çağrısı (Pages/CallWebAPI. Razor)
HTTP Isteği Sınayıcısı (Bileşenler/HTTPRequestTester. Razor)

Paketler
Deneysel Microsoft. aspnetcore.Blazorbaşvurun. Proje dosyasındaki HttpClient NuGet paketi.
Microsoft.AspNetCore.Blazor.HttpClient , HttpClient ve System. Text. JSONtabanlıdır.

Kararlı bir API kullanmak için, Newtonsoft. Json/JSON.netkullanan Microsoft. Aspnet. WebApi. Client paketini
kullanın. Microsoft.AspNet.WebApi.Client ' de kararlı API kullanmak, bu konu başlığı altında açıklanan, deneysel
Microsoft.AspNetCore.Blazor.HttpClient paketine özgü olan JSON yardımcıları sağlamaz.

HttpClient ve JSON yardımcıları


Blazor WebAssembly uygulamasında, HttpClient , istekleri kaynak sunucuya geri getirmek için önceden
yapılandırılmış bir hizmet olarak kullanılabilir.
Blazor sunucusu uygulaması, varsayılan olarak bir HttpClient hizmeti içermez. HttpClient Factory
altyapısınıkullanarak uygulamaya HttpClient sağlayın.
HttpClient ve JSON yardımcıları, üçüncü taraf Web API uç noktalarını çağırmak için de kullanılır. HttpClient ,
tarayıcı getirme API 'si kullanılarak uygulanır ve aynı kaynak ilkesini zorlama dahil olmak üzere sınırlamalarına
tabidir.
İstemcinin temel adresi, kaynak sunucunun adresine ayarlanır. @inject yönergesini kullanarak bir HttpClient
örneği ekleme:

@using System.Net.Http
@inject HttpClient Http
Aşağıdaki örneklerde, bir Todo Web API 'SI oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemlerini işler.
Örnekler, aşağıdakileri depolayan bir TodoItem sınıfına dayalıdır:
Öğenin benzersiz KIMLIĞI – KIMLIK ( Id , long ).
Öğenin adı ( Name``string ) – adı.
Durum ( IsComplete , bool ) Todo öğesi tamamlandığında gösterge –.

private class TodoItem


{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}

JSON yardımcı yöntemleri bir URI 'ye (aşağıdaki örneklerde bir Web API 'si) istek gönderir ve yanıtı işler:
GetJsonAsync – bir HTTP GET isteği gönderir ve bir nesne oluşturmak için JSON yanıt gövdesini ayrıştırır.
Aşağıdaki kodda _todoItems bileşen tarafından görüntülenir. GetTodoItems yöntemi, bileşen işlemeyi
tamamladığında tetiklenir (Onınitializedadsync). Örnek uygulamaya bkz. örnek uygulama.

@using System.Net.Http
@inject HttpClient Http

@code {
private TodoItem[] _todoItems;

protected override async Task OnInitializedAsync() =>


_todoItems = await Http.GetJsonAsync<TodoItem[]>("api/TodoItems");
}

PostJsonAsync –, JSON kodlu içerik dahil olmak üzere bir HTTP POST isteği gönderir ve bir nesne
oluşturmak için JSON yanıt gövdesini ayrıştırır.
Aşağıdaki kodda, _newItemName bileşenin bağlantılı bir öğesi tarafından sağlanır. AddItem yöntemi bir
<button> öğesi seçilerek tetiklenir. Örnek uygulamaya bkz. örnek uygulama.

@using System.Net.Http
@inject HttpClient Http

<input @bind="_newItemName" placeholder="New Todo Item" />


<button @onclick="@AddItem">Add</button>

@code {
private string _newItemName;

private async Task AddItem()


{
var addItem = new TodoItem { Name = _newItemName, IsComplete = false };
await Http.PostJsonAsync("api/TodoItems", addItem);
}
}

PutJsonAsync –, JSON kodlu içerik dahil olmak üzere bir HTTP PUT isteği gönderir.
Aşağıdaki kodda, Name ve IsCompleted değerlerinin _editItem , bileşenin bağlantılı öğeleri tarafından
sağlanır. Öğenin Id , öğe Kullanıcı arabiriminin başka bir bölümünde seçildiğinde ve EditItem
çağrıldığında ayarlanır. SaveItem yöntemi, Kaydet <button> öğesi seçilerek tetiklenir. Örnek uygulamaya
bkz. örnek uygulama.
@using System.Net.Http
@inject HttpClient Http

<input type="checkbox" @bind="_editItem.IsComplete" />


<input @bind="_editItem.Name" />
<button @onclick="@SaveItem">Save</button>

@code {
private TodoItem _editItem = new TodoItem();

private void EditItem(long id)


{
var editItem = _todoItems.Single(i => i.Id == id);
_editItem = new TodoItem { Id = editItem.Id, Name = editItem.Name,
IsComplete = editItem.IsComplete };
}

private async Task SaveItem() =>


await Http.PutJsonAsync($"api/TodoItems/{_editItem.Id}, _editItem);
}

System.Net.Http, HTTP istekleri göndermeye ve HTTP yanıtlarını almaya yönelik ek uzantı yöntemleri içerir.
HttpClient. DeleteAsync , BIR Web API 'SINE http delete isteği göndermek için kullanılır.
Aşağıdaki kodda, DELETE <button> öğesi DeleteItem yöntemini çağırır. Bağlantılı <input> öğesi, silinecek
öğenin id sağlar. Örnek uygulamaya bkz. örnek uygulama.

@using System.Net.Http
@inject HttpClient Http

<input @bind="_id" />


<button @onclick="@DeleteItem">Delete</button>

@code {
private long _id;

private async Task DeleteItem() =>


await Http.DeleteAsync($"api/TodoItems/{_id}");
}

Çıkış noktaları arası kaynak paylaşımı (CORS)


Tarayıcı güvenliği, bir Web sayfasının, Web sayfasını sunduğundan farklı bir etki alanına istek yapmasını engeller.
Bu kısıtlamaya aynı-Origin ilkesiadı verilir. Aynı-kaynak ilkesi, kötü niyetli bir sitenin gizli verileri başka bir siteden
okumasını engeller. Tarayıcıdan farklı bir kaynağa sahip bir uç noktaya istek yapmak için uç noktanın , çıkış
noktaları arası kaynak PAYLAŞıMı 'nı (CORS )etkinleştirmesi gerekir.
Blazor WebAssembly örnek uygulaması (BlazorWebAssemblySample) , Web API bileşeninde CORS 'nin
kullanımını gösterir (Pages/callwebapi. Razor).
Diğer sitelerin uygulamanıza çıkış noktaları arası kaynak paylaşımı (CORS ) istekleri yapmasına izin vermek için
bkz. ASP.NET Core 'de çıkış noktaları arası Istekleri (CORS ) etkinleştirme.

API istek seçeneklerini getiren HttpClient ve HttpRequestMessage


Blazor WebAssembly uygulamasında WebAssembly üzerinde çalışırken, istekleri özelleştirmek için HttpClient ve
HttpRequestMessage kullanın. Örneğin, istek URI 'SI, HTTP yöntemi ve istenen istek üst bilgilerini belirtebilirsiniz.
@using System.Net.Http
@using System.Net.Http.Headers
@inject HttpClient Http

@code {
private async Task PostRequest()
{
Http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "{OAUTH TOKEN}");

var requestMessage = new HttpRequestMessage()


{
Method = new HttpMethod("POST"),
RequestUri = new Uri("https://localhost:10000/api/TodoItems"),
Content =
new StringContent(
@"{""name"":""A New Todo Item"",""isComplete"":false}")
};

requestMessage.Content.Headers.ContentType =
new System.Net.Http.Headers.MediaTypeHeaderValue(
"application/json");

requestMessage.Content.Headers.TryAddWithoutValidation(
"x-custom-header", "value");

var response = await Http.SendAsync(requestMessage);


var responseStatusCode = response.StatusCode;
var responseBody = await response.Content.ReadAsStringAsync();
}
}

API seçenekleri getirme hakkında daha fazla bilgi için bkz. MDN Web belgeleri: WindowOrWorkerGlobalScope.
Fetch ():P arameters.
CORS isteklerinde kimlik bilgileri (yetkilendirme tanımlama bilgileri/üstbilgileri) gönderilirken, CORS ilkesi
tarafından Authorization üst bilgisine izin verilmelidir.
Aşağıdaki ilke için yapılandırma içerir:
İstek kaynakları ( http://localhost:5000 , https://localhost:5001 ).
Any yöntemi (fiil).
Content-Type ve Authorization üst bilgileri. Özel bir üstbilgiye (örneğin, x-custom-header ) izin vermek için,
WithHeadersçağrılırken üstbilgiyi listeleyin.
İstemci tarafı JavaScript kodu tarafından ayarlanan kimlik bilgileri ( credentials Özellik include olarak
ayarlanır).

app.UseCors(policy =>
policy.WithOrigins("http://localhost:5000", "https://localhost:5001")
.AllowAnyMethod()
.WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, "x-custom-header")
.AllowCredentials());

Daha fazla bilgi için bkz. ASP.NET Core 'de çıkış noktaları arası Istekleri (CORS ) etkinleştirme ve örnek
uygulamanın HTTP Isteği Sınayıcısı bileşeni (Bileşenler/HTTPRequestTester. Razor).

Ek kaynaklar
ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP istekleri yapın
ASP.NET Core 'de HTTPS 'yi zorla
Kestrel HTTPS uç noktası yapılandırması
W3C üzerinde çapraz kaynak kaynak paylaşımı (CORS )
ASP.NET Core Blazor barındırma ve dağıtma
27.11.2019 • 5 minutes to read • Edit Online

, Luke Latham, Rainer Stropekve Daniel Roth tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Uygulamayı yayımlama
Uygulamalar yayın yapılandırmasında dağıtım için yayımlanır.
Visual Studio
.NET Core CLI
1. Gezinti çubuğundan derleme > {APPLICATION } Yayımla ' yı seçin.
2. Yayımla hedefiniseçin. Yerel olarak yayımlamak için klasör' ü seçin.
3. Klasör seçin alanında varsayılan konumu kabul edin veya farklı bir konum belirtin. Yayımla düğmesini seçin.
Uygulamanın yayımlanması, projenin bağımlılıklarını geri yüklemeyi tetikler ve dağıtım için varlıkları oluşturmadan
önce projeyi oluşturur . Yapı işleminin bir parçası olarak, uygulama indirme boyutunu ve yükleme sürelerini
azaltmak için kullanılmayan Yöntemler ve derlemeler kaldırılır.
Blazor WebAssembly uygulaması /BIN/Release/{Target Framework}/publish/{ASSEMBLY Name}/Dist klasörüne
yayımlanır. Bir Blazor sunucusu uygulaması /BIN/Release/{Target Framework}/Publish klasörüne yayımlanır.
Klasördeki varlıklar Web sunucusuna dağıtılır. Dağıtım, kullanımdaki geliştirme araçlarına bağlı olarak el ile veya
otomatik bir süreç olabilir.

Uygulama temel yolu


Uygulama temel yolu , UYGULAMANıN kök URL yoludur. Aşağıdaki ASP.NET Core uygulamayı ve Blazor alt
uygulamayı göz önünde bulundurun:
ASP.NET Core uygulamasının adı MyApp :
Uygulama fiziksel olarak d:/MyAppkonumunda bulunur.
İstekler https://www.contoso.com/{MYAPP RESOURCE} alındı.
CoolApp adlı bir Blazor uygulaması, MyApp alt uygulamasıdır:
Alt uygulama fiziksel olarak d:/MyApp/CoolAppkonumunda bulunur.
İstekler https://www.contoso.com/CoolApp/{COOLAPP RESOURCE} alındı.
CoolApp için ek yapılandırma belirtmeden, Bu senaryodaki alt uygulama, sunucuda nerede bulunduğu konusunda
bilgi sahibi değildir. Örneğin, uygulama, /CoolApp/ göreli URL yolunda bulunduğunu bilmeden kaynaklarına doğru
göreli URL 'Ler oluşturamıyoruz.
Blazor uygulamasının temel https://www.contoso.com/CoolApp/ yolu için yapılandırma sağlamak üzere <base>
etiketinin href özniteliği Pages/_Host. cshtml dosyasında (Blazor Server) veya wwwroot/index.html dosyasında
(Blazor webassembly) göreli kök yolu olarak ayarlanır:
<base href="/CoolApp/">

Blazor sunucu uygulamaları, uygulamanın Startup.Configure istek ardışık düzeninde UsePathBase çağırarak
sunucu tarafı taban yolunu da ayarlar:

app.UsePathBase("/CoolApp");

Göreli URL yolunu sağlayarak, kök dizinde olmayan bir bileşen, uygulamanın kök yoluna göre URL 'Ler
oluşturabilir. Farklı dizin yapısı düzeylerindeki bileşenler, uygulama genelinde konumlardaki diğer kaynakların
bağlantılarını oluşturabilir. Uygulama temel yolu Ayrıca, bağlantının href hedefinin uygulama temel yolu URI alanı
içinde olduğu seçili köprüleri ele almak için de kullanılır. Blazor yönlendirici iç gezintiyi işler.
Birçok barındırma senaryosunda, uygulamanın göreli URL yolu uygulamanın köküdür. Bu durumlarda,
uygulamanın göreli URL taban yolu bir Blazor uygulamasının varsayılan yapılandırması olan eğik çizgi (
<base href="/" /> ) olur. GitHub sayfaları ve IIS alt uygulamaları gibi diğer barındırma senaryolarında, uygulama
temel yolu, sunucunun uygulamanın göreli URL 'SI yolu olarak ayarlanmalıdır.
Uygulamanın temel yolunu ayarlamak için, Pages/_Host. cshtml dosyasının (Blazor Server) veya
wwwroot/index.html dosyasının (Blazor webassembly) <head> etiketi öğeleri içindeki <base> etiketini
güncelleştirin. href öznitelik değerini /{RELATIVE URL PATH}/ olarak ayarlayın (sondaki eğik çizgi gereklidir),
burada {RELATIVE URL PATH} uygulamanın tam göreli URL yoludur.
Kök olmayan göreli URL yolu (örneğin, <base href="/CoolApp/"> ) olan bir Blazor WebAssembly uygulaması için,
uygulama yerel olarak çalıştırıldığındakaynaklarını bulamaz. Yerel geliştirme ve test sırasında bu sorunu aşmak için,
çalışma zamanında <base> etiketinin href değeriyle eşleşen bir yol temel bağımsız değişkeni sağlayabilirsiniz.
Sondaki eğik çizgi eklemeyin. Uygulamayı yerel olarak çalıştırırken yol temel bağımsız değişkenini geçirmek için,
--pathbase seçeneğiyle uygulamanın dizininden dotnet run komutunu yürütün:

dotnet run --pathbase=/{RELATIVE URL PATH (no trailing slash)}

Göreli URL yolu /CoolApp/ ( <base href="/CoolApp/"> ) olan bir Blazor WebAssembly uygulaması için, komut şu
şekilde olur:

dotnet run --pathbase=/CoolApp

Blazor WebAssembly uygulaması, http://localhost:port/CoolApp yerel olarak yanıt verir.

Dağıtım
Dağıtım Kılavuzu için aşağıdaki konulara bakın:
ASP.NET Core Blazor WebAssembly 'ı barındırma ve dağıtma
ASP.NET Core Blazor sunucusu barındırma ve dağıtma
ASP.NET Core Blazor WebAssembly 'ı barındırma ve
dağıtma
13.11.2019 • 17 minutes to read • Edit Online

, Luke Latham, Rainer Stropekve Daniel Roth tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor WebAssembly barındırma modeliyle:


Blazor uygulaması, bağımlılıkları ve .NET çalışma zamanı tarayıcıya indirilir.
Uygulama doğrudan tarayıcı kullanıcı arabirimi iş parçacığında yürütülür.
Aşağıdaki dağıtım stratejileri desteklenir:
Blazor uygulama ASP.NET Core bir uygulama tarafından sunulur. Bu strateji ASP.NET Core bölümünde
barındırılan dağıtımda ele alınmıştır.
Blazor uygulaması, .NET Blazor uygulamasına hizmet vermek için kullanılmayan bir statik barındırma Web
sunucusuna veya hizmetine yerleştirilir. Bu strateji tek başına dağıtım bölümünde ele alınmıştır. Bu, bir Blazor
WebAssembly UYGULAMASıNı bir IIS alt uygulaması olarak barındırma hakkında bilgiler içerir.

Doğru yönlendirme için URL 'Leri yeniden yazın


Blazor WebAssembly uygulamasındaki sayfa bileşenlerine yönelik yönlendirme istekleri, Blazor sunucusu,
barındırılan bir uygulamada yönlendirme istekleri kadar basittir. İki bileşeni olan bir Blazor WebAssembly
uygulaması düşünün:
Main. razor – uygulamanın köküne yüklenir ve About bileşenine bir bağlantı içerir ( href="About" ).
. Razor – About bileşeni hakkında.
Uygulamanın varsayılan belgesi, tarayıcının adres çubuğu kullanılarak istendiğinde (örneğin,
https://www.contoso.com/ ):

1. Tarayıcı bir istek yapar.


2. Varsayılan sayfa döndürülür, bu genellikle index. html'dir.
3. uygulamanın index. html önyükleme.
4. Blazoryönlendirici yükleri ve Razor Main bileşeni işlenir.
Ana sayfada, Blazor yönlendirici tarayıcının About için www.contoso.com için bir istek yapmasını durdurduğundan
ve işlenmiş About bileşeninin kendisini hizmet ettiğinden, About bileşene olan bağlantıyı seçmek istemcide çalışır.
Blazor WebAssembly uygulaması içindeki iç uç noktalara yönelik tüm istekler aynı şekilde çalışır: istekler tarayıcı
tabanlı istekleri Internet 'teki sunucu tarafından barındırılan kaynaklara tetiklemez. Yönlendirici istekleri dahili olarak
işler.
www.contoso.com/About için tarayıcının adres çubuğu kullanılarak bir istek yapılırsa, istek başarısız olur. Uygulamanın
Internet ana bilgisayarında böyle bir kaynak yok, bu nedenle 404 -bulunamayan bir yanıt döndürülür.
Tarayıcılar, istemci tarafı sayfaları için Internet tabanlı konaklara istek yaptığından, Web sunucuları ve barındırma
hizmetleri, fiziksel olarak sunucu üzerinde olmayan kaynakların tüm isteklerini Dizin. html sayfasına yeniden
yazmalıdır. İndex. html döndürüldüğünde, uygulamanın Blazor yönlendiricisi, doğru kaynakla yararlanır ve yanıt
verir.
Bir IIS sunucusuna dağıtım yaparken, URL yeniden yazma modülünü uygulamanın yayınlanan Web. config
dosyasıyla birlikte kullanabilirsiniz. Daha fazla bilgi için IIS bölümüne bakın.

ASP.NET Core ile barındırılan dağıtım


Barındırılan bir dağıtım , bir Web sunucusu üzerinde çalışan bir ASP.NET Core uygulamasındaki tarayıcılara Blazor
webassembly uygulamasını sunar.
Blazor uygulaması, yayımlanan çıktıda ASP.NET Core uygulamasına dahildir, böylece iki uygulama birlikte dağıtılır.
ASP.NET Core uygulamasını barındırabilen bir Web sunucusu gereklidir. Barındırılan bir dağıtım için Visual Studio,
barındırılan seçeneği belirlenmiş olarak, Blazor Webassembly uygulama projesi şablonunu ( DotNet New
komutu kullanılırken blazorwasm şablonu) içerir.
Uygulama barındırma ve dağıtım ASP.NET Core hakkında daha fazla bilgi için bkz. ASP.NET Core barındırma ve
dağıtma.
Azure App Service dağıtma hakkında daha fazla bilgi için bkz. Visual Studio ile Azure'a bir ASP.NET Core
uygulaması yayımlama.

Tek başına dağıtım


Tek başına dağıtım , istemci tarafından doğrudan istenen statik dosyalar kümesi olarak Blazor WebAssembly
uygulamasına hizmet verir. Herhangi bir statik dosya sunucusu Blazor uygulamasına sunabilir.
Tek başına dağıtım varlıkları bin/Release/{Target Framework}/publish/{ASSEMBLY Name}/Dist klasöründe
yayımlanır.
IIS
IIS, Blazor uygulamalar için özellikli bir statik dosya sunucusudur. IIS 'yi Blazorbarındıracak şekilde yapılandırmak
için bkz. IIS 'de statik Web sitesi oluşturma.
Yayımlanan varlıklar /BIN/Release/{Target Framework}/Publish klasöründe oluşturulur. Web sunucusunda veya
barındırma hizmetinde Yayımlama klasörünün içeriğini barındırın.
Web. config
Bir Blazor projesi yayımlandığında, aşağıdaki IIS yapılandırmasıyla bir Web. config dosyası oluşturulur:
MIME türleri aşağıdaki dosya uzantıları için ayarlanır:
. dll – application/octet-stream
. json – application/json
. – application/wasm
. WOFF – application/font-woff
. woff2 – application/font-woff
Aşağıdaki MIME türleri için HTTP sıkıştırması etkindir:
application/octet-stream
application/wasm
URL yeniden yazma modülü kuralları oluşturuldu:
Uygulamanın statik varlıklarının bulunduğu alt dizini ( {Assembly Name}/dist/{PATH istenen} ) sunar.
Dosya olmayan varlıklar için isteklerin statik varlıklar klasöründe ( {Assembly Name}/Dist/index.html)
uygulamanın varsayılan belgesine yeniden YÖNLENDIRILMESI için Spa geri dönüş yönlendirmesi
oluşturun.
URL yeniden yazma modülünü yükler
URL yeniden yazma modülü , URL 'leri yeniden yazmak için gereklidir. Modül varsayılan olarak yüklenmez ve bir
Web sunucusu (IIS ) rol hizmeti özelliği olarak yükleme için kullanılamaz. Modül IIS Web sitesinden indirilmelidir.
Modülünü yüklemek için Web Platformu Yükleyicisi 'ni kullanın:
1. Yerel olarak, URL yeniden yazma modülü İndirmeleri sayfasınagidin. Ingilizce sürümünde, WebPI yükleyicisini
indirmek için WebPI ' ı seçin. Diğer diller için, yükleyiciyi indirmek üzere sunucu için uygun mimariyi (x86/x64)
seçin.
2. Yükleyiciyi sunucuya kopyalayın. Yükleyiciyi çalıştırın. , Install düğmesini seçin ve lisans koşullarını kabul edin.
Yüklemesi tamamlandıktan sonra sunucu yeniden başlatması gerekli değildir.
Web sitesini yapılandırma
Web sitesinin fiziksel yolunu uygulamanın klasörüne ayarlayın. Klasör şunları içerir:
Gerekli yeniden yönlendirme kuralları ve dosya içerik türleri dahil olmak üzere IIS 'nin Web sitesini
yapılandırmak için kullandığı Web. config dosyası.
Uygulamanın statik varlık klasörü.
IIS alt uygulaması olarak barındırma
Tek başına bir uygulama bir IIS alt uygulaması olarak barındırılıyorsa, aşağıdakilerden birini yapın:
Devralınan ASP.NET Core modülü işleyicisini devre dışı bırakın.
Dosyaya bir <handlers> bölümü ekleyerek Blazor uygulamasının yayınlanan Web. config dosyasındaki
işleyiciyi kaldırın:

<handlers>
<remove name="aspNetCore" />
</handlers>

inheritInChildApplications olarak ayarlanan <location> bir öğesi kullanarak kök (üst) uygulamanın
false
<system.webServer> bölümünü devralmayı devre dışı bırakın:

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" ... />
</handlers>
<aspNetCore ... />
</system.webServer>
</location>
</configuration>

İşleyicinin kaldırılması veya devralma devre dışı bırakılması, uygulamanın temel yolunun yapılandırılmasınaek
olarak gerçekleştirilir. Uygulamanın index. html dosyasındaki uygulama temel yolunu, IIS 'de alt uygulamayı
YAPıLANDıRıRKEN kullanılan IIS diğer adına ayarlayın.
Sorun giderme
500 -Iç sunucu hatası ALıNMıŞSA ve IIS Yöneticisi Web sitesinin yapılandırmasına erişmeye çalışırken hatalar
OLUŞTURURSA, URL yeniden yazma modülünün yüklü olduğunu doğrulayın. Modül yüklü olmadığında, Web.
config dosyası IIS tarafından ayrıştırılamaz. Bu, IIS yöneticisinin Web sitesinin yapılandırmasını ve Web sitesinin
Blazorstatik dosyalarına hizmet etmesini engeller.
IIS ile dağıtım sorunlarını giderme hakkında daha fazla bilgi için bkz. Azure App Service ve IIS 'de ASP.NET Core
sorunlarını giderme.
Azure Depolama
Azure depolama statik dosya barındırma, sunucusuz Blazor uygulama barındırılmasına olanak sağlar. Özel etki alanı
adları, Azure Content Delivery Network (CDN ) ve HTTPS desteklenir.
Blob hizmeti bir depolama hesabında barındırılan statik Web sitesi için etkinleştirildiğinde:
Dizin belgesi adını index.html olarak ayarlayın.
Hata belge yolunu index.html olarak ayarlayın. Razor bileşenleri ve diğer dosya olmayan uç noktaları, blob
hizmeti tarafından depolanan statik içerikte fiziksel yollarda yer vermez. Blazor yönlendiricisinin işlemesi
gereken bu kaynaklardan birine yönelik bir istek alındığında, blob hizmeti tarafından oluşturulan 404 -
bulunamayan hata, isteği hata belge yolunayönlendirir. İndex. html blobu döndürülür ve Blazor yönlendirici
yolu yükler ve işler.
Daha fazla bilgi için bkz. Azure Storage 'Da statik Web sitesi barındırma.
NGINX
Aşağıdaki NGINX. conf dosyası, NGINX 'in, disk üzerinde karşılık gelen bir dosyayı bulamadığı her seferinde index.
html dosyasını göndermek üzere nasıl yapılandırılacağını gösterecek şekilde basitleştirilmiştir.

events { }
http {
server {
listen 80;

location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
}
}
}

Üretim NGINX web sunucusu yapılandırması hakkında daha fazla bilgi için bkz. NGINX Plus ve NGINX
yapılandırma dosyaları oluşturma.
Docker 'da NGINX
Docker 'da NGINX kullanarak Blazor barındırmak için Dockerfile 'ı alp tabanlı NGINX görüntüsünü kullanacak
şekilde ayarlayın. Dockerfile dosyasını, NGINX. config dosyasını kapsayıcıya kopyalamak için güncelleştirin.
Aşağıdaki örnekte gösterildiği gibi Dockerfile dosyasına bir satır ekleyin:

FROM nginx:alpine
COPY ./bin/Release/netstandard2.0/publish /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf

Apache
CentOS 7 veya üzeri bir Blazor WebAssembly uygulaması dağıtmak için:
1. Apache yapılandırma dosyasını oluşturun. Aşağıdaki örnek basitleştirilmiş bir yapılandırma dosyasıdır
(blazorapp. config):
<VirtualHost *:80>
ServerName www.example.com
ServerAlias *.example.com

DocumentRoot "/var/www/blazorapp"
ErrorDocument 404 /index.html

AddType aplication/wasm .wasm


AddType application/octet-stream .dll

<Directory "/var/www/blazorapp">
Options -Indexes
AllowOverride None
</Directory>

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/octet-stream
AddOutputFilterByType DEFLATE application/wasm
<IfModule mod_setenvif.c>
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
</IfModule>
</IfModule>

ErrorLog /var/log/httpd/blazorapp-error.log
CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>

2. Apache yapılandırma dosyasını, CentOS 7 ' de varsayılan Apache yapılandırma dizini olan
/etc/httpd/conf.d/ dizinine yerleştirin.

3. Uygulamanın dosyalarını /var/www/blazorapp dizinine yerleştirin (yapılandırma dosyasına DocumentRoot için


belirtilen konum).
4. Apache hizmetini yeniden başlatın.
Daha fazla bilgi için bkz. mod_mime ve mod_deflate.
GitHub sayfaları
URL yeniden işlemesini işlemek için, isteği index. html sayfasına yönlendirmeyi işleyen bir betiği olan bir 404. html
dosyası ekleyin. Topluluk tarafından sunulan örnek bir uygulama için bkz. GitHub sayfaları Için tek sayfalı
uygulamalar (GitHub üzerinde rafrex/Spa-GitHub-Pages). Topluluk yaklaşımını kullanan bir örnek, GitHub ( canlı
site) üzerinde blazor-demo/blazor-demo. GitHub. IO adresinde görülebilir.
Bir kuruluş sitesi yerine bir proje sitesi kullanırken, index. htmldosyasına <base> etiketi ekleyin veya güncelleştirin.
href öznitelik değerini, sondaki eğik çizgiyle (örneğin, my-repository/ ) GitHub depo adına ayarlayın.

Ana bilgisayar yapılandırma değerleri


Blazor WebAssembly Apps , geliştirme ortamındaki çalışma zamanında aşağıdaki ana bilgisayar yapılandırma
değerlerini komut satırı bağımsız değişkenleri olarak kabul edebilir.
İçerik kökü
--contentroot bağımsız değişkeni, uygulamanın içerik dosyalarını (içerik kökü) içeren dizinin mutlak yolunu
ayarlar. Aşağıdaki örneklerde, /content-root-path , uygulamanın içerik kök yoludur.
Uygulamayı bir komut isteminde yerel olarak çalıştırırken bağımsız değişkenini geçirin. Uygulamanın
dizininden şunu yürütün:

dotnet run --contentroot=/content-root-path

IIS Express profilindeki uygulamanın launchsettings. JSON dosyasına bir giriş ekleyin. Bu ayar, uygulama
Visual Studio hata ayıklayıcıyla ve dotnet run ile bir komut isteminden çalıştırıldığında kullanılır.

"commandLineArgs": "--contentroot=/content-root-path"

Visual Studio 'da > hata ayıklama > uygulama bağımsız değişkenlerinin Özelliklerbölümünde
bağımsız değişkenini belirtin. Visual Studio özellik sayfasında bağımsız değişkeni ayarlama, bağımsız
değişkenini Launchsettings. JSON dosyasına ekler.

--contentroot=/content-root-path

Yol tabanı
--pathbase bağımsız değişkeni, kök olmayan göreli URL yoluyla yerel olarak çalıştırılan bir uygulamanın uygulama
temel yolunu ayarlar ( <base> etiketi href , hazırlama ve üretim için / dışında bir yola ayarlanır). Aşağıdaki
örneklerde, /relative-URL-path , uygulamanın yol tabanı olur. Daha fazla bilgi için bkz. uygulama temel yolu.

IMPORTANT
<base> etiketinin href olarak belirtilen yolun aksine, --pathbase bağımsız değişken değeri geçirilirken sondaki eğik çizgi (
/ ) eklemeyin. Uygulama temel yolu <base> etiketinde <base href="/CoolApp/"> (sondaki eğik çizgi içeriyorsa) olarak
sağlanmışsa, komut satırı bağımsız değişken değerini --pathbase=/CoolApp (sondaki eğik çizgi olmadan) olarak geçirin.

Uygulamayı bir komut isteminde yerel olarak çalıştırırken bağımsız değişkenini geçirin. Uygulamanın
dizininden şunu yürütün:

dotnet run --pathbase=/relative-URL-path

IIS Express profilindeki uygulamanın launchsettings. JSON dosyasına bir giriş ekleyin. Bu ayar, uygulamayı
Visual Studio hata ayıklayıcıyla ve dotnet run ile bir komut isteminden çalıştırırken kullanılır.

"commandLineArgs": "--pathbase=/relative-URL-path"

Visual Studio 'da > hata ayıklama > uygulama bağımsız değişkenlerinin Özelliklerbölümünde
bağımsız değişkenini belirtin. Visual Studio özellik sayfasında bağımsız değişkeni ayarlama, bağımsız
değişkenini Launchsettings. JSON dosyasına ekler.

--pathbase=/relative-URL-path

URL'ler
--urls bağımsız değişkeni, istekler için dinlemek üzere bağlantı noktaları ve protokollerle IP adreslerini veya
konak adreslerini ayarlar.
Uygulamayı bir komut isteminde yerel olarak çalıştırırken bağımsız değişkenini geçirin. Uygulamanın
dizininden şunu yürütün:
dotnet run --urls=http://127.0.0.1:0

IIS Express profilindeki uygulamanın launchsettings. JSON dosyasına bir giriş ekleyin. Bu ayar, uygulamayı
Visual Studio hata ayıklayıcıyla ve dotnet run ile bir komut isteminden çalıştırırken kullanılır.

"commandLineArgs": "--urls=http://127.0.0.1:0"

Visual Studio 'da > hata ayıklama > uygulama bağımsız değişkenlerinin Özelliklerbölümünde
bağımsız değişkenini belirtin. Visual Studio özellik sayfasında bağımsız değişkeni ayarlama, bağımsız
değişkenini Launchsettings. JSON dosyasına ekler.

--urls=http://127.0.0.1:0

Bağlayıcıyı yapılandırma
Blazor, çıkış derlemelerinden gereksiz Il 'yi kaldırmak için her bir derlemede ara dil (IL ) bağlamayı gerçekleştirir.
Derleme bağlama, derleme üzerinde denetlenebilir. Daha fazla bilgi için bkz. ASP.NET Core Blazor için bağlayıcı
yapılandırma.
Blazor sunucusu barındırma ve dağıtma
9.12.2019 • 6 minutes to read • Edit Online

, Luke Latham, Rainer Stropekve Daniel Roth tarafından

Ana bilgisayar yapılandırma değerleri


Blazor Server uygulamaları genel ana bilgisayar yapılandırma değerlerinikabul edebilir.

Dağıtım
Blazor sunucusu barındırma modelinikullanarak, Blazor sunucuda bir ASP.NET Core uygulaması içinden yürütülür.
Kullanıcı Arabirimi güncelleştirmeleri, olay işleme ve JavaScript çağrıları SignalR bir bağlantı üzerinden işlenir.
ASP.NET Core uygulaması barındırabilen bir Web sunucusu gerekiyor. Visual Studio, DotNet New komutu
kullanılırken Blazor Server uygulaması proje şablonunu ( blazorserverside şablonu) içerir.

Ölçeklenebilirlik
Bir Blazor sunucusu uygulaması için kullanılabilir altyapıyı en iyi şekilde kullanmasını sağlamak üzere bir dağıtım
planlayın. Blazor Server uygulama ölçeklenebilirliğini karşılamak için aşağıdaki kaynaklara bakın:
Blazor Server uygulamalarının temelleri
Güvenli ASP.NET Core Blazor Server uygulamaları
Dağıtım sunucusu
Tek bir sunucunun ölçeklenebilirliğini değerlendirirken (ölçeği büyütme), bir uygulama için kullanılabilir olan bellek
büyük olasılıkla uygulamanın kullanıcı talebi arttıkça arttırabileceği ilk kaynaktır. Sunucudaki kullanılabilir bellek
şunları etkiler:
Bir sunucunun destekleyebileceği etkin devre sayısı.
İstemcide UI gecikme süresi.
Güvenli ve ölçeklenebilir Blazor sunucu uygulamaları oluşturma hakkında yönergeler için bkz. Güvenli ASP.NET
Core Blazor Server uygulamaları.
Her bağlantı hattı en düşük Merhaba Dünyastilinde bir uygulama için YAKLAŞıK 250 KB bellek kullanır. Bir
devrenin boyutu, uygulamanın koduna ve her bileşenle ilişkili durum bakım gereksinimlerine bağlıdır. Uygulama ve
altyapınız için geliştirme sırasında kaynak taleplerini ölçmenizi öneririz, ancak aşağıdaki taban çizgisi, dağıtım
hedefini planlamada bir başlangıç noktası olabilir: uygulamanızın 5.000 eşzamanlı kullanıcı desteklemesini
istiyorsanız, şu adreste bütçeleme yapmayı düşünün: uygulamaya en az 1,3 GB sunucu belleği (veya Kullanıcı
başına ~ 273 KB ).
SignalR yapılandırması
Blazor sunucu uygulamaları tarayıcıyla iletişim kurmak için ASP.NET Core SignalR kullanır. SignalRbarındırma ve
ölçeklendirme koşulları Blazor sunucu uygulamaları için geçerlidir.
daha düşük gecikme süresi, güvenilirlik ve güvenliknedeniyle SignalR taşıma olarak WebSockets kullanırken Blazor
en iyi şekilde işe yarar. Uzun yoklama, WebSockets kullanılamadığında veya uygulama açıkça uzun yoklamayı
kullanacak şekilde yapılandırıldığında SignalR tarafından kullanılır. Azure App Service dağıtım sırasında,
uygulamayı hizmetin Azure portal ayarları içinde kullanmak üzere yapılandırın. Azure App Service için uygulamayı
yapılandırma hakkında ayrıntılı bilgi için bkz. SignalR yayımlama yönergeleri.
Azure SignalR hizmeti
Blazor Server uygulamaları için Azure SignalR hizmetini kullanmanızı öneririz. Hizmet, Blazor sunucu
uygulamasının ölçeğini çok sayıda eşzamanlı SignalR bağlantı ile ölçeklendirmeye olanak tanır. Ayrıca, SignalR
hizmetin küresel erişim ve yüksek performanslı veri merkezleri Coğrafya nedeniyle gecikme süresini azaltmaya
önemli ölçüde yardımcı olur. Azure SignalR hizmetini bir uygulamayı yapılandırmak (ve isteğe bağlı olarak
sağlamak) için:
1. Prerendering sırasında istemciler aynı sunucuya geri yönlendirildiği yapışkan oturumlarıdesteklemek için
hizmeti etkinleştirin. ServerStickyMode seçeneğini veya yapılandırma değerini Required olarak ayarlayın.
Genellikle, bir uygulama aşağıdaki yaklaşımlardan birini kullanarak yapılandırmayı oluşturur:
Startup.ConfigureServices :

services.AddSignalR().AddAzureSignalR(options =>
{
options.ServerStickyMode =
Microsoft.Azure.SignalR.ServerStickyMode.Required;
});

Yapılandırma (aşağıdaki yaklaşımlardan birini kullanın):


appSettings. JSON:

"Azure:SignalR:ServerStickyMode": "Required"

App Service 'in yapılandırma Azure Portal uygulama ayarları > (ad:
Azure:SignalR:ServerStickyMode , değer: Required ).

2. Blazor Server uygulaması için Visual Studio 'da bir Azure Apps yayımlama profili oluşturun.
3. Azure SignalR hizmeti bağımlılığını profile ekleyin. Azure aboneliğinin uygulamaya atanacak önceden
mevcut bir Azure SignalR hizmeti örneği yoksa, yeni bir hizmet örneği sağlamak için Yeni bir azure
SignalR hizmet örneği oluştur ' u seçin.
4. Uygulamayı Azure’da yayımlama.
IIS
IIS kullanırken, yapışkan oturumlar uygulama Isteği yönlendirme ile etkinleştirilir. Daha fazla bilgi için bkz.
uygulama Isteği yönlendirme kullanarak HTTP yük dengelemesi.
Kubernetes
Yapışkan oturumlar için aşağıdaki Kubernetes ek açıklamalarınıiçeren bir giriş tanımı oluşturun:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: <ingress-name>
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "affinity"
nginx.ingress.kubernetes.io/session-cookie-expires: "14400"
nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"

Ölçü ağı gecikmesi


Aşağıdaki örnekte gösterildiği gibi, js birlikte çalışması ağ gecikmesini ölçmek için kullanılabilir:
@inject IJSRuntime JS

@if (latency is null)


{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}

@code
{
private DateTime startTime;
private TimeSpan? latency;

protected override async Task OnInitializedAsync()


{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
}
}

Makul bir kullanıcı arabirimi deneyimi için, 250ms veya daha az sayıda sürekli Kullanıcı arabirimi gecikme süresi
önerilir.
ASP.NET Core Blazor için bağlayıcı yapılandırma
26.11.2019 • 2 minutes to read • Edit Online

Luke Latham tarafından

IMPORTANT
Önizlemede Blazor Weelsembly
Blazor sunucusu ASP.NET Core 3,0 ' de desteklenir. Blazor WebAssembly ASP.NET Core 3,1 için önizlemededir.

Blazor, uygulamanın çıkış derlemelerinden gereksiz Il 'yi kaldırmak için bir derleme sırasında ara dil (IL ) bağlamayı
gerçekleştirir.
Aşağıdaki yaklaşımlardan birini kullanarak derleme bağlamayı kontrol edin:
MSBuild özelliğiile genel olarak bağlamayı devre dışı bırakın.
Yapılandırma dosyasıile derleme temelinde bağlama denetimi.

MSBuild özelliği ile bağlamayı devre dışı bırak


Bir uygulama oluşturulduğunda, yayımlama de dahil olmak üzere varsayılan olarak bağlama etkindir. Tüm
derlemeler için bağlamayı devre dışı bırakmak için BlazorLinkOnBuild MSBuild özelliğini proje dosyasında false
olarak ayarlayın:

<PropertyGroup>
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
</PropertyGroup>

Yapılandırma dosyası ile bağlamayı denetleme


Bir XML yapılandırma dosyası sağlayarak ve dosyayı proje dosyasında MSBuild öğesi olarak belirterek, derleme
başına temelinde bağlamayı denetleyin:

<ItemGroup>
<BlazorLinkerDescriptor Include="Linker.xml" />
</ItemGroup>

Bağlayıcı. xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!--
This file specifies which parts of the BCL or Blazor packages must not be
stripped by the IL Linker even if they aren't referenced by user code.
-->
<linker>
<assembly fullname="mscorlib">
<!--
Preserve the methods in WasmRuntime because its methods are called by
JavaScript client-side code to implement timers.
Fixes: https://github.com/aspnet/Blazor/issues/239
-->
<type fullname="System.Threading.WasmRuntime" />
</assembly>
<assembly fullname="System.Core">
<!--
System.Linq.Expressions* is required by Json.NET and any
expression.Compile caller. The assembly isn't stripped.
-->
<type fullname="System.Linq.Expressions*" />
</assembly>
<!--
In this example, the app's entry point assembly is listed. The assembly
isn't stripped by the IL Linker.
-->
<assembly fullname="MyCoolBlazorApp" />
</linker>

Daha fazla bilgi için bkz. Il Bağlayıcısı: XML tanımlayıcısının sözdizimi.


Bağlayıcıyı uluslararası duruma getirme için yapılandırma
Varsayılan olarak, Blazor WebAssembly uygulamaları için Blazorbağlayıcı yapılandırması, açıkça istenen yerel
ayarlar dışında uluslararası duruma getirme bilgilerini kaldırır. Bu derlemelerin kaldırılması uygulamanın boyutunu
en aza indirir.
Hangi I18N derlemelerinin korunacağını denetlemek için, proje dosyasında <MonoLinkerI18NAssemblies> MSBuild
özelliğini ayarlayın:

<PropertyGroup>
<MonoLinkerI18NAssemblies>{all|none|REGION1,REGION2,...}</MonoLinkerI18NAssemblies>
</PropertyGroup>

BÖLGE DEĞERI MONO BÖLGESI DERLEMESI

all Tüm derlemeler dahil

cjk I18N. CJK. dll

mideast I18N. MIDEAST. dll

none (varsayılan) Yok.

other I18N. Diğer. dll

rare I18N. Nadir. dll

west I18N. Batı. dll


Birden çok değeri ayırmak için virgül kullanın (örneğin, mideast,west ).
Daha fazla bilgi için bkz. I18N: Pnetlib uluslararası duruma getirme çerçeve Libary (Mono/Mono GitHub deposu).
Angular proje şablonunu ASP.NET Core ile kullanma
19.09.2019 • 12 minutes to read • Edit Online

Güncelleştirilmiş angular proje şablonu, zengin, istemci tarafı Kullanıcı arabirimi (UI) uygulamak için angular ve
angular CLı kullanan ASP.NET Core uygulamalar için uygun bir başlangıç noktası sağlar.
Şablon, bir API arka ucu görevi gören bir ASP.NET Core projesi ve Kullanıcı arabirimi olarak davranacak angular
CLı projesi oluşturma ile eşdeğerdir. Şablon, her iki proje türünü tek bir uygulama projesinde barındırmanın
kolaylığını sunar. Sonuç olarak, uygulama projesi tek bir birim olarak oluşturulup yayımlanabilir.

Yeni bir uygulama oluşturma


ASP.NET Core 2,1 yüklüyse, angular proje şablonunu yüklemeye gerek yoktur.
Boş bir dizinde komutunu dotnet new angular kullanarak komut isteminden yeni bir proje oluşturun. Örneğin,
aşağıdaki komutlar uygulamayı Yeni bir uygulama dizininde oluşturur ve bu dizine geçer:

dotnet new angular -o my-new-app


cd my-new-app

Uygulamayı Visual Studio 'dan veya .NET Core CLI çalıştırın:


Visual Studio
.NET Core CLI
Oluşturulan . csproj dosyasını açın ve uygulamayı buradan normal olarak çalıştırın.
Yapı işlemi ilk çalıştırmada NPM bağımlılıklarını geri yükler ve bu işlem birkaç dakika sürebilir. Sonraki derlemeler
çok daha hızlıdır.
Proje şablonu, bir ASP.NET Core uygulaması ve angular uygulaması oluşturur. ASP.NET Core uygulaması veri
erişimi, yetkilendirme ve diğer sunucu tarafı sorunları için kullanılmak üzere tasarlanmıştır. Clientapp alt dizininde
bulunan angular uygulamasının tüm Kullanıcı arabirimi sorunları için kullanılması amaçlanmıştır.

Sayfa, resim, stil, modül vb. ekleyin


Clientapp dizini standart ANGULAR CLI uygulaması içerir. Daha fazla bilgi için bkz. resmi angular belgeleri .
Bu şablon tarafından oluşturulan angular uygulaması ve angular CLI 'nın kendisi (aracılığıyla ng new ) tarafından
oluşturulan küçük farklılıklar vardır; ancak, uygulamanın özellikleri değiştirilmez. Şablon tarafından oluşturulan
uygulama, önyüklemetabanlı bir düzen ve temel bir yönlendirme örneği içerir.

Çalıştır komutları
Bir komut isteminde clientapp alt dizinine geçin:

cd ClientApp

ng Araç genel olarak yüklüyse, komutlarından birini çalıştırabilirsiniz. Örneğin, diğer ng lint angular CLI
komutlarındanbirini veya birini çalıştırabilirsiniz ng test . ASP.NET Core uygulamanız uygulamanızın sunucu
tarafı ve ng serve istemci tarafı bölümlerine sunma konusunda anlaştığından, ancak bu çalışmaya gerek yoktur.
Dahili olarak, geliştirme ng serve sürecinde kullanır.
Yüklü bir npm run ng araç yoksa, bunun yerine çalıştırın. ng Örneğin, veya npm run ng lint npm run ng test
çalıştırabilirsiniz.

NPM paketlerini yükler


Üçüncü taraf NPM paketlerini yüklemek için clientapp alt dizininde bir komut istemi kullanın. Örneğin:

cd ClientApp
npm install --save <package_name>

Yayımla ve dağıt
Geliştirme aşamasında uygulama, geliştirici kolaylığı için iyileştirilmiş bir modda çalışır. Örneğin, JavaScript demeti
kaynak eşlemeleri içerir (hata ayıklarken, özgün TypeScript kodunuzu görebilirsiniz). Uygulama TypeScript, HTML
ve CSS dosya değişikliklerini diskte izler ve bu dosya değişikliğini gördüğünde otomatik olarak yeniden derlenir
ve yeniden yükler.
Üretimde, uygulamanızın performans için iyileştirilmiş bir sürümünü sunar. Bu otomatik olarak gerçekleşecek
şekilde yapılandırılmıştır. Yayımladığınızda, derleme yapılandırması, istemci tarafı kodunuzun küçültülmüş,
önceden derlenmiş bir derlemesini yayar. Geliştirme derlemesinin aksine, üretim derlemesi, Node. js ' nin
sunucuya yüklenmesini gerektirmez (sunucu tarafı işlemesini (SSR ) etkinleştirmediğiniz müddetçe).
Standart ASP.NET Core barındırma ve dağıtım yöntemlerikullanabilirsiniz.

Bağımsız olarak "ng hizmeti" Çalıştır


Proje, ASP.NET Core uygulaması geliştirme modunda başladığında arka planda kendi angular CLı sunucusu
örneğini başlatacak şekilde yapılandırılmıştır. Ayrı bir sunucuyu el ile çalıştırmak zorunda olmadığınızdan bu
kullanışlıdır.
Bu varsayılan Kurulumun bir dezavantajı vardır. C# Kodunuzun her değiştirilişinde ve ASP.NET Core
uygulamanızın yeniden başlatılması gerektiğinde, ANGULAR CLI sunucusu yeniden başlatılır. Yeniden başlatmak
için yaklaşık 10 saniye gereklidir. Sık karşılaşılan C# kod düzenlemeleri yapıyorsanız ve ANGULAR CLI 'nın
yeniden başlatılmasını beklemek Istemiyorsanız, angular clı sunucusunu ASP.NET Core işleminden bağımsız
olarak dışarıdan çalıştırın. Bunu yapmak için:
1. Bir komut isteminde clientapp alt dizinine geçin ve ANGULAR CLI geliştirme sunucusunu başlatın:

cd ClientApp
npm start

IMPORTANT
npm start Package. JSON içindeki yapılandırmanın kullanılması için değil ng serve , angular CLI geliştirme
sunucusunu başlatmak için kullanın. Angular CLI sunucusuna ek parametreler geçirmek için bunları scripts
Package. JSON dosyanızdaki ilgili satıra ekleyin.

2. ASP.NET Core uygulamanızı, kendi kendine birini başlatmak yerine dış angular CLı örneğini kullanacak
şekilde değiştirin. Başlangıç sınıfınıza, spa.UseAngularCliServer çağrıyı aşağıdaki ile değiştirin:
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");

ASP.NET Core uygulamanızı başlattığınızda, angular CLı sunucusunu başlatmayacaktır. Bunun yerine el ile
başlattığınız örnek kullanılır. Bu, daha hızlı başlamasını ve yeniden başlatılmasını sağlar. Artık, istemci uygulamanızı
her seferinde yeniden oluşturmak için angular CLı bekliyor.
.NET kodundan verileri TypeScript koduna geçirme
SSR sırasında, ASP.NET Core uygulamanızdaki istek başına verileri angular uygulamanıza geçirmek
isteyebilirsiniz. Örneğin, tanımlama bilgisi bilgilerini veya bir veritabanından okunan bir şeyi geçirebilirsiniz. Bunu
yapmak için Başlangıç sınıfınızı düzenleyin. İçin UseSpaPrerendering geri çağırmada, aşağıdaki gibi bir
options.SupplyData değer ayarlayın:

options.SupplyData = (context, data) =>


{
// Creates a new value called isHttpsRequest that's passed to TypeScript code
data["isHttpsRequest"] = context.Request.IsHttps;
};

SupplyData Geri arama, isteğe bağlı olarak, JSON ile seri hale getirilebilir verileri (örneğin, dizeler, Boole değerleri
veya sayılar) geçirmenize olanak sağlar. Main. Server. TS kodunuz bunu olarak params.data alır. Örneğin,
yukarıdaki kod örneği params.data.isHttpsRequest createServerRenderer geri çağırmada olduğu gibi bir Boole
değeri geçirir. Bunu uygulamanızın diğer bölümlerine, angular tarafından desteklenen herhangi bir yolla
geçirebilirsiniz. Örneğin, bkz. Main. Server. TS BASE_URL değeri, Oluşturucusu onu almak için bildirildiği herhangi
bir bileşene geçirir.
SSR 'nin dezavantajları
Tüm uygulamalar SSR 'den faydalanır. Birincil avantaj, performans algılanır. Yavaş bir ağ bağlantısı veya yavaş
mobil cihazlarda uygulamanıza ulaşan ziyaretçiler, JavaScript paketlerini getirme veya ayrıştırma sırasında bile ilk
Kullanıcı arabirimine hızlı bir şekilde bakın. Ancak, çoğu maça genellikle uygulamanın neredeyse anında
göründüğü hızlı bilgisayarlarda hızlı, dahili şirket ağları üzerinde kullanılır.
Aynı zamanda SSR 'yi etkinleştirmenin önemli sakıncaları vardır. Geliştirme sürecinizi karmaşıklık altına ekler.
Kodunuzun iki farklı ortamda çalışması gerekir: istemci tarafı ve sunucu tarafı (ASP.NET Core bir Node. js
ortamında çağrılır). Göz önünde bulundurmanız gereken bazı şeyler aşağıda verilmiştir:
SSR, üretim sunucularınızda bir Node. js yüklemesi gerektirir. Azure uygulama hizmetleri gibi bazı dağıtım
senaryolarında bu durum otomatik olarak yapılır, ancak Azure Service Fabric gibi diğerleri için de değildir.
Yapı bayrağını BuildServerSideRenderer etkinleştirmek, node_modules dizininizin yayımlamasına neden
olur. Bu klasör, dağıtım süresini artıran 20000 + dosyalarını içerir.
Kodunuzu bir Node. js ortamında çalıştırmak için, window veya localStorage gibi tarayıcıya özgü
JavaScript API 'lerinin varlığına bağlı olamaz. Kodunuz (veya başvuru yaptığınız bazı üçüncü taraf kitaplığı)
Bu API 'Leri kullanmayı denediğinde SSR sırasında bir hata alırsınız. Örneğin, birçok yerde tarayıcıya özgü
API 'Lere başvurduğundan jQuery kullanmayın. Hataları önlemek için SSR 'yi kullanmaktan veya tarayıcıya
özgü API 'lerden ya da kitaplıklardan kaçınmalısınız. Bu tür API 'lere yapılan çağrıları SSR sırasında
çağrıdıklarından emin olmak için, denetimleri içinde kaydırabilirsiniz. Örneğin, JavaScript veya TypeScript
kodunda aşağıdakiler gibi bir denetim kullanın:

if (typeof window !== 'undefined') {


// Call browser-specific APIs here
}
Ek kaynaklar
ASP.NET Core tek sayfalı uygulamalar için kimlik doğrulamaya giriş
ASP.NET Core ile tepki verme proje şablonunu
kullanın
31.10.2019 • 7 minutes to read • Edit Online

Güncelleştirilmiş tepki verme projesi şablonu, zengin, istemci tarafı Kullanıcı arabirimi (UI) uygulamak için tepki
verme ve oluşturma- yanıt verme (CRA) kurallarını kullanan ASP.NET Core uygulamalar için uygun bir başlangıç
noktası sağlar.
Şablon, API arka ucu olarak davranacak bir ASP.NET Core projesi ve bir kullanıcı arabirimi olarak görev yapacak
standart CRA tepki veren bir proje oluşturmaya eşdeğerdir, ancak her ikisini de tek bir birim olarak oluşturulup
yayımlanabilen tek bir uygulama projesinde barındırmanın rahatlığını sağlar.
Tepki verme projesi şablonu, sunucu tarafı işleme (SSR ) için tasarlanmamıştır. Yanıt verme ve Node. js ile SSR için,
Next. js veya rampale'yı göz önünde bulundurun.

Yeni bir uygulama oluşturun


ASP.NET Core 2,1 yüklüyse, tepki verme projesi şablonunu yüklemeniz gerekmez.
Boş bir dizinde komut dotnet new react kullanarak komut isteminden yeni bir proje oluşturun. Örneğin,
aşağıdaki komutlar uygulamayı Yeni bir uygulama dizininde oluşturur ve bu dizine geçer:

dotnet new react -o my-new-app


cd my-new-app

Uygulamayı Visual Studio 'dan veya .NET Core CLI çalıştırın:


Visual Studio
.NET Core CLI
Oluşturulan . csproj dosyasını açın ve uygulamayı buradan normal olarak çalıştırın.
Yapı işlemi ilk çalıştırmada NPM bağımlılıklarını geri yükler ve bu işlem birkaç dakika sürebilir. Sonraki derlemeler
çok daha hızlıdır.
Proje şablonu, bir ASP.NET Core uygulaması ve bir tepki verme uygulaması oluşturur. ASP.NET Core uygulaması
veri erişimi, yetkilendirme ve diğer sunucu tarafı sorunları için kullanılmak üzere tasarlanmıştır. Clientapp alt
dizininde bulunan tepki verme uygulaması, tüm Kullanıcı arabirimi endişeleri için kullanılmak üzere tasarlanmıştır.

Sayfa, resim, stil, modül vb. ekleyin


Clientapp dizini standart bir CRA tepki uygulamadır. Daha fazla bilgi için resmi CRA belgelerine bakın.
Bu şablon tarafından oluşturulan ve CRA tarafından oluşturulan tepki verme uygulaması arasında hafif farklar
vardır; Ancak, uygulamanın özellikleri değiştirilmez. Şablon tarafından oluşturulan uygulama, önyüklemetabanlı
bir düzen ve temel bir yönlendirme örneği içerir.

NPM paketlerini yükler


Üçüncü taraf NPM paketlerini yüklemek için clientapp alt dizininde bir komut istemi kullanın. Örneğin:
cd ClientApp
npm install --save <package_name>

Yayımla ve dağıt
Geliştirme aşamasında uygulama, geliştirici kolaylığı için iyileştirilmiş bir modda çalışır. Örneğin, JavaScript
demeti kaynak eşlemeleri içerir (hata ayıklarken, özgün kaynak kodunuzu görebilirsiniz). Uygulama JavaScript,
HTML ve CSS dosya değişikliklerini diskte izler ve bu dosya değişikliğini gördüğünde otomatik olarak yeniden
derlenir ve yeniden yükler.
Üretimde, uygulamanızın performans için iyileştirilmiş bir sürümünü sunar. Bu otomatik olarak gerçekleşecek
şekilde yapılandırılmıştır. Yayımladığınızda, derleme yapılandırması, istemci tarafı kodunuzun küçültülmüş,
transpiled derlemesini yayar. Geliştirme derlemesinin aksine, üretim derlemesi için Node. js ' nin sunucuya
yüklenmesi gerekmez.
Standart ASP.NET Core barındırma ve dağıtım yöntemlerikullanabilirsiniz.

CRA sunucusunu bağımsız olarak çalıştırma


Proje, ASP.NET Core uygulama geliştirme modunda başladığında, CRA geliştirme sunucusunun kendi örneğini
arka planda başlatacak şekilde yapılandırılmıştır. Bu kullanışlı bir yöntemdir çünkü bu, ayrı bir sunucuyu el ile
çalıştırmak zorunda olmadığınız anlamına gelir.
Bu varsayılan Kurulumun bir dezavantajı vardır. C# Kodunuzun her değiştirilişinde ve ASP.NET Core
uygulamanızın yeniden başlatılması gerektiğinde CRA sunucusu yeniden başlatılır. Yeniden başlamak için birkaç
saniye gerekir. Sık C# kod düzenlemeleri yapıyorsanız ve CRA sunucusunun yeniden başlamasını beklemek
istemiyorsanız, cra sunucusunu ASP.NET Core işleminden bağımsız olarak dışarıdan çalıştırın. Bunu yapmak için:
1. Clientapp alt dizinine aşağıdaki ayarla bir . env dosyası ekleyin:

BROWSER=none

Bu, CRA sunucusunu dışarıdan başlatırken Web tarayıcınızın açılmasını engeller.


2. Bir komut isteminde clientapp alt dizinine geçin ve CRA geliştirme sunucusunu başlatın:

cd ClientApp
npm start

3. ASP.NET Core uygulamanızı, kendi kendine birini başlatmak yerine dış CRA sunucu örneğini kullanacak
şekilde değiştirin. Başlangıç sınıfınıza spa.UseReactDevelopmentServer çağrılmasını aşağıdaki kodla
değiştirin:

spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");

ASP.NET Core uygulamanızı başlattığınızda, bir CRA sunucusu başlatılmaz. Bunun yerine el ile başlattığınız örnek
kullanılır. Bu, daha hızlı başlamasını ve yeniden başlatılmasını sağlar. Artık, yanıt verme uygulamanızın her
seferinde yeniden derlenmesini beklemiyordu.
IMPORTANT
"Sunucu tarafı işleme", bu şablonun desteklenen bir özelliği değildir. Bu şablonla olan amamız "oluşturma-tepki-uygulama" ile
eşlik sağlamaktır. Bu nedenle, "oluşturma-yanıt verme uygulaması" projesine (SSR gibi) dahil olmayan senaryolar ve özellikler
desteklenmez ve Kullanıcı için bir alıştırma olarak kalır.

Ek kaynaklar
ASP.NET Core tek sayfalı uygulamalar için kimlik doğrulamaya giriş
ASP.NET Core ile React-ile-Redux proje şablonu
kullanın
10.05.2019 • 2 minutes to read • Edit Online

Güncelleştirilmiş Redux ile React proje şablonu kullanarak ASP.NET Core uygulamaları, React Redux, uygun bir
başlama noktası sağlar ve oluşturma-react-app (CRA) kuralları, istemci tarafı zengin kullanıcı arabirimi (UI)
uygulamak için.
Proje oluşturma komutuna dışında React-ile-Redux şablonu hakkındaki tüm bilgileri React şablonu ile aynıdır. Bu
proje türü oluşturmak için çalıştırılması dotnet new reactredux yerine dotnet new react . Her iki React tabanlı
şablonlar için ortak olan işlevselliği hakkında daha fazla bilgi için bkz: React şablon belgeleri.
IIS React-ile-Redux bir alt uygulama yapılandırma hakkında daha fazla bilgi için bkz: açarken kilitlenmesi şablon
2.1: IIS üzerinde SPA kullanılamıyor (aspnet/şablon #555).
ASP.NET Core içinde tek sayfalı uygulamalar
oluşturmak için JavaScript hizmetlerini kullanın
19.09.2019 • 19 minutes to read • Edit Online

Tarafından Scott Addie ve Fiyaz Hasan


Tek sayfa uygulama (SPA) web uygulamasının kendi devralınan zengin kullanıcı deneyimi nedeniyle popüler bir
türdür. ASP.NET Core gibi sunucu tarafı çerçeveleri ile, angular veya yanıt verme gibi ISTEMCI tarafı Spa
çerçevelerini veya kitaplıklarınıtümleştirme zor olabilir. Tümleştirme sürecinde uçuşmayı azaltmak için JavaScript
Hizmetleri geliştirilmiştir. Ancak, farklı istemci ve sunucu teknoloji yığınları arasında sorunsuz bir işlemi etkinleştirir.

WARNING
Bu makalede açıklanan özellikler ASP.NET Core 3,0 itibariyle kullanımdan kalkmıştır. Microsoft. AspNetCore. SpaServices.
Extensions NuGet paketinde daha basıt bir spa çerçeveleri tümleştirme mekanizması mevcuttur. Daha fazla bilgi için bkz.
Microsoft. aspnetcore. spaservices ve Microsoft. AspNetCore. NodeServices üzerinde kullanımdan bulunan [Duyuru] .

JavaScript Hizmetleri nedir?


JavaScript Hizmetleri, ASP.NET Core yönelik istemci tarafı teknolojilerinin bir koleksiyonudur. ASP.NET Core
geliştiricilerinin Spa'lar oluşturmaya yönelik olarak tercih edilen sunucu tarafı platformu olarak yerleştirmek için
hedefi sağlamaktır.
JavaScript Hizmetleri iki ayrı NuGet paketi içerir:
Microsoft.AspNetCore.NodeServices (NodeServices)
Microsoft.AspNetCore.SpaServices (SpaServices)
Bu paketler, aşağıdaki senaryolarda faydalıdır:
Sunucu üzerinde JavaScript çalıştırma
SPA altyapı veya kitaplığı kullanın
İstemci tarafı Web varlıklarla oluşturun
Bu makalenin odak çoğunu SpaServices paketini kullanarak yerleştirilir.

SpaServices nedir
ASP.NET Core geliştiricilerinin Spa'lar oluşturmaya yönelik olarak tercih edilen sunucu tarafı platformu olarak
yerleştirmek için SpaServices oluşturulur. Istenmeyen hizmetler ASP.NET Core ile maça geliştirmek için gerekli
değildir ve geliştiricileri belirli bir istemci çerçevesinde kilitlemez.
SpaServices gibi kullanışlı bir altyapı sağlar:
Sunucu tarafı prerendering
Web geliştirme ara yazılımı
Sık erişimli modülü değiştirme
Yönlendirme Yardımcıları
Toplu olarak, bu altyapı bileşenlerini, hem geliştirme iş akışını hem de çalışma zamanı deneyimi geliştirin.
Bileşenleri ayrı ayrı önemsenmeksizin devralınabilir.
SpaServices kullanmanın önkoşulları
SpaServices ile çalışmak için aşağıdakileri yükleyin:
Node.js (sürüm 6 veya sonrası) npm ile
Bu bileşenler yüklenir ve bulunabilir doğrulamak için komut satırından aşağıdaki komutu çalıştırın:

node -v && npm -v

Bir Azure Web sitesine dağıtım yapıyorsanız hiçbir işlem gerekli—değildir. js, sunucu ortamlarında
yüklenir ve kullanılabilir.
.NET core SDK 2.0 veya üzeri
Visual Studio 2017 kullanarak Windows 'da SDK, .NET Core platformlar arası geliştirme iş yükü
seçilerek yüklenir.
Microsoft.AspNetCore.SpaServices NuGet paketi

Sunucu tarafı prerendering


Bir evrensel (isomorphic olarak da bilinir) uygulama özellikli olan hem çalışan sunucu ve istemci üzerindeki bir
JavaScript uygulamasıdır. Angular, React ve diğer popüler çerçeveleri için bu uygulama geliştirme stili Evrensel bir
platform sağlar. İlk Node.js aracılığıyla sunucuda framework bileşenleri oluşturma ve yürütme istemciye daha fazla
temsilci olur.
ASP.NET Core etiket Yardımcıları tarafından sağlanan SpaServices server JavaScript işlevleri çağrılarak sunucu
tarafı prerendering uygulamasını basitleştirin.
Sunucu tarafı prerendering önkoşulları
ASPNET-prerendering NPM paketini yükler:

npm i -S aspnet-prerendering

Sunucu tarafı prerendering yapılandırması


Etiket Yardımcıları projesinin ad kayıt bulunabilir yapılan _viewımports.cshtml dosyası:

@using SpaServicesSampleApp
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"

Bu etiket Yardımcıları hemen bir HTML benzeri sözdizimi Razor görünüm içinde yararlanarak alt düzey API'ler ile
doğrudan iletişim ayrıntılı olarak incelenmektedir soyut:

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

ASP-PreRender-Module etiketi Yardımcısı


asp-prerender-module Etiketi Yardımcısı, önceki kod örneğinde kullanılan yürütür ClientApp/dist/main-server.js
Node.js aracılığıyla sunucuda. Açıklık'ın çok için ana server.js dosyasıdır TypeScript JavaScript transpilation görevin
bir yapıt Web derleme işlemi. Web tanımlayan bir giriş noktası diğer main-server ; ve bu diğer adı için bağımlılık
grafiği geçişini başlar ClientApp/önyükleme-server.ts dosyası:
entry: { 'main-server': './ClientApp/boot-server.ts' },

Aşağıdaki Angular örnekte ClientApp/önyükleme-server.ts dosya kullanır createServerRenderer işlevi ve


RenderResult tür aspnet-prerendering npm paketi, sunucu işleme Node.js aracılığıyla yapılandırılır. Kesin türü
belirtilmiş bir JavaScript içinde sarmalanmış bir Çözümle işlev çağrısı için sunucu tarafı işleme geçirilen
hedefleyen bir HTML biçimlendirmesi Promise nesne. Promise Nesnenin önemi olan, zaman uyumsuz olarak
DOM'ın yer tutucu öğesi yerleştirmeye sayfasına HTML biçimlendirme sağlar.

import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {


const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];

return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {


const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);

return new Promise<RenderResult>((resolve, reject) => {


zone.onError.subscribe(errorInfo => reject(errorInfo));
appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: state.renderToString()
});
moduleRef.destroy();
});
});
});
});
});

ASP-PreRender-veri etiketi Yardımcısı


İle birlikte zaman asp-prerender-module etiketi Yardımcısı asp-prerender-data etiketi Yardımcısı, bağlamsal bilgiler
için sunucu tarafı JavaScript Razor görünümden geçirmek için kullanılabilir. Örneğin, kullanıcı verilerini aşağıdaki
biçimlendirme geçirir main-server Modülü:

<app asp-prerender-module="ClientApp/dist/main-server"
asp-prerender-data='new {
UserName = "John Doe"
}'>Loading...</app>

Alınan bağımsız değişkeni yerleşik JSON serileştirici kullanılarak serileştirilmiş ve depolanan


UserName
params.data nesne. Angular aşağıdaki örnekte veri içinde kişiselleştirilmiş bir karşılama oluşturmak için kullanılan
bir h1 öğesi:
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {


const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];

return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {


const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);

return new Promise<RenderResult>((resolve, reject) => {


const result = `<h1>Hello, ${params.data.userName}</h1>`;

zone.onError.subscribe(errorInfo => reject(errorInfo));


appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: result
});
moduleRef.destroy();
});
});
});
});
});

Etiket yardımcılarının geçirildiği Özellik adları PascalCase gösterimi ile temsil edilir. Burada aynı özellik adları ile
gösterilir, JavaScript, Karşıtlık camelCase. Bu fark için varsayılan JSON seri hale getirme yapılandırması
sorumludur.
Yukarıdaki kod örneğinde genişletmek için verileri sunucudan görünüme hydrating tarafından geçirilebilir
globals özelliği için sağlanan resolve işlevi:
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {


const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
];

return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {


const appRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);

return new Promise<RenderResult>((resolve, reject) => {


const result = `<h1>Hello, ${params.data.userName}</h1>`;

zone.onError.subscribe(errorInfo => reject(errorInfo));


appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report
setImmediate(() => {
resolve({
html: result,
globals: {
postList: [
'Introduction to ASP.NET Core',
'Making apps with Angular and ASP.NET Core'
]
}
});
moduleRef.destroy();
});
});
});
});
});

postList İçinde tanımlanan bir dizi globals nesne bağlı tarayıcının genel window nesne. Bu değişken hoisting
genel kapsam için aynı verileri bir kez sunucuda ve istemcinin yeniden yüklenmesi için özellikle ilgili olarak çaba,
çoğaltma ortadan kaldırır.

Web geliştirme ara yazılımı


Web geliştirme ara yazılım yapabildiği Web yapılar kaynakları isteğe bağlı olarak Basitleştirilmiş geliştirme iş akışı
sunar. Ara yazılım, otomatik olarak derler ve bir sayfa tarayıcıya yeniden yüklendiğinde istemci-tarafı kaynaklar
sunar. Başka bir üçüncü taraf bağımlılığı veya özel kod değiştiğinde Web projenin npm derleme betiği aracılığıyla
el ile başlatmak için yaklaşımdır. Bir npm derleme betiği package.json dosya, aşağıdaki örnekte gösterilmiştir:

"build": "npm run build:vendor && npm run build:custom",

WebPack dev ara yazılım önkoşulları


ASPNET-WebPack NPM paketini yükler:

npm i -D aspnet-webpack

WebPack dev ara yazılım yapılandırması


HTTP istek işlem hattı aşağıdaki kod aracılığıyla içine kayıtlı Web geliştirme ara yazılım Startup.cs dosyanın
Configure yöntemi:

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

// Call UseWebpackDevMiddleware before UseStaticFiles


app.UseStaticFiles();

UseWebpackDevMiddleware Genişletme yöntemi çağrıldığında, önce statik dosya barındırma kaydetme aracılığıyla
UseStaticFiles genişletme yöntemi. Uygulama geliştirme modunda çalıştırıldığında güvenlik nedenleriyle, ara
yazılım kaydedin.
Webpack.config.js dosyanın output.publicPath özelliği söyler izlemek için bir ara yazılım dist klasördeki
değişiklikleri:

module.exports = (env) => {


output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},

Sık erişimli modülü değiştirme


Web'ın düşünebilirsiniz sık erişimli modülü değiştirme (HMR ) özelliği'nın Gelişmiş hali olarak Web geliştirme ara
yazılım. HMR aynı avantajları sunar, ancak otomatik olarak değişiklikleri derledikten sonra sayfa içeriği
güncelleştirerek daha fazla geliştirme iş akışı kolaylaştırır. Bu, geçerli bellek içi durumu ve hata ayıklama oturumu
SPA ile neden tarayıcı yenileme ile karıştırmayın. Web geliştirme ara yazılım hizmeti ve değişiklikleri tarayıcıya
gönderilmesini anlamına gelir tarayıcı arasında canlı bir bağlantı yoktur.
Sık kullanılan modül değiştirme önkoşulları
WebPack-Hot-ara yazılım NPM paketini yükler:

npm i -D webpack-hot-middleware

Sık kullanılan modül değiştirme yapılandırması


HMR bileşen MVC'nin HTTP istek işlem hattı, kaydedilmesi gerekir Configure yöntemi:

app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
HotModuleReplacement = true
});

İle doğru olarak Web geliştirme ara yazılım, UseWebpackDevMiddleware genişletme yöntemi çağrıldığında, önce
UseStaticFiles genişletme yöntemi. Uygulama geliştirme modunda çalıştırıldığında güvenlik nedenleriyle, ara
yazılım kaydedin.
Webpack.config.js dosya tanımlamalıdır bir plugins dizi bile boş bırakılır:

module.exports = (env) => {


plugins: [new CheckerPlugin()]

Uygulamayı tarayıcıda yüklendikten sonra geliştirici araçları konsol sekmesi HMR Etkinleştirme Onayı sağlar:

Yönlendirme Yardımcıları
Çoğu ASP.NET Core tabanlı maça, istemci tarafı yönlendirme genellikle sunucu tarafı yönlendirmeye ek olarak
istenir. SPA ve MVC yönlendirme sistemleri girişim bağımsız olarak çalışabilir. Yoktur, ancak bir kenar büyük/küçük
harf taşıyor sorunlarını: HTTP 404 yanıtları tanımlayan.
Senaryoyu göz önünde bulundurun uzantısız bir yolu /some/page kullanılır. İstek deseni-sunucu tarafı rota match
değil, ancak desenine bir istemci-tarafı rota ile eşleşmekte varsayılır. Şimdi gelen bir istek için göz önünde
bulundurun /images/user-512.png , hangi genellikle bekliyor sunucudaki bir görüntü dosyası bulunamıyor. İstenen
kaynak yolu herhangi bir sunucu tarafı yolu veya statik dosya ile eşleşmiyorsa, istemci tarafı uygulamanın bu—
işlemi genellikle bir 404 HTTP durum kodu döndürerek işlemesi çok düşüktür.
Yönlendirme Yardımcıları önkoşulları
İstemci tarafı yönlendirme NPM paketini yükler. Angular örnek olarak kullanıp:

npm i -S @angular/router

Yönlendirme Yardımcıları yapılandırması


Adlı bir genişletme yöntemi MapSpaFallbackRoute kullanılır Configure yöntemi:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});

Yollar yapılandırıldıkları sırayla değerlendirilir. Sonuç olarak, default rota önceki kod örneğinde kullanılan ilk
desen eşleştirmesi için.

Yeni bir proje oluşturma


JavaScript Hizmetleri önceden yapılandırılmış uygulama şablonları sağlar. Istenmeyen hizmetler, bu şablonlarda,
angular, tepki ve Redux gibi farklı çerçeveler ve kitaplıklarla birlikte kullanılır.
Bu şablonlar, aşağıdaki komutu çalıştırarak, .NET Core CLI yüklenebilir:

dotnet new --install Microsoft.AspNetCore.SpaTemplates::*

Kullanılabilir SPA şablonlar listesi görüntülenir:

ŞABLONLAR KISA AD DIL ETIKETLER

Angular ile ASP.NET Core Angular [C#] MVC/Web/SPA


MVC

React.js ile ASP.NET Core react [C#] MVC/Web/SPA


MVC

ASP.NET Core MVC React.js açarken kilitlenmesi [C#] MVC/Web/SPA


ve Redux

SPA şablonlardan birini kullanarak yeni bir proje oluşturmak için dahil kısa ad şablonda, yeni dotnet komutu.
Aşağıdaki komut, sunucu tarafı için yapılandırılan ASP.NET Core MVC ile Angular bir uygulama oluşturur:

dotnet new angular

Çalışma zamanı yapılandırma modunu ayarlayın


Birincil çalışma zamanı yapılandırma için iki mod vardır:
Geliştirme:
Hata ayıklamayı kolaylaştırmak için kaynak eşlemeleri içerir.
İstemci tarafı kod performans için en iyi duruma değil.
Üretim:
Kaynak eşlemeleri dışlar.
Paketleme ve küçültmeye göre istemci tarafı kodunu iyileştirir.
ASP.NET Core kullanan adlı bir ortam değişkeni ASPNETCORE_ENVIRONMENT yapılandırma modunu depolamak için.
Daha fazla bilgi için bkz. ortamı ayarlama.
.NET Core CLI ile Çalıştır
Proje kök dizininde aşağıdaki komutu çalıştırarak gerekli NuGet ve npm paketlerini geri yükleyin:

dotnet restore && npm i

Derleme ve uygulamayı çalıştırın:

dotnet run

Şunlara göre localhost üzerinde uygulama başladığında çalışma zamanı yapılandırma modunu. Gezinme
http://localhost:5000 tarayıcısında giriş sayfası görüntüler.

Visual Studio 2017 ile çalıştırma


Açık .csproj tarafından oluşturulan dosya yeni dotnet komutu. Gerekli NuGet ve npm paketleri proje üzerinde
otomatik olarak geri yüklenir. Bu geri yükleme işlemi birkaç dakika sürebilir ve tamamlandığında çalıştırmaya hazır
bir uygulamadır. Yeşil çalıştırma düğmesine veya tuşuna tıklayın Ctrl + F5 , ve tarayıcıda uygulama giriş sayfası
açılır. Uygulama ayarına göre localhost üzerinde çalışır çalışma zamanı yapılandırma modunu.

Uygulamayı test etme


SpaServices şablonları kullanarak istemci tarafı testleri çalıştırmak için önceden yapılandırılmış Karma ve Jasmine.
Test Çalıştırıcısı bu testler için karma bilgileriyse jasmine bir popüler birim testi çerçevesi için JavaScript, ' dir.
Karma çalışmak üzere yapılandırılmış Web geliştirme ara yazılım sağlayacak şekilde Geliştirici durdurmak ve
değişiklikler her zaman test çalıştırması için gerekli değildir. Test çalışması veya test çalışması karşı çalışan kod olup
olmadığını test otomatik olarak çalıştırılır.
Angular uygulamasını örnek olarak kullanıp, Jasmine iki test çalışmaları zaten için sağlanan CounterComponent
içinde counter.component.spec.ts dosyası:

it('should display a title', async(() => {


const titleText = fixture.nativeElement.querySelector('h1').textContent;
expect(titleText).toEqual('Counter');
}));

it('should start with count 0, then increments by 1 when clicked', async(() => {
const countElement = fixture.nativeElement.querySelector('strong');
expect(countElement.textContent).toEqual('0');

const incrementButton = fixture.nativeElement.querySelector('button');


incrementButton.click();
fixture.detectChanges();
expect(countElement.textContent).toEqual('1');
}));

Komut istemi açın ClientApp dizin. Şu komutu çalıştırın:

npm test

Komut dosyası içinde tanımlanan ayarlarını okur Karma test Çalıştırıcısı başlatır karma.conf.js dosya. Diğer ayarlar
arasında karma.conf.js aracılığıyla yürütülecek test dosyalarını tanımlar, files dizi:
module.exports = function (config) {
config.set({
files: [
'../../wwwroot/dist/vendor.js',
'./boot-tests.ts'
],

Uygulamayı yayımlama
Oluşturulan istemci-tarafı varlıkları ve yayımlanan ASP.NET Core yapıları dağıtmak için hazır bir pakete birleştiren
çok uğraşmayı gerektirebilir. Ne SpaServices adlı özel bir MSBuild hedefi ile tüm yayın işlem düzenler RunWebpack :

<Target Name="RunWebpack" AfterTargets="ComputeFilesToPublish">


<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec Command="npm install" />
<Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod" />
<Exec Command="node node_modules/webpack/bin/webpack.js --env.prod" />

<!-- Include the newly-built files in the publish output -->


<ItemGroup>
<DistFiles Include="wwwroot\dist\**; ClientApp\dist\**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>

MSBuild hedefi aşağıdaki sorumluluklara sahiptir:


1. NPM paketlerini geri yükleyin.
2. Üçüncü taraf, istemci tarafı varlıkların üretim sınıfı derlemesini oluşturun.
3. Özel istemci tarafı varlıkların üretim sınıfı derlemesini oluşturma.
4. Web paketi tarafından oluşturulan varlıkları Yayımla klasörüne kopyalayın.
MSBuild hedefi çalıştırılırken çağrılır:

dotnet publish -c Release

Ek kaynaklar
Angular belgeleri
LibMan ile ASP.NET Core istemci tarafı kitaplık alma
11.09.2019 • 2 minutes to read • Edit Online

Scott Ade tarafından


Kitaplık Yöneticisi (LibMan), basit, istemci tarafı bir kitaplık alma aracıdır. LibMan, dosya sisteminden veya bir içerik
teslim ağından (CDN )popüler kitaplıkları ve çerçeveleri indirir. Desteklenen CDNs, Cdnjs, jsdelivrve unpkg'yi içerir.
Seçilen kitaplık dosyaları getirildi ve ASP.NET Core projesi içindeki uygun konuma yerleştirildi.

LibMan kullanım örnekleri


LibMan aşağıdaki avantajları sunar:
Yalnızca ihtiyacınız olan kitaplık dosyaları indirilir.
Node. js, NPMve WebPackgibi ek araçlar, bir kitaplıktaki dosyaların alt kümesini almak için gerekli değildir.
Dosyalar, derleme görevleri veya el ile dosya kopyalama işlemleri yapılmadan belirli bir konuma yerleştirilebilir.
Libman 'ın avantajları hakkında daha fazla bilgi için Visual Studio 2017 ' de modern ön uç Web geliştirmesini
izleyin: LibMan segmenti.
LibMan bir paket yönetim sistemi değildir. Zaten NPM veya Yarngibi bir paket Yöneticisi kullanıyorsanız, bunu
yapmaya devam edin. LibMan, bu araçların yerini alacak şekilde geliştirilmedi.

Ek kaynaklar
Visual Studio'da ASP.NET Core ile LibMan kullanın
ASP.NET Core ile LibMan komut satırı arabirimini (CLı) kullanın
LibMan GitHub deposu
ASP.NET Core ile LibMan komut satırı arabirimini
(CLı) kullanın
13.11.2019 • 12 minutes to read • Edit Online

Scott Ade tarafından


Libman CLI, .NET Core 'un desteklendiği her yerde desteklenen platformlar arası bir araçtır.

Prerequisites
.NET core 2.1 SDK veya üzeri

Yükleme
LibMan CLı 'yı yüklemek için:

dotnet tool install -g Microsoft.Web.LibraryManager.Cli

.NET Core küresel aracı , Microsoft. Web. LibraryManager. CLI NuGet paketinden yüklenir.
Belirli bir NuGet paket kaynağından LibMan CLı 'yı yüklemek için:

dotnet tool install -g Microsoft.Web.LibraryManager.Cli --version 1.0.94-g606058a278 --add-source C:\Temp\

Yukarıdaki örnekte, yerel Windows makinenin C:\Temp\Microsoft.Web.LibraryManager.cli.1.0.94 -


g606058a278.nupkg dosyasından bir .NET Core genel aracı yüklenir.

Kullanım
CLı başarıyla yüklendikten sonra aşağıdaki komut kullanılabilir:

libman

Yüklü CLı sürümünü görüntülemek için:

libman --version

Kullanılabilir CLı komutlarını görüntülemek için:

libman --help

Yukarıdaki komut aşağıdakine benzer bir çıktı görüntüler:


1.0.163+g45474d37ed

Usage: libman [options] [command]

Options:
--help|-h Show help information
--version Show version information

Commands:
cache List or clean libman cache contents
clean Deletes all library files defined in libman.json from the project
init Create a new libman.json
install Add a library definition to the libman.json file, and download the
library to the specified location
restore Downloads all files from provider and saves them to specified
destination
uninstall Deletes all files for the specified library from their specified
destination, then removes the specified library definition from
libman.json
update Updates the specified library

Use "libman [command] --help" for more information about a command.

Aşağıdaki bölümlerde kullanılabilir CLı komutları ana hatlarıyla verilmiştir.

Projedeki LibMan 'ı Başlat


libman init komutu, yoksa bir Libman. JSON dosyası oluşturur. Dosya varsayılan öğe şablonu içeriğiyle
oluşturulur.
Özeti

libman init [-d|--default-destination] [-p|--default-provider] [--verbosity]


libman init [-h|--help]

Seçenekler
libman init komutu için aşağıdaki seçenekler kullanılabilir:
-d|--default-destination <PATH>

Geçerli klasöre göreli bir yol. Libman. JSONiçindeki bir kitaplık için destination özelliği tanımlanmamışsa
kitaplık dosyaları bu konuma yüklenir. <PATH> değeri Libman. JSONöğesinin defaultDestination özelliğine
yazılır.
-p|--default-provider <PROVIDER>

Belirli bir kitaplık için hiçbir sağlayıcı tanımlanmamışsa kullanılacak sağlayıcı. <PROVIDER> değeri Libman.
JSONöğesinin defaultProvider özelliğine yazılır. <PROVIDER> aşağıdaki değerlerden biriyle değiştirin:
cdnjs
filesystem
jsdelivr
unpkg

-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>
Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:
quiet
normal
detailed

Örnekler
ASP.NET Core projesinde bir Libman. JSON dosyası oluşturmak için:
Proje köküne gidin.
Şu komutu çalıştırın:

libman init

Varsayılan sağlayıcının adını yazın veya varsayılan CDNJS sağlayıcısını kullanmak için Enter ' a basın.
Geçerli değerler şunlardır:
cdnjs
filesystem
jsdelivr
unpkg

Aşağıdaki içeriğe sahip proje köküne bir Libman. JSON dosyası eklenir:

{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": []
}

Kitaplık dosyaları Ekle


libman installkomutu, kitaplık dosyalarını indirir ve projeye yükler. Bir Libman. JSON dosyası yoksa eklenir.
Libman. JSON dosyası kitaplık dosyaları için yapılandırma ayrıntılarını depolayacak şekilde değiştirilir.
Özeti

libman install <LIBRARY> [-d|--destination] [--files] [-p|--provider] [--verbosity]


libman install [-h|--help]

Arguments
LIBRARY

Yüklenecek kitaplığın adı. Bu ad, sürüm numarası gösterimi içerebilir (örneğin, @1.2.0 ).
Seçenekler
libman install komutu için aşağıdaki seçenekler kullanılabilir:
-d|--destination <PATH>

Kitaplığın yükleneceği konum. Belirtilmemişse, varsayılan konum kullanılır. Libman. JSONiçinde


defaultDestination özelliği belirtilmemişse, bu seçenek gereklidir.

--files <FILE>

Kitaplıktan yüklenecek dosyanın adını belirtin. Belirtilmemişse, kitaplıktaki tüm dosyalar yüklenir.
Yüklenecek dosya başına bir --files seçeneği belirtin. Göreli yollar da desteklenir. Örneğin:
--files dist/browser/signalr.js .

-p|--provider <PROVIDER>

Kitaplık alımı için kullanılacak sağlayıcının adı. <PROVIDER> aşağıdaki değerlerden biriyle değiştirin:
cdnjs
filesystem
jsdelivr
unpkg
Belirtilmemişse, Libman. JSON içindeki defaultProvider özelliği kullanılır. Libman. JSONiçinde
defaultProvider özelliği belirtilmemişse, bu seçenek gereklidir.

-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
Aşağıdaki Libman. JSON dosyasını göz önünde bulundurun:

{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": []
}

JQuery sürümü 3.2.1 jQuery. min. js dosyasını CDNJS sağlayıcısını kullanarak Wwwroot/Scripts/jQuery klasörüne
yüklemek için:

libman install jquery@3.2.1 --provider cdnjs --destination wwwroot/scripts/jquery --files jquery.min.js

Libman. JSON dosyası şuna benzer:


{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "jquery@3.2.1",
"destination": "wwwroot/scripts/jquery",
"files": [
"jquery.min.js"
]
}
]
}

C:\temp\contosotakvim\ dosya sistemi sağlayıcısını kullanarak Calendar. js ve Calendar. css dosyalarını yüklemek
için:

libman install C:\temp\contosoCalendar\ --provider filesystem --files calendar.js --files calendar.css

Aşağıdaki istem iki nedenden dolayı görünür:


Libman. JSON dosyası bir defaultDestination özelliği içermiyor.
libman install komutu -d|--destination seçeneğini içermez.

Varsayılan hedefi kabul ettikten sonra, Libman. JSON dosyası şuna benzer:
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "jquery@3.2.1",
"destination": "wwwroot/scripts/jquery",
"files": [
"jquery.min.js"
]
},
{
"library": "C:\\temp\\contosoCalendar\\",
"provider": "filesystem",
"destination": "wwwroot/lib/contosoCalendar",
"files": [
"calendar.js",
"calendar.css"
]
}
]
}

Kitaplık dosyalarını geri yükleme


libman restore komutu Libman. JSONiçinde tanımlanan kitaplık dosyalarını yüklüyor. Aşağıdaki kurallar
geçerlidir:
Proje kökünde bir Libman. JSON dosyası yoksa bir hata döndürülür.
Bir kitaplık bir sağlayıcıyı belirtiyorsa, Libman. JSON içindeki defaultProvider özelliği yok sayılır.
Bir kitaplık bir hedef belirtiyorsa, Libman. JSON içinde defaultDestination özelliği yok sayılır.
Özeti

libman restore [--verbosity]


libman restore [-h|--help]

Seçenekler
libman restore komutu için aşağıdaki seçenekler kullanılabilir:
-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
Libman. JSON' da tanımlanan kitaplık dosyalarını geri yüklemek için:

libman restore
Kitaplık dosyalarını sil
libman clean komutu, daha önce LibMan aracılığıyla geri yüklenen kitaplık dosyalarını siler. Bu işlemden sonra
boş olacak klasörler silinir. Libman. JSON ' nin libraries özelliğindeki kitaplık dosyalarının ilişkili yapılandırması
kaldırılmaz.
Özeti

libman clean [--verbosity]


libman clean [-h|--help]

Seçenekler
libman clean komutu için aşağıdaki seçenekler kullanılabilir:
-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
LibMan aracılığıyla yüklenen kitaplık dosyalarını silmek için:

libman clean

Kitaplık dosyalarını kaldır


libman uninstall komutu:
Belirtilen kitaplıkla ilişkili tüm dosyaları Libman. JSONdosyasındaki hedefle siler.
Libman. JSON' dan ilişkili kitaplık yapılandırmasını kaldırır.
Şu durumlarda bir hata oluşur:
Proje kökünde Libman. JSON dosyası yok.
Belirtilen kitaplık yok.
Aynı ada sahip birden fazla kitaplık yüklüyse, bir tane seçmeniz istenir.
Özeti

libman uninstall <LIBRARY> [--verbosity]


libman uninstall [-h|--help]

Arguments
LIBRARY

Kaldırılacak kitaplığın adı. Bu ad, sürüm numarası gösterimi içerebilir (örneğin, @1.2.0 ).
Seçenekler
libman uninstall komutu için aşağıdaki seçenekler kullanılabilir:
-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
Aşağıdaki Libman. JSON dosyasını göz önünde bulundurun:

{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "jquery@3.3.1",
"files": [
"jquery.min.js",
"jquery.js",
"jquery.min.map"
],
"destination": "wwwroot/lib/jquery/"
},
{
"provider": "unpkg",
"library": "bootstrap@4.1.3",
"destination": "wwwroot/lib/bootstrap/"
},
{
"provider": "filesystem",
"library": "C:\\temp\\lodash\\",
"files": [
"lodash.js",
"lodash.min.js"
],
"destination": "wwwroot/lib/lodash/"
}
]
}

JQuery 'i kaldırmak için aşağıdaki komutlardan biri başarılı olur:

libman uninstall jquery

libman uninstall jquery@3.3.1

filesystem sağlayıcısı aracılığıyla yüklenen Lodash dosyalarını kaldırmak için:

libman uninstall C:\temp\lodash\


Kitaplık sürümünü Güncelleştir
libman update komutu, LibMan aracılığıyla yüklenen bir kitaplığı belirtilen sürüme güncelleştirir.
Şu durumlarda bir hata oluşur:
Proje kökünde Libman. JSON dosyası yok.
Belirtilen kitaplık yok.
Aynı ada sahip birden fazla kitaplık yüklüyse, bir tane seçmeniz istenir.
Özeti

libman update <LIBRARY> [-pre] [--to] [--verbosity]


libman update [-h|--help]

Arguments
LIBRARY

Güncelleştirilecek kitaplığın adı.


Seçenekler
libman update komutu için aşağıdaki seçenekler kullanılabilir:
-pre

Kitaplığın en son yayın öncesi sürümünü edinin.


--to <VERSION>

Kitaplığın belirli bir sürümünü edinin.


-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
JQuery 'i en son sürüme güncelleştirmek için:

libman update jquery

JQuery 'i 3.3.1 sürümüne güncelleştirmek için:

libman update jquery --to 3.3.1

JQuery 'i en son ön sürüm sürümüne güncelleştirmek için:

libman update jquery -pre


Kitaplık önbelleğini Yönet
libman cache komutu LibMan kitaplık önbelleğini yönetir. filesystem sağlayıcı kitaplık önbelleğini kullanmaz.
Özeti

libman cache clean [<PROVIDER>] [--verbosity]


libman cache list [--files] [--libraries] [--verbosity]
libman cache [-h|--help]

Arguments
PROVIDER

Yalnızca clean komutuyla birlikte kullanılır. Temizleyen sağlayıcı önbelleğini belirtir. Geçerli değerler şunlardır:
cdnjs
filesystem
jsdelivr
unpkg

Seçenekler
libman cache komutu için aşağıdaki seçenekler kullanılabilir:
--files

Önbelleğe alınan dosyaların adlarını listeleyin.


--libraries

Önbelleğe alınan kitaplıkların adlarını listeleyin.


-h|--help

Yardım bilgilerini gösterir.


--verbosity <LEVEL>

Çıkışın ayrıntı düzeyini ayarlayın. Değiştirin <LEVEL> aşağıdaki değerlerden biriyle:


quiet
normal
detailed

Örnekler
Sağlayıcı başına önbelleğe alınmış kitaplıkların adlarını görüntülemek için aşağıdaki komutlardan birini
kullanın:

libman cache list

libman cache list --libraries

Aşağıdakine benzer bir çıktı görüntülenir:


Cache contents:
---------------
unpkg:
knockout
react
vue
cdnjs:
font-awesome
jquery
knockout
lodash.js
react

Sağlayıcı başına önbelleğe alınmış kitaplık dosyalarının adlarını görüntülemek için:

libman cache list --files

Aşağıdakine benzer bir çıktı görüntülenir:

Cache contents:
---------------
unpkg:
knockout:
<list omitted for brevity>
react:
<list omitted for brevity>
vue:
<list omitted for brevity>
cdnjs:
font-awesome
metadata.json
jquery
metadata.json
3.2.1\core.js
3.2.1\jquery.js
3.2.1\jquery.min.js
3.2.1\jquery.min.map
3.2.1\jquery.slim.js
3.2.1\jquery.slim.min.js
3.2.1\jquery.slim.min.map
3.3.1\core.js
3.3.1\jquery.js
3.3.1\jquery.min.js
3.3.1\jquery.min.map
3.3.1\jquery.slim.js
3.3.1\jquery.slim.min.js
3.3.1\jquery.slim.min.map
knockout
metadata.json
3.4.2\knockout-debug.js
3.4.2\knockout-min.js
lodash.js
metadata.json
4.17.10\lodash.js
4.17.10\lodash.min.js
react
metadata.json

Yukarıdaki çıktıda, 3.2.1 ve 3.3.1 jQuery sürümlerinin CDNJS sağlayıcısı altında önbelleğe alındığını
görürsünüz.
CDNJS sağlayıcısı için kitaplık önbelleğini boşaltmak için:
libman cache clean cdnjs

CDNJS sağlayıcı önbelleğini boşaltdıktan sonra, libman cache list komutu şunları görüntüler:

Cache contents:
---------------
unpkg:
knockout
react
vue
cdnjs:
(empty)

Tüm desteklenen sağlayıcıların önbelleğini boşaltmak için:

libman cache clean

Tüm sağlayıcı önbellekleri boşaltıldıktan sonra, libman cache list komutu şunları görüntüler:

Cache contents:
---------------
unpkg:
(empty)
cdnjs:
(empty)

Ek kaynaklar
Küresel bir araç yükler
Visual Studio'da ASP.NET Core ile LibMan kullanın
LibMan GitHub deposu
Visual Studio'da ASP.NET Core ile LibMan kullanın
11.07.2019 • 13 minutes to read • Edit Online

Tarafından Scott Addie


Visual Studio için yerleşik desteği vardır LibMan dahil olmak üzere, ASP.NET Core projelerinde:
Yapılandırma ve yapı LibMan geri yükleme işlemleri çalıştırma desteği.
LibMan geri yükleme ve temizleme işlemlerini tetikleme menü öğeleri.
Kitaplıkları bulma ve dosyalar projeye ekleme için arama iletişim kutusu.
Düzenleme için desteği libman.json—LibMan bildirim dosyası.
Görüntüleme veya indirme örnek kodu (karşıdan yükleme)

Önkoşullar
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü

Kitaplık dosyaları Ekle


Kitaplık dosyalarını bir ASP.NET Core projesi için iki farklı şekilde eklenebilir:
1. İstemci tarafı kitaplık Ekle iletişim kutusunu kullanın
2. LibMan bildirim dosyası girişlerini el ile yapılandırma
İstemci tarafı kitaplık Ekle iletişim kutusunu kullanın
Bir istemci-tarafı kitaplığını yüklemek için aşağıdaki adımları izleyin:
İçinde Çözüm Gezgini, hangi dosyaların eklenmelidir proje klasörüne sağ tıklayın. Seçin ekleme >
istemci tarafı kitaplık. İstemci tarafı kitaplık Ekle iletişim kutusu görüntülenir:

Kitaplık sağlayıcısından seçin sağlayıcısı açılır. CDNJS varsayılan sağlayıcıdır.


İçinde getirilecek kitaplığı adı Kitaplığı metin kutusu. IntelliSense belirtilen metinle başlayan kitaplıkların
bir listesi sağlar.
IntelliSense listeden kitaplığı seçin. Bildirimi kitaplık adı soneki ile @ sembol ve seçili sağlayıcıya bilinen en
son kararlı sürümü.
Dahil etmek için hangi dosyaların karar verin:
Seçin tüm kitaplık dosyalarını dahil et tüm kitaplık dosyalarını içerecek şekilde radyo düğmesi.
Seçin belirli dosyaları seçin kitaplığın dosyaların bir alt kümesine eklenecek radyo düğmesi. Dosya
Seçici ağaç radyo düğmesi seçili olduğunda etkindir. İndirmek için dosya adlarını sol tarafındaki kutuları
işaretleyin.
Dosyaları depolamak için proje klasörü belirtin hedef konum metin kutusu. Bir öneri olarak, her kitaplık
ayrı bir klasörde depolar.
Önerilen hedef konum klasör konumu iletişim kutusu, başlatılan dayanır:
Başlatılan proje kök ise:
wwwroot/lib kullanılır wwwroot bulunmaktadır.
LIB kullanılır wwwroot yok.
Başlatılan proje klasöründen, karşılık gelen klasörü adı kullanılır.
Klasör öneri kitaplık adı ile soneki. Aşağıdaki tabloda, jQuery Razor sayfaları projesinde yüklerken klasör
öneriler gösterilmektedir.

BAŞLATMA KONUMU ÖNERILEN KLASÖRÜ

Proje kök dizinini (varsa wwwroot var) wwwroot/lib/jquery /

Proje kök dizinini (varsa wwwroot yok) lib/jquery/

Sayfaları proje klasöründe Sayfa/jquery /

Tıklayın yükleme başına yapılandırma dosyalarını indirmek için düğmeye libman.json.


Gözden geçirme Kitaplık Yöneticisi akışı çıkış yükleme Ayrıntıları penceresi. Örneğin:

Restore operation started...


Restoring libraries for project LibManSample
Restoring library jquery@3.3.1... (LibManSample)
wwwroot/lib/jquery/jquery.min.js written to destination (LibManSample)
wwwroot/lib/jquery/jquery.js written to destination (LibManSample)
wwwroot/lib/jquery/jquery.min.map written to destination (LibManSample)
Restore operation completed
1 libraries restored in 2.32 seconds

LibMan bildirim dosyası girişlerini el ile yapılandırma


Proje kök 's LibMan bildiriminin içeriği üzerinde Visual Studio'da tüm LibMan işlemleri temel alır (libman.json). El
ile düzenleyebilirsiniz libman.json proje için kitaplık dosyalarını yapılandırmak için. Visual Studio tüm kitaplık
dosyalarını bir kez yükler libman.json kaydedilir.
Açmak için libman.json düzenlemek için aşağıdaki seçenekler mevcuttur:
Çift libman.json dosyası Çözüm Gezgini.
Projeye sağ Çözüm Gezgini seçip istemci tarafı kitaplıkları yönetmek. †
Seçin istemci tarafı kitaplıkları yönetmek Visual Studio'dan proje menüsü. †
† Varsa libman.json dosya proje kök dizininde zaten yoksa, varsayılan öğe şablonu içeriği ile oluşturulur.
Visual Studio düzenleme desteği renklendirme gibi biçimlendirme, IntelliSense ve şema doğrulama zengin JSON
sunar. LibMan bildirim JSON şeması bulunduğu https://json.schemastore.org/libman .
Aşağıdaki bildirim dosyası ile tanımlanan yapılandırma başına LibMan alır libraries özelliği. Bir açıklama içinde
tanımlanan nesne değişmez değerlerinin libraries izler:
Bir alt kümesini jQuery sürüm 3.3.1 CDNJS sağlayıcısından alınır. Alt tanımlanan files özelliği—jquery.min.js,
jquery.js, ve jquery.min.map. Dosyalar projesinin yerleştirilir wwwroot/lib/jquery klasör.
Tamamen önyükleme sürüm 4.1.3 alınır ve yerleştirilmiş bir wwwroot/lib/önyükleme klasör. Nesne sabit değeri
provider özelliklerine defaultProvider özellik değeri. LibMan unpkg sağlayıcısından önyükleme dosyaları alır.
Bir alt kümesini Lodash unsurun kuruluştaki tarafından onaylandı. Lodash.js ve lodash.min.js dosyaları yerel
dosya sisteminden alınır C:\temp\lodash\ . Dosyalar projenin kopyalanır wwwroot/lib/lodash klasör.

{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "jquery@3.3.1",
"files": [
"jquery.min.js",
"jquery.js",
"jquery.min.map"
],
"destination": "wwwroot/lib/jquery/"
},
{
"provider": "unpkg",
"library": "bootstrap@4.1.3",
"destination": "wwwroot/lib/bootstrap/"
},
{
"provider": "filesystem",
"library": "C:\\temp\\lodash\\",
"files": [
"lodash.js",
"lodash.min.js"
],
"destination": "wwwroot/lib/lodash/"
}
]
}

NOTE
LibMan yalnızca her kitaplığının her sağlayıcısından bir sürümünü destekler. Libman.json dosya aynı kitaplık adı verilen
sağlayıcı için iki kitaplıklarıyla içeriyorsa, şema doğrulaması başarısız olur.

Kitaplık dosyaları geri yükleme


Visual Studio içinden kitaplık dosyaları geri yüklemek için olmalıdır geçerli bir libman.json proje kök dosyasında.
Geri yüklenen dosya projenin her kitaplık için belirtilen konuma yerleştirilir.
ASP.NET Core projesinde iki yolla kitaplık dosyalarını geri yüklenebilir:
1. Derleme sırasında dosyaları geri yükleme
2. Dosyaları el ile geri yükleme
Derleme sırasında dosyaları geri yükleme
LibMan yapı işleminin bir parçası olarak tanımlanan kitaplık dosyalarını geri yükleyebilirsiniz. Varsayılan olarak,
derleme üzerinde geri yükleme davranışı devre dışı bırakıldı.
Ve test derleme üzerinde geri yükleme davranışı etkinleştirmek için:
Sağ libman.json içinde Çözüm Gezgini seçip etkinleştirme geri istemci-tarafı kitaplıklarını temel
yapı bağlam menüsünden.
Tıklayın Evet NuGet paketini yüklemek isteyip istemediğiniz sorulduğunda düğmesi.
Microsoft.Web.LibraryManager.Build NuGet paketini projeye eklendi:

<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="1.0.113" />

LibMan dosya geri yüklemesi gerçekleşir doğrulamak için projeyi derleyin.


Microsoft.Web.LibraryManager.Build Paket LibMan projenin derleme işlemi sırasında çalıştırılan bir MSBuild
hedefi yerleştirir.
Gözden geçirme derleme akışı çıkış LibMan etkinlik günlüğü penceresi:

1>------ Build started: Project: LibManSample, Configuration: Debug Any CPU ------
1>
1>Restore operation started...
1>Restoring library jquery@3.3.1...
1>Restoring library bootstrap@4.1.3...
1>
1>2 libraries restored in 10.66 seconds
1>LibManSample -> C:\LibManSample\bin\Debug\netcoreapp2.1\LibManSample.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Derleme üzerinde geri yükleme davranışı etkinleştirildiğinde libman.json bağlam menüsünü görüntüler bir devre
dışı bırakma geri istemci-tarafı kitaplıklarını temel yapı seçeneği. Bu seçeneğin belirlenmesi kaldırır
Microsoft.Web.LibraryManager.Build paket proje dosyasından başvuru. Sonuç olarak, istemci tarafı kitaplıkları
üzerinde her derleme artık geri yüklenir.
Derleme üzerinde geri yükleme ayar ne olursa olsun, el ile diledikleri zaman geri yükleyebilirsiniz libman.json
bağlam menüsü. Daha fazla bilgi için dosyaları el ile geri.
Dosyaları el ile geri yükleme
Kitaplık dosyaları el ile geri yüklemek için:
Çözümdeki tüm projeleri için:
İçinde çözüm adına sağ tıklayın Çözüm Gezgini.
Seçin geri istemci tarafı kitaplıkları seçeneği.
Belirli bir proje için:
Sağ libman.json dosyası Çözüm Gezgini.
Seçin geri istemci tarafı kitaplıkları seçeneği.
Geri yükleme işlemi devam ederken:
Görev durumu Merkezi (TSC ) simgesi Visual Studio durum çubuğunda animasyon uygulanır ve okuyacaksa
geri yükleme işlemi başladı. Simgesine tıklayarak, bilinen arka plan görevleri listeleme bir araç ipucu açılır.
Durum çubuğundaki ileti gönderilecek ve Kitaplık Yöneticisi akışı çıkış penceresi. Örneğin:
Restore operation started...
Restoring libraries for project LibManSample
Restoring library jquery@3.3.1... (LibManSample)
wwwroot/lib/jquery/jquery.min.js written to destination (LibManSample)
wwwroot/lib/jquery/jquery.js written to destination (LibManSample)
wwwroot/lib/jquery/jquery.min.map written to destination (LibManSample)
Restore operation completed
1 libraries restored in 2.32 seconds

Kitaplık dosyaları sil


Gerçekleştirilecek temiz Visual Studio'da daha önce geri kitaplık dosyaları silen işlemi:
Sağ libman.json dosyası Çözüm Gezgini.
Seçin temiz istemci tarafı kitaplıkları seçeneği.
Kitaplık olmayan dosyaları kaldırılmamıştır önlemek için temizleme işlemi tüm dizinleri silmez. Yalnızca önceki geri
yükleme dahil edilen dosyalar da kaldırır.
Temizleme işlemi devam ederken:
Visual Studio durum çubuğunda TSC simge animasyon uygulanır ve okuyacaksa istemci kitaplıkları işlemi
başlatıldı. Simgesine tıklayarak, bilinen arka plan görevleri listeleme bir araç ipucu açılır.
İletileri için durum çubuğu gönderilir ve Kitaplık Yöneticisi akışı çıkış penceresi. Örneğin:

Clean libraries operation started...


Clean libraries operation completed
2 libraries were successfully deleted in 1.91 secs

Temizleme işlemi, yalnızca dosyaları projeden siler. Kitaplık dosyaları için daha hızlı alma gelecekteki geri yükleme
işlemleri üzerindeki önbellekte kalır. Yerel makinenin önbelleğinde depolanan kitaplık dosyalarını yönetmek için
kullandığınız LibMan CLI.

Kitaplık dosyaları kaldırma


Kitaplık dosyaları kaldırmak için:
Açık libman.json.
Giriş işaretini içinde karşılık gelen konum libraries nesne sabit değeri.
Sol kenar boşluğunda görünür ampul simgesini tıklatın ve seçin kaldırma <library_name >
@<library_version > :

Alternatif olarak, el ile düzenleyebilir ve LibMan bildirimi kaydetmek ( libman.json). Geri yükleme işlemi dosyası
kaydedildiğinde çalıştırır. Artık tanımlanan kitaplık dosyalarını libman.json projeden kaldırıldı.
Kitaplık sürümünü güncelleştirme
Bir güncelleştirilen kitaplığı sürümünü denetlemek için:
Açık libman.json.
Giriş işaretini içinde karşılık gelen konum libraries nesne sabit değeri.
Sol kenar boşluğunda görünür ampul simgesini tıklatın. Üzerine Güncelleştirmeleri denetle.
LibMan yüklü olan sürümden daha yeni bir kitaplık sürümü olup olmadığını denetler. Aşağıdaki sonuçlar ortaya
çıkabilir:
A güncelleştirme bulunamadı en son sürümü zaten yüklü değilse, ileti görüntülenir.
En son kararlı sürüm görüntülenme olmasa bile zaten yüklü.

Yüklü olan sürümden daha yeni bir ön sürüm varsa, ön sürümü görüntülenir.
Eski bir kitaplığı sürümünün indirgemek için el ile düzenlemeniz libman.json dosya. Dosya kaydedildiğinde,
LibMan geri yükleme işlemi:
Gereksiz dosyaları önceki sürümden kaldırır.
Yeni ve güncelleştirilmiş dosyaları yeni sürümden ekler.

Ek kaynaklar
ASP.NET Core ile LibMan komut satırı arabirimini (CLı) kullanın
LibMan GitHub deposu
ASP.NET Core Grönyı kullanma
6.12.2019 • 15 minutes to read • Edit Online

Grrete, komut dosyası küçültmeye, TypeScript derlemesini, kod kalitesi "Lint" araçlarını, CSS ön işlemcilerini ve
yalnızca istemci geliştirmeyi desteklemek için gereken tüm yinelenen chore 'yi otomatikleştiren bir JavaScript
görev Çalıştırıcısı. Gryeniden bağlama Visual Studio 'da tam olarak desteklenir.
Bu örnek, başlangıç noktası olarak boş bir ASP.NET Core projesi kullanarak, istemci derleme işleminin sıfırdan
nasıl otomatikleştirileceğini gösterir.
Tamamlanmış örnek, hedef dağıtım dizinini temizler, JavaScript dosyalarını birleştirir, kod kalitesini denetler,
JavaScript dosya içeriğini daraltabilir ve Web uygulamanızın köküne dağıtır. Aşağıdaki paketleri kullanacağız:
gryeniden bağlama: gryeniden görev Çalıştırıcısı paketi.
gryeniden bağlama-contrib-Clean: dosya veya dizinleri kaldıran bir eklenti.
grkıt-contrib-jshınt: JavaScript kod kalitesini inceleyen bir eklenti.
gryeniden bağlama-contrib-Concat: dosyaları tek bir dosyaya birleştiren bir eklenti.
gryeniden bağlama-contrib-utimy: boyutu azaltmak Için JavaScript 'i mini görüntüleyen bir eklenti.
gryeniden bağlama-contrib-Watch: dosya etkinliğini izleyen bir eklenti.

Uygulama hazırlanıyor
Başlamak için yeni bir boş Web uygulaması ayarlayın ve TypeScript örnek dosyaları ekleyin. TypeScript dosyaları
varsayılan Visual Studio ayarları kullanılarak JavaScript 'e otomatik olarak derlenir ve Grönyı kullanarak işlemek
için ham malzemelerimiz olacaktır.
1. Visual Studio 'da yeni bir ASP.NET Web Application oluşturun.
2. Yeni ASP.NET projesi Iletişim kutusunda boş şablon ASP.NET Core seçin ve Tamam düğmesine tıklayın.
3. Çözüm Gezgini, proje yapısını gözden geçirin. \src klasör boş wwwroot ve Dependencies düğümlerini
içerir.

4. Proje dizininize TypeScript adlı yeni bir klasör ekleyin.


5. Herhangi bir dosya eklemeden önce, Visual Studio 'Nun TypeScript dosyaları için ' kaydetme sırasında derle
' seçeneğinin işaretli olduğundan emin olun. Araçlar > Seçenekler > metin Düzenleyicisi > TypeScript
> projesi' ne gidin:

6. TypeScript dizinine sağ tıklayın ve bağlam menüsünden > yeni öğe Ekle ' yi seçin. JavaScript dosya
öğesini seçin ve dosyayı tastes. TS olarak adlandırın (*. TS uzantısını aklınızda edin). Aşağıdaki TypeScript
kodu satırını dosyaya kopyalayın (kaydettiğinizde, JavaScript kaynağıyla yeni bir tastes. js dosyası görünür).

enum Tastes { Sweet, Sour, Salty, Bitter }

7. TypeScript dizinine ikinci bir dosya ekleyin ve Food.ts adlandırın. Aşağıdaki kodu dosyasına kopyalayın.

class Food {
constructor(name: string, calories: number) {
this._name = name;
this._calories = calories;
}

private _name: string;


get Name() {
return this._name;
}

private _calories: number;


get Calories() {
return this._calories;
}

private _taste: Tastes;


get Taste(): Tastes { return this._taste }
set Taste(value: Tastes) {
this._taste = value;
}
}

NPM 'yi yapılandırma


Daha sonra, NPM 'yi, grer ve grsıt-görevler 'i indirmek için yapılandırın
1. Çözüm Gezgini, projeye sağ tıklayın ve bağlam menüsünden > yeni öğe Ekle ' yi seçin. NPM
yapılandırma dosyası öğesini seçin, varsayılan adı Package. JSONolarak bırakın ve Ekle düğmesine
tıklayın.
2. Package. JSON dosyasında, devDependencies nesne ayraçları içinde "grönbağlama" yazın. IntelliSense
listesinden grunt ' yi seçin ve ENTER tuşuna basın. Visual Studio gryeniden paket adını teklif eder ve iki
nokta üst üste ekler. İki nokta üst üste, IntelliSense listesinin en üstünden paketin en son kararlı sürümünü
seçin (IntelliSense görünmüyorsa Ctrl-Space ' a basın).

NOTE
NPM, bağımlılıkları düzenlemek için anlamsal sürüm oluşturmayı kullanır. SemVer olarak da bilinen anlamsal sürüm
oluşturma, büyük > <numaralandırma düzenine sahip paketleri tanımlar.<küçük >.<Patch >. IntelliSense yalnızca
birkaç ortak seçeneği göstererek anlamsal sürüm oluşturmayı basitleştirir. IntelliSense listesindeki üst öğe (Yukarıdaki
örnekte 0.4.5), paketin en son kararlı sürümü olarak değerlendirilir. Şapka (^) simgesi en son ana sürümle eşleşir ve
tilde (~) en son ikincil sürümle eşleşir. SemVer 'in sağladığı tam ifade çekimi için bir kılavuz olarak NPM semver sürüm
ayrıştırıcısı başvurusuna bakın.

3. Aşağıdaki örnekte gösterildiği gibi, Clean, jshınt, Concat, uıshowmyve Watch için grkıt-contrib-* paketlerine
yük daha fazla bağımlılık ekleyin. Sürümlerin örnekle eşleşmesi gerekmez.

"devDependencies": {
"grunt": "0.4.5",
"grunt-contrib-clean": "0.6.0",
"grunt-contrib-jshint": "0.11.0",
"grunt-contrib-concat": "0.5.1",
"grunt-contrib-uglify": "0.8.0",
"grunt-contrib-watch": "0.6.1"
}

4. Package. JSON dosyasını kaydedin.


Her bir devDependencies öğesi için paketler, her paketin gerektirdiği tüm dosyalarla birlikte indirilir. Paket
dosyalarını, Çözüm Gezgini tüm dosyaları göster düğmesini etkinleştirerek node_modules dizininde
bulabilirsiniz.

NOTE
Gerekirse, Dependencies\NPM ' a sağ tıklayıp paketleri geri yükle menü seçeneğini belirleyerek Çözüm Gezgini
bağımlılıkları el ile geri yükleyebilirsiniz.
Grönbağlama yapılandırma
Gror, el ile çalıştırılabilecek veya Visual Studio 'daki olaylara göre otomatik olarak çalışacak şekilde yapılandırılmış
görevleri tanımlayan, yükleyen ve kaydeden Gruntfile. js adlı bir bildirim kullanılarak yapılandırılır.
1. Projeye sağ tıklayın ve > Yeni öğe Ekle ' yi seçin. JavaScript dosya öğesi şablonunu seçin, adı Gruntfile.
jsolarak değiştirin ve Ekle düğmesine tıklayın.
2. Gruntfile. js' ye aşağıdaki kodu ekleyin. initConfig işlevi her bir paket için seçenekleri ayarlar ve modülün
geri kalanı görevleri yükler ve kaydeder.

module.exports = function (grunt) {


grunt.initConfig({
});
};

3. initConfig işlevi içinde, aşağıdaki örnek Gruntfile. js ' de gösterildiği gibi clean görevi için seçenekler
ekleyin. clean görevi Dizin dizeleri dizisini kabul eder. Bu görev, dosyaları Wwwroot/lib 'den kaldırır ve tüm
/Temp klasörüne yazılır dizinini kaldırır.

module.exports = function (grunt) {


grunt.initConfig({
clean: ["wwwroot/lib/*", "temp/"],
});
};

4. initConfig işlevinin altında, grunt.loadNpmTasks için bir çağrı ekleyin. Bu işlem, görevin Visual Studio 'dan
bir şekilde bir şekilde bir şekilde bir şekilde

grunt.loadNpmTasks("grunt-contrib-clean");

5. Gruntfile. js dosyasınıkaydedin. Dosya aşağıdaki ekran görüntüsüne benzer şekilde görünmelidir.

6. Gruntfile. js ' ye sağ tıklayın ve bağlam menüsünden görev Çalıştırıcısı Gezgini ' ni seçin. Görev
çalıştırıcı Gezgini penceresi açılır.

7. clean görev Çalıştırıcısı Gezgininde Görevler altında görüntülendiğini doğrulayın.


8. Temizleme görevine sağ tıklayın ve bağlam menüsünden Çalıştır ' ı seçin. Bir komut penceresi, görevin
ilerlemesini görüntüler.

NOTE
Henüz temizleyene dosya veya dizin yok. İsterseniz, bunları Çözüm Gezgini el ile oluşturabilir ve sonra temiz görevi bir
test olarak çalıştırabilirsiniz.

9. initConfig işlevinde, aşağıdaki kodu kullanarak concat için bir giriş ekleyin.
src Property dizisi birleştirilecek dosyaları, birleştirilmeleri gereken sırayla listeler. dest özelliği, üretilen
Birleşik dosyanın yolunu atar.

concat: {
all: {
src: ['TypeScript/Tastes.js', 'TypeScript/Food.js'],
dest: 'temp/combined.js'
}
},

NOTE
Yukarıdaki koddaki all özelliği bir hedefin adıdır. Hedefler, bazı Grsi görevlerinde birden çok derleme ortamına izin
vermek için kullanılır. IntelliSense kullanarak yerleşik hedefleri görüntüleyebilir veya kendi kendinize atayabilirsiniz.

10. Aşağıdaki kodu kullanarak jshint görevini ekleyin.


Jshınt code-quality yardımcı programı, Temp dizininde bulunan her JavaScript dosyasında çalıştırılır.

jshint: {
files: ['temp/*.js'],
options: {
'-W069': false,
}
},
NOTE
"-W069" seçeneği, JavaScript, nokta gösterimi yerine bir özellik atamak için köşeli ayraç sözdizimi kullandığında jshınt
tarafından oluşturulan bir hatadır, örneğin Tastes.Sweet yerine Tastes["Sweet"] . Seçeneği, işlemin geri kalanının
devam etmesine izin vermek için uyarıyı kapatır.

11. Aşağıdaki kodu kullanarak uglify görevini ekleyin.


Görev, Temp dizininde bulunan birleştirilmiş. js dosyasını mini olarak oluşturur ve standart adlandırma
kuralı <dosya adı>. min. js' den sonra sonuç dosyasını Wwwroot/lib içinde oluşturur.

uglify: {
all: {
src: ['temp/combined.js'],
dest: 'wwwroot/lib/combined.min.js'
}
},

12. grunt-contrib-cleanyükleyen grunt.loadNpmTasks çağrısı altında, aşağıdaki kodu kullanarak jshınt, Concat
ve UART My için aynı çağrıyı ekleyin.

grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');

13. Gruntfile. js dosyasınıkaydedin. Dosya aşağıdaki örnekteki gibi görünmelidir.

14. Görev çalıştırıcı Gezgini görev listesi clean , concat , jshint ve uglify görevleri içerdiğine dikkat edin.
Her görevi sırayla çalıştırın ve Çözüm Gezginisonuçları gözlemleyin. Her görev hatasız çalışmalıdır.
Concat görevi yeni bir birleştirilmiş. js dosyası oluşturur ve bunu Temp dizinine koyar. jshint görevi
yalnızca çalışır ve çıkış üretmez. uglify görevi yeni bir birleştirilmiş. min. js dosyası oluşturur ve bunu
Wwwroot/lib'e koyar. Tamamlandığında, çözüm aşağıdaki ekran görüntüsüne benzer şekilde görünmelidir:

NOTE
Her pakete ilişkin seçenekler hakkında daha fazla bilgi için https://www.npmjs.com/ ziyaret edin ve ana sayfadaki
arama kutusunda paket adını arayın. Örneğin, tüm parametrelerini açıklayan bir belge bağlantısı almak için grcönt-
contrib-Clean paketini arayabilirsiniz.

Şimdi hepsi bir arada


Belirli bir dizideki bir dizi görevi çalıştırmak için Gryeniden registerTask() yöntemini kullanın. Örneğin, yukarıdaki
örnek adımları sırayla çalıştırmak için > Concat-> jshınt-> uıshowmy ' a gidin ve aşağıdaki kodu modüle ekleyin.
Kod, InitConfig dışında loadNpmTasks () çağrılarıyla aynı düzeye eklenmelidir.

grunt.registerTask("all", ['clean', 'concat', 'jshint', 'uglify']);

Yeni görev, görev Çalıştırıcısı Gezgini 'nde diğer ad görevleri altında görüntülenir. Bunu, diğer görevleri yaptığınız
gibi sağ tıklayıp çalıştırabilirsiniz. all görevi sırasıyla clean , concat , jshint ve uglify çalışacaktır.
Değişiklik izleme
watch bir görev, dosyaları ve dizinleri göz önünde bulundurur. İzleme, değişiklikleri algılarsa görevleri otomatik
olarak tetikler. TypeScript dizinindeki *. js dosyalarında yapılan değişiklikleri izlemek için aşağıdaki kodu InitConfig
dosyasına ekleyin. Bir JavaScript dosyası değiştirilirse watch all görevini çalıştırır.

watch: {
files: ["TypeScript/*.js"],
tasks: ["all"]
}

Görev çalıştırıcı Gezgini 'nde watch görevi göstermek için loadNpmTasks() bir çağrı ekleyin.

grunt.loadNpmTasks('grunt-contrib-watch');

Görev çalıştırıcı Gezgini ' nde gözcü görevine sağ tıklayın ve bağlam menüsünden Çalıştır ' ı seçin. Çalışan izleme
görevini gösteren komut penceresinde "bekleniyor..." görüntülenir İleti. TypeScript dosyalarından birini açın, bir
boşluk ekleyin ve dosyayı kaydedin. Bu işlem, izleme görevini tetikler ve diğer görevleri sırayla çalışacak şekilde
tetikler. Aşağıdaki ekran görüntüsünde örnek bir çalıştırma gösterilmektedir.

Visual Studio olaylarına bağlama


Visual Studio 'da her çalıştığınızda görevlerinizi el ile başlatmak istemediğiniz müddetçe, derleme, Temizlemeve
proje açık olayları sonrasında derlemeden öncegörevleri bağlayın.
watch , Visual Studio her açıldığında çalışacak şekilde bağlayın. Görev çalıştırıcı Gezgini ' nde, Gözcü görevine sağ
tıklayın ve bağlam menüsünden bağlamalar > Proje Aç ' ı seçin.

Projeyi kaldırın ve yeniden yükleyin. Proje yeniden yüklendiğinde, izleme görevi otomatik olarak çalışmaya başlar.
Özet
Gryeniden oluşturma, çoğu istemci derleme görevini otomatikleştirmek için kullanılabilen güçlü bir görev
Çalıştırıcısı. Grsıt, paketlerini teslim etmek için NPM 'den yararlanır ve Visual Studio ile tümleştirme özellikleri
sağlar. Visual Studio 'nun görev Çalıştırıcısı Gezgini yapılandırma dosyalarındaki değişiklikleri algılar ve görevleri
çalıştırmak, çalışan görevleri görüntülemek ve görevleri Visual Studio olaylarına bağlamak için uygun bir arabirim
sağlar.
ASP.NET Core statik varlıkları paketleyin ve azın
4.12.2019 • 16 minutes to read • Edit Online

Scott Ade ve David çam tarafından


Bu makalede, bu özelliklerin ASP.NET Core Web uygulamalarıyla nasıl kullanılabileceği da dahil olmak üzere
paketleme ve küçültmeye yönelik uygulama avantajları açıklanmaktadır.

Paketlemeyi ve küçültmeye göre


Paketleme ve küçültme, bir Web uygulamasında uygulayabileceğiniz iki ayrı performans iyileştirmesidir. Birlikte
kullanıldığında, paketleme ve minbirleştirime, sunucu isteklerinin sayısını azaltarak ve istenen statik varlıkların
boyutunu azaltarak performansı geliştirir.
Paketleme ve minbirleştirmesi birincil olarak ilk sayfa isteği yükleme süresini geliştirir. Bir Web sayfası
istendiğinde, tarayıcı statik varlıkları (JavaScript, CSS ve görüntüler) önbelleğe alır. Sonuç olarak, aynı sayfada veya
sayfalarda aynı varlıkları talep eden aynı siteye veya sayfalara istekte bulunduğunda, paketleme ve minlıme
performansı artırmayın. Süre sonu üst bilgisi varlıklarda doğru ayarlanmamışsa ve paketleme ve küçültme
kullanılmıyorsa, tarayıcının yenilik buluşsal yöntemleri, varlıkları birkaç günden daha eski bir süre sonra işaretler.
Ayrıca, tarayıcı her varlık için bir doğrulama isteği gerektirir. Bu durumda, paketleme ve minbirleşme, ilk sayfa
isteğinden sonra bile bir performans geliştirmesi sağlar.
Paketleme
Paketleme, birden çok dosyayı tek bir dosya halinde birleştirir. Paketleme, Web sayfası gibi bir Web varlığını
işlemek için gerekli olan sunucu isteği sayısını azaltır. Özellikle CSS, JavaScript vb. için istediğiniz sayıda ayrı paket
oluşturabilirsiniz. Daha az dosya tarayıcıdan sunucuya veya uygulamanızı sağlayan hizmetten daha az HTTP
isteğinin olması anlamına gelir. Bu, geliştirilmiş ilk sayfa yükü performansına neden olur.
Küçültme
Minbirleşme işlevleri işlevselliği değiştirmeden koddan gereksiz karakterleri kaldırır. Sonuç, istenen varlıklarda
(CSS, görüntüler ve JavaScript dosyaları gibi) önemli bir boyut azalmasıyla sonuçlanır. Yaygın olarak kullanılan yan
etkileri, değişken adlarını tek bir karaktere kısaltmayı ve açıklamaları ve gereksiz boşlukları kaldırmayı içerir.
Aşağıdaki JavaScript işlevini göz önünde bulundurun:

AddAltToImg = function (imageTagAndImageID, imageContext) {


///<signature>
///<summary> Adds an alt tab to the image
// </summary>
//<param name="imgElement" type="String">The image selector.</param>
//<param name="ContextForImage" type="String">The image context.</param>
///</signature>
var imageElement = $(imageTagAndImageID, imageContext);
imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

Minbirleşme işlevi şu şekilde azaltır:

AddAltToImg=function(t,a){var r=$(t,a);r.attr("alt",r.attr("id").replace(/ID/,""))};

Açıklamaları ve gereksiz boşlukları kaldırmanın yanı sıra aşağıdaki parametre ve değişken adları şu şekilde yeniden
adlandırıldı:
ÖZGÜN İSIM

imageTagAndImageID t

imageContext a

imageElement r

Paketleme ve küçültmeye yönelik etkileri


Aşağıdaki tabloda, tek tek yükleme varlıkları ve paketleme ve küçültme kullanımı arasındaki farklılıklar
özetlenmektedir:

EYLEM B/M ILE B/M OLMADAN DEĞIŞIKLIK

Dosya Istekleri 7 18 157%

KB aktarıldı 156 264.68 70%

Yükleme süresi (MS) 885 2360 167%

Tarayıcılar HTTP istek üst bilgileriyle ilgili oldukça ayrıntılıdır. Gönderilen toplam bayt ölçümü, paketleme sırasında
önemli bir düşüş gördük. Yükleme zamanı önemli bir geliştirme gösterir, ancak bu örnek yerel olarak çalışır.Ağ
üzerinden aktarılan varlıklarla paketleme ve küçültmeye karşı kullanım sırasında daha fazla performans artışı
gerçekleştirilir.

Bir paketleme ve küçültmeye karşı bir strateji seçin


MVC ve Razor Pages proje şablonları, bir JSON yapılandırma dosyasından oluşan paketleme ve küçültmeye
yönelik kullanıma hazır bir çözüm sunar. Grdalar görev Çalıştırıcısı gibi üçüncü taraf araçlar, aynı görevleri biraz
daha karmaşıklıkla yerine getirmiş. Geliştirme iş akışınız, bağlama ve görüntü iyileştirmesi gibi—, paket oluşturma
ve küçültmeye göre işleme gerektirdiğinde, üçüncü taraf bir araç harika bir araçtır. Tasarım zamanı paketleme ve
küçültme kullanarak, küçültülmüş dosyalar uygulamanın dağıtımından önce oluşturulur. Dağıtımdan önce
paketleme ve küçültme, azaltılmış sunucu yükünün avantajlarından faydalanabilmenizi sağlar. Bununla birlikte,
tasarım zamanı paketleme ve küçültme, derleme karmaşıklığını artırır ve yalnızca statik dosyalarla birlikte
kullanılabilir.

Paketlemeyi ve küçültmeye göre yapılandırma


ASP.NET Core 2,0 veya önceki sürümlerde, MVC ve Razor Pages proje şablonları her bir paket için seçenekleri
tanımlayan bir paketleme liconfig. JSON yapılandırma dosyası sağlar:
ASP.NET Core 2,1 veya sonraki sürümlerde, MVC veya Razor Pages proje köküne paketleme liconfig. JSONadlı
yenı bir JSON dosyası ekleyin. Aşağıdaki JSON 'yi bir başlangıç noktası olarak bu dosyaya ekleyin:
[
{
"outputFileName": "wwwroot/css/site.min.css",
"inputFiles": [
"wwwroot/css/site.css"
]
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"wwwroot/js/site.js"
],
"minify": {
"enabled": true,
"renameLocals": true
},
"sourceMap": false
}
]

Paketleme liconfig. JSON dosyası her bir paket için seçenekleri tanımlar. Yukarıdaki örnekte, özel JavaScript
(Wwwroot/js/site. js) ve stil sayfası (Wwwroot/CSS/site. css) dosyaları için tek bir paket yapılandırması
tanımlanmıştır.
Yapılandırma seçenekleri şunlardır:
outputFileName : çıkış yapılacak paket dosyasının adı. , Paketleme liconfig. JSON dosyasından göreli bir yol
içerebilir. Gerekli
inputFiles : birlikte paketedilecek dosya dizisi. Bunlar yapılandırma dosyasına yönelik göreli yollardır. isteğe
bağlı* boş bir değer boş bir çıktı dosyasıyla sonuçlanır. Glob desenleri desteklenir.
minify : çıkış türü için minbirleşme seçenekleri. isteğe bağlı, varsayılan minify: { enabled: true }
Yapılandırma seçenekleri çıkış dosyası türü başına kullanılabilir.
CSS minifier
JavaScript minifier
HTML minifier
includeInProject : oluşturulan dosyaların proje dosyasına eklenip eklenmeyeceğini belirten bayrak. isteğe
bağlı, Varsayılan-yanlış
sourceMap : paketlenmiş dosya için bir kaynak eşlemesi oluşturulup oluşturulmayacağını belirten bayrak. isteğe
bağlı, Varsayılan-yanlış
sourceMapRootPath : oluşturulan kaynak eşleme dosyasını depolamak için kök yolu.

Paketleme ve küçültmeye yönelik derleme zamanı yürütme


BuildBundlerMinifier NuGet paketi, derleme zamanında paketleme ve küçültmeye karşı yürütmeyi mümkün bir
şekilde sunar. Paket, derleme ve Temizleme zamanında çalıştırılan MSBuild hedeflerini çıkartır. Paketleme liconfig.
JSON dosyası, tanımlanan yapılandırmaya göre çıkış dosyalarını oluşturmak için yapı işlemi tarafından çözümlenir.

NOTE
BuildBundlerMinifier, GitHub 'da Microsoft 'un destek sunmamakta olan topluluk odaklı bir projeye aittir. Sorunlar
buradadosyalanmalıdır.

Visual Studio
.NET Core CLI
BuildBundlerMinifier paketini projenize ekleyin.
Projeyi oluşturun. Çıkış penceresinde aşağıdakiler görüntülenir:

1>------ Build started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>
1>Bundler: Begin processing bundleconfig.json
1> Minified wwwroot/css/site.min.css
1> Minified wwwroot/js/site.min.js
1>Bundler: Done processing bundleconfig.json
1>BuildBundlerMinifierApp -> C:\BuildBundlerMinifierApp\bin\Debug\netcoreapp2.0\BuildBundlerMinifierApp.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Projeyi temizleyin. Çıkış penceresinde aşağıdakiler görüntülenir:

1>------ Clean started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>
1>Bundler: Cleaning output from bundleconfig.json
1>Bundler: Done cleaning output file from bundleconfig.json
========== Clean: 1 succeeded, 0 failed, 0 skipped ==========

Paketlemeyi ve küçültmeye karşı geçici yürütme


Paketleme ve küçültmeye yönelik görevleri, projeyi oluşturmadan geçici olarak çalıştırmak mümkündür.
BundlerMinifier. Core NuGet paketini projenize ekleyin:

<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.6.362" />

NOTE
BundlerMinifier. Core, GitHub 'da Microsoft 'un destek sunmamakta olan topluluk odaklı bir projeye aittir. Sorunlar
buradadosyalanmalıdır.

Bu paket, .NET Core CLI DotNet-demeti aracını içerecek şekilde genişletir. Aşağıdaki komut, Paket Yöneticisi
Konsolu (PMC ) penceresinde veya bir komut kabuğunda çalıştırılabilir:

dotnet bundle

IMPORTANT
NuGet Paket Yöneticisi, *. csproj dosyasına <PackageReference /> düğümleri olarak bağımlılıklar ekler. dotnet bundle
komutu, yalnızca bir <DotNetCliToolReference /> düğümü kullanıldığında .NET Core CLI kaydedilir. *. Csproj dosyasını
uygun şekilde değiştirin.

İş akışına dosya ekleme


Aşağıdakilere benzer bir ek özel. css dosyası eklendiğini bir örnek düşünün:
.about, [role=main], [role=complementary] {
margin-top: 60px;
}

footer {
margin-top: 10px;
}

Custom. css dosyasını küçültmeye ve site. css ' yi bir site. min. css dosyasına paketlemek için, ilgili yolu paketleme
liconfig. JSONöğesine ekleyin:

[
{
"outputFileName": "wwwroot/css/site.min.css",
"inputFiles": [
"wwwroot/css/site.css",
"wwwroot/css/custom.css"
]
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"wwwroot/js/site.js"
],
"minify": {
"enabled": true,
"renameLocals": true
},
"sourceMap": false
}
]

NOTE
Alternatif olarak, aşağıdaki glob deseninin kullanılması gerekir:

"inputFiles": ["wwwroot/**/!(*.min).css" ]

Bu glob model tüm CSS dosyalarıyla eşleşir ve küçültülmüş dosya modelini dışlar.

Uygulamayı derleyin. Site. min. css dosyasını açın ve Custom. css içeriğinin dosyanın sonuna ekleneceğini
unutmayın.

Ortam tabanlı paketleme ve minbirleşme


En iyi uygulama olarak, uygulamanızın paketlenmiş ve küçültülmüş dosyaları bir üretim ortamında kullanılmalıdır.
Geliştirme sırasında, özgün dosyalar uygulamanın hata ayıklamasını daha kolay hale getirir.
Görünümlerinizde ortam etiketi yardımcısını kullanarak sayfalarınıza hangi dosyaların ekleneceğini belirleyin.
Ortam etiketi Yardımcısı yalnızca belirli ortamlardaçalışırken içeriğini işler.
Aşağıdaki environment etiketi, Development ortamında çalışırken işlenmemiş CSS dosyalarını işler:

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>

Aşağıdaki environment etiketi, Development dışında bir ortamda çalışırken paketlenmiş ve küçültülmüş CSS
dosyalarını işler. Örneğin, Production veya Staging içinde çalıştırmak, bu stil sayfaları işlemesini tetikler:

<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>

<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-
value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>

Gulp adresinden paketleme liconfig. JSON kullanın


Uygulamanın paketleme ve küçültmeye yönelik iş akışının ek işlem gerektirdiği durumlar vardır. Örnek görüntü
iyileştirmesi, önbellek performansı ve CDN varlık işleme sayılabilir. Bu gereksinimleri karşılamak için, paketleme ve
küçültmeye yönelik iş akışını Gulp kullanacak şekilde dönüştürebilirsiniz.
Paketleme & minifier uzantısını kullanma
Visual Studio Paketcisi & minifier uzantısı, Gulp 'e dönüştürmeyi işler.

NOTE
Paketleme & minifier uzantısı, Microsoft 'un hiçbir destek sunmamakta olan GitHub 'daki topluluk odaklı bir projeye aittir.
Sorunlar buradadosyalanmalıdır.

Çözüm Gezgini paketleme liconfig. JSON dosyasına sağ tıklayın ve paketler & minifier ' ı seçin > Gulp 'e
Dönüştür... :

Gulpfile. js ve Package. JSON dosyaları projeye eklenir. Package. JSON dosyasının devDependencies bölümünde
listelenen NPM paketlerinin desteklenmesi yüklüdür.
Gulp CLı 'yi genel bağımlılık olarak yüklemek için PMC penceresinde aşağıdaki komutu çalıştırın:
npm i -g gulp-cli

Gulpfile. js dosyası, girdiler, çıktılar ve ayarlar için paketleme liconfig. JSON dosyasını okur.

'use strict';

var gulp = require('gulp'),


concat = require('gulp-concat'),
cssmin = require('gulp-cssmin'),
htmlmin = require('gulp-htmlmin'),
uglify = require('gulp-uglify'),
merge = require('merge-stream'),
del = require('del'),
bundleconfig = require('./bundleconfig.json');

// Code omitted for brevity

El ile Dönüştür
Visual Studio ve/veya paketleme & minifier uzantısı kullanılamıyorsa, el ile dönüştürün.
Proje köküne aşağıdaki devDependencies sahip bir Package. JSON dosyası ekleyin:

WARNING
gulp-uglify modülü ECMAScript (ES) 2015/ES6 ve üstünü desteklemez. ES2015/ES6 veya sonraki bir sürümü kullanmak
için gulp-uglify yerine Gulp-Terser 'i yükler.

"devDependencies": {
"del": "^3.0.0",
"gulp": "^4.0.0",
"gulp-concat": "^2.6.1",
"gulp-cssmin": "^0.2.0",
"gulp-htmlmin": "^3.0.0",
"gulp-uglify": "^3.0.0",
"merge-stream": "^1.0.1"
}

Aşağıdaki komutu Package. JSONile aynı düzeyde çalıştırarak bağımlılıkları yükler:

npm i

Gulp CLı 'yı genel bağımlılık olarak yükler:

npm i -g gulp-cli

Aşağıdaki gulpfile. js dosyasını proje köküne kopyalayın:

'use strict';

var gulp = require('gulp'),


concat = require('gulp-concat'),
cssmin = require('gulp-cssmin'),
htmlmin = require('gulp-htmlmin'),
uglify = require('gulp-uglify'),
merge = require('merge-stream'),
del = require('del'),
del = require('del'),
bundleconfig = require('./bundleconfig.json');

const regex = {
css: /\.css$/,
html: /\.(html|htm)$/,
js: /\.js$/
};

gulp.task('min:js', async function () {


merge(getBundles(regex.js).map(bundle => {
return gulp.src(bundle.inputFiles, { base: '.' })
.pipe(concat(bundle.outputFileName))
.pipe(uglify())
.pipe(gulp.dest('.'));
}))
});

gulp.task('min:css', async function () {


merge(getBundles(regex.css).map(bundle => {
return gulp.src(bundle.inputFiles, { base: '.' })
.pipe(concat(bundle.outputFileName))
.pipe(cssmin())
.pipe(gulp.dest('.'));
}))
});

gulp.task('min:html', async function () {


merge(getBundles(regex.html).map(bundle => {
return gulp.src(bundle.inputFiles, { base: '.' })
.pipe(concat(bundle.outputFileName))
.pipe(htmlmin({ collapseWhitespace: true, minifyCSS: true, minifyJS: true }))
.pipe(gulp.dest('.'));
}))
});

gulp.task('min', gulp.series(['min:js', 'min:css', 'min:html']));

gulp.task('clean', () => {
return del(bundleconfig.map(bundle => bundle.outputFileName));
});

gulp.task('watch', () => {
getBundles(regex.js).forEach(
bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:js"])));

getBundles(regex.css).forEach(
bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:css"])));

getBundles(regex.html).forEach(
bundle => gulp.watch(bundle.inputFiles, gulp.series(['min:html'])));
});

const getBundles = (regexPattern) => {


return bundleconfig.filter(bundle => {
return regexPattern.test(bundle.outputFileName);
});
};

gulp.task('default', gulp.series("min"));

Gulp görevlerini Çalıştır


Proje Visual Studio 'da yapılandırmadan önce Gulp minbirleşme görevini tetiklemek için, *. csproj dosyasına
aşağıdaki MSBuild hedefini ekleyin:
<Target Name="MyPreCompileTarget" BeforeTargets="Build">
<Exec Command="gulp min" />
</Target>

Bu örnekte, MyPreCompileTarget hedefi içinde tanımlanan tüm görevler önceden tanımlanmış Build hedeften
önce çalışır. Visual Studio 'nun çıkış penceresinde aşağıdakine benzer bir çıktı görüntülenir:

1>------ Build started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>BuildBundlerMinifierApp -> C:\BuildBundlerMinifierApp\bin\Debug\netcoreapp2.0\BuildBundlerMinifierApp.dll
1>[14:17:49] Using gulpfile C:\BuildBundlerMinifierApp\gulpfile.js
1>[14:17:49] Starting 'min:js'...
1>[14:17:49] Starting 'min:css'...
1>[14:17:49] Starting 'min:html'...
1>[14:17:49] Finished 'min:js' after 83 ms
1>[14:17:49] Finished 'min:css' after 88 ms
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Ek kaynaklar
Grunt kullanma
Birden çok ortam kullanma
Etiket Yardımcıları
ASP.NET Core tarayıcı bağlantısı
13.11.2019 • 7 minutes to read • Edit Online

, Nicolò Carandini, Mike, sonve Tom Dykstra tarafından


Tarayıcı bağlantısı, Visual Studio 'da geliştirme ortamı ile bir veya daha fazla Web tarayıcısı arasında bir iletişim
kanalı oluşturan bir özelliktir. Tarayıcı bağlantısını, Web uygulamanızı birden çok tarayıcıda tek seferde yenilemek
için kullanabilirsiniz. Bu, tarayıcılar arası testler için kullanışlıdır.

Tarayıcı bağlantısı kurulumu


ASP.NET Core 2,0 projesi ASP.NET Core 2,1 ' e dönüştürülürken ve Microsoft. AspNetCore. app metapackage'e
geçiş yaparken, browserlink Işlevselliği için Microsoft. VisualStudio. Web. browserlink paketini yükledikten sonra.
ASP.NET Core 2,1 proje şablonları varsayılan olarak Microsoft.AspNetCore.App metapaketini kullanır.
ASP.NET Core 2,0 Web uygulaması, Emptyve Web API proje şablonları, Microsoft. VisualStudio. Web.
browserlinkIçin bir paket başvurusu içeren Microsoft. aspnetcore. All meta paketinikullanır. Bu nedenle,
Microsoft.AspNetCore.All metapackage 'in kullanılması, tarayıcı bağlantısının kullanılabilir olmasını sağlamak için
başka bir eylem gerektirmez.
ASP.NET Core 1. x Web uygulaması proje şablonunda, Microsoft. VisualStudio. Web. browserlink paketi için bir
paket başvurusu vardır. Boş veya Web apı şablonu projeleri Microsoft.VisualStudio.Web.BrowserLink için bir paket
başvurusu eklemenizi gerektirir.
Bu bir Visual Studio özelliği olduğundan, paketi boş veya Web API şablonu projesine eklemenin en kolay yolu,
Paket Yöneticisi konsolu 'nu açmak ( diğer Windows > Paket Yöneticisi konsolunu>görüntüleyin ) ve şu
komutu çalıştırmalıdır:

install-package Microsoft.VisualStudio.Web.BrowserLink

Alternatif olarak, NuGet Paket Yöneticisi' ni kullanabilirsiniz. Çözüm Gezgini ' de proje adına sağ tıklayın ve
NuGet Paketlerini Yönet' i seçin:
Paketi bulun ve yükledikten sonra:

Yapılandırma
Startup.Configure yönteminde:

app.UseBrowserLink();

Genellikle kod, burada gösterildiği gibi yalnızca geliştirme ortamında tarayıcı bağlantısını sağlayan bir if
bloğunun içindedir:

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}

Daha fazla bilgi için bkz. birden çok ortam kullanma.

Tarayıcı bağlantısı kullanma


Bir ASP.NET Core projesi açıkken, Visual Studio hata ayıklama hedefi araç çubuğu denetiminin yanında tarayıcı
bağlantısı araç çubuğu denetimini gösterir:

Tarayıcı bağlantısı araç çubuğu denetiminden şunları yapabilirsiniz:


Web uygulamasını aynı anda birkaç tarayıcıda yenileyin.
Tarayıcı bağlantısı panosunuaçın.
Tarayıcı bağlantısınıetkinleştirin veya devre dışı bırakın. Note: tarayıcı bağlantısı, Visual Studio 2017 (15,3)
içinde varsayılan olarak devre dışıdır.
CSS otomatik eşitlemesinietkinleştirin veya devre dışı bırakın.

NOTE
Bazı Visual Studio eklentileri, en önemlisi Web uzantısı paketi 2015 ve web uzantısı paketi 2017, tarayıcı bağlantısı için
genişletilmiş işlevsellik sunar, ancak bazı ek özellikler ASP.NET Core projelerle çalışmaz.

Aynı anda birkaç tarayıcıda Web uygulamasını yenileyin


Projeyi başlatırken başlatılacak tek bir Web tarayıcısı seçmek için, Hata Ayıkla hedef araç çubuğu denetimindeki
açılan menüyü kullanın:

Aynı anda birden çok tarayıcı açmak için, aynı açılan listeden ... öğesine gidin ' i seçin. İstediğiniz tarayıcıları
seçmek için CTRL tuşunu basılı tutarak, ardından da Araştır' a tıklayın:
Visual Studio 'Yu Açık Dizin görünümü ve iki açık tarayıcıyla gösteren bir ekran görüntüsü aşağıda verilmiştir:

Projeye bağlı tarayıcıları görmek için tarayıcı bağlantısı araç çubuğu denetiminin üzerine gelin:
Dizin görünümünü değiştirin ve tarayıcı bağlantısı yenileme düğmesine tıkladığınızda tüm bağlı tarayıcılar
güncelleştirilir:

Tarayıcı bağlantısı, Visual Studio dışından başlamış ve uygulama URL 'sine gidebileceğiniz tarayıcılarla de
kullanılabilir.
Tarayıcı bağlantısı panosu
Açık tarayıcılarla bağlantıyı yönetmek için tarayıcı bağlantısı açılan menüsünden tarayıcı bağlantısı panosunu açın:
Hiçbir tarayıcı bağlı değilse, Tarayıcıda görüntüle bağlantısını seçerek hata ayıklama olmayan bir oturum
başlatabilirsiniz:

Aksi halde, bağlı tarayıcılar her bir tarayıcının gösterdiği sayfanın yoluyla gösterilir:
İsterseniz, bu tek tarayıcıyı yenilemek için listelenen bir tarayıcı adına tıklayabilirsiniz.
Tarayıcı bağlantısını etkinleştir veya devre dışı bırak
Tarayıcı bağlantısını devre dışı bıraktıktan sonra yeniden etkinleştirdiğinizde, bunları yeniden bağlamak için
tarayıcıları yenilemeniz gerekir.
CSS otomatik eşitlemesini etkinleştir veya devre dışı bırak
CSS otomatik eşitleme etkinleştirildiğinde, CSS dosyalarında herhangi bir değişiklik yaptığınızda bağlantılı
tarayıcılar otomatik olarak yenilenir.

Nasıl çalıştığı
Tarayıcı bağlantısı, Visual Studio ile tarayıcı arasında bir iletişim kanalı oluşturmak için SignalR kullanır. Tarayıcı
bağlantısı etkinleştirildiğinde, Visual Studio birden çok istemcinin (tarayıcının) bağlanabileceği bir SignalR
sunucusu gibi davranır. Tarayıcı bağlantısı ayrıca ASP.NET Core isteği ardışık düzenine bir ara yazılım bileşeni
kaydeder. Bu bileşen, sunucudan her sayfa isteğine özel <script> başvurularını çıkarır. Tarayıcıda Görünüm
kaynağı ' nı seçerek komut dosyası başvurularını görebilir ve <body> Tag içeriğinin sonuna kadar kaydırma
yapabilirsiniz:

<!-- Visual Studio Browser Link -->


<script type="application/json" id="__browserLink_initializationData">
{"requestId":"a717d5a07c1741949a7cefd6fa2bad08","requestMappingFromServer":false}
</script>
<script type="text/javascript" src="http://localhost:54139/b6e36e429d034f578ebccd6a79bf19bf/browserLink"
async="async"></script>
<!-- End Browser Link -->
</body>

Kaynak dosyalarınız değiştirilmez. Ara yazılım bileşeni, betik başvurularını dinamik olarak çıkarır.
Tarayıcı tarafı kodu tüm JavaScript olduğundan, tarayıcı eklentisi gerekmeden SignalR desteklediği tüm
tarayıcılarda çalışıyor olur.
ASP.NET Core oturum ve uygulama durumu
13.11.2019 • 27 minutes to read • Edit Online

By Rick Anderson, Steve Smith, Diana Lagülve Luke Latham


HTTP durum bilgisiz bir protokoldür. Ek adımlar uygulamadan, HTTP istekleri Kullanıcı değerlerini veya uygulama
durumunu içermeyen bağımsız iletilerdir. Bu makalede, istekler arasında kullanıcı verilerini ve uygulama
durumunu korumak için çeşitli yaklaşımlar açıklanmaktadır.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Durum yönetimi
Durum, çeşitli yaklaşımlar kullanılarak depolanabilir. Her yaklaşım, bu konunun ilerleyen kısımlarında
açıklanmıştır.

DEPOLAMA YAKLAŞIMI DEPOLAMA MEKANIZMASI

Çerezler HTTP tanımlama bilgileri (sunucu tarafı uygulama kodu


kullanılarak depolanan veriler içerebilir)

Oturum durumu HTTP tanımlama bilgileri ve sunucu tarafı uygulama kodu

TempData HTTP tanımlama bilgileri veya oturum durumu

Sorgu dizeleri HTTP sorgu dizeleri

Gizli alanlar HTTP form alanları

HttpContext. Items Sunucu tarafı uygulama kodu

Önbellek Sunucu tarafı uygulama kodu

Bağımlılık Ekleme Sunucu tarafı uygulama kodu

Özgü
Tanımlama bilgileri istekler arasında veri depolar. Tanımlama bilgileri her istekle birlikte gönderildiğinden,
boyutları minimum olarak tutulmalıdır. İdeal olarak, uygulama tarafından depolanan verileri içeren bir tanımlama
bilgisinde yalnızca bir tanımlayıcı depolanmalıdır. Tarayıcıların çoğu, tanımlama bilgisi boyutunu 4096 bayt olarak
kısıtlar. Her etki alanı için yalnızca sınırlı sayıda tanımlama bilgisi vardır.
Tanımlama bilgileri değişikliklere tabi olduğundan, uygulama tarafından doğrulanması gerekir. Tanımlama bilgileri
kullanıcılar tarafından silinebilir ve istemciler üzerinde zaman alabilir. Ancak, tanımlama bilgileri genellikle
istemcide en dayanıklı veri kalıcılığı biçimidir.
Tanımlama bilgileri genellikle içerik bilinen bir kullanıcı için özelleştirildiğinde kişiselleştirme için kullanılır.
Kullanıcı yalnızca tanımlı ve kimlik doğrulaması değil çoğu durumda. Tanımlama bilgisi kullanıcının adını, hesap
adını veya benzersiz kullanıcı KIMLIĞINI (GUID gibi) saklayabilir. Daha sonra kullanıcının tercih ettiği Web sitesi
arka plan rengi gibi kişiselleştirilmiş ayarlarına erişmek için tanımlama bilgisini kullanabilirsiniz.
Tanımlama bilgilerini verirken ve gizlilik kaygılarıyla ilgilenirken Avrupa Birliği genel veri koruma düzenlemelerine
(GDPR ) sahip olun. Daha fazla bilgi için ASP.NET Core genel veri koruma yönetmeliği (GDPR ) desteğiniinceleyin.

Oturum durumu
Oturum durumu, Kullanıcı bir Web uygulamasına göz atarken Kullanıcı verilerinin depolanması için bir ASP.NET
Core senaryodur. Oturum durumu, bir istemciden gelen istekler arasında verileri kalıcı hale getirmek için
uygulama tarafından tutulan bir depoyu kullanır. Oturum verileri bir önbellek tarafından desteklenir ve geçici veri
olarak kabul edilir—site oturum verileri olmadan çalışmaya devam etmelidir. Kritik uygulama verileri Kullanıcı
veritabanında depolanmalıdır ve oturum yalnızca bir performans iyileştirmesi olarak önbelleğe alınmalıdır.

NOTE
SignalR uygulamalarında oturum desteklenmiyor, çünkü bir SignalR hub 'ı bir http bağlamından bağımsız olarak
yürütülemeyebilir. Örneğin, bir uzun yoklama isteği, isteğin HTTP bağlamının ömrü ötesinde bir hub tarafından açık
tutulduğunda bu durum oluşabilir.

ASP.NET Core, her istekle birlikte uygulamaya gönderilen oturum KIMLIĞI içeren istemciye bir tanımlama bilgisi
sağlayarak oturum durumunu korur. Uygulama, oturum verilerini getirmek için oturum KIMLIĞINI kullanır.
Oturum durumu aşağıdaki davranışları sergiler:
Oturum tanımlama bilgisi tarayıcıya özel olduğundan, oturumlar tarayıcılar arasında paylaşılmaz.
Tarayıcı oturumu sona erdiğinde oturum tanımlama bilgileri silinir.
Kullanım dışı bir oturum için tanımlama bilgisi alınmışsa, aynı oturum tanımlama bilgisini kullanan yeni bir
oturum oluşturulur.
Boş oturumlar korunmaz—oturum, oturum istekleri arasında kalıcı hale getirmek için en az bir değere
ayarlanmış olmalıdır. Bir oturum tutulmadığı zaman, her yeni istek için yeni bir oturum KIMLIĞI oluşturulur.
Uygulama, son istekten sonra sınırlı bir süre boyunca bir oturum tutar. Uygulama, oturum zaman aşımını
ayarlar ya da 20 dakikalık varsayılan değeri kullanır. Oturum durumu, belirli bir oturuma özgü kullanıcı
verilerini depolamak için idealdir, ancak verilerin oturumlarda kalıcı depolama gerektirmez.
Oturum verileri, ISession. Clear uygulaması çağrıldığında veya oturumun süresi dolarsa silinir.
Uygulama kodunu istemci tarayıcısının kapatıldığını veya istemcide oturum tanımlama bilgisinin silindiği veya
süresi dolduğunda bilgilendirmeye yönelik varsayılan bir mekanizma yoktur.
ASP.NET Core MVC ve Razor sayfaları şablonları, Genel Veri Koruma Yönetmeliği (GDPR ) desteğini içerir.
Oturum durumu tanımlama bilgileri varsayılan olarak temel olarak işaretlenmez, bu nedenle site ziyaretçisi
tarafından izlemeye izin verilmediği takdirde oturum durumu işlevsel değildir. Daha fazla bilgi için bkz.
ASP.NET Core Genel Veri Koruma Yönetmeliği (GDPR ) desteği.

WARNING
Gizli verileri oturum durumunda depolamayin. Kullanıcı tarayıcıyı Kapatmayabilir ve oturum tanımlama bilgisini temizleyebilir.
Bazı tarayıcılar tarayıcı pencereleri arasında geçerli oturum tanımlama bilgilerini korur. Bir oturum tek bir kullanıcıyla
kısıtlanmayabilir—sonraki Kullanıcı aynı oturum tanımlama bilgisiyle uygulamaya gözatmaya devam edebilir.

Bellek içi önbellek sağlayıcısı, oturum verilerini uygulamanın bulunduğu sunucunun belleğinde depolar. Sunucu
grubu senaryosunda:
Her oturumu tek bir sunucudaki belirli bir uygulama örneğine bağlamak için yapışkan oturumları kullanın.
Azure App Service , varsayılan olarak yapışkan oturumları zorlamak Için uygulama isteği yönlendirme (ARR )
kullanır. Ancak, yapışkan oturumlar ölçeklenebilirliği etkileyebilir ve Web uygulaması güncelleştirmelerini
karmaşıklaştırır. Daha iyi bir yaklaşım, yapışkan oturum gerektirmeyen bir redya veya SQL Server dağıtılmış
önbellek kullanmaktır. Daha fazla bilgi için bkz. ASP.NET Core 'de dağıtılmış önbelleğe alma.
Oturum tanımlama bilgisi, ıdataprotectoraracılığıyla şifrelenir. Veri koruma, her makinede oturum tanımlama
bilgilerini okumak için düzgün şekilde yapılandırılmalıdır. Daha fazla bilgi için bkz. ASP.NET Core veri
koruması ve anahtar depolama sağlayıcıları.
Oturum durumunu yapılandırma
Microsoft. AspNetCore. app metapackageiçinde yer alan Microsoft. Aspnetcore. Session paketi, oturum
durumunu yönetmek için ara yazılım sağlar. Oturum ara yazılımını etkinleştirmek için Startup şunları içermelidir:
Idistributedönbellek belleği önbellekler. IDistributedCache uygulama, oturum için bir yedekleme deposu
olarak kullanılır. Daha fazla bilgi için bkz. ASP.NET Core 'de dağıtılmış önbelleğe alma.
ConfigureServices 'de Addsession çağrısı.
Configure 'de Usesession çağrısı.

Aşağıdaki kod, bellek içi oturum sağlayıcısının IDistributedCache varsayılan bir bellek içi uygulamasıyla nasıl
ayarlanacağını gösterir:

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();

services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
// Make the session cookie essential
options.Cookie.IsEssential = true;
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseHttpContextItemsMiddleware();
app.UseMvc();
}
}

Ara yazılım sırası önemlidir. Yukarıdaki örnekte, UseMvc sonra UseSession çağrıldığında
InvalidOperationException bir özel durum oluşur. Daha fazla bilgi için bkz. Ara yazılım sıralaması.

HttpContext. Session , oturum durumu yapılandırıldıktan sonra kullanılabilir.


UseSession çağrılmadan önce HttpContext.Session erişilemez.
Uygulama yanıt akışına yazmaya başladıktan sonra yeni bir oturum tanımlama bilgisine sahip yeni bir oturum
oluşturulamıyor. Özel durum Web sunucusu günlüğüne kaydedilir ve tarayıcıda gösterilmez.
Oturum durumunu zaman uyumsuz olarak yükle
ASP.NET Core varsayılan oturum sağlayıcısı, arka plandaki ıdistributedcache 'ten oturum kayıtlarını, yalnızca
ISession. LoadAsync yöntemi doğrudan TryGetValue, setveya Remove yöntemleriyle önce çağrılırsa zaman
uyumsuz olarak yükler. İlk olarak LoadAsync çağrılmadıysa, temel alınan oturum kaydı zaman uyumlu olarak
yüklenir ve bu da ölçekte performans cezası oluşturabilir.
Uygulamaların bu kalıbı zorunlu kılmak için, LoadAsync yöntemi TryGetValue , Set veya Remove önce
çağrılmıyorsa, Distributedsessionstore ve distributedoturum uygulamalarını bir özel durum oluşturan sürümlerle
sarın. Sarmalanan sürümleri hizmetler kapsayıcısına kaydedin.
Oturum seçenekleri
Oturum varsayılanlarını geçersiz kılmak için SessionOptions' ı kullanın.

SEÇENEK AÇIKLAMA

Bilgilerinin Tanımlama bilgisini oluşturmak için kullanılan ayarları belirler.


Ad varsayılan olarak Sessiondefaults. tanımlama adı (
.AspNetCore.Session ) olarak belirlenmiştir. Yol varsayılan
olarak Sessiondefaults. tarif ıepath ( / ) olarak belirlenmiştir.
SameSite varsayılan olarak samesitemode. lax ( 1 ) olarak
belirlenmiştir. HttpOnly varsayılan olarak true . IsEssential
varsayılan olarak false .

Timeout IdleTimeout , oturumun içeriği terk edilmeden önce ne


kadar süreyle boşta kalabileceğini gösterir. Her oturum erişimi
zaman aşımını sıfırlar. Bu ayar, tanımlama bilgisi değil yalnızca
oturumun içeriği için geçerlidir. Varsayılan değer 20 dakikadır.

IOTimeout Mağazadan bir oturumu yüklemesine veya depolama alanına


geri kaydetmeye izin verilen en uzun süre. Bu ayar yalnızca
zaman uyumsuz işlemlere uygulanabilir. Bu zaman aşımı,
InfiniteTimeSpankullanılarak devre dışı bırakılabilir. Varsayılan
değer 1 dakikadır.

Oturum, tek bir tarayıcıdan gelen istekleri izlemek ve tanımlamak için bir tanımlama bilgisi kullanır. Varsayılan
olarak, bu tanımlama bilgisinin .AspNetCore.Session adı verilir ve / bir yolu kullanır. Tanımlama bilgisi varsayılan
olarak bir etki alanı belirtmediğinden, sayfada istemci tarafı komut dosyası için kullanılamaz hale getirilmez (
HttpOnly yalnızca true için varsayılan değerdir).
Tanımlama bilgisi oturum varsayılanlarını geçersiz kılmak için SessionOptions kullanın:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddDistributedMemoryCache();

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddSession(options =>
{
options.Cookie.Name = ".AdventureWorks.Session";
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.IsEssential = true;
});
}

Uygulama, sunucunun önbelleğindeki içeriği terk edilmeden önce bir oturumun ne kadar süreyle boşta
kalabileceğini anlamak için IdleTimeout özelliğini kullanır. Bu özellik, tanımlama bilgisi bitiş zamanından
bağımsızdır. Oturum ara yazılımı üzerinden geçen her istek zaman aşımını sıfırlar.
Oturum durumu kilitlideğil. İki istek aynı anda bir oturumun içeriğini değiştirmeyi denerseniz, son istek ilk
geçersiz kılar. Session tutarlı bir oturumolarak uygulanır. Bu, tüm içeriklerin birlikte depolandığı anlamına gelir.İki
istek farklı oturum değerlerini değiştirmek için arama yaparken, son istek ilk tarafından yapılan oturum
değişikliklerini geçersiz kılabilir.
Oturum değerlerini ayarlama ve edinme
Razor Pages Pagemodel sınıfından ya da HttpContext. Sessionile MVC Denetleyici sınıfından oturum durumuna
erişilir. Bu özellik bir ISession uygulamasıdır.
ISession uygulama, tamsayı ve dize değerlerini ayarlamak ve almak için birkaç uzantı yöntemi sağlar. Uzantı
yöntemleri, proje tarafından Microsoft. AspNetCore. http. Extensions paketine başvurulduğunda Microsoft.
aspnetcore. http ad alanında (uzantı yöntemlerine erişim kazanmak için bir using Microsoft.AspNetCore.Http;
bildirisi ekleyin). Her iki paket de Microsoft. AspNetCore. app metapackage'e dahildir.
ISession uzantısı yöntemleri:
Al (ISession, dize)
Getınt32 (ISession, dize)
GetString (ISession, dize)
Setınt32 (ISession, dize, Int32)
SetString (ISession, dize, dize)
Aşağıdaki örnek, bir Razor Pages sayfasındaki IndexModel.SessionKeyName anahtarı (örnek uygulamada _Name ) için
oturum değerini alır:

@page
@using Microsoft.AspNetCore.Http
@model IndexModel

...

Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)
Aşağıdaki örnek, bir tamsayı ve bir dizenin nasıl ayarlanacağını ve alınacağını gösterir:

public class IndexModel : PageModel


{
public const string SessionKeyName = "_Name";
public const string SessionKeyAge = "_Age";
const string SessionKeyTime = "_Time";

public string SessionInfo_Name { get; private set; }


public string SessionInfo_Age { get; private set; }
public string SessionInfo_CurrentTime { get; private set; }
public string SessionInfo_SessionTime { get; private set; }
public string SessionInfo_MiddlewareValue { get; private set; }

public void OnGet()


{
// Requires: using Microsoft.AspNetCore.Http;
if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
{
HttpContext.Session.SetString(SessionKeyName, "The Doctor");
HttpContext.Session.SetInt32(SessionKeyAge, 773);
}

var name = HttpContext.Session.GetString(SessionKeyName);


var age = HttpContext.Session.GetInt32(SessionKeyAge);

Tüm oturum verileri, bellek içi önbellek kullanılırken bile dağıtılmış önbellek senaryosunu etkinleştirmek üzere
serileştirilmelidir. En az dize ve numara serileştiricileri sağlanır (bkz. ISession'un yöntemlerine ve genişletme
yöntemlerine bakın). Karmaşık türler JSON gibi başka bir mekanizma kullanılarak Kullanıcı tarafından
serileştirilmelidir.
Seri hale getirilebilir nesneleri ayarlamak ve almak için aşağıdaki uzantı yöntemlerini ekleyin:

public static class SessionExtensions


{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}

public static T Get<T>(this ISession session, string key)


{
var value = session.GetString(key);

return value == null ? default(T) :


JsonConvert.DeserializeObject<T>(value);
}
}

Aşağıdaki örnek, uzantı yöntemleriyle bir serileştirilebilir nesnenin nasıl ayarlanacağını ve alınacağını gösterir:

// Requires you add the Set and Get extension method mentioned in the topic.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default(DateTime))
{
HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}

TempData
ASP.NET Core, Razor Pages TempData veya Controller TempDatakullanıma sunar. Bu özellik, verileri başka bir
istekte okunana kadar depolar. Sakla (dize) ve Peek (dize) yöntemleri, isteğin sonunda silme yapılmadan verileri
incelemek için kullanılabilir. Keep () sözlükte tüm öğeleri bekletme için işaretler. TempData , bir tek istekten daha
fazla veri gerektiğinde yeniden yönlendirme için özellikle kullanışlıdır. TempData , tanımlama bilgileri veya oturum
durumu kullanılarak TempData sağlayıcılar tarafından uygulanır.

TempData örnekleri
Bir müşteri oluşturan aşağıdaki sayfayı göz önünde bulundurun:

public class CreateModel : PageModel


{
private readonly RazorPagesContactsContext _context;

public CreateModel(RazorPagesContactsContext context)


{
_context = context;
}

public IActionResult OnGet()


{
return Page();
}

[TempData]
public string Message { get; set; }

[BindProperty]
public Customer Customer { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";

return RedirectToPage("./IndexPeek");
}
}

Aşağıdaki sayfada TempData["Message"] görüntülenir:

@page
@model IndexModel

<h1>Peek Contacts</h1>

@{
if (TempData.Peek("Message") != null)
{
<h3>Message: @TempData.Peek("Message")</h3>
}
}

@*Content removed for brevity.*@

Önceki biçimlendirmede, isteğin sonunda, Peek kullanıldığından TempData["Message"] silinmez. Sayfayı


yenilemek TempData["Message"] görüntüler.
Aşağıdaki biçimlendirme önceki koda benzerdir, ancak isteğin sonundaki verileri korumak için Keep kullanır:

@page
@model IndexModel

<h1>Contacts Keep</h1>

@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
TempData.Keep("Message");
}

@*Content removed for brevity.*@

Indexpeek ve ındexkeep sayfaları arasında gezinmek TempData["Message"] silmez.


Aşağıdaki kod TempData["Message"] görüntüler, ancak isteğin sonunda TempData["Message"] silinir:

@page
@model IndexModel

<h1>Index no Keep or Peek</h1>

@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
}

@*Content removed for brevity.*@

TempData sağlayıcıları
Tanımlama bilgisi tabanlı TempData sağlayıcısı, TempData 'ı tanımlama bilgilerinde depolamak için varsayılan
olarak kullanılır.
Tanımlama bilgisi verileri, Base64UrlTextEncoderile kodlanan ve sonra öbekli ıdataprotectorkullanılarak şifrelenir.
Tanımlama bilgisi öbekli olduğundan, ASP.NET Core 1. x içinde bulunan tek tanımlama bilgisi boyut sınırı
uygulanmaz. Şifreli verileri sıkıştırmak, suç ve ihlal saldırıları gibi güvenlik sorunlarına yol açacağından, tanımlama
bilgisi verileri sıkıştırılmaz. Tanımlama bilgisi tabanlı TempData sağlayıcısı hakkında daha fazla bilgi için bkz.
tanımlama, ıetempdataprovider.
Bir TempData sağlayıcısı seçin
Bir TempData sağlayıcısı seçmek şöyle bazı hususlar içerir:
1. Uygulama oturum durumunu zaten kullanıyor mu? Bu durumda, oturum durumu, TempData Provider 'ın
kullanılması uygulamaya ek bir ücret vermez (verilerin boyutundan itibaren).
2. Uygulama yalnızca görece küçük miktarlarda veri (500 bayta kadar) için TempData kullanıyor mu? Bu
durumda, bir tanımlama bilgisi TempData Provider, TempData kullanan her isteğe küçük bir maliyet ekler. Aksi
takdirde, oturum durumu TempData Provider, Geçicimiz veri tüketilene kadar her istekte büyük miktarda veri
dönüşü olmaması yararlı olabilir.
3. Uygulama, birden çok sunucuda bir sunucu grubunda mi çalışıyor? Bu durumda, veri koruma dışındaki
tanımlama bilgisi TempData sağlayıcısını kullanmak için ek yapılandırma gerekmez (bkz. ASP.NET Core veri
koruması ve anahtar depolama sağlayıcıları).

NOTE
Çoğu Web istemcisi (Web tarayıcıları gibi), her tanımlama bilgisinin en büyük boyutu, toplam tanımlama bilgisi sayısı veya
her ikisi için sınır uygular. Bu tanımlama bilgisi TempData sağlayıcısını kullanırken, uygulamanın bu sınırları aşmadığını
doğrulayın. Verilerin toplam boyutunu göz önünde bulundurun. Şifreleme ve parçalama nedeniyle tanımlama bilgisi
boyutundaki artışlar için hesap.

TempData sağlayıcısını yapılandırma


Tanımlama bilgisi tabanlı TempData sağlayıcısı varsayılan olarak etkindir.
Oturum tabanlı TempData sağlayıcısını etkinleştirmek için Addsessionstatetempdataprovider genişletme
yöntemini kullanın:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddSessionStateTempDataProvider();

services.AddSession();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseMvc();
}

Ara yazılım sırası önemlidir. Yukarıdaki örnekte, UseMvc sonra UseSession çağrıldığında
InvalidOperationException bir özel durum oluşur. Daha fazla bilgi için bkz. Ara yazılım sıralaması.

IMPORTANT
.NET Framework hedefleme ve oturum tabanlı TempData sağlayıcısını kullanıyorsanız, Microsoft. AspNetCore. Session
paketini projeye ekleyin.

Sorgu dizeleri
Yeni isteğin sorgu dizesine eklenerek sınırlı miktarda veri, bir istekten diğerine geçirilebilir. Bu durum, gömülü
durum ile bağlantıların e-posta veya sosyal ağlar aracılığıyla paylaşılmasını sağlamak için durumu kalıcı bir şekilde
yakalamak için yararlıdır. URL sorgu dizeleri ortak olduğundan, gizli veriler için hiçbir şekilde Sorgu dizelerini
kullanmayın.
Sorgu dizelerindeki veriler de dahil olmak üzere, istenmeyen paylaşıma ek olarak, siteler arası Istek forgery
(CSRF ) saldırıları için fırsat oluşturabilir ve bu da kullanıcıların kimliği doğrulandığında kötü amaçlı siteleri ziyaret
etmesini sağlayabilir. Saldırganlar daha sonra Kullanıcı verilerini uygulamadan çalabilir veya Kullanıcı adına kötü
amaçlı eylemler gerçekleştirebilir. Korunan uygulamaların veya oturum durumunun CSRF saldırılarına karşı
korunması gerekir. Daha fazla bilgi için bkz. siteler arası Istek forgery (XSRF/CSRF ) saldırılarını önleme.

Gizli alanlar
Veriler gizli form alanlarına kaydedilebilir ve sonraki istek üzerine geri gönderilebilir. Bu çok sayfalı formlarda
yaygındır. İstemci verilerle oynayabilir olabileceğinden, uygulamanın gizli alanlarda depolanan verileri her zaman
yeniden doğrulaması gerekir.

HttpContext. Items
HttpContext. Items koleksiyonu, tek bir isteği işlerken verileri depolamak için kullanılır. Koleksiyon içeriği bir istek
işlendikten sonra atılır. Items koleksiyonu, genellikle bir istek sırasında farklı noktalarda çalıştıklarında ve
parametreleri geçirmek için doğrudan bir yol olmadığında bileşenlerin veya ara yazılımların iletişim kurmasına
izin vermek için kullanılır.
Aşağıdaki örnekte, Ara yazılım Items koleksiyonuna isVerified ekler.

app.Use(async (context, next) =>


{
// perform some verification
context.Items["isVerified"] = true;
await next.Invoke();
});

Ardışık düzen daha sonra, başka bir ara yazılım isVerified değerine erişebilir:

app.Run(async (context) =>


{
await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
});

Yalnızca tek bir uygulama tarafından kullanılan ara yazılım için string anahtarları kabul edilebilir. Uygulama
örnekleri arasında paylaşılan ara yazılım, anahtar çakışmalarını önlemek için benzersiz nesne anahtarları
kullanmalıdır. Aşağıdaki örnek, bir ara yazılım sınıfında tanımlanan benzersiz bir nesne anahtarının nasıl
kullanılacağını gösterir:
public class HttpContextItemsMiddleware
{
private readonly RequestDelegate _next;
public static readonly object HttpContextItemsMiddlewareKey = new Object();

public HttpContextItemsMiddleware(RequestDelegate next)


{
_next = next;
}

public async Task Invoke(HttpContext httpContext)


{
httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";

await _next(httpContext);
}
}

public static class HttpContextItemsMiddlewareExtensions


{
public static IApplicationBuilder
UseHttpContextItemsMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpContextItemsMiddleware>();
}
}

Diğer kod, ara yazılım sınıfı tarafından kullanıma sunulan anahtar kullanılarak HttpContext.Items içinde
depolanan değere erişebilir:

HttpContext.Items
.TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey,
out var middlewareSetValue);
SessionInfo_MiddlewareValue =
middlewareSetValue?.ToString() ?? "Middleware value not set!";

Bu yaklaşım ayrıca koddaki anahtar dizelerinin kullanımını ortadan kaldırma avantajına sahiptir.

Önbellek
Önbelleğe alma, verileri depolamak ve almak için etkili bir yoldur. Uygulama, önbelleğe alınmış öğelerin ömrünü
denetleyebilir.
Önbelleğe alınan veriler belirli bir istek, Kullanıcı veya oturumla ilişkili değildir. Diğer kullanıcıların istekleri
tarafından alınabilecek kullanıcıya özgü verileri önbelleğe alma konusunda dikkatli olun.
Daha fazla bilgi için bkz. ASP.NET Core 'de yanıt önbelleğe alma.

Bağımlılık Ekleme
Verilerin tüm kullanıcılar tarafından kullanılabilmesini sağlamak için bağımlılık ekleme 'yi kullanın:
1. Verileri içeren bir hizmet tanımlayın. Örneğin, MyAppData adlı bir sınıf tanımlanmıştır:

public class MyAppData


{
// Declare properties and methods
}
2. Hizmet sınıfını Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddSingleton<MyAppData>();
}

3. Veri hizmeti sınıfını tüketme:

public class IndexModel : PageModel


{
public IndexModel(MyAppData myService)
{
// Do something with the service
// Examples: Read data, store in a field or property
}
}

Sık karşılaşılan hatalar


"' Microsoft. AspNetCore. Session. DistributedSessionStore ' etkinleştirilmeye çalışılırken ' Microsoft.
Extensions. Caching. Distributed. ıdistributedcache ' türü için hizmet çözümlenemiyor."
Bunun nedeni genellikle en az bir IDistributedCache uygulamasını yapılandırma başarısız olmuştur. Daha
fazla bilgi için bkz. ASP.NET Core 'de dağıtılmış önbelleğe alma ve ASP.NET Core 'de önbellek belleği.
Oturum ara yazılımı bir oturumu kalıcı hale getiremediğinde (örneğin, yedekleme deposu
kullanılamıyorsa), ara yazılım özel durumu günlüğe kaydeder ve istek normal olarak devam eder. Bu,
öngörülemeyen davranışa yol açar.
Örneğin, bir Kullanıcı bir alışveriş sepetini oturum içinde depolar. Kullanıcı sepete bir öğe ekler, ancak kayıt
başarısız olur. Uygulama hata hakkında bilgi sahibi değildir, bu nedenle bu, doğru olmayan, kullanıcıya
öğenin sepetine eklendiğini bildirir.
Hataları denetlemek için önerilen yaklaşım, uygulama oturuma yazma işlemi tamamlandığında uygulama
kodundan await feature.Session.CommitAsync(); çağırmalıdır. yedekleme deposu kullanılamıyorsa
CommitAsync bir özel durum oluşturur. CommitAsync başarısız olursa, uygulama özel durumu işleyebilir.
LoadAsync , veri deposunun kullanılamadığı koşulların altında oluşturulur.

SignalR ve oturum durumu


SignalR uygulamalar, bilgileri depolamak için oturum durumunu kullanmamalıdır. SignalR uygulamalar, hub 'da
Context.Items her bağlantı durumunu depolayabilirler.

Ek kaynaklar
Web çiftliğinde ASP.NET Core ana bilgisayar
ASP.NET Core düzen
25.11.2019 • 10 minutes to read • Edit Online

Steve Smith ve bave Brock tarafından


Sayfalar ve görünümler genellikle görsel ve programlı öğeleri paylaşır. Bu makalede nasıl
yapılacağı gösterilmektedir:
Ortak düzenleri kullanın.
Komutları paylaşma.
Sayfaları veya görünümleri işlemeden önce ortak kodu çalıştırın.
Bu belgede, ASP.NET Core MVC: Razor Pages ve denetleyicilerin görünümleriyle olan iki farklı
yaklaşım için düzenler açıklanmaktadır. Bu konu için, farklar en az:
Razor Pages, Sayfalar klasöründedir.
Görünümleri olan denetleyiciler görünümler için bir Görünümler klasörü kullanır.

Düzen nedir?
Çoğu Web uygulaması, bir sayfadan sayfaya gezindikleri sürece kullanıcıya tutarlı bir deneyim
sağlayan ortak bir düzene sahiptir. Düzen genellikle uygulama üstbilgisi, gezinti veya menü
öğeleri ve alt bilgi gibi ortak kullanıcı arabirimi öğelerini içerir.

Betikler ve stil sayfaları gibi ortak HTML yapıları de bir uygulama içindeki birçok sayfa tarafından
sık kullanılır. Bu paylaşılan öğelerin tümü, bir Düzen dosyasında tanımlanabilir ve bu daha sonra
uygulama içinde kullanılan herhangi bir görünüm tarafından başvurulabilirler. Düzenler
görünümlerde yinelenen kodu azaltır.
Kurala göre, bir ASP.NET Core uygulamasının varsayılan düzeni _Layout. cshtmlolarak
adlandırılır. Şablonlarla oluşturulan yeni ASP.NET Core projelerine yönelik düzen dosyaları
şunlardır:
Razor Pages: sayfa/paylaşılan/_Layout. cshtml
Görünümler içeren denetleyici: views/Shared/_Layout. cshtml

Düzen, uygulamadaki görünümler için üst düzey bir şablon tanımlar. Uygulamalar bir düzen
gerektirmez. Uygulamalar, farklı düzenleri belirleyen farklı görünümlerle birden fazla düzen
tanımlayabilir.
Aşağıdaki kod, bir şablon tarafından oluşturulan ve bir denetleyici ve görünümleri olan bir proje
için Düzen dosyasını gösterir:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebApplication1</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet"
href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-
fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-
target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">WebApplication1</a>
<a asp-page="/Index" class="navbar-brand">WebApplication1</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Contact">Contact</a></li>
</ul>
</div>
</div>
</nav>

<partial name="_CookieConsentPartial" />

<div class="container body-content">


@RenderBody()
<hr />
<footer>
<p>&copy; 2018 - WebApplication1</p>
</footer>
</div>

<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-
tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn &&
window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-
Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>

@RenderSection("Scripts", required: false)


</body>
</html>

Düzen belirtme
Razor görünümlerinin Layout bir özelliği vardır. Bireysel görünümler bu özelliği ayarlayarak bir
düzen belirtir:

@{
Layout = "_Layout";
}

Belirtilen Düzen tam yol (örneğin, /Pages/Shared/_Layout. cshtml veya /views/Shared/_Layout.


cshtml) ya da kısmi bir ad kullanabilir (örnek: _Layout ). Kısmi bir ad sağlandığında, Razor
görüntüleme altyapısı, kendi standart bulma işlemini kullanarak düzen dosyasını arar. Önce
işleyici yönteminin (veya denetleyicinin) bulunduğu klasör, sonra paylaşılan klasör tarafından
aranır. Bu bulma işlemi, kısmi görünümleribulmak için kullanılan işlemle aynıdır.
Varsayılan olarak, her düzen RenderBody çağırmalıdır. RenderBody çağrısının yerleştirildiği her
yerde, görünümün içerikleri işlenir.
Bölümler
Bir düzen, RenderSection çağırarak, isteğe bağlı olarak bir veya daha fazla bölümebaşvurabilir.
Bölümler, belirli sayfa öğelerinin yerleştirilmesi gereken yerleri düzenlemek için bir yol sağlar. Her
RenderSection çağrısı, bu bölümün gerekli veya isteğe bağlı olup olmadığını belirtebilir:

<script type="text/javascript" src="~/scripts/global.js"></script>

@RenderSection("Scripts", required: false)

Gerekli bir bölüm bulunamazsa, bir özel durum oluşturulur. Tek görünümler, @section Razor söz
dizimi kullanarak bir bölüm içinde işlenecek içeriği belirtir. Bir sayfa veya görünüm bir bölümü
tanımlıyorsa, oluşturulması gerekir (veya bir hata oluşur).
Razor Pages görünümündeki bir örnek @section tanımı:

@section Scripts {
<script type="text/javascript" src="~/scripts/main.js"></script>
}

Yukarıdaki kodda betikler/Main. js bir sayfa veya görünümdeki scripts bölümüne eklenir. Aynı
uygulamadaki diğer sayfalar veya görünümler bu betiği gerektirmeyebilir ve betikler bölümü
tanımlamaz.
Aşağıdaki biçimlendirme _ValidationScriptsPartial. cshtmlöğesini Işlemek Için kısmi etiket
yardımcısını kullanır:

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

Önceki biçimlendirme, Yapı Iskelesi kimliğitarafından oluşturulmuştur.


Bir sayfada veya görünümde tanımlanan bölümler yalnızca kendi düzen sayfasında kullanılabilir.
Parçalardan başvurulamaz, bileşenleri veya görünüm sisteminin diğer kısımlarını bunlara
başvuramaz.
Bölümler yoksayılıyor
Varsayılan olarak, içerik sayfasındaki gövde ve tüm bölümler Düzen sayfası tarafından
işlenmelidir. Razor görünümü altyapısı, gövdenin ve her bölümün işlenip işlenmeyeceğini
izleyerek bunu zorlar.
Görünüm altyapısına gövde veya bölümleri yok saymasını bildirmek için IgnoreBody ve
IgnoreSection yöntemlerini çağırın.

Bir Razor sayfasındaki gövde ve her bölüm işlenen ya da yoksayıldı olmalıdır.

Paylaşılan yönergeler içeri aktarılıyor


Görünümler ve sayfalar, ad alanlarını içeri aktarmak ve bağımlılık ekleme'yi kullanmak için Razor
yönergeleri kullanabilir. Birçok görünüm tarafından paylaşılan yönergeler, ortak bir _ViewImports.
cshtml dosyasında belirtilebilir. _ViewImports dosyası aşağıdaki yönergeleri destekler:
@addTagHelper
@removeTagHelper
@tagHelperPrefix
@using
@model
@inherits
@inject

Dosya, işlevler ve bölüm tanımları gibi diğer Razor özelliklerini desteklemez.


Örnek bir _ViewImports.cshtml dosyası:

@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

ASP.NET Core MVC uygulamasının _ViewImports. cshtml dosyası genellikle Sayfalar (veya
Görünümler) klasörüne yerleştirilir. Bir _ViewImports. cshtml dosyası herhangi bir klasöre
yerleştirilebilir, bu durumda yalnızca söz konusu klasör ve alt klasörleri içindeki sayfalara veya
görünümlere uygulanacaktır. _ViewImports dosyalar, kök düzeyinden başlayarak işlenir ve sonra
her bir klasör için sayfanın konumu veya görünümü görüntülenir. kök düzeyinde belirtilen
_ViewImports ayarları klasör düzeyinde geçersiz kılınabilir.

Örneğin, şunu varsayın:


Kök düzeyi _ViewImports. cshtml dosyası @model MyModel1 ve @addTagHelper *, MyTagHelper1
içerir.
Bir alt klasör _ViewImports. cshtml dosyası @model MyModel2 ve @addTagHelper *, MyTagHelper2
içerir.
Alt klasördeki sayfaların ve görünümlerin her ikisi de etiket yardımcılarını ve MyModel2 modeli
erişimine sahip olur.
Dosya hiyerarşisinde birden çok _ViewImports. cshtml dosyası bulunursa, yönergelerin
birleştirilmiş davranışı şunlardır:
@addTagHelper , @removeTagHelper: tüm çalıştırma, sırasıyla
@tagHelperPrefix : en yakın bir görünüm, diğerlerini geçersiz kılar
@model : en yakın bir görünüm, diğerlerini geçersiz kılar
@inherits : en yakın bir görünüm, diğerlerini geçersiz kılar
@using : tümü dahildir; yinelemeler yoksayıldı
@inject : her bir özellik için, görünümün en yakın olanı aynı özellik adına sahip diğerlerini
geçersiz kılar

Her görünümden önce kod çalıştırma


Her görünüm veya sayfadan önce çalıştırılması gereken kod _ViewStart. cshtml dosyasına
yerleştirilmelidir. Kurala göre, _ViewStart. cshtml dosyası Sayfalar (veya Görünümler) klasöründe
bulunur. _ViewStart. cshtml 'de listelenen deyimler her tam görünüm (düzen değil ve kısmi
görünümler değil) öncesinde çalıştırılır. Viewwimports. cshtmlgibi _ViewStart. cshtml de
hiyerarşiktir. Görünüm veya sayfalar klasöründe bir _ViewStart. cshtml dosyası tanımlanmışsa,
Sayfalar (veya Görünümler) klasörünün kökünde (varsa) tanımlandıktan sonra çalıştırılır.
Örnek bir _ViewStart. cshtml dosyası:

@{
Layout = "_Layout";
}

Yukarıdaki dosya tüm görünümlerin _Layout. cshtml mizanpajını kullanacağı belirtir.


_ViewStart. cshtml ve _ViewImports. cshtml genellikle /Pages/Shared (veya /views/Shared)
klasörüne yerleştirilmez . Bu dosyaların uygulama düzeyi sürümleri doğrudan /Pages (veya
/views) klasörüne yerleştirilmelidir.
ASP.NET Core Razor söz dizimi başvurusu
9.12.2019 • 28 minutes to read • Edit Online

Tarafından Rick Anderson, Luke Latham, Taylor Mullen, ve Dan Vicarel


Razor kod sunucu tabanlı Web sayfalarını eklemek için bir biçimlendirme sözdizimi aşağıdaki gibidir.
Razor işaretlemesi Razor sözdizimini oluşur C#ve HTML. Razor genellikle içeren dosyalarınız bir
.cshtml dosya uzantısı. Razor, Razor bileşenleri dosyalarında ( . Razor) de bulunur.

HTML işleme
HTML varsayılan Razor dilidir. HTML Razor işaretlemesi işleme bir HTML dosyasından HTML'yi
işlemeye değerinden farklı değildir. HTML biçimlendirmede .cshtml Razor dosyaları değiştirilmemiş
sunucu tarafından işlenir.

Razor söz dizimi


Razor destekler C# ve kullandığı @ HTML geçiş sembolünden C#. Razor değerlendirir C# ifadeleri ve
bunları HTML çıktısında oluşturur.
Olduğunda bir @ sembol tarafından izlenen bir Razor ayrılmış anahtar sözcüğü, Razor özgü
biçimlendirme geçer. Aksi takdirde düz geçiş C#.
Kaçış için bir @ sembol Razor işaretlemede, ikinci bir kullanın @ sembol:

<p>@@Username</p>

Kodunu HTML ile tek bir işlenen @ sembol:

<p>@Username</p>

Olmayan HTML öznitelikleri ve e-posta adreslerini içeren bir içerik işleme @ geçiş karakter olarak
sembol. Aşağıdaki örnekte e-posta adresleri tarafından Razor ayrıştırma olduğu:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Örtük Razor ifadeleri


Örtük Razor ifadeleri ile başlayıp @ ardından C# kod:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

Dışında C# await anahtar sözcüğü, örtük ifadeleri boşluk içermemelidir. Varsa C# deyimi açık bir bitiş
sahipse, boşluk intermingled:

<p>@await DoSomething("hello", "world")</p>


Örtük ifade olamaz içeren C# köşeli ayraçlar içindeki karakterler olarak genel türler ( <> ) bir HTML
etiketi yorumlanır. Aşağıdaki kod değil geçerli:

<p>@GenericMethod<int>()</p>

Yukarıdaki kod, aşağıdakilerden birini benzer bir derleyici hatası oluşturur:


"İnt" öğesi kapalı değildi. Tüm öğeleri olmalıdır kendi kendine kapanan veya eşleşen bir bitiş etiketi
sahip.
Yöntem grubu 'object' türü temsilci GenericMethod' dönüştürülemiyor. Bir yöntemi çağırmak mı
istiyordunuz?'
Genel yöntem çağrılarını sarmalanmış, içinde bir Razor açık ifadesi veya Razor kodu bloğu.

Açık Razor ifadeleri


Açık Razor ifadeleri oluşur bir @ dengeli parantez ile simge. Geçen haftaki zaman işlemek için
aşağıdaki Razor işaretlemesi kullanılır:

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

İçinde herhangi bir içerik @() parantez değerlendirilir ve işlenen çıkışı.


Önceki bölümde açıklanan, örtük ifadeleri genellikle boşluk içeremez. Aşağıdaki kodda, bir hafta, geçerli
saatten çıkarılabilir değil:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

Kod aşağıdaki HTML'yi oluşturur:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

Açık ifadeler, metin bir ifadenin sonucu ile birleştirmek için kullanılabilir:

@{
var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

Açık bir ifade olmadan <p>Age@joe.Age</p> bir e-posta adresi kabul edilir ve <p>Age@joe.Age</p> işlenir.
Açık bir ifade olarak yazılırken <p>Age33</p> işlenir.
Açık ifadeleri, genel yöntemleri gelen çıkış işleme için kullanılabilir .cshtml dosyaları. Aşağıdaki
biçimlendirmede gösterilen hatayı düzeltmek gösterilmektedir köşeli parantez önceki neden bir C#
genel. Kodu açık bir ifade olarak yazılır:

<p>@(GenericMethod<int>())</p>

İfade kodlama
C#HTML kodlu bir dizeye değerlendirilen ifadeleri var. C#değerlendirmek için ifadeleri IHtmlContent
doğrudan aracılığıyla işlenir IHtmlContent.WriteTo . C#Değerlendirme yok ifadeleri IHtmlContent
tarafından bir dizeye dönüştürülür ToString ve bunlar işlenen önce kodlanır.

@("<span>Hello World</span>")

Kod aşağıdaki HTML'yi oluşturur:

&lt;span&gt;Hello World&lt;/span&gt;

HTML tarayıcı gösterilir:

<span>Hello World</span>

HtmlHelper.Raw Çıktı kodlanmış değildir, ancak geri HTML biçimlendirmesi olarak çizilir.

WARNING
Kullanarak HtmlHelper.Raw unsanitized kullanıcı girişi bir güvenlik riski oluşturur. Kullanıcı girişi, kötü amaçlı
JavaScript veya diğer saldırılara içerebilir. Kullanıcı girişi temizlenirken zordur. Kullanmaktan kaçının
HtmlHelper.Raw kullanıcı girişi ile.

@Html.Raw("<span>Hello World</span>")

Kod aşağıdaki HTML'yi oluşturur:

<span>Hello World</span>

Razor kodu bloğu


Razor kod blokları kullanmaya başlama @ ve tarafından alınmış {} . İfadeler, aksine C# olmayan kod
blokları içinde kod çizilir. Kod blokları ve ifadeler bir görünümdeki aynı kapsamı paylaşan ve sırayla
tanımlanır:

@{
var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

Kod aşağıdaki HTML'yi oluşturur:

<p>The future depends on what you do today. - Mahatma Gandhi</p>


<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

Kod blokları ' nda, şablon oluşturma yöntemleri olarak kullanılacak biçimlendirme ile yerel işlevler
bildirin:

@{
void RenderName(string name)
{
<p>Name: <strong>@name</strong></p>
}

RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}

Kod aşağıdaki HTML'yi oluşturur:

<p>Name: <strong>Mahatma Gandhi</strong></p>


<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Örtük geçişleri
Bir kod bloğu varsayılan dilde C#, ancak Razor sayfası HTML olarak geçiş yapabilir:

@{
var inCSharp = true;
<p>Now in HTML, was in C# @inCSharp</p>
}

Açık ayrılmış geçiş


HTML oluşturması gereken bir kod bloğunun alt bölümünü tanımlamak için, karakterleri Razor <text>
etiketiyle çevreleyin:

@for (var i = 0; i < people.Length; i++)


{
var person = people[i];
<text>Name: @person.Name</text>
}

Tarafından HTML etiketleri arasına olmayan HTML oluşturmak için bu yaklaşımı kullanın. Bir HTML
veya Razor etiket olmadan, bir Razor çalışma zamanı hatası oluşur.
<text> etiketi, içerik işlerken boşluğu denetlemek için yararlıdır:
Yalnızca <text> etiketi arasındaki içerik işlenir.
HTML çıktısında <text> etiketi görüntülenmeden önce veya sonra boşluk yok.
Açık satır geçişi
Tüm satırın geri kalanını bir kod bloğu içinde HTML olarak işlemek için @: söz dizimini kullanın:

@for (var i = 0; i < people.Length; i++)


{
var person = people[i];
@:Name: @person.Name
}

Olmadan @: kodda bir Razor çalışma zamanı hatası oluşturulur.


Razor dosyasındaki ek @ karakterler, bloktaki daha sonra bulunan deyimlerde derleyici hatalarına
neden olabilir. Bu derleyici hataları önce bildirilen hatayı gerçek bir hata oluştuğu için anlamak zor
olabilir. Bu hata, tek bir kod bloğunun birden çok örtük/açık ifadelere birleştirdikten sonra yaygındır.

Denetim yapıları
Denetim yapıları kod bloğu bir uzantı var. Kod blokları tüm yönlerini (biçimlendirme, satır içi geçiş C#)
aşağıdaki yapılar için de geçerlidir:
Conditionals, else if, Else ve @Switch @
@if kod çalıştığında denetimleri:

@if (value % 2 == 0)
{
<p>The value was even.</p>
}

else ve else if gerektirmeyen @ sembol:

@if (value % 2 == 0)
{
<p>The value was even.</p>
}
else if (value >= 1337)
{
<p>The value is large.</p>
}
else
{
<p>The value is odd and small.</p>
}

Aşağıdaki biçimlendirme switch deyimi kullanma işlemini gösterir:

@switch (value)
{
case 1:
<p>The value is 1!</p>
break;
case 1337:
<p>Your number is 1337!</p>
break;
default:
<p>Your number wasn't 1 or 1337.</p>
break;
}

İçin döngü @, @foreach, @sırasında ve @do


Şablonlu HTML denetim ifadeleri döngü ile oluşturulabilir. Kişi listesini oluşturmak için:

@{
var people = new Person[]
{
new Person("Weston", 33),
new Person("Johnathon", 41),
...
};
}
Aşağıdaki döngü deyimi desteklenir:
@for

@for (var i = 0; i < people.Length; i++)


{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
}

@foreach

@foreach (var person in people)


{
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
}

@while

@{ var i = 0; }
@while (i < people.Length)
{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>

i++;
}

@do while

@{ var i = 0; }
@do
{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>

i++;
} while (i < people.Length);

Kullanarak bileşik @
İçinde C#, using deyimi, bir nesne kullanıldığında emin olmak için kullanılır. Razor aynı mekanizmayı
ek içeriklere sahip bir HTML Yardımcıları oluşturmak için kullanılır. Aşağıdaki kodda, HTML Yardımcıları
@using ifadesiyle bir <form> etiketi işlerler:

@using (Html.BeginForm())
{
<div>
Email: <input type="email" id="Email" value="">
<button>Register</button>
</div>
}

@TRY, catch, finally


Özel durum işleme benzer C#:

@try
{
throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
<p>The exception message: @ex.Message</p>
}
finally
{
<p>The finally statement.</p>
}

@kilidi
Razor kilit deyimleri kritik bölümlerle korumanın yeteneğine sahiptir:

@lock (SomeLock)
{
// Do critical section work
}

Açıklamalar
Razor destekler C# ve HTML yorumlarında:

@{
/* C# comment */
// Another C# comment
}
<!-- HTML comment -->

Kod aşağıdaki HTML'yi oluşturur:

<!-- HTML comment -->

Web sayfası işlenmeden önce razor açıklama sunucu tarafından kaldırılır. Razor kullanan @* *@
açıklamaları sınırlandırmak için. Sunucu tüm biçimlendirme işlemesi yapmıyor için aşağıdaki kodu,
geçersiz kılınan:

@*
@{
/* C# comment */
// Another C# comment
}
<!-- HTML comment -->
*@

Yönergeler
Razor yönergesi örtük ayrılmış anahtar sözcükler aşağıdaki deyimlerle tarafından temsil edilir @
simgesi. Bir yönergesi, genellikle bir görünüm ayrıştırılır veya farklı bir işlevsellik sağlar şeklini değiştirir.
Razor kod görünümü nasıl oluşturur? anlama yönergeleri nasıl çalıştığını anlamak kolaylaştırır.
@{
var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

Kod aşağıdaki gibi bir sınıf oluşturur:

public class _Views_Something_cshtml : RazorPage<dynamic>


{
public override async Task ExecuteAsync()
{
var output = "Getting old ain't for wimps! - Anonymous";

WriteLiteral("/r/n<div>Quote of the Day: ");


Write(output);
WriteLiteral("</div>");
}
}

Bölümü bu makalenin ilerleyen bölümlerinde Razor İnceleme C# bir görünümü için oluşturulan sınıf bu
oluşturulan sınıf görüntülemek açıklanmaktadır.
@özniteliği
@attribute yönergesi, verilen özniteliği oluşturulan sayfanın veya görünümün sınıfına ekler. Aşağıdaki
örnek [Authorize] özniteliğini ekler:

@attribute [Authorize]

@kodu
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
@code bloğu bir Razor bileşeninin bir bileşene üye ( C# alanlar, Özellikler ve Yöntemler) eklemesini
sağlar:

@code {
// C# members (fields, properties, and methods)
}

Razor bileşenleri için, @code @functions diğer adı @functions üzerinde önerilir. Birden fazla @code
bloğu izin verilir.
@işlevleri
@functions yönergesi, oluşturulan sınıfa C# üye (alanlar, Özellikler ve Yöntemler) eklemeyi sağlar:

@functions {
// C# members (fields, properties, and methods)
}

Razor bileşenlerinde, üye eklemek C# için @functions üzerinde @code kullanın.


Örneğin:
@functions {
public string GetHello()
{
return "Hello";
}
}

<div>From method: @GetHello()</div>

Kod aşağıdaki HTML biçimlendirmeyi oluşturur:

<div>From method: Hello</div>

Aşağıdaki kodu oluşturulmuş Razor olan C# sınıfı:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>


{
// Functions placed between here
public string GetHello()
{
return "Hello";
}
// And here.
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
WriteLiteral("\r\n<div>From method: ");
Write(GetHello());
WriteLiteral("</div>\r\n");
}
#pragma warning restore 1998

@functions Yöntemler, biçimlendirme olduğunda şablon oluşturma yöntemleri olarak görev yapar:

@{
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}

@functions {
private void RenderName(string name)
{
<p>Name: <strong>@name</strong></p>
}
}

Kod aşağıdaki HTML'yi oluşturur:

<p>Name: <strong>Mahatma Gandhi</strong></p>


<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@uygular
@implements yönergesi, oluşturulan sınıf için bir arabirim uygular.
Aşağıdaki örnek, Dispose yönteminin çağrılabilmesi için System.IDisposable uygular:
@implements IDisposable

<h1>Example</h1>

@functions {
private bool _isDisposed;

...

public void Dispose() => _isDisposed = true;


}

@devralır
@inherits Yönergesi görünümü devralan sınıf tam denetim sağlar:

@inherits TypeNameOfClassToInheritFrom

Aşağıdaki kod bir özel bir Razor sayfası türüdür:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>


{
public string CustomText { get; } =
"Gardyloo! - A Scottish warning yelled from a window before dumping" +
"a slop bucket on the street below.";
}

CustomText Bir görünümde görüntülenir:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

Kod aşağıdaki HTML'yi oluşturur:

<div>
Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
a slop bucket on the street below.
</div>

@model ve @inherits aynı görünümde kullanılabilir. @inherits kullanılabilir bir _viewımports.cshtml


görünümü alır dosyası:

@inherits CustomRazorPage<TModel>

Aşağıdaki kod, kesin türü belirtilmiş görünüm örneğidir:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>


<div>Custom text: @CustomText</div>

Varsa "rick@contoso.com" geçirilen modeldeki görünümünü aşağıdaki HTML biçimlendirmeyi


oluşturur:

<div>The Login Email: rick@contoso.com</div>


<div>
Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
a slop bucket on the street below.
</div>

@ekleme
@inject Yönergesi sağlayan bir hizmet eklemesine Razor sayfası hizmet kapsayıcı bir görünümde.
Daha fazla bilgi için görünümlere bağımlılık ekleme.
@düzeni
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
@layout yönergesi Razor bileşeninin bir yerleşimini belirtir. Düzen bileşenleri kod yinelemeyi ve
tutarsızlığın önüne geçmek için kullanılır. Daha fazla bilgi için bkz. ASP.NET Core Blazor düzenleri.
@modeli
Bu senaryo yalnızca MVC görünümleri ve Razor Pages (. cshtml) için geçerlidir.
@model yönergesi, bir görünüme veya sayfaya geçirilen modelin türünü belirtir:

@model TypeNameOfModel

Bir ASP.NET Core MVC veya bireysel kullanıcı hesaplarıyla oluşturulan Razor Pages uygulama,
Görünümler/Account/Login. cshtml aşağıdaki model bildirimini içerir:

@model LoginViewModel

Oluşturulan sınıf devraldığı RazorPage<dynamic> :

public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>

Razor sunan bir Model modeli erişmek için özelliği geçirilen görünümü:

<div>The Login Email: @Model.Email</div>

@model yönergesi Model özelliğinin türünü belirtir. Yönergesi belirtir T içinde RazorPage<T>
türetildiği görünümü oluşturulan, sınıfın. Varsa @model yönergesi belirtilmediyse, Model özelliği
türüdür dynamic . Daha fazla bilgi için bkz. türü kesin belirlenmiş modeller ve @model anahtar sözcüğü.
@ad alanı
@namespace yönergesi:
Oluşturulan Razor sayfası, MVC görünümü veya Razor bileşeni sınıfının ad alanını ayarlar.
Bir sayfa, görünüm veya bileşen sınıfının kök türetilmiş ad alanlarını dizin ağacındaki en yakın içeri
aktarmalar dosyasından, _ViewImports. cshtml (görünümler veya sayfalar) veya _Imports. Razor
(Razor bileşenleri) olarak ayarlar.

@namespace Your.Namespace.Here
Aşağıdaki tabloda gösterilen Razor Pages örneği için:
Her sayfa sayfaları/_ViewImports. cshtml'yi içeri aktarır.
Pages/_ViewImports. cshtml @namespace Hello.World içerir.
Her sayfa, ad alanının kökü olarak Hello.World sahiptir.

SAYFA AD ALANI

Pages/Index. cshtml Hello.World

Sayfa/fazla sayfa/sayfa. cshtml Hello.World.MorePages

Pages/te Pages/Evente Pages/Page. cshtml Hello.World.MorePages.EvenMorePages

Yukarıdaki ilişkiler, MVC görünümleri ve Razor bileşenleriyle kullanılan dosyaları içeri aktarmak için
geçerlidir.
Birden çok içeri aktarma dosyası @namespace yönergesine sahip olduğunda, kök ad alanını ayarlamak
için dizin ağacındaki sayfaya, görünüme veya bileşene en yakın dosya kullanılır.
Yukarıdaki örnekteki evente Pages klasörünün @namespace Another.Planet bir içeri aktarmalar dosyası
varsa (veya sayfa/değer sayfaları/Evente Pages/Page. cshtml dosyası @namespace Another.Planet
içeriyorsa), sonuç aşağıdaki tabloda gösterilmiştir.

SAYFA AD ALANI

Pages/Index. cshtml Hello.World

Sayfa/fazla sayfa/sayfa. cshtml Hello.World.MorePages

Pages/te Pages/Evente Pages/Page. cshtml Another.Planet

@sayfası
@page yönergesinin göründüğü dosyanın türüne bağlı olarak farklı etkileri vardır. Yönergesi:

İçindeki bir . cshtml dosyasında, dosyanın bir Razor sayfası olduğunu gösterir. Daha fazla bilgi için
bkz. özel rotalar ve ASP.NET Core Razor Pages giriş.
Bir Razor bileşeninin istekleri doğrudan işlemesini belirtir. Daha fazla bilgi için bkz. ASP.NET Core
Blazor yönlendirme.
Bir . cshtml dosyasının ilk satırındaki @page yönergesi, dosyanın bir Razor sayfası olduğunu gösterir.
Daha fazla bilgi için bkz. ASP.NET Core Razor Pages giriş.
@bölümü
Bu senaryo yalnızca MVC görünümleri ve Razor Pages (. cshtml) için geçerlidir.
@section yönergesi, görünümler veya sayfaların HTML sayfasının farklı bölümlerinde içerik işlemesini
sağlamak için MVC ve Razor Pages düzenleriyle birlikte kullanılır. Daha fazla bilgi için bkz. ASP.NET
Core düzen.
kullanarak @
@using Yönergesi ekler C# using yönerge oluşturulmuş görünümü için:
@using System.IO
@{
var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

Razor bileşenlerinde @using Ayrıca hangi bileşenlerin kapsamda olduğunu denetler.

Yönerge öznitelikleri
@öznitelikleri
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
@attributes , bir bileşenin bildirilmeyen öznitelikleri işlemesini sağlar. Daha fazla bilgi için bkz.
ASP.NET Core Razor bileşenleri oluşturma ve kullanma.
@bağlama
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
Bileşenlerdeki veri bağlama @bind özniteliğiyle gerçekleştirilir. Daha fazla bilgi için bkz. ASP.NET Core
Razor bileşenleri oluşturma ve kullanma.
{EVENT } üzerinde @
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
Razor, bileşenler için olay işleme özellikleri sağlar. Daha fazla bilgi için bkz. ASP.NET Core Razor
bileşenleri oluşturma ve kullanma.
{EVENT }:p reventDefault @
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
Olay için varsayılan eylemi engeller.
{EVENT } üzerinde @: Stopyayma
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
Olay için olay yaymayı sonlandırır.
@anahtarı
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
@key Directive özniteliği, bileşenlerin, anahtar değerine göre öğelerin veya bileşenlerin korunmasını
güvence altına almasına neden olur. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenleri
oluşturma ve kullanma.
@ref
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
Bileşen başvuruları ( @ref ) bir bileşen örneğine başvurmak için bir yol sağlar, böylece bu örneğe komut
verebilirsiniz. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenleri oluşturma ve kullanma.
@typeparam
Bu senaryo yalnızca Razor bileşenleri (. Razor ) için geçerlidir.
@typeparam yönergesi, oluşturulan bileşen sınıfı için genel bir tür parametresi bildirir. Daha fazla bilgi
için bkz. ASP.NET Core Razor bileşenleri oluşturma ve kullanma.
Şablonlu Razor temsilciler
Razor şablonları aşağıdaki biçimde bir kullanıcı Arabirimi parçacığı tanımlamanıza izin ver:

@<tag>...</tag>

Aşağıdaki örnekte, şablonlu Razor temsilci olarak belirtmek verilmektedir bir Func<T,TResult>.
Dinamik tür temsilci kapsülleyen yönteminin parametresi için belirtilir. Bir nesne türü temsilcinin dönüş
değeri olarak belirtilir. Şablon ile kullanılan bir List<T> , Pet olan bir Name özelliği.

public class Pet


{
public string Name { get; set; }
}

@{
Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

var pets = new List<Pet>


{
new Pet { Name = "Rin Tin Tin" },
new Pet { Name = "Mr. Bigglesworth" },
new Pet { Name = "K-9" }
};
}

Şablon ile işlenen pets tarafından sağlanan bir foreach deyimi:

@foreach (var pet in pets)


{
@petTemplate(pet)
}

İşlenmiş çıkışı:

<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>


<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

Bir yöntem bağımsız değişkeni olarak bir satır içi Razor şablonu da sağlayabilirsiniz. Aşağıdaki örnekte,
Repeat yöntem Razor şablonu alır. Yöntemi, HTML içerik ile sağlanan bir listeden öğeleri yineler
üretmek için şablonu kullanır:
@using Microsoft.AspNetCore.Html

@functions {
public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
Func<dynamic, IHtmlContent> template)
{
var html = new HtmlContentBuilder();

foreach (var item in items)


{
for (var i = 0; i < times; i++)
{
html.AppendHtml(template(item));
}
}

return html;
}
}

Önceki örnekte, Evcil Hayvanlar listesi kullanarak Repeat yöntemi çağrıldığında:


List<T> ' ın Pet .
Her evcil hayvan yineleme sayısı.
Satır içi şablon sırasız bir listesini liste öğeleri için kullanın.

<ul>
@Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

İşlenmiş çıkışı:

<ul>
<li>Rin Tin Tin</li>
<li>Rin Tin Tin</li>
<li>Rin Tin Tin</li>
<li>Mr. Bigglesworth</li>
<li>Mr. Bigglesworth</li>
<li>Mr. Bigglesworth</li>
<li>K-9</li>
<li>K-9</li>
<li>K-9</li>
</ul>

Etiket Yardımcıları
Bu senaryo yalnızca MVC görünümleri ve Razor Pages (. cshtml) için geçerlidir.
İlgili üç yönergeleri vardır etiket Yardımcıları.

YÖNERGESI İŞLEV

@addTagHelper Etiket Yardımcıları bir görünüm için kullanılabilir hale


getirir.

@removeTagHelper Daha önce bir görünümden eklenen etiket Yardımcıları


kaldırır.
YÖNERGESI İŞLEV

@tagHelperPrefix Etiket Yardımcısı desteğinin etkinleştirmek ve etiket


Yardımcısı kullanım açık hale getirmek için bir etiket
öneki belirtir.

Razor ayrılmış anahtar sözcükler


Razor anahtar sözcükleri
sayfa (ASP.NET Core 2,1 veya üzeri bir sürüm gerektirir)
ad alanı
işlevleri
Devralan
{1>model<1}
section
yardımcı (şu anda ASP.NET Core tarafından desteklenmez)
Razor anahtar sözcükleri kaçış ile @(Razor Keyword) (örneğin, @(functions) ).
C#Razor anahtar sözcükleri
büyük/küçük harf
do
{1>default<1}
for
foreach
if
else
lock
anahtarı
deneyin
Yakalama
finally
kullanma
while
C#Razor anahtar sözcükleri çift kaçış ile olmalıdır @(@C# Razor Keyword) (örneğin, @(@case) ). İlk @
Razor ayrıştırıcısı atlar. İkinci @ çıkışları C# ayrıştırıcı.
Razor tarafından kullanılmayan ayrılmış anahtar sözcükler
sınıf

Razor İnceleme C# bir görünümü için oluşturulan sınıfı


.NET Core SDK'sını 2.1 veya daha sonra Razor SDK derleme Razor dosyaları işler. Bir proje derlenirken
Razor SDK'sı oluşturur bir obj / < build_configuration > / < target_framework_moniker > / Razor
proje kök dizini. Dizin yapısında Razor dizini proje dizin yapısına yansıtır.
.NET Core 2.1 hedefleyen ASP.NET Core 2.1 Razor sayfaları projesinde aşağıdaki dizin yapısını göz
önünde bulundurun:
Alanlar /
Yönetim /
Sayfa /
Index.cshtml
Index.cshtml.cs
Sayfa /
Paylaşılan /
_Layout.cshtml
_Viewımports.cshtml
_ViewStart.cshtml
Index.cshtml
Index.cshtml.cs
Projenin oluşturulmasında hata ayıklama yapılandırma aşağıdaki verir obj dizini:
obj /
Hata ayıklama /
netcoreapp2.1 /
Razor /
Alanlar /
Yönetim /
Sayfa /
Index.g.cshtml.cs
Sayfa /
Paylaşılan /
_Layout.g.cshtml.cs
_ViewImports.g.cshtml.cs
_ViewStart.g.cshtml.cs
Index.g.cshtml.cs
Oluşturulan sınıf için görüntülenecek Pages/Index.cshtmlaçın
obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs.
Aşağıdaki sınıf, ASP.NET Core MVC projeye ekleyin:

using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;

public class CustomTemplateEngine : MvcRazorTemplateEngine


{
public CustomTemplateEngine(RazorEngine engine, RazorProject project)
: base(engine, project)
{
}

public override RazorCSharpDocument GenerateCode(RazorCodeDocument codeDocument)


{
var csharpDocument = base.GenerateCode(codeDocument);
var generatedCode = csharpDocument.GeneratedCode;

// Look at generatedCode

return csharpDocument;
}
}
İçinde Startup.ConfigureServices , geçersiz kılma RazorTemplateEngine ile MVC tarafından eklenen
CustomTemplateEngine sınıfı:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc();
services.AddSingleton<RazorTemplateEngine, CustomTemplateEngine>();
}

Bir kesme noktası ayarlamak return csharpDocument; deyiminin CustomTemplateEngine . Program


yürütme kesme noktasında durduğunda değerini görüntülemek generatedCode .

Görünüm aramaları ve büyük/küçük harfe duyarlılık


Razor görüntüleme motorunu büyük küçük harfe duyarlı aramalar, görünümler için gerçekleştirir.
Ancak, gerçek arama, temel alınan dosya sistemi tarafından belirlenir:
Dosya tabanlı kaynağı:
Büyük küçük harfe duyarlı dosya sistemleri (örneğin, Windows) ile işletim sistemlerinde,
fiziksel dosya sağlayıcısı aramaları büyük küçük harfe duyarlı. Örneğin, return View("Test")
eşleşmelerini sonuçlanıyor /Views/Home/Test.cshtml, /Views/home/test.cshtmlve diğer
büyük/küçük harf değişken.
Büyük küçük harfe duyarlı dosya sistemlerindeki (örneğin, Linux, OSX ile
EmbeddedFileProvider ), büyük küçük harfe duyarlı aramalar. Örneğin, return View("Test")
özellikle eşleşen /Views/Home/Test.cshtml.
Görünümleri önceden derlenmiş: ASP.NET Core 2.0 ve sonraki sürümleri, önceden derlenmiş
görünümleri arama büyük/küçük harf tüm işletim sistemlerinde büyük harflere duyarlı değildir.
Davranış Windows fiziksel dosya Sağlayıcısı'nın davranış aynıdır. Önceden derlenmiş iki görünüm
yalnızca durumda farklıysa, arama sonucu belirleyici değildir.
Geliştiriciler, dosya ve dizin adlarını büyük küçük harfleri büyük/küçük harf eşleşmesi için önerilir:
Alan, denetleyici ve eylem adları.
Razor sayfaları.
Eşleşen servis talebi, temel alınan dosya sisteminden bağımsız olarak kendi görünümler dağıtımları Bul
sağlar.
ASP.NET Core 'de Razor Sınıf Kitaplığı projesini
kullanarak yeniden kullanılabilir kullanıcı arabirimi
oluşturma
29.10.2019 • 17 minutes to read • Edit Online

Rick Anderson tarafından


Razor görünümleri, sayfalar, denetleyiciler, sayfa modelleri,Razor bileşenleri, Görünüm bileşenlerive veri
modelleri Razor sınıf kitaplığı 'nda (RCL ) yerleşik olarak bulunabilir. RCL paketlenebilir ve yeniden
kullanılabilir. Uygulamalar RCL 'yi içerebilir ve içerdiği görünümleri ve sayfaları geçersiz kılabilir. Hem Web
uygulamasında hem de RCL 'de bir görünüm, kısmi görünüm veya Razor sayfası bulunduğunda, Web
uygulamasındaki Razor biçimlendirmesi ( . cshtml dosyası) önceliklidir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Razor Kullanıcı arabirimi içeren bir sınıf kitaplığı oluşturma


Visual Studio
.NET Core CLI
Visual Studio 'dan Yeni bir proje oluştur' u seçin.
Razor sınıfı kitaplığı > İleri ' yiseçin.
Kitaplığı adlandırın (örneğin, "RazorClassLib"), > Oluştur. Oluşturulan görünüm kitaplığıyla bir dosya adı
çarpışmasını önlemek için, kitaplık adının .Views ' da bitmediğinden emin olun.
Görünümleri desteketmeniz gerekiyorsa destek sayfaları ve görünümleri ' ni seçin. Varsayılan olarak
yalnızca Razor Pages desteklenir. Oluştur' u seçin.
Razor sınıf kitaplığı (RCL ) şablonu varsayılan olarak Razor bileşen geliştirmeyi varsayılan olarak belirler.
Destek sayfaları ve görünümleri seçeneği sayfaları ve görünümleri destekler.
RCL 'ye Razor dosyaları ekleyin.
ASP.NET Core şablonları RCL içeriğinin Areas klasöründe olduğunu varsayar. ~/Areas/Pages yerine ~/Pages
içeriği kullanıma sunan bir RCL oluşturmak için RCL Pages düzenine bakın.

RCL içeriğine başvur


RCL 'ye şu şekilde başvurulabilir:
NuGet paketi. Bkz. NuGet paketleri oluşturma ve DotNet paket ekleme ve bir NuGet paketi oluşturma ve
yayımlama.
{ProjectName}. csproj. Bkz. DotNet-başvuru Ekle.

Görünümleri, kısmi görünümleri ve sayfaları geçersiz kıl


Hem Web uygulamasında hem de RCL 'de bir görünüm, kısmi görünüm veya Razor sayfası bulunduğunda,
Web uygulamasındaki Razor biçimlendirmesi ( . cshtml dosyası) önceliklidir. Örneğin,
WebApp1/Areas/MyFeature/Pages/Sayfa1. cshtml öğesini WebApp1 öğesine ekleyin ve WebApp1 içindeki
Sayfa1, RCL 'deki Sayfa1 'e göre öncelikli olur.
Örnek indirme içinde WebApp1/Areas/MyFeature2 öğesini WebApp1/Areas/myfeature olarak yeniden
adlandırın ve test önceliğini belirtin.
RazorUIClassLib/Areas/myfeature/Pages/Shared/_Message. cshtml kısmi görünümünü
WebApp1/Areas/Myfeature/Pages/Shared/_Message. cshtml'ye kopyalayın. Biçimlendirmeyi yeni konumu
belirtecek şekilde güncelleştirin. Uygulamanın kısmi sürümünün kullanılmakta olduğunu doğrulamak için
uygulamayı derleyin ve çalıştırın.
RCL sayfaları düzeni
RCL içeriğine, Web uygulamasının Sayfalar klasörünün bir parçası olmasına rağmen başvurmak için,
aşağıdaki dosya yapısıyla RCL projesini oluşturun:
RazorUIClassLib/sayfalar
RazorUIClassLib/sayfalar/paylaşılan
RazorUIClassLib/Pages/Shared iki kısmi dosya Içerir: _header. cshtml ve _footer. cshtml. <partial> Etiketler
_Layout. cshtml dosyasına eklenebilir:

<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>

Statik varlıklar içeren bir RCL oluşturma


RCL, RCL 'nin tüketen uygulaması tarafından başvurulabilen, yardımcı statik varlıklar gerektirebilir. ASP.NET
Core, tüketen bir uygulama tarafından kullanılabilen statik varlıkları içeren RCLs oluşturulmasına izin verir.
Yardımcı varlıkları RCL 'nin bir parçası olarak dahil etmek için, sınıf kitaplığında bir Wwwroot klasörü
oluşturun ve gerekli dosyaları bu klasöre ekleyin.
RCL 'yi paketleyerek, Wwwroot klasöründeki tüm yardımcı varlıklar pakete otomatik olarak eklenir.
Statik varlıkları hariç tut
Statik varlıkları dışlamak için, istenen dışlama yolunu proje dosyasındaki $(DefaultItemExcludes) özellik
grubuna ekleyin. Girişleri noktalı virgülle ayırın ( ; ).
Aşağıdaki örnekte, Wwwroot klasöründeki lib. css stil sayfası statik bir varlık olarak değerlendirilmez ve
yayımlanan RCL 'ye dahil değildir:

<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>

TypeScript tümleştirmesi
TypeScript dosyalarını RCL 'ye eklemek için:
1. TypeScript dosyalarını ( . TS ) Wwwroot klasörünün dışına yerleştirin. Örneğin, dosyaları bir istemci
klasörüne yerleştirin.
2. Wwwroot klasörü için TypeScript derleme çıkışını yapılandırın. Proje dosyasında bir PropertyGroup
içinde TypescriptOutDir özelliğini ayarlayın:

<TypescriptOutDir>wwwroot</TypescriptOutDir>
3. Proje dosyasında bir PropertyGroupiçine aşağıdaki hedefi ekleyerek TypeScript hedefini
ResolveCurrentProjectStaticWebAssets hedefinin bir bağımlılığı olarak ekleyin:

<ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
CompileTypeScript;
$(ResolveCurrentProjectStaticWebAssetsInputs)
</ResolveCurrentProjectStaticWebAssetsInputsDependsOn>

Başvurulan bir RCL 'den içerik tüketme


RCL 'nin Wwwroot klasörüne eklenen dosyalar, _content/{LIBRARY NAME}/ önek altında tüketen uygulamaya
sunulur. Örneğin, Razor. Class. lib adlı bir kitaplık _content/Razor.Class.Lib/ statik içerik yolu ile sonuçlanır.
Kullanan uygulama, kitaplık tarafından <script> , <style> , <img> ve diğer HTML etiketleriyle sunulan statik
varlıklara başvurur. Tüketim uygulaması Startup.Configure ' de statik dosya desteğinin etkin olması gerekir:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
...

app.UseStaticFiles();

...
}

Yapı çıktısından tüketen uygulamayı çalıştırırken ( dotnet run ), statik Web varlıkları geliştirme ortamında
varsayılan olarak etkindir. Derleme çıktılarından çalışırken diğer ortamlardaki varlıkları desteklemek için,
program.cs' deki konak oluşturucusu 'nda UseStaticWebAssets ' ı çağırın:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

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.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
});
}

Yayımlanan çıktıdan bir uygulama çalıştırılırken çağrı UseStaticWebAssets gerekmez ( dotnet publish ).
Çoklu projeli geliştirme akışı
Kullanan uygulama şu şekilde çalışır:
RCL içindeki varlıklar özgün klasörlerinde kalır. Varlıklar, tüketim uygulamasına taşınmaz.
RCL 'nin Wwwroot klasörü içindeki tüm değişiklikler, RCL yeniden oluşturulduktan ve tüketen uygulamayı
yeniden oluşturmadan önce tüketen uygulamaya yansıtılır.
RCL yapılandırıldığında, statik Web varlık konumlarını açıklayan bir bildirim oluşturulur. Tüketen uygulama,
başvurulan proje ve paketlerden varlıkları kullanmak için çalışma zamanında bildirimi okur. Bir RCL 'ye yeni bir
varlık eklendiğinde, bir uygulamanın yeni varlığa erişebilmesi için bildirim güncellemek üzere RCL 'nin
yeniden oluşturulması gerekir.
Yayınlamanız
Uygulama yayımlandığında, tüm başvurulan projeler ve paketlerin yardımcı varlıkları
_content/{LIBRARY NAME}/ altında Yayınlanan uygulamanın Wwwroot klasörüne kopyalanır.

Razor görünümleri, sayfalar, denetleyiciler, sayfa modelleri,Razor bileşenleri, Görünüm bileşenlerive veri
modelleri Razor sınıf kitaplığı 'nda (RCL ) yerleşik olarak bulunabilir. RCL paketlenebilir ve yeniden
kullanılabilir. Uygulamalar RCL 'yi içerebilir ve içerdiği görünümleri ve sayfaları geçersiz kılabilir. Hem Web
uygulamasında hem de RCL 'de bir görünüm, kısmi görünüm veya Razor sayfası bulunduğunda, Web
uygulamasındaki Razor biçimlendirmesi ( . cshtml dosyası) önceliklidir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Razor Kullanıcı arabirimi içeren bir sınıf kitaplığı oluşturma


Visual Studio
.NET Core CLI
Visual Studio Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması' nı seçin.
Kitaplığı adlandırın (örneğin, "RazorClassLib") > Tamam. Oluşturulan görünüm kitaplığıyla bir dosya adı
çarpışmasını önlemek için, kitaplık adının .Views ' da bitmediğinden emin olun.
ASP.NET Core 2,1 veya sonraki bir sürümü seçildiğini doğrulayın.
Razor sınıfı kitaplığı > Tamam ' ıseçin.
RCL aşağıdaki proje dosyasına sahiptir:

<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
</ItemGroup>

</Project>

RCL 'ye Razor dosyaları ekleyin.


ASP.NET Core şablonları RCL içeriğinin Areas klasöründe olduğunu varsayar. ~/Areas/Pages yerine ~/Pages
içeriği kullanıma sunan bir RCL oluşturmak için RCL Pages düzenine bakın.

RCL içeriğine başvur


RCL 'ye şu şekilde başvurulabilir:
NuGet paketi. Bkz. NuGet paketleri oluşturma ve DotNet paket ekleme ve bir NuGet paketi oluşturma ve
yayımlama.
{ProjectName}. csproj. Bkz. DotNet-başvuru Ekle.

İzlenecek yol: bir Razor Pages projesinden bir RCL projesi oluşturma
ve kullanma
Tüm projeyi indirebilir ve oluşturmak yerine test edebilirsiniz. Örnek indirme, projenin test olmasını
kolaylaştıran ek kod ve bağlantılar içerir. Yükleme örnekleri ve adım adım yönergeler hakkındaki
açıklamalarınızla Bu GitHub sorunuyla ilgili geri bildirimde bulunun.
İndirme uygulamasını test etme
Tamamlanmış uygulamayı indirmediyseniz ve gözden geçirme projesi oluşturmak istiyorsanız, sonraki
bölümeatlayın.
Visual Studio
.NET Core CLI
Visual Studio 'da . sln dosyasını açın. Uygulamayı çalıştırın.
Test WebApp1 içindeki yönergeleri izleyin

RCL oluşturma
Bu bölümde bir RCL oluşturulur. Razor dosyaları RCL 'ye eklenir.
Visual Studio
.NET Core CLI
RCL projesini oluşturun:
Visual Studio Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması' nı seçin.
> Tamam, uygulamayı RazorUIClassLib olarak adlandırın.
ASP.NET Core 2,1 veya sonraki bir sürümü seçildiğini doğrulayın.
Razor sınıfı kitaplığı > Tamam ' ıseçin.
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message. cshtmladlı bir Razor kısmi görünüm dosyası
ekleyin.
Projeye Razor dosyaları ve klasörleri ekleme
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message. cshtml içindeki biçimlendirmeyi aşağıdaki
kodla değiştirin:

<h3>_Message.cshtml partial view.</h3>

<p>RazorUIClassLib\Areas\MyFeature\Pages\Shared\_Message.cshtml</p>

RazorUIClassLib/Areas/MyFeature/Pages/Sayfa1. cshtml içindeki biçimlendirmeyi aşağıdaki kodla


değiştirin:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h2>Hello from a Razor UI class library!</h2>


<p> From RazorUIClassLib\Areas\MyFeature\Pages\Page1.cshtml</p>

<partial name="_Message" />

kısmi görünümü kullanmak için @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers gereklidir (


<partial name="_Message" /> ). @addTagHelper yönergesini dahil etmek yerine, _Viewwimports. cshtml
dosyası ekleyebilirsiniz. Örneğin:

dotnet new viewimports -o RazorUIClassLib/Areas/MyFeature/Pages

_Viewwimports. cshtmlhakkında daha fazla bilgi için bkz. paylaşılan yönergeleri içeri aktarma
Derleyici hatası olmadığını doğrulamak için sınıf kitaplığı oluşturun:

dotnet build RazorUIClassLib

Derleme çıkışı RazorUIClassLib. dll ve RazorUIClassLib. views. dlliçerir. RazorUIClassLib. views. dll derlenen
Razor içeriğini içerir.
Razor Pages projesinden Razor Kullanıcı arabirimi kitaplığını kullanma
Visual Studio
.NET Core CLI
Razor Pages Web uygulaması oluşturun:
Çözüm Gezgini>yeni proje eklemek > çözüme sağ tıklayın.
ASP.NET Core Web uygulaması' nı seçin.
Uygulamayı WebApp1olarak adlandırın.
ASP.NET Core 2,1 veya sonraki bir sürümü seçildiğini doğrulayın.
Web uygulaması > Tamam ' ıseçin.
Çözüm Gezgini, WebApp1 ' ye sağ tıklayın ve Başlangıç projesi olarak ayarla' yı seçin.
Çözüm Gezgini, WebApp1 ' ye sağ tıklayın ve derleme bağımlılıkları > Proje bağımlılıkları' nı
seçin.
WebApp1'in bağımlılığı olarak RazorUIClassLib denetleyin.
Çözüm Gezgini, WebApp1 ' a sağ tıklayıp > başvurusu Ekle ' yi seçin.
Başvuru Yöneticisi Iletişim kutusunda RazorUIClassLib > Tamam' ı işaretleyin.
Uygulamayı çalıştırın.
Test WebApp1
Razor UI sınıfı kitaplığının kullanımda olduğunu doğrulamak için /MyFeature/Page1 ' a gidin.

Görünümleri, kısmi görünümleri ve sayfaları geçersiz kıl


Hem Web uygulamasında hem de RCL 'de bir görünüm, kısmi görünüm veya Razor sayfası bulunduğunda,
Web uygulamasındaki Razor biçimlendirmesi ( . cshtml dosyası) önceliklidir. Örneğin,
WebApp1/Areas/MyFeature/Pages/Sayfa1. cshtml öğesini WebApp1 öğesine ekleyin ve WebApp1 içindeki
Sayfa1, RCL 'deki Sayfa1 'e göre öncelikli olur.
Örnek indirme içinde WebApp1/Areas/MyFeature2 öğesini WebApp1/Areas/myfeature olarak yeniden
adlandırın ve test önceliğini belirtin.
RazorUIClassLib/Areas/myfeature/Pages/Shared/_Message. cshtml kısmi görünümünü
WebApp1/Areas/Myfeature/Pages/Shared/_Message. cshtml'ye kopyalayın. Biçimlendirmeyi yeni konumu
belirtecek şekilde güncelleştirin. Uygulamanın kısmi sürümünün kullanılmakta olduğunu doğrulamak için
uygulamayı derleyin ve çalıştırın.
RCL sayfaları düzeni
RCL içeriğine, Web uygulamasının Sayfalar klasörünün bir parçası olmasına rağmen başvurmak için,
aşağıdaki dosya yapısıyla RCL projesini oluşturun:
RazorUIClassLib/sayfalar
RazorUIClassLib/sayfalar/paylaşılan
RazorUIClassLib/Pages/Shared iki kısmi dosya Içerir: _header. cshtml ve _footer. cshtml. <partial> Etiketler
_Layout. cshtml dosyasına eklenebilir:

<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
ASP.NET Core yerleşik etiket Yardımcıları
12.07.2019 • 2 minutes to read • Edit Online

Tarafından Peter Kellner


Etiket Yardımcıları genel bakış için bkz. ASP.NET Core etiket yardımcıları.
Bu belgede listelenen olmayan yerleşik etiket Yardımcıları vardır. Listelenmemiş etiket Yardımcıları tarafından
dahili olarak kullanılan Razor görünüm altyapısı. Etiket Yardımcıları ~ (tilde) karakteridir listeden kaldırıldı. Tilde
işareti etiketi Yardımcısı Web sitesinin kök yolunu genişletir.

Yerleşik ASP.NET Core etiket yardımcıları


Tutturucu etiketi Yardımcısı
Önbellek etiketi Yardımcısı
Dağıtılmış önbellek etiketi Yardımcısı
Ortam etiketi Yardımcısı
Form etiketi Yardımcısı
Form eylemi etiketi Yardımcısı
Resim etiketi Yardımcısı
Giriş etiketi Yardımcısı
Etiket etiketi Yardımcısı
Bağlantı etiketi Yardımcısı
Kısmi etiket Yardımcısı
Betik etiketi Yardımcısı
Etiket yardımcısını seçin
TextArea etiketi Yardımcısı
Doğrulama Iletisi etiketi Yardımcısı
Doğrulama Özeti etiketi Yardımcısı

Ek kaynaklar
ASP.NET Core etiket yardımcıları
ASP.NET Core içindeki etiket Yardımcısı bileşenleri
ASP.NET Core etiket yardımcıları
26.11.2019 • 21 minutes to read • Edit Online

Rick Anderson tarafından

Etiket Yardımcıları nelerdir


Etiket Yardımcıları, Razor dosyalarında HTML öğeleri oluşturma ve işlemeye
katılmak için sunucu tarafı kodu etkinleştirir. Örneğin, yerleşik ImageTagHelper
görüntü adına bir sürüm numarası ekleyebilir. Görüntü her değiştiğinde,
sunucu görüntü için yeni bir benzersiz sürüm oluşturur, bu nedenle
istemcilerin geçerli görüntüyü alma garantisi vardır (eski önbelleğe alınmış bir
görüntü yerine). Yaygın görevler için, genel GitHub depolarında ve NuGet
paketleri olarak formlar, bağlantılar, yükleme varlıkları ve daha fazlasını ve
daha fazlasını oluşturma gibi birçok yerleşik etiket yardımcıları vardır. Etiket
Yardımcıları ' de C#yazılır ve öğe adı, öznitelik adı veya üst etıkete göre HTML
öğelerini hedefleyin. Örneğin, LabelTagHelper öznitelikleri uygulandığında
yerleşik LabelTagHelper HTML <label> öğesini hedefleyebilir. HTML
Yardımcılarıhakkında bilginiz varsa, ETIKET yardımcıları HTML ve C# Razor
görünümlerinde açık geçişleri azaltır. Birçok durumda, HTML Yardımcıları
belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için
bir etiket Yardımcısı olmadığını bilmek önemlidir. HTML yardımcılarına kıyasla
etiket yardımcıları daha ayrıntılı olarak açıklanır.

Hangi etiket yardımcıları sağlar


HTML kullanımı kolay bir geliştirme deneyimi Çoğu bölümde, etiket
yardımcıları kullanan Razor işaretlemesi standart HTML gibi görünür. Ön uç
tasarımcıları HTML/CSS/JavaScript ile iletişim Razor söz dizimi, öğrenmeden
C# Razor 'yi düzenleyebilir.
HTML ve Razor biçimlendirmesi oluşturmak için zengin bir
IntelliSense ortamı Bu, daha önceki bir deyişle, Razor görünümlerinde,
sunucu tarafı biçimlendirme oluşturmaya yönelik önceki yaklaşım olan HTML
yardımcılarından daha keskin karşıtlığa sahiptir. HTML yardımcılarına kıyasla
etiket yardımcıları daha ayrıntılı olarak açıklanır. Etiket Yardımcıları Için
IntelliSense desteği , IntelliSense ortamını açıklar. Razor C# söz dizimi ile
karşılaşılan geliştiriciler, Razor Işaretlemesi yazmadan C# etiket yardımcıları
kullanılarak daha üretken olmanızı sağlar.
Daha üretken olmanızı sağlamak ve yalnızca sunucuda bulunan
bilgileri kullanarak daha sağlam, güvenilir ve sürdürülebilir kodlar
elde etmek Için bir yol Örneğin, geçmişe dönük olarak görüntülerin
güncelleştirilmesi, görüntüyü değiştirdiğinizde görüntünün adını değiştiriydi.
Görüntülerin performans nedenleriyle bir şekilde ön belleğe alınması gerekir
ve bir görüntünün adını değiştirmediğiniz takdirde, istemcilerin eski bir kopya
alıyor olması risklidir. Tarihsel olarak, bir görüntü düzenlendikten sonra ad
değiştirilmelidir ve Web uygulamasındaki görüntünün güncellenmesi için
gereken her başvuru. Bu çok işçiliği yoğun bir şekilde değil, bu da hataya
açıktır (bir başvuruyu kaçırmanızı, yanlışlıkla yanlış dize girmeniz vb.) Yerleşik
ImageTagHelper bunu sizin için otomatik olarak yapabilir. ImageTagHelper
görüntü adına bir sürüm numarası ekleyebilir, böylece görüntü her
değiştiğinde sunucu otomatik olarak görüntü için yeni bir benzersiz sürüm
oluşturur. İstemcilerin geçerli görüntüyü alması garanti edilir. Bu sağlamlık ve
işgücü tasarrufları ImageTagHelper kullanılarak ücretsizdir.
Çoğu yerleşik etiket yardımcıları standart HTML öğelerini hedefleyin ve öğesi
için sunucu tarafı öznitelikleri sağlar. Örneğin, Görünümler/hesap
klasöründeki birçok görünümde kullanılan <input> öğesi asp-for
özniteliğini içerir. Bu öznitelik, belirtilen model özelliğinin adını işlenmiş
HTML içine ayıklar. Aşağıdaki modelle bir Razor görünümü göz önünde
bulundurun:

public class Movie


{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}

Aşağıdaki Razor biçimlendirmesi:

<label asp-for="Movie.Title"></label>

Aşağıdaki HTML 'yi oluşturur:

<label for="Movie_Title">Title</label>

asp-for özniteliği Labeltaghelper'daki For özelliği tarafından kullanılabilir


hale getirilir. Daha fazla bilgi için bkz. Yazar etiketi yardımcıları .

Etiket Yardımcısı kapsamını yönetme


Etiket Yardımcıları kapsamı, @addTagHelper , @removeTagHelper ve "!" geri
çevirme karakterinin bir birleşimi tarafından denetlenir.
@addTagHelper etiket yardımcıları kullanılabilir hale getirir
Authoringtaghelmakaadıadlı yeni bir ASP.NET Core Web uygulaması
oluşturursanız, projenize aşağıdaki Görünümler/_ViewImports. cshtml dosyası
eklenecektir:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AuthoringTagHelpers

@addTagHelper yönergesi, etiket yardımcılarını görünüm için kullanılabilir hale


getirir. Bu durumda, görünüm dosyası sayfalar /_ViewImports. cshtml'dir ve
varsayılan olarak Sayfalar klasörü ve alt klasörlerdeki tüm dosyalar tarafından
devralınır. Etiket Yardımcıları kullanılabilir hale getirme. Yukarıdaki kod,
belirtilen derlemedeki tüm etiket yardımcılarını (Microsoft. AspNetCore. Mvc.
Taghelmakat), Görünümler dizinindeki veya alt dizininde bulunan her
görünüm dosyası için kullanılabilir olacağını belirtmek için joker karakter söz
dizimini ("*") kullanır. @addTagHelper sonraki ilk parametre, yüklenecek etiket
yardımcıları (tüm etiket yardımcıları için "*" kullanıyoruz) ve ikinci parametre
olan "Microsoft. AspNetCore. Mvc. Taghelmakat", etiket yardımcıları içeren
derlemeyi belirtir. Microsoft. AspNetCore. Mvc. Taghelmakatem , yerleşik
ASP.NET Core etiket yardımcıları için derlemedir.
Bu projedeki tüm etiket yardımcılarını ortaya çıkarmak için (
Authoringtaghelmakatıadlı bir derleme oluşturur), aşağıdakileri kullanın:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AuthoringTagHelpers

Projeniz varsayılan ad alanı ( AuthoringTagHelpers.TagHelpers.EmailTagHelper )


ile bir EmailTagHelper içeriyorsa, etiket yardımcısından tam nitelikli adı (FQN )
sağlayabilirsiniz:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper AuthoringTagHelpers.TagHelpers.EmailTagHelper,
AuthoringTagHelpers

Bir FQN kullanarak bir görünüme etiket Yardımcısı eklemek için, önce FQN (
AuthoringTagHelpers.TagHelpers.EmailTagHelper ) ve ardından derleme adı
(Authoringtaghelmakaı) eklersiniz. Çoğu geliştirici, "*" joker sözdizimini
kullanmayı tercih eder. Joker karakter sözdizimi, bir FQN içinde sonek olarak
"*" joker karakterini eklemenizi sağlar. Örneğin, aşağıdaki yönergelerden
herhangi biri EmailTagHelper alınacaktır:

@addTagHelper AuthoringTagHelpers.TagHelpers.E*, AuthoringTagHelpers


@addTagHelper AuthoringTagHelpers.TagHelpers.Email*, AuthoringTagHelpers

Daha önce belirtildiği gibi, views/_ViewImports. cshtml dosyasına


@addTagHelper yönergesini eklemek, etiket Yardımcısı ' nı Görünümler
dizinindeki ve alt dizinlerindeki tüm görünüm dosyaları için kullanılabilir hale
getirir. Etiket yardımcısını yalnızca bu görünümlerde kullanıma sunmak
istiyorsanız, belirli görünüm dosyalarında @addTagHelper yönergesini
kullanabilirsiniz.
@removeTagHelper etiket yardımcıları kaldırır
@removeTagHelper @addTagHelper aynı iki parametreye sahiptir ve daha önce
eklenmiş bir etiket yardımcısını kaldırır. Örneğin, belirli bir görünüme
uygulanan @removeTagHelper , belirtilen etiket yardımcısını görünümden
kaldırır. Bir views/Folder/_ViewImports. cshtml dosyasında @removeTagHelper
kullanmak, belirtilen etiket yardımcısını klasördekitüm görünümlerden
kaldırır.
Etiket Yardımcısı kapsamını _ViewImports. cshtml dosyası ile denetleme
Herhangi bir görünüm klasörüne _ViewImports. cshtml ekleyebilirsiniz ve
Görünüm altyapısı, bu dosya ve Görünümler/_ViewImports. cshtml
dosyasından yönergeleri uygular. Giriş görünümleri için boş bir
Görünümler/Home/_ViewImports. cshtml dosyası eklediyseniz, _ViewImports.
cshtml dosyası eklenebilir olduğundan hiçbir değişiklik olmaz.
Görünümler/Home/_ViewImports. cshtml dosyasına eklediğiniz (varsayılan
görünümlerde/_ViewImports. cshtml dosyasında olmayan) tüm
@addTagHelper yönergeleri, bu etiket yardımcılarını yalnızca giriş klasöründeki
görünümlerde kullanıma sunar.
Ayrı öğelerin dışında tutma
Etiket Yardımcısı geri çevirme karakteriyle ("!") birlikte öğe düzeyinde bir
etiket yardımcısını devre dışı bırakabilirsiniz. Örneğin, Email doğrulaması
etiket Yardımcısı geri çevirme karakteriyle <span> devre dışı bırakılır:

<!span asp-validation-for="Email" class="text-danger"></!span>

Açılış ve kapanış etiketine etiket Yardımcısı geri çevirme karakterini


uygulamanız gerekir. (Açılış etiketine bir tane eklediğinizde, Visual Studio
Düzenleyicisi, kapatma etiketine otomatik olarak bir kapanış karakteri ekler).
Kabul etme karakterini ekledikten sonra, öğe ve etiket Yardımcısı öznitelikleri
artık farklı bir yazı tipinde gösterilmez.
Etiket Yardımcısı kullanımını açık hale getirmek için @tagHelperPrefix kullanma
@tagHelperPrefix yönergesi etiket Yardımcısı desteğini etkinleştirmek ve
etiket Yardımcısı kullanımını açık hale getirmek için bir etiket öneki dizesi
belirtmenize olanak tanır. Örneğin, aşağıdaki biçimlendirmeyi
views/_ViewImports. cshtml dosyasına ekleyebilirsiniz:

@tagHelperPrefix th:

Aşağıdaki kod görüntüsünde, etiket Yardımcısı ön eki th: olarak ayarlanır. bu


nedenle, yalnızca ön th: eki kullanan öğeler etiket yardımcıları destekler
(etiket Yardımcısı etkin öğeleri farklı bir yazı tipine sahiptir). <label> ve
<input> öğeleri etiket Yardımcısı ön ekine sahiptir ve etiket Yardımcısı etkin,
ancak <span> öğesi değil.

@addTagHelper için uygulanan aynı hiyerarşi kuralları @tagHelperPrefix için de


geçerlidir.

Kendi kendine kapanan etiket yardımcıları


Birçok etiket yardımcıları, kendinden kapanış etiketleri olarak kullanılamaz.
Bazı etiket yardımcıları, kendinden kapanış etiketleri olacak şekilde
tasarlanmıştır. Kendi kendini kapatmak üzere tasarlanmamış bir etiket
Yardımcısı kullanılması işlenmiş çıktıyı bastırır. Bir etiket Yardımcısı kendinden
kapanış, işlenen çıktıda kendi kendine kapanan bir etikete neden olur. Daha
fazla bilgi için bkz. etiket yardımcılarını yazma.

C#Etiket Yardımcıları özniteliğinde/bildiriminde


Etiket Yardımcıları öğenin özniteliğinde veya C# etiket bildirim alanında izin
vermez. Örneğin, aşağıdaki kod geçerli değildir:

<input asp-for="LastName"
@(Model?.LicenseId == null ? "disabled" : string.Empty) />

Yukarıdaki kod şöyle yazılabilir:

<input asp-for="LastName"
disabled="@(Model?.LicenseId == null)" />

Etiket Yardımcıları için IntelliSense desteği


Visual Studio 'da yeni bir ASP.NET Core Web uygulaması oluşturduğunuzda,
"Microsoft. AspNetCore. Razor. Tools" NuGet paketini ekler. Bu, etiket
Yardımcısı araçları ekleyen pakettir.
Bir HTML <label> öğesi yazmayı düşünün. Visual Studio düzenleyicisinde
<l girdiğinizde, IntelliSense eşleşen öğeleri görüntüler:

Yalnızca HTML Yardımı edinmeyin ancak simgenin ("@" symbol with "< >"
altında ").

öğesi etiket yardımcıları tarafından hedeflenen şekilde tanımlar. Saf HTML


öğeleri ( fieldset gibi) "< >" simgesini görüntüler.
Saf HTML <label> etiketi, HTML etiketini (varsayılan Visual Studio renk
teması ile) bir kahverengi yazı tipinde, kırmızı olan özniteliklere ve öznitelik
değerlerini mavi olarak görüntüler.

<label girdikten sonra, IntelliSense kullanılabilen HTML/CSS özniteliklerini


ve etiket Yardımcısı 'nın hedeflenen özniteliklerini listeler:
IntelliSense deyimin tamamlanması, seçili değere sahip ifadeyi tamamlamak
için sekme tuşunu girmenizi sağlar:

Etiket Yardımcısı özniteliği girildiğinde, Tag ve Attribute yazı tipleri değişir.


Varsayılan Visual Studio "mavi" veya "hafif" renkli temasını kullanarak yazı tipi
kalın mor olur. "Koyu" temasını kullanıyorsanız, yazı tipi kalın deniz mavisi
olur. Bu belgedeki görüntüler varsayılan tema kullanılarak alınmıştır.

Visual Studio CompleteWord kısayolunu (Ctrl + Ara çubuğu), çift tırnak


işaretleri ("") içinde varsayılan değer olan ve artık ' de C#olduğu gibi, bir C#
sınıfta olacak şekilde girebilirsiniz. IntelliSense, sayfa modelindeki tüm
yöntemleri ve özellikleri görüntüler. Özellik türü ModelExpression olduğundan
Yöntemler ve özellikler kullanılabilir. Aşağıdaki görüntüde Register
görünümünü düzenledim, bu nedenle RegisterViewModel kullanılabilir.

IntelliSense, sayfada modelin kullanabileceği özellikleri ve yöntemleri listeler.


Zengin IntelliSense ortamı, CSS sınıfını seçmenize yardımcı olur:
HTML Yardımcıları ile karşılaştırılan etiket
yardımcıları
Etiket Yardımcıları Razor görünümlerinde HTML öğelerine iliştirirken, HTML
Yardımcıları Razor görünümlerinde HTML ile yöntemler olarak çağrılır. CSS
sınıfı "Caption" içeren bir HTML etiketi oluşturan aşağıdaki Razor
işaretlemesini göz önünde bulundurun:

@Html.Label("FirstName", "First Name:", new {@class="caption"})

At ( @ ) simgesi, Razor 'in kodun başlangıcı olduğunu söyler. Sonraki iki


parametre ("FirstName" ve "First Name:") dizelerdir, bu nedenle IntelliSense
yardımcı olamaz. Son bağımsız değişken:

new {@class="caption"}

Öznitelikleri temsil etmek için kullanılan anonim bir nesnedir. class ' de
C#ayrılmış bir anahtar sözcük olduğundan, bir sembol olarak @class=
yorumlama zorlamak C# için @ sembolünü kullanın (özellik adı). Bir ön uç
tasarımcısına (HTML/CSS/JavaScript 'e ve diğer istemci teknolojilerine
tanıdık ancak C# ve Razor hakkında bilgi sahibi olmayan bir kişiye), satırın
çoğu yabancı olur. Tüm satır, IntelliSense 'den yardım olmadan yazılmalıdır.
LabelTagHelper kullanarak, aynı biçimlendirme şöyle yazılabilir:

<label class="caption" asp-for="FirstName"></label>

Etiket yardımcı sürümünde, Visual Studio düzenleyicisinde <l girdiğinizde


IntelliSense eşleşen öğeleri görüntüler:

IntelliSense, tüm satırı yazmanıza yardımcı olur.


Aşağıdaki kod görüntüsünde, Visual Studio 'da bulunan ASP.NET 4.5. x MVC
şablonundan oluşturulan views/Account/Register. cshtml Razor görünümünün
form kısmı gösterilmektedir.
Visual Studio Düzenleyicisi gri bir C# arka plana sahip kodu görüntüler.
Örneğin, AntiForgeryToken HTML Yardımcısı:

@Html.AntiForgeryToken()

gri bir arka planla görüntülenir. Kayıt görünümündeki biçimlendirmenin çoğu


C#. Etiket Yardımcıları kullanarak eşdeğer yaklaşımla karşılaştırın:

Biçimlendirme çok daha temiz ve HTML Yardımcıları yaklaşımıyla daha kolay


okunabilir, düzenlenebilir ve korunur. C# Kod, sunucunun hakkında bilgi sahibi
olması gereken en düşük düzeyde azaltılır. Visual Studio Düzenleyicisi, bir
etiket Yardımcısı tarafından hedeflenen biçimlendirmeyi farklı bir yazı tipinde
görüntüler.
E -posta grubunu göz önünde bulundurun:
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>

"ASP -" özniteliklerinin her biri "e-posta" değerine sahiptir, ancak "e-posta" bir
dize değildir. Bu bağlamda, "e-posta" RegisterViewModel C# model ifadesi
özelliğidir.
Visual Studio Düzenleyicisi, kayıt formunun etiket Yardımcısı yaklaşımında
Tüm biçimlendirmeyi yazmanıza yardımcı olur, ancak Visual STUDIO, HTML
Yardımcıları yaklaşımında kodun çoğu için yardım vermez. Etiket Yardımcıları
Için IntelliSense desteği , Visual Studio düzenleyicisinde etiket yardımcıları ile
çalışma hakkında ayrıntılı bilgiler alır.

Web sunucusu denetimleriyle karşılaştırılan etiket


yardımcıları
Etiket Yardımcıları ilişkili oldukları öğeye sahip değil; yalnızca öğe ve
içerik işleme katılır. ASP.NET Web sunucusu denetimleri bir sayfada
bildirilmiştir ve çağrılır.
Web sunucusu denetimlerinde geliştirme ve hata ayıklama zor hale
getirmek için önemsiz olmayan bir yaşam döngüsü vardır.
Web sunucusu denetimleri, istemci denetimi kullanarak istemci Belge
Nesne Modeli (DOM ) öğelerine işlevsellik eklemenize olanak tanır.
Etiket yardımcıların DOM 'ı yok.
Web sunucusu denetimleri otomatik tarayıcı algılamayı içerir. Etiket
yardımcılarına tarayıcı bilgisi yok.
Birden çok etiket yardımcıları aynı öğe üzerinde işlem yapabilir (bkz.
etiket Yardımcısı çakışmalarını önleme ), genellikle Web sunucusu
denetimleri oluşturamazsınız.
Etiket Yardımcıları, kapsamında oldukları HTML öğelerinin etiketini ve
içeriğini değiştirebilir ancak sayfada başka bir şeyi doğrudan
değiştirmez. Web sunucusu denetimleri, daha az belirli bir kapsama
sahiptir ve Sayfanızın diğer bölümlerini etkileyen eylemler
gerçekleştirebilir; istenmeyen yan etkileri etkinleştirme.
Web sunucusu denetimleri, dizeleri nesnelere dönüştürmek için tür
dönüştürücüler kullanır. Etiket Yardımcıları sayesinde yerel olarak ' de
C#çalışır, bu nedenle tür dönüştürmesi yapmanız gerekmez.
Web sunucusu denetimleri, bileşenlerin ve denetimlerin çalışma
zamanı ve tasarım zamanı davranışını uygulamak için System.
ComponentModel kullanır. System.ComponentModel , öznitelik ve tür
dönüştürücüler uygulamak, veri kaynaklarına bağlama ve lisans
bileşenlerine yönelik temel sınıflar ve arabirimler içerir. Genellikle
TagHelper türeten ve TagHelper temel sınıftan türetilen yardımcıları
etiketleyerek, Process ve ProcessAsync yalnızca iki yöntem sunar.
Etiket Yardımcısı öğe yazı tipini özelleştirme
Yazı tipi ve renklendirmeyi araçlar > seçenekler > ortam > yazı tipi ve
renkler' de özelleştirebilirsiniz:

Yerleşik ASP.NET Core etiket yardımcıları


Tutturucu etiketi Yardımcısı
Önbellek etiketi Yardımcısı
Dağıtılmış önbellek etiketi Yardımcısı
Ortam etiketi Yardımcısı
Form etiketi Yardımcısı
Form eylemi etiketi Yardımcısı
Resim etiketi Yardımcısı
Giriş etiketi Yardımcısı
Etiket etiketi Yardımcısı
Bağlantı etiketi Yardımcısı
Kısmi etiket Yardımcısı
Betik etiketi Yardımcısı
Etiket yardımcısını seçin
TextArea etiketi Yardımcısı
Doğrulama Iletisi etiketi Yardımcısı
Doğrulama Özeti etiketi Yardımcısı
Ek kaynaklar
Yazar etiketi yardımcıları
Formlarla Çalışma
GitHub 'Daki Taghelpersamples , önyüklemeIle çalışmaya yönelik etiket
Yardımcısı örnekleri içerir.
ASP.NET core'da Yazar etiket Yardımcıları
6.12.2019 • 24 minutes to read • Edit Online

Tarafından Rick Anderson


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Etiket Yardımcıları ile çalışmaya başlama


Bu öğreticide programlama etiket Yardımcıları tanıtır. Etiket Yardımcıları giriş etiket Yardımcıları sağlayan
avantajlarına açıklar.
Etiket Yardımcısı uygulayan sınıf olan ITagHelper arabirimi. Etiket Yardımcısı geliştirdiğinizde, Bununla birlikte,
genellikle öğesinden türetilen TagHelper , yapmak için bunu erişmenizi Process yöntemi.
1. Adlı yeni bir ASP.NET Core projesi oluşturma AuthoringTagHelpers. Bu proje için kimlik doğrulaması
gerekmez.
2. Adlı etiket Yardımcıları tutmak için bir klasör oluşturun TagHelpers. TagHelpers klasördür değil gerekli,
ancak bunu makul bir kuraldır. Şimdi bazı basit etiket Yardımcıları yazmaya başlayalım.

En az bir etiketi Yardımcısı


Bu bölümde, bir e-posta etiketi güncelleştiren etiket Yardımcısı yazmaya. Örneğin:

<email>Support</email>

Sunucu, bizim e-posta etiketi Yardımcısı, biçimlendirme ve bunlar aşağıdaki şekilde dönüştürmek için kullanır:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Diğer bir deyişle, bir yer işareti etiketi, bu e-posta bağlantısı sağlar. Blog altyapısıdır ve yazma ve aynı etki alanı
için pazarlama desteği ve diğer kişiler için e-posta göndermek istiyorsanız bunu yapmak isteyebilirsiniz.
1. Aşağıdaki EmailTagHelper sınıfının TagHelpers klasör.

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;

namespace AuthoringTagHelpers.TagHelpers
{
public class EmailTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces <email> with <a> tag
}
}
}

Etiket Yardımcıları kök sınıf adı öğelerini hedefleyen bir adlandırma kuralını kullanın (eksi
TagHelper sınıf adı kısmı). Bu örnekte, kök adı EmailTagHelper olduğu e-posta, bu nedenle
<email> etiketi hedeflenecek. Bu adlandırma çoğu etiket Yardımcıları için çalışır, daha sonra bu
geçersiz kılma göstereceğiz.
EmailTagHelper Sınıf türetilir TagHelper . TagHelper SAX yöntemleri ve özellikleri etiket
Yardımcıları yazmak için.
Geçersiz kılınan Process yöntemi denetimleri etiketi Yardımcısı yürütüldüğünde yapar. TagHelper
Sınıfı zaman uyumsuz bir sürümü sağlar ( ProcessAsync ) aynı parametrelere sahip.
Bağlam parametresi Process (ve ProcessAsync ) geçerli HTML etiketinin yürütme ile ilgili bilgiler
içerir.
Çıkış parametresi Process (ve ProcessAsync ) bir HTML etiketi ve içerik oluşturmak için kullanılan
özgün kaynağını temsil eden bir durum bilgisi olan HTML öğesi içeriyor.
Bizim sınıf adı son eki olan TagHelper, olduğu değil gerekli, ancak bir en iyi yöntem kuralı dikkate
almıştır. Sınıf olarak bildirebilirsiniz:

public class Email : TagHelper

2. EmailTagHelper sınıfını tüm Razor görünümlerimize kullanılabilir hale getirmek için, addTagHelper
yönergesini views/_ViewImports. cshtml dosyasına ekleyin:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AuthoringTagHelpers

Yukarıdaki kod, bizim derlemedeki tüm etiket Yardımcıları kullanılabilir olacağını belirtmek için joker
karakter sözdizimini kullanır. Sonra ilk dize @addTagHelper yüklemek için etiket Yardımcısı belirtir (kullan
"*" tüm etiket Yardımcıları için), ve ikinci dize "AuthoringTagHelpers" etiketi Yardımcısı olan derlemeyi
belirtir. Ayrıca, ikinci satırın joker karakter söz dizimini kullanarak ASP.NET Core MVC etiket
yardımcılarına getirdiğine unutmayın (Bu yardımcılar etiket yardımcılarına girişbölümünde ele alınmıştır.)
Bu, etiket yardımcısını Razor görünümü için kullanılabilir hale getiren @addTagHelper yönergedir.
Alternatif olarak, aşağıda gösterildiği gibi bir etiket Yardımcısı'nın (FQN ) tam nitelikli ad sağlayabilirsiniz:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper AuthoringTagHelpers.TagHelpers.EmailTagHelper, AuthoringTagHelpers

FQN kullanarak bir görünüme bir etiket Yardımcısı eklemek için, önce FQN (
AuthoringTagHelpers.TagHelpers.EmailTagHelper ) ve ardından derleme adı (authoringtaghel, namespace )
eklersiniz. Çoğu geliştirici, joker karakter sözdizimini kullanmayı tercih eder. Etiket Yardımcıları giriş etiket
Yardımcısı ekleme, kaldırma, hiyerarşi ve joker karakter sözdizimi, ayrıntıya gider.
1. Biçimlendirme içinde güncelleştirme Views/Home/Contact.cshtml bu değişikliklerle dosyası:
@{
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<address>
One Microsoft Way<br />
Redmond, WA 98052<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong><email>Support</email><br />
<strong>Marketing:</strong><email>Marketing</email>
</address>

2. Uygulamayı çalıştırın ve e-posta etiketler ile bağlantı biçimlendirme değiştirilir doğrulayabilmeniz için
HTML kaynağını görüntülemek için sık kullandığınız tarayıcıyı kullanabilirsiniz (örneğin, <a>Support</a> ).
Destek ve pazarlama bir bağlantı olarak işlenir ancak bir href işlevsel hale getirmek için özniteliği.
Sonraki bölümde, gidereceğiz.

SetAttribute ve SetContent
Bu bölümde, güncelleştireceğiz EmailTagHelper böylece e-posta için bir geçerli yer işareti etiketi oluşturur. Razor
görünümü bilgilerinden gerçekleştirecek şekilde güncelleştireceğiz (biçiminde bir mail-to özniteliği) ve bağlantı
oluşturmak kullanın.
Güncelleştirme EmailTagHelper aşağıdaki sınıfı:

public class EmailTagHelper : TagHelper


{
private const string EmailDomain = "contoso.com";

// Can be passed via <email mail-to="..." />.


// PascalCase gets translated into kebab-case.
public string MailTo { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)


{
output.TagName = "a"; // Replaces <email> with <a> tag

var address = MailTo + "@" + EmailDomain;


output.Attributes.SetAttribute("href", "mailto:" + address);
output.Content.SetContent(address);
}
}

Etiket Yardımcıları için Pascal özellikli sınıf ve özellik adları, Kebab durumlarınaçevrilir. Bu nedenle,
kullanılacak MailTo kullanacağınız özniteliği <email mail-to="value"/> eşdeğer.
Son satırı tamamlanmış içeriği bizim için en düşük düzeyde işlevsel etiket Yardımcısı ayarlar.
Vurgulanan satır öznitelikleri eklemek için sözdizimini gösterir:
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces <email> with <a> tag

var address = MailTo + "@" + EmailDomain;


output.Attributes.SetAttribute("href", "mailto:" + address);
output.Content.SetContent(address);
}

Şu anda öznitelikleri koleksiyonda yok sürece bu yaklaşımı "href =" özniteliği için çalışır. Ayrıca
output.Attributes.Add etiketi yardımcı öznitelik etiketi özniteliklerinin koleksiyonunu sonuna eklemek için
yöntemi.
1. Biçimlendirme içinde güncelleştirme Views/Home/Contact.cshtml bu değişikliklerle dosyası:

@{
ViewData["Title"] = "Contact Copy";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<address>
One Microsoft Way Copy Version <br />
Redmond, WA 98052-6399<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong><email mail-to="Support"></email><br />
<strong>Marketing:</strong><email mail-to="Marketing"></email>
</address>

2. Uygulamayı çalıştırın ve doğrulayın, doğru bağlantıları oluşturur.

NOTE
E-posta kendi kendine kapanan etiket yazmak için olsaydı ( <email mail-to="Rick" /> ), son Çıkışta aynı zamanda kendi
kendine kapanan olacaktır. Etiketi yalnızca bir başlangıç etiketiyle ( <email mail-to="Rick"> ) yazma özelliğini
etkinleştirmek için, sınıfı şu şekilde işaretlemeniz gerekir:

[HtmlTargetElement("email", TagStructure = TagStructure.WithoutEndTag)]


public class EmailVoidTagHelper : TagHelper
{
private const string EmailDomain = "contoso.com";
// Code removed for brevity

Bir kendi kendine kapanan e-posta etiket Yardımcısı ile çıkış olacaktır <a href="mailto:Rick@contoso.com" /> .
Kendi kendine kapanan bağlantı etiketler geçerli HTML oluşturmak istemezsiniz, ancak kendi kendine kapanan
etiket Yardımcısı oluşturmak isteyebilirsiniz değildir. Etiket Yardımcıları türünü ayarlayın TagMode sonra bir
etiketi okuma özelliği.
ProcessAsync
Bu bölümde, biz bir zaman uyumsuz bir e-posta yardımcı yazacaksınız.
1. Değiştirin EmailTagHelper aşağıdaki kodla sınıfı:
public class EmailTagHelper : TagHelper
{
private const string EmailDomain = "contoso.com";
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces <email> with <a> tag
var content = await output.GetChildContentAsync();
var target = content.GetContent() + "@" + EmailDomain;
output.Attributes.SetAttribute("href", "mailto:" + target);
output.Content.SetContent(target);
}
}

Notlar:
Bu sürüm, zaman uyumsuz kullanır ProcessAsync yöntemi. Zaman uyumsuz
GetChildContentAsync döndürür bir Task içeren TagHelperContent .
Kullanım output parametresi HTML öğesinden içeriği alamadı.
2. Aşağıdaki değişiklik Views/Home/Contact.cshtml etiketi Yardımcısı hedef e-posta alabilmeniz için dosya.

@{
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<address>
One Microsoft Way<br />
Redmond, WA 98052<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong><email>Support</email><br />
<strong>Marketing:</strong><email>Marketing</email>
</address>

3. Uygulamayı çalıştırın ve geçerli bir e-posta bağlantılarını oluşturur doğrulayın.


RemoveAll ve PreContent.SetHtmlContent PostContent.SetHtmlContent
1. Aşağıdaki BoldTagHelper sınıfının TagHelpers klasör.

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace AuthoringTagHelpers.TagHelpers
{
[HtmlTargetElement(Attributes = "bold")]
public class BoldTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.RemoveAll("bold");
output.PreContent.SetHtmlContent("<strong>");
output.PostContent.SetHtmlContent("</strong>");
}
}
}
[HtmlTargetElement] Özniteliği belirten bir HTML öznitelik içeren herhangi bir HTML öğesi "bold"
adlı bir öznitelik parametresi eşleşir, geçişleri ve Process sınıfı yöntemi geçersiz kılma çalışır. Bizim
örnek içinde Process yöntemi "kalın" özniteliğini kaldırır ve içeren biçimlendirme çevreleyen
<strong></strong> .

İçerik var olan etiket değiştirilecek istemediğinden açılış yazmanız gereken <strong> ile etiketi
PreContent.SetHtmlContent yöntemi ve kapatma </strong> ile etiketi PostContent.SetHtmlContent
yöntemi.
2. Değiştirme About.cshtml görünümü içerecek bir bold öznitelik değeri. Tamamlanan kodu aşağıda
gösterilmiştir.

@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p bold>Use this area to provide additional information.</p>

<bold> Is this bold?</bold>

3. Uygulamayı çalıştırın. Kaynak inceleyin ve biçimlendirme doğrulamak için sık kullandığınız tarayıcıyı
kullanabilirsiniz.
[HtmlTargetElement] Yukarıdaki özniteliği bir öznitelik adı "kalın" sağlayan HTML biçimlendirmesi
hedefler. <bold> Öğesi etiketi Yardımcısı tarafından değiştirilen değildi.
4. Açıklama [HtmlTargetElement] özniteliği satır ve varsayılan hedeflemeye <bold> etiketleri, diğer bir
deyişle, HTML biçimlendirmesi formun <bold> . Unutmayın, varsayılan adlandırma kuralı, sınıf adı eşleşir
kalıniçin TagHelper <bold> etiketler.
5. Uygulamayı çalıştırın ve doğrulayın <bold> etiketin, etiket Yardımcısı tarafından işlenir.

Bir sınıf birden çok dekorasyon [HtmlTargetElement] hedefleri mantıksal-veya sonuçlarını öznitelikleri. Örneğin,
aşağıdaki kodu kullanarak, kalın bir etiket veya bold özniteliğinin eşleşir.

[HtmlTargetElement("bold")]
[HtmlTargetElement(Attributes = "bold")]
public class BoldTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.RemoveAll("bold");
output.PreContent.SetHtmlContent("<strong>");
output.PostContent.SetHtmlContent("</strong>");
}
}

Birden çok öznitelik için aynı deyimde eklendiğinde, çalışma zamanı bunları bir mantıksal-and davranır Örneğin,
aşağıdaki kod bir HTML öğesi "bold" adlı bir öznitelik ile "bold" olarak adlandırılmalıdır ( <bold bold /> )
eşleştirilecek.

[HtmlTargetElement("bold", Attributes = "bold")]

Ayrıca [HtmlTargetElement] hedeflenen öğesi adını değiştirmek için. İsterseniz örneğin BoldTagHelper hedef
<MyBold> etiketleri, aşağıdaki öznitelik kullanmanız gerekir:
[HtmlTargetElement("MyBold")]

Etiket Yardımcısı için bir model geçirin


1. Ekleme bir modelleri klasör.
2. Aşağıdaki WebsiteContext sınıfının modelleri klasörü:

using System;

namespace AuthoringTagHelpers.Models
{
public class WebsiteContext
{
public Version Version { get; set; }
public int CopyrightYear { get; set; }
public bool Approved { get; set; }
public int TagsToShow { get; set; }
}
}

3. Aşağıdaki WebsiteInformationTagHelper sınıfının TagHelpers klasör.

using System;
using AuthoringTagHelpers.Models;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace AuthoringTagHelpers.TagHelpers
{
public class WebsiteInformationTagHelper : TagHelper
{
public WebsiteContext Info { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)


{
output.TagName = "section";
output.Content.SetHtmlContent(
$@"<ul><li><strong>Version:</strong> {Info.Version}</li>
<li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
<li><strong>Approved:</strong> {Info.Approved}</li>
<li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
output.TagMode = TagMode.StartTagAndEndTag;
}
}
}

Daha önce belirtildiği gibi, etiket yardımcıları, etiket yardımcıları için C# Pascal özellikli sınıf
adlarını ve özellikleri Kebab örneğineçevirir. Bu nedenle, kullanılacak WebsiteInformationTagHelper
Razor içinde yazacaksınız <website-information /> .
Açıkça hedef öğeyi tanımlayan değil [HtmlTargetElement] özniteliği, bunu varsayılan
website-information hedeflenir. Aşağıdaki özniteliği (kebab durum geçerli değildir ama sınıfın
adıyla eşleşen unutmayın) uygulandığında:

[HtmlTargetElement("WebsiteInformation")]

Kebab Case etiketi <website-information /> eşleşmiyor. Kullanmak istediğiniz [HtmlTargetElement]


özniteliği, aşağıda gösterildiği gibi kebab çalışması kullanmanız:
[HtmlTargetElement("Website-Information")]

Kendi kendine kapanan öğeler hiçbir içeriğe sahip. Bu örnekte, bir kendi kendine kapanan etiketi
Razor işaretlemesi kullanır, ancak etiketi Yardımcısı oluşturma bir bölümü öğesi (hangi kendi
kendine kapanan değildir ve içeriği yazıyorsanız section öğesi). Bu nedenle, ayarlanacak
ihtiyacınız TagMode için StartTagAndEndTag çıkışını yazmak için. Satır ayarını WMI'ya alternatif
olarak, yorum TagMode ve bir kapatma etiketi ile işaretleme yazma. (Daha sonra Bu öğreticide
örnek biçimlendirme sağlanır.)
$ (Dolar işareti) dosyasında aşağıdaki satırı kullanan bir ilişkilendirilmiş bir dizedir:

$@"<ul><li><strong>Version:</strong> {Info.Version}</li>

4. İçin aşağıdaki işaretlemeyi ekleyin About.cshtml görünümü. Vurgulanan biçimlendirme web site bilgilerini
görüntüler.

@using AuthoringTagHelpers.Models
@{
ViewData["Title"] = "About";
WebsiteContext webContext = new WebsiteContext {
Version = new Version(1, 3),
CopyrightYear = 1638,
Approved = true,
TagsToShow = 131 };
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p bold>Use this area to provide additional information.</p>

<bold> Is this bold?</bold>

<h3> web site info </h3>


<website-information info="webContext" />

NOTE
Aşağıda gösterilen Razor biçimlendirme içinde:

<website-information info="webContext" />

Razor bilir info özniteliği bir sınıf, bir dize değil ve C# kodu yazmak istediğiniz. Herhangi bir dize olmayan etiketi
yardımcı öznitelik olmadan yazılmalıdır @ karakter.

5. Uygulamayı çalıştırın ve web sitesi bilgileri görmek için hakkında görünümüne gidin.

NOTE
Aşağıdaki biçimlendirme bir kapatma etiketi ile kullanın ve içeren satırı Kaldır TagMode.StartTagAndEndTag etiketi
Yardımcısı'nda:

<website-information info="webContext" >


</website-information>
Koşul etiketi Yardımcısı
True değeri geçirildiğinde çıkış koşulu etiket Yardımcısı işler.
1. Aşağıdaki ConditionTagHelper sınıfının TagHelpers klasör.

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace AuthoringTagHelpers.TagHelpers
{
[HtmlTargetElement(Attributes = nameof(Condition))]
public class ConditionTagHelper : TagHelper
{
public bool Condition { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)


{
if (!Condition)
{
output.SuppressOutput();
}
}
}
}

2. Öğesinin içeriğini değiştirin Views/Home/Index.cshtml aşağıdaki işaretlemeyle dosyası:

@using AuthoringTagHelpers.Models
@model WebsiteContext

@{
ViewData["Title"] = "Home Page";
}

<div>
<h3>Information about our website (outdated):</h3>
<Website-InforMation info="Model" />
<div condition="Model.Approved">
<p>
This website has <strong surround="em">@Model.Approved</strong> been approved yet.
Visit www.contoso.com for more information.
</p>
</div>
</div>

3. Değiştirin Index yönteminde Home aşağıdaki kodla denetleyicisi:

public IActionResult Index(bool approved = false)


{
return View(new WebsiteContext
{
Approved = approved,
CopyrightYear = 2015,
Version = new Version(1, 3, 3, 7),
TagsToShow = 20
});
}

4. Uygulamayı çalıştırın ve giriş sayfasına göz atın. Koşullu biçimlendirmeyi div işlenmez. Sorgu dizesini
URL'ye ?approved=true URL'sine (örneğin, http://localhost:1235/Home/Index?approved=true ). approved
TRUE olarak ve koşullu biçimlendirme görüntülenir.
NOTE
Kullanım nameof işleci ile kalın etiket Yardımcısı yaptığınız gibi dize belirtme yerine hedef özniteliğe belirtmek için:

[HtmlTargetElement(Attributes = nameof(Condition))]
// [HtmlTargetElement(Attributes = "condition")]
public class ConditionTagHelper : TagHelper
{
public bool Condition { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)


{
if (!Condition)
{
output.SuppressOutput();
}
}
}

Nameof işleci korumak kod hiç olmadığı kadar yeniden (biz adını değiştirmek de isteyebilirsiniz RedCondition ).

Etiket Yardımcısı çakışmaları


Bu bölümde, otomatik bağlama etiket Yardımcıları çifti yazın. İlk biçimlendirme içeren bir HTML yer işareti
etiketi aynı URL'yi içeren (ve bu nedenle bağlantı URL'si sonuçlanmıyor) HTTP ile başlayan bir URL yerini alır.
İkinci aynı WWW ile başlayan bir URL yapar.
Bu iki Yardımcıları yakından ilgili ve gelecekte yeniden çünkü bunların aynı dosyada saklayacağız.
1. Aşağıdaki AutoLinkerHttpTagHelper sınıfının TagHelpers klasör.

[HtmlTargetElement("p")]
public class AutoLinkerHttpTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent.GetContent(),
@"\b(?:https?://)(\S+)\b",
"<a target=\"_blank\" href=\"$0\">$0</a>")); // http link version}
}
}

NOTE
AutoLinkerHttpTagHelper Sınıfı hedefler p öğeleri ve kullanıyor Regex bağlantı oluşturmak için.

2. Sonuna aşağıdaki işaretlemeyi ekleyin Views/Home/Contact.cshtml dosyası:


@{
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<address>
One Microsoft Way<br />
Redmond, WA 98052<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>

<address>
<strong>Support:</strong><email>Support</email><br />
<strong>Marketing:</strong><email>Marketing</email>
</address>

<p>Visit us at http://docs.asp.net or at www.microsoft.com</p>

3. Uygulamayı çalıştırın ve etiket Yardımcısı bağlantı doğru şekilde işlediğinden emin olun.
4. Güncelleştirme AutoLinker içerecek şekilde sınıfı AutoLinkerWwwTagHelper hangi www metne dönüştürme
ayrıca orijinal www metni içeren bir yer işareti etiketi. Güncelleştirilmiş kod aşağıda vurgulanır:

[HtmlTargetElement("p")]
public class AutoLinkerHttpTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent.GetContent(),
@"\b(?:https?://)(\S+)\b",
"<a target=\"_blank\" href=\"$0\">$0</a>")); // http link version}
}
}

[HtmlTargetElement("p")]
public class AutoLinkerWwwTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent.GetContent(),
@"\b(www\.)(\S+)\b",
"<a target=\"_blank\" href=\"http://$0\">$0</a>")); // www version
}
}
}

5. Uygulamayı çalıştırın. Www metin bağlantı olarak işlenir ancak HTTP metin değil dikkat edin. Her iki
sınıflarda kesme noktası koymak, HTTP etiket Yardımcısı sınıfı ilk çalıştığını görebilirsiniz. Etiket
Yardımcısı çıkışı önbelleğe alınır ve WWW etiketi Yardımcısı çalıştırdığınızda, önbelleğe alınan HTTP
etiketi Yardımcısı çıktısı üzerine yazar sorunudur. Etiket Yardımcıları Çalıştır sırasını denetlemek nasıl
öğreticinin ilerleyen bölümlerinde göreceğiz. Kodu aşağıdakiler ile gidereceğiz:
public class AutoLinkerHttpTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = output.Content.IsModified ? output.Content.GetContent() :
(await output.GetChildContentAsync()).GetContent();

// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent,
@"\b(?:https?://)(\S+)\b",
"<a target=\"_blank\" href=\"$0\">$0</a>")); // http link version}
}
}

[HtmlTargetElement("p")]
public class AutoLinkerWwwTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = output.Content.IsModified ? output.Content.GetContent() :
(await output.GetChildContentAsync()).GetContent();

// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent,
@"\b(www\.)(\S+)\b",
"<a target=\"_blank\" href=\"http://$0\">$0</a>")); // www version
}
}

NOTE
Otomatik bağlama etiket Yardımcıları, ilk sürümünde, aşağıdaki kod ile hedef içeriğini alındı:

var childContent = await output.GetChildContentAsync();

Diğer bir deyişle, çağırma GetChildContentAsync kullanarak TagHelperOutput yöntemlere geçirilen


ProcessAsync yöntemi. Belirtildiği gibi daha önce çıktıyı önbelleğe alındığından, son etiket WINS çalışmasına
yardımcı. Aşağıdaki kod ile ilgili sorun düzeltildi:

var childContent = output.Content.IsModified ? output.Content.GetContent() :


(await output.GetChildContentAsync()).GetContent();

Yukarıdaki kod içeriği değiştirildi ve varsa, çıkış arabellek içeriği alır olup olmadığını denetler.

6. Uygulamayı çalıştırın ve iki bağlantı beklendiği gibi çalıştığını doğrulayın. Bizim otomatik bağlayıcı etiket
Yardımcısı doğru ve eksiksiz görünebilir, ancak ince bir sorun var. WWW etiketi Yardımcısı ilk
çalıştırıyorsa, www bağlantıları doğru olmayacaktır. Ekleyerek kodu güncelleştirmeniz Order etiket
çalışan sırasını denetlemek için aşırı yükleme. Order Özelliği aynı öğeye hedefleyen diğer etiket
Yardımcıları göre yürütme sırasını belirler. Varsayılan sıra değeri sıfırdır ve düşük değerler örnekleriyle
önce yürütülür.
public class AutoLinkerHttpTagHelper : TagHelper
{
// This filter must run before the AutoLinkerWwwTagHelper as it searches and replaces http and
// the AutoLinkerWwwTagHelper adds http to the markup.
public override int Order
{
get { return int.MinValue; }
}

Yukarıdaki kod, HTTP etiketi Yardımcısı önce WWW etiketi Yardımcısı çalıştığını garanti eder. Değişiklik
Order için MaxValue ve WWW etiketi için oluşturulmuş biçimlendirmeyi yanlış olduğundan emin olun.

Alt içeriği almak ve İnceleme


Etiket Yardımcıları içerik almak için çeşitli özellikler sağlar.
Sonucu GetChildContentAsync eklenerek output.Content .
Sonucu inceleyebilirsiniz GetChildContentAsync ile GetContent .
Değiştirirseniz output.Content , TagHelper gövdesi olmaz yürütülen veya siz işlenen GetChildContentAsync
otomatik bağlayıcı örneğimizi olduğu gibi:

public class AutoLinkerHttpTagHelper : TagHelper


{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = output.Content.IsModified ? output.Content.GetContent() :
(await output.GetChildContentAsync()).GetContent();

// Find Urls in the content and replace them with their anchor tag equivalent.
output.Content.SetHtmlContent(Regex.Replace(
childContent,
@"\b(?:https?://)(\S+)\b",
"<a target=\"_blank\" href=\"$0\">$0</a>")); // http link version}
}
}

Birden çok çağrılar GetChildContentAsync aynı değeri döndürür ve yeniden yürütülmez TagHelper önbelleğe
alınan sonuç kullanmayı gösteren yanlış parametre geçirmezseniz gövde.

Mini yükleme küçük bir kısmı görüntüleme TagHelper


Üretim ortamlarında, Mini karşılaşılan kısmi görünümler yüklenirken performans artırılabilir. Üretimde
küçültülmüş kısmi görünümden faydalanmak için:
Kısmi görünümleri mini görüntülemesi için derleme öncesi bir işlem oluşturun/ayarlayın.
Geliştirme dışı ortamlarda mini kullanılan kısmi görünümleri yüklemek için aşağıdaki kodu kullanın.
public class MinifiedVersionPartialTagHelper : PartialTagHelper
{
public MinifiedVersionPartialTagHelper(ICompositeViewEngine viewEngine,
IViewBufferScope viewBufferScope)
: base(viewEngine, viewBufferScope)
{

public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)


{
// Append ".min" to load the minified partial view.
if (!IsDevelopment())
{
Name += ".min";
}

return base.ProcessAsync(context, output);


}

private bool IsDevelopment()


{
return Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
== EnvironmentName.Development;
}
}
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core içindeki etiket Yardımcısı bileşenleri
6.12.2019 • 8 minutes to read • Edit Online

Scott Ade ve fiyaz bin hasan tarafından


Etiket Yardımcısı bileşeni, sunucu tarafı kodundan HTML öğelerini koşullu olarak değiştirmenize veya eklemenize
olanak sağlayan bir etiket yardımcıdır. Bu özellik ASP.NET Core 2,0 veya üzeri sürümlerde kullanılabilir.
ASP.NET Core iki yerleşik etiket Yardımcısı bileşeni içerir: head ve body .
Microsoft.AspNetCore.Mvc.Razor.TagHelpers ad alanında konumlanır ve hem MVC hem de Razor Pages
kullanılabilir. Etiket Yardımcısı bileşenleri _ViewImports. cshtml'de uygulamayla kayıt gerektirmez.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Uygulama alanları
Etiket Yardımcısı bileşenlerinin iki yaygın kullanım durumu şunlardır:
1. <head> bir <link> ekleme.
2. <body> bir <script> ekleme.

Aşağıdaki bölümlerde bu kullanım durumları açıklanır.


HTML Head öğesine Ekle
HTML <head> öğesinin içinde, CSS dosyaları genellikle HTML <link> öğesiyle içeri aktarılır. Aşağıdaki kod head
etiketi Yardımcısı bileşenini kullanarak bir <link> öğesini <head> öğesine çıkartır:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace RazorPagesSample.TagHelpers
{
public class AddressStyleTagHelperComponent : TagHelperComponent
{
private readonly string _style =
@"<link rel=""stylesheet"" href=""/css/address.css"" />";

public override int Order => 1;

public override Task ProcessAsync(TagHelperContext context,


TagHelperOutput output)
{
if (string.Equals(context.TagName, "head",
StringComparison.OrdinalIgnoreCase))
{
output.PostContent.AppendHtml(_style);
}

return Task.CompletedTask;
}
}
}

Yukarıdaki kodda:
AddressStyleTagHelperComponent TagHelperComponentuygular. Soyutlama:
TagHelperContextile sınıfın başlatılmasına izin verir.
HTML öğeleri eklemek veya değiştirmek için etiket Yardımcısı bileşenlerinin kullanılmasını sağlar.
Order özelliği, bileşenlerin işlendiği sırayı tanımlar. bir uygulamada birden çok etiket Yardımcısı bileşeni
kullanımı olduğunda Order gereklidir.
ProcessAsync, yürütme bağlamının TagName özellik değerini head karşılaştırır. Karşılaştırma true olarak
değerlendirilirse, _style alanının içeriği HTML <head> öğesine eklenir.
HTML Body öğesine Ekle
body Tag yardımcı bileşeni <body> öğesine bir <script> öğesi ekleyebilir. Aşağıdaki kod bu tekniği
göstermektedir:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace RazorPagesSample.TagHelpers
{
public class AddressScriptTagHelperComponent : TagHelperComponent
{
public override int Order => 2;

public override async Task ProcessAsync(TagHelperContext context,


TagHelperOutput output)
{
if (string.Equals(context.TagName, "body",
StringComparison.OrdinalIgnoreCase))
{
var script = await File.ReadAllTextAsync(
"TagHelpers/Templates/AddressToolTipScript.html");
output.PostContent.AppendHtml(script);
}
}
}
}

<script> öğesini depolamak için ayrı bir HTML dosyası kullanılır. HTML dosyası, kod temizleyici ve daha
sürdürülebilir hale gelir. Önceki kod TagHelpers/Templates/AddressToolTipScript.html içeriğini okur ve etiket
Yardımcısı çıktısına ekler. Addresstooltipscript. html dosyası aşağıdaki biçimlendirmeyi içerir:

<script>
$("address[printable]").hover(function() {
$(this).attr({
"data-toggle": "tooltip",
"data-placement": "right",
"title": "Home of Microsoft!"
});
});
</script>

Yukarıdaki kod, bir önyükleme araç ipucu pencere öğesini bir printable özniteliği içeren herhangi bir <address>
öğesine bağlar. Bir fare işaretçisi öğenin üzerine geldiğinde efekt görünür.

Bir bileşeni kaydetme


Uygulamanın etiket Yardımcısı bileşenleri koleksiyonuna bir etiket Yardımcısı bileşeni eklenmelidir. Koleksiyona
eklemenin üç yolu vardır:
Hizmetler kapsayıcısı aracılığıyla kayıt
Razor dosyası aracılığıyla kayıt
Sayfa modeli veya denetleyici aracılığıyla kaydolma
Hizmetler kapsayıcısı aracılığıyla kayıt
Etiket Yardımcısı bileşen sınıfı ITagHelperComponentManagerile yönetilmemişse, bağımlılık ekleme (dı) sistemine
kaydedilmelidir. Aşağıdaki Startup.ConfigureServices kod, AddressStyleTagHelperComponent ve
AddressScriptTagHelperComponent sınıflarını geçici bir yaşam süresinekaydeder:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddTransient<ITagHelperComponent,
AddressScriptTagHelperComponent>();
services.AddTransient<ITagHelperComponent,
AddressStyleTagHelperComponent>();
}

Razor dosyası aracılığıyla kayıt


Etiket Yardımcısı bileşeni, DI ile kayıtlı değilse, bir Razor Pages sayfasından veya bir MVC görünümünden kayıt
olabilir. Bu teknik, eklenen biçimlendirmeyi ve bir Razor dosyasından bileşen yürütme sırasını denetlemek için
kullanılır.
ITagHelperComponentManager etiket Yardımcısı bileşenleri eklemek veya uygulamadan kaldırmak için kullanılır.
Aşağıdaki kod, AddressTagHelperComponent ile bu tekniği gösterir:

@using RazorPagesSample.TagHelpers;
@using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
@inject ITagHelperComponentManager manager;

@{
string markup;

if (Model.IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}

manager.Components.Add(new AddressTagHelperComponent(markup, 1));


}

Yukarıdaki kodda:
@injectyönergesi ITagHelperComponentManager örneğini sağlar. Örnek, Razor dosyasındaki erişim yönündeki
manager adlı bir değişkene atanır.
Uygulamanın etiket Yardımcısı bileşenleri koleksiyonuna bir AddressTagHelperComponent örneği eklenir.

AddressTagHelperComponent , markup ve order parametrelerini kabul eden bir oluşturucuya uyacak şekilde
değiştirilmiştir:

private readonly string _markup;

public override int Order { get; }

public AddressTagHelperComponent(string markup = "", int order = 1)


{
_markup = markup;
Order = order;
}

Belirtilen markup parametresi ProcessAsync içinde aşağıdaki gibi kullanılır:

public override async Task ProcessAsync(TagHelperContext context,


TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
TagHelperContent childContent = await output.GetChildContentAsync();
string content = childContent.GetContent();
output.Content.SetHtmlContent(
$"<div>{content}<br>{_markup}</div>{_printableButton}");
}
}

Sayfa modeli veya denetleyici aracılığıyla kaydolma


Etiket Yardımcısı bileşeni, DI ile kayıtlı değilse, bir Razor Pages sayfa modelinden veya bir MVC denetleyicisinden
kaydedilebilir. Bu teknik, Razor dosyalarından mantık C# ayırmak için faydalıdır.
ITagHelperComponentManager örneğine erişmek için Oluşturucu ekleme kullanılır. Etiket Yardımcısı bileşeni, örneğin
etiket Yardımcısı bileşenleri koleksiyonuna eklenir. Aşağıdaki Razor Pages sayfa modelinde bu teknik
AddressTagHelperComponent gösterilmektedir:
using System;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesSample.TagHelpers;

public class IndexModel : PageModel


{
private readonly ITagHelperComponentManager _tagHelperComponentManager;

public bool IsWeekend


{
get
{
var dayOfWeek = DateTime.Now.DayOfWeek;

return dayOfWeek == DayOfWeek.Saturday ||


dayOfWeek == DayOfWeek.Sunday;
}
}

public IndexModel(ITagHelperComponentManager tagHelperComponentManager)


{
_tagHelperComponentManager = tagHelperComponentManager;
}

public void OnGet()


{
string markup;

if (IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}

_tagHelperComponentManager.Components.Add(
new AddressTagHelperComponent(markup, 1));
}
}

Yukarıdaki kodda:
örneğine erişmek için Oluşturucu ekleme kullanılır.
ITagHelperComponentManager
Uygulamanın etiket Yardımcısı bileşenleri koleksiyonuna bir AddressTagHelperComponent örneği eklenir.

Bileşen oluşturma
Özel bir etiket Yardımcısı bileşeni oluşturmak için:
TagHelperComponentTagHelpertüreten bir ortak sınıf oluşturun.
Sınıfa bir [HtmlTargetElement] özniteliği uygulayın. Hedef HTML öğesinin adını belirtin.
Isteğe bağlı: türün IntelliSense 'de görüntülenmesini engellemek için sınıfa bir
[EditorBrowsable(EditorBrowsableState.Never)] özniteliği uygulayın.

Aşağıdaki kod, <address> HTML öğesini hedefleyen özel bir etiket Yardımcısı bileşeni oluşturur:
using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;

namespace RazorPagesSample.TagHelpers
{
[HtmlTargetElement("address")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class AddressTagHelperComponentTagHelper : TagHelperComponentTagHelper
{
public AddressTagHelperComponentTagHelper(
ITagHelperComponentManager componentManager,
ILoggerFactory loggerFactory) : base(componentManager, loggerFactory)
{
}
}
}

HTML işaretlemesini aşağıdaki gibi eklemek için özel address Tag yardımcı bileşenini kullanın:

public class AddressTagHelperComponent : TagHelperComponent


{
private readonly string _printableButton =
"<button type='button' class='btn btn-info' onclick=\"window.open(" +
"'https://binged.it/2AXRRYw')\">" +
"<span class='glyphicon glyphicon-road' aria-hidden='true'></span>" +
"</button>";

public override int Order => 3;

public override async Task ProcessAsync(TagHelperContext context,


TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
var content = await output.GetChildContentAsync();
output.Content.SetHtmlContent(
$"<div>{content.GetContent()}</div>{_printableButton}");
}
}
}

Yukarıdaki ProcessAsync yöntemi, eşleşen <address> öğesine SetHtmlContent için belirtilen HTML 'yi çıkarır.
Ekleme şu durumlarda oluşur:
Yürütme bağlamının TagName Özellik değeri address eşittir.
Karşılık gelen <address> öğesi printable bir özniteliğe sahip.

Örneğin, aşağıdaki <address> öğesi işlenirken if deyiminin doğru sonucu verilmiştir:

<address printable>
One Microsoft Way<br />
Redmond, WA 98052-6399<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
Ek kaynaklar
ASP.NET Core bağımlılık ekleme
ASP.NET core'da görünümlere bağımlılık ekleme
ASP.NET Core yerleşik etiket Yardımcıları
ASP.NET Core 'de bağlayıcı etiketi Yardımcısı
15.10.2019 • 10 minutes to read • Edit Online

By Peter Kellner ve Scott Ade


Tutturucu etiketi Yardımcısı , yeni öznitelikler ekleyerek standart HTML bağlayıcısı ( <a ... ></a> )
etiketini geliştirir. Kurala göre, öznitelik adlarına önek olarak asp- eklenir. İşlenmiş bağlayıcı
öğesinin href öznitelik değeri, asp- özniteliklerinin değerleriyle belirlenir.
Etiket Yardımcıları 'na genel bakış için bkz. ASP.NET Core etiket yardımcıları.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Speakercontroller bu belgenin tamamında örneklerde kullanılır:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

public class SpeakerController : Controller


{
private List<Speaker> Speakers =
new List<Speaker>
{
new Speaker {SpeakerId = 10},
new Speaker {SpeakerId = 11},
new Speaker {SpeakerId = 12}
};

[Route("Speaker/{id:int}")]
public IActionResult Detail(int id) =>
View(Speakers.FirstOrDefault(a => a.SpeakerId == id));

[Route("/Speaker/Evaluations",
Name = "speakerevals")]
public IActionResult Evaluations() => View();

[Route("/Speaker/EvaluationsCurrent",
Name = "speakerevalscurrent")]
public IActionResult Evaluations(
int speakerId,
bool currentYear) => View();

public IActionResult Index() => View(Speakers);


}

public class Speaker


{
public int SpeakerId { get; set; }
}

Tutturucu etiketi yardımcı öznitelikleri


ASP-Controller
ASP -Controller ÖZNITELIĞI, URL oluşturmak için kullanılan denetleyiciyi atar. Aşağıdaki
biçimlendirme tüm hoparlörleri listeler:
<a asp-controller="Speaker"
asp-action="Index">All Speakers</a>

Oluşturulan HTML:

<a href="/Speaker">All Speakers</a>

@No__t-0 özniteliği belirtilirse ve asp-action değilse, varsayılan asp-action değeri, yürütülmekte


olan görünüm ile ilişkili denetleyici eylemi olur. @No__t-0 önceki işaretten atlanırsa ve bağlayıcı
etiketi Yardımcısı HomeController'ın Dizin görünümünde ( /Home) kullanılırsa, oluşturulan HTML:

<a href="/Home">All Speakers</a>

ASP-eylem
ASP -Action öznitelik değeri, oluşturulan href özniteliğinde bulunan denetleyici eylemi adını
temsil eder. Aşağıdaki biçimlendirme oluşturulan href öznitelik değerini konuşmacı
değerlendirmeleri sayfasına ayarlar:

<a asp-controller="Speaker"
asp-action="Evaluations">Speaker Evaluations</a>

Oluşturulan HTML:

<a href="/Speaker/Evaluations">Speaker Evaluations</a>

@No__t-0 özniteliği belirtilmezse, geçerli görünümü yürüten görünümü çağıran varsayılan


denetleyici kullanılır.
@No__t-0 öznitelik değeri Index ise, URL 'ye hiçbir eylem eklenmez ve bu, varsayılan Index
eyleminin çağrılması için önde gelen bir eylem yoktur. Belirtilen eylem (veya varsayılan olarak)
asp-controller ' da başvurulan denetleyicide var olmalıdır.

ASP-Route -{Value }
ASP -Route-{Value} özniteliği bir joker karakter yolu öneki sunar. @No__t-0 yer tutucusunu
kullanan herhangi bir değer olası bir yol parametresi olarak yorumlanır. Varsayılan bir yol
bulunmazsa, bu yol öneki, bir istek parametresi ve değeri olarak oluşturulan href özniteliğine
eklenir. Aksi takdirde, yol şablonunda değiştirilir.
Aşağıdaki denetleyici eylemini göz önünde bulundurun:

public IActionResult AnchorTagHelper(int id)


{
var speaker = new Speaker
{
SpeakerId = id
};

return View(speaker);
}

Başlangıçta tanımlanmış varsayılan bir yol şablonuyla . Yapılandır:


app.UseMvc(routes =>
{
// need route and attribute on controller: [Area("Blogs")]
routes.MapRoute(name: "mvcAreaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");

// default route for non-areas


routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

MVC görünümü, aşağıdaki gibi eylem tarafından belirtilen modeli kullanır:

@model Speaker
<!DOCTYPE html>
<html>
<body>
<a asp-controller="Speaker"
asp-action="Detail"
asp-route-id="@Model.SpeakerId">SpeakerId: @Model.SpeakerId</a>
</body>
</html>

Varsayılan yolun {id?} yer tutucusu eşleşti. Oluşturulan HTML:

<a href="/Speaker/Detail/12">SpeakerId: 12</a>

Aşağıdaki MVC görünümünde olduğu gibi, yol ön ekinin eşleşen yönlendirme şablonunun bir
parçası olmadığını varsayın:

@model Speaker
<!DOCTYPE html>
<html>
<body>
<a asp-controller="Speaker"
asp-action="Detail"
asp-route-speakerid="@Model.SpeakerId">SpeakerId: @Model.SpeakerId</a>
<body>
</html>

Eşleşen rotada speakerid bulunamadığı için aşağıdaki HTML oluşturuldu:

<a href="/Speaker/Detail?speakerid=12">SpeakerId: 12</a>

@No__t-0 ya da asp-action belirtilmemişse, asp-route özniteliğinde olduğu gibi aynı varsayılan


işleme de olur.
ASP-Route
ASP -Route özniteliği, doğrudan adlandırılmış bir yola bağlanan bir URL oluşturmak için kullanılır.
Yönlendirme özniteliklerinikullanarak, bir yol SpeakerController ' de gösterildiği gibi
adlandırılabilir ve Evaluations eyleminde kullanılır:
[Route("/Speaker/Evaluations",
Name = "speakerevals")]
public IActionResult Evaluations() => View();

Aşağıdaki biçimlendirmede, asp-route özniteliği adlandırılmış yola başvurur:

<a asp-route="speakerevals">Speaker Evaluations</a>

Tutturucu etiketi Yardımcısı, /Hoparlörker/değerlendirmeleriURL 'sini kullanarak bu denetleyiciye


doğrudan bir yol oluşturur. Oluşturulan HTML:

<a href="/Speaker/Evaluations">Speaker Evaluations</a>

@No__t-0 veya asp-action asp-route ' ye ek olarak belirtilmişse, oluşturulan yol beklediğiniz
şekilde olmayabilir. Bir yol çakışmasını önlemek için, asp-route asp-controller ve asp-action
öznitelikleriyle kullanılmamalıdır.
ASP-All-Route -Data
ASP -All-Route-Data özniteliği, anahtar-değer çiftleri sözlüğü oluşturmayı destekler. Anahtar
parametre adıdır ve değer parametre değeridir.
Aşağıdaki örnekte, bir sözlük başlatılmış ve Razor görünümüne geçirilir. Alternatif olarak, veriler
modelinize iletilebilir.

@{
var parms = new Dictionary<string, string>
{
{ "speakerId", "11" },
{ "currentYear", "true" }
};
}

<a asp-route="speakerevalscurrent"
asp-all-route-data="parms">Speaker Evaluations</a>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<a href="/Speaker/EvaluationsCurrent?speakerId=11&currentYear=true">Speaker Evaluations</a>

@No__t-0 sözlüğü, aşırı yüklenmiş Evaluations eyleminin gereksinimlerini karşılayan bir


QueryString oluşturmak üzere düzleştirilir:

[Route("/Speaker/EvaluationsCurrent",
Name = "speakerevalscurrent")]
public IActionResult Evaluations(
int speakerId,
bool currentYear) => View();

Sözlükteki herhangi bir anahtar yol parametreleriyle eşleşiyorsa, bu değerler rotada uygun şekilde
değiştirilir. Diğer eşleşme olmayan değerler istek parametreleri olarak oluşturulur.
ASP-Fragment
ASP -Fragment özniteliği URL 'ye eklenecek URL parçasını tanımlar. Tutturucu etiketi Yardımcısı,
karma karakterini (#) ekler. Aşağıdaki biçimlendirmeyi göz önünde bulundurun:

<a asp-controller="Speaker"
asp-action="Evaluations"
asp-fragment="SpeakerEvaluations">Speaker Evaluations</a>

Oluşturulan HTML:

<a href="/Speaker/Evaluations#SpeakerEvaluations">Speaker Evaluations</a>

Karma Etiketler, istemci tarafı uygulamalar oluşturulurken faydalıdır. JavaScript 'te kolay
işaretlemek ve aramak için kullanılabilirler.
ASP-alanı
ASP -Area özniteliği, uygun yolu ayarlamak için kullanılan alan adını ayarlar. Aşağıdaki örneklerde
asp-area özniteliğinin yolların yeniden eşleştirmesine neden olduğu gösterilmektedir.

Razor Pages kullanımı


Razor Pages alan ASP.NET Core 2,1 veya sonraki sürümlerde desteklenir.
Aşağıdaki dizin hiyerarşisini göz önünde bulundurun:
{Proje adı}
Wwwroot
Alanlar
Bağlanabilecek
Sayfalar
_ViewStart. cshtml
Index. cshtml
Index.cshtml.cs
Sayfalar
Oturum alanı dizini Razor sayfasına başvurmak için yapılan biçimlendirme şunlardır:

<a asp-area="Sessions"
asp-page="/Index">View Sessions</a>

Oluşturulan HTML:

<a href="/Sessions">View Sessions</a>

TIP
Razor Pages uygulamasındaki bölgeleri desteklemek için aşağıdakilerden birini yapın
Startup.ConfigureServices :

Uyumluluk sürümünü 2,1 veya üzeri olarak ayarlayın.


RazorPagesOptions. AllowAreas özelliğini true olarak ayarlayın:

services.AddMvc()
.AddRazorPagesOptions(options => options.AllowAreas = true);
MVC 'de kullanım
Aşağıdaki dizin hiyerarşisini göz önünde bulundurun:
{Proje adı}
Wwwroot
Alanlar
Bloglar
Denetleyiciler
HomeController.cs
Görünümler
Sayfa
AboutBlog. cshtml
Index. cshtml
_ViewStart. cshtml
Denetleyiciler
@No__t-0 ' i "blogları" olarak ayarlamak, Dizin alanları/bloglarını bu tutturucu etiketi için ilişkili
denetleyicilerin ve görünümlerin yollarına ön ekler. Aboutblog görünümüne başvurmak için
yapılan biçimlendirme şu şekilde yapılır:

<a asp-area="Blogs"
asp-controller="Home"
asp-action="AboutBlog">About Blog</a>

Oluşturulan HTML:

<a href="/Blogs/Home/AboutBlog">About Blog</a>

TIP
MVC uygulamasındaki bölgeleri desteklemek için, yol şablonu varsa alana bir başvuru içermelidir. Bu şablon,
başlangıçta routes.MapRoute yöntem çağrısının ikinci parametresiyle temsil edilir . configure:

app.UseMvc(routes =>
{
// need route and attribute on controller: [Area("Blogs")]
routes.MapRoute(name: "mvcAreaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");

// default route for non-areas


routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

ASP-protokol
ASP -Protocol ÖZNITELIĞI, URL 'nize bir protokol (örneğin, https ) belirtmek içindir. Örneğin:

<a asp-protocol="https"
asp-controller="Home"
asp-action="About">About</a>

Oluşturulan HTML:
<a href="https://localhost/Home/About">About</a>

Örnekteki ana bilgisayar adı localhost 'tur. Tutturucu etiketi Yardımcısı, URL oluştururken Web
sitesinin ortak etki alanını kullanır.
ASP-ana bilgisayar
ASP -Host ÖZNITELIĞI, URL 'niz için bir ana bilgisayar adı belirtmektir. Örneğin:

<a asp-protocol="https"
asp-host="microsoft.com"
asp-controller="Home"
asp-action="About">About</a>

Oluşturulan HTML:

<a href="https://microsoft.com/Home/About">About</a>

asp-sayfa
ASP -Page özniteliği Razor Pages ile kullanılır. Bir bağlayıcı etiketinin href öznitelik değerini belirli
bir sayfaya ayarlamak için kullanın. Sayfa adının eğik çizgiyle ("/") önek olarak URL 'SI oluşturulur.
Aşağıdaki örnek, katılımcı Razor sayfasına işaret eder:

<a asp-page="/Attendee">All Attendees</a>

Oluşturulan HTML:

<a href="/Attendee">All Attendees</a>

@No__t-0 özniteliği, asp-route , asp-controller ve asp-action öznitelikleriyle birbirini dışlıyor.


Ancak, aşağıdaki biçimlendirmede gösterildiği gibi asp-page asp-route-{value} ile birlikte
yönlendirmeyi denetlemek için kullanılabilir:

<a asp-page="/Attendee"
asp-route-attendeeid="10">View Attendee</a>

Oluşturulan HTML:

<a href="/Attendee?attendeeid=10">View Attendee</a>

ASP-Page -Handler
ASP -Page-Handler özniteliği Razor Pages ile birlikte kullanılır. Belirli sayfa işleyicileriyle bağlantı
için tasarlanmıştır.
Aşağıdaki sayfa işleyicisini göz önünde bulundurun:
public void OnGetProfile(int attendeeId)
{
ViewData["AttendeeId"] = attendeeId;

// code omitted for brevity


}

Sayfa modelinin ilişkili biçimlendirmesi OnGetProfile sayfa işleyicisine bağlanır. @No__t-1


öznitelik değerinde sayfa işleyicisi yöntem adının On<Verb> öneki atlandığına göz ardı edin.
Yöntem zaman uyumsuz olduğunda, Async soneki de atlanır.

<a asp-page="/Attendee"
asp-page-handler="Profile"
asp-route-attendeeid="12">Attendee Profile</a>

Oluşturulan HTML:

<a href="/Attendee?attendeeid=12&handler=Profile">Attendee Profile</a>

Ek kaynaklar
ASP.NET Core bölgeler
ASP.NET Core Razor Pages giriş
ASP.NET Core MVC için uyumluluk sürümü
Önbellek etiketi Yardımcısı, ASP.NET Core MVC
12.07.2019 • 7 minutes to read • Edit Online

Tarafından Peter Kellner ve Luke Latham


Önbellek etiketi Yardımcısı iç ASP.NET Core önbelleği sağlayıcısı için içeriği önbelleğe alarak ASP.NET Core
uygulamanızı performansını olanağı sağlar.
Etiket Yardımcıları genel bakış için bkz. ASP.NET Core etiket yardımcıları.
Aşağıdaki Razor biçimlendirme, geçerli tarihi önbelleğe alır:

<cache>@DateTime.Now</cache>

Etiket Yardımcısını içeren sayfasında ilk isteği, geçerli tarihi görüntüler. (Varsayılan 20 dakika) önbelleğe süresi
dolana kadar veya önbellekten önbelleğe alınan tarih veriler çıkarıldığında kadar ek isteklerin önbelleğe alınan
değeri gösterilir.

Önbellek etiketi Yardımcısı öznitelikleri


Etkin
ÖZNITELIK TÜRÜ ÖRNEKLER VARSAYILAN

Boole değeri true , false true

enabled Önbellek etiketi Yardımcısı tarafından alınmış içeriği önbelleğe alınmış belirler. Varsayılan, true
değeridir. Varsa kümesine false , işlenmiş çıktı değil önbelleğe alınmış.
Örnek:

<cache enabled="true">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

süresi dolmadan açma


ÖZNITELIK TÜRÜ ÖRNEK

DateTimeOffset @new DateTime(2025,1,29,17,02,0)

expires-on önbelleğe alınan öğe için bir mutlak sona erme tarihi ayarlar.
Aşağıdaki örnek, 17:02:00 29 Ocak 2025 üzerinde kadar önbellek etiketi Yardımcısı içeriğini önbelleğe alır:

<cache expires-on="@new DateTime(2025,1,29,17,02,0)">


Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

süresi dolduktan sonra


ÖZNITELIK TÜRÜ ÖRNEK VARSAYILAN

TimeSpan @TimeSpan.FromSeconds(120) 20 dakika

expires-after İçeriği önbelleğe almak için ilk isteği zamanından sürenin uzunluğunu ayarlar.
Örnek:

<cache expires-after="@TimeSpan.FromSeconds(120)">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

Razor görüntüleme motorunu varsayılan ayarlar expires-after yirmi dakika değeri.


süresi dolmadan kayan
ÖZNITELIK TÜRÜ ÖRNEK

TimeSpan @TimeSpan.FromSeconds(60)

Değerini erişilmeyen, önbellek girişi çıkarılacak süreyi ayarlar.


Örnek:

<cache expires-sliding="@TimeSpan.FromSeconds(60)">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

Vary-tarafından-üstbilgisi
ÖZNITELIK TÜRÜ ÖRNEKLER

Dize User-Agent , User-Agent,content-encoding

vary-by-header Bunlar değiştirdiğinizde, önbellek yenileme tetiklemek üstbilgi değerlerini virgülle ayrılmış
listesini kabul eder.
Aşağıdaki örnekte üst bilgi değeri izler User-Agent . Bu örnek için içerikleri önbelleğe alan her farklı User-Agent
web sunucusuna sunulur:

<cache vary-by-header="User-Agent">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

farklı-tarafından-sorgu
ÖZNITELIK TÜRÜ ÖRNEKLER

Dize Make , Make,Model

vary-by-query bir virgülle ayrılmış listesini kabul eder Keys bir sorgu dizesinde (Query), tetikleme önbellek
yenileme herhangi bir değerini listelenen anahtar değişiklikler.
Aşağıdaki örnek değerleri izler Make ve Model . Bu örnek için içerikleri önbelleğe alan her farklı Make ve Model
web sunucusuna sunulur:
<cache vary-by-query="Make,Model">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

farklı-tarafından-route
ÖZNITELIK TÜRÜ ÖRNEKLER

Dize Make , Make,Model

vary-by-route Rota veri parametre değeri değiştiğinde bir önbellek yenileme tetikleyen rota parametre
adlarının virgülle ayrılmış listesini kabul eder.
Örnek:
Startup.cs:

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{Make?}/{Model?}");

Index.cshtml:

<cache vary-by-route="Make,Model">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

farklı-tarafından-tanımlama bilgisi
ÖZNITELIK TÜRÜ ÖRNEKLER

Dize .AspNetCore.Identity.Application ,
.AspNetCore.Identity.Application,HairColor

vary-by-cookie tanımlama bilgisi değerleri değiştiğinde önbelleği yenileme tetiklemek tanımlama bilgisi
adlarının virgülle ayrılmış listesini kabul eder.
Aşağıdaki örnek, ASP.NET Core kimliği ile ilişkili tanımlama izler. Bir kullanıcının kimliği doğrulandığında, kimlik
tanımlama değişikliği bir önbellek yenileme tetikleyen:

<cache vary-by-cookie=".AspNetCore.Identity.Application">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

farklı kullanıcı tarafından


ÖZNITELIK TÜRÜ ÖRNEKLER VARSAYILAN

Boole değeri true , false true

vary-by-user oturum açmış kullanıcı (veya bağlam sorumlusu) değiştiğinde önbelleği sıfırlar olup olmadığını
belirtir. Geçerli kullanıcı olarak da bilinen istek bağlamı sorumlusu ve bir Razor Görünümü'nde başvurarak
görüntülenebilir @User.Identity.Name .
Aşağıdaki örnek, geçerli bir önbellek yenileme tetiklemek için kullanıcı oturum izler:

<cache vary-by-user="true">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

Bu özniteliği kullanarak içerikleri önbellekte aracılığıyla bir oturum açma ve oturum kapatma döngüsü tutar.
Değer ayarlandığında true , önbellek kimliği doğrulanmış kullanıcı için bir kimlik doğrulama döngüsü geçersiz
kılar. Yeni bir benzersiz tanımlama bilgisi değeri, bir kullanıcının kimliği doğrulandığında oluşturulmuş olduğu
için önbellek geçersiz kılınır. Önbellek anonim durumu için tanımlama bilgisi mevcut olduğunda veya tanımlama
bilgisinin doldu korunur. Kullanıcı, değil kimliği doğrulanmış ve önbellek korunur.
değişiklik tarafından
ÖZNITELIK TÜRÜ ÖRNEK

Dize @Model

vary-by hangi verilerin önbelleğe alınmış bir özelleştirme için sağlar. Önbellek etiketi Yardımcısı içeriğini
özniteliğin dize değeri değiştiğinde tarafından başvurulan nesne güncelleştirildiğinde. Genellikle, model
değerlerinin dize birleştirme bu özniteliğe atanır. Etkili bir şekilde, burada önbellek nesnelerindeki değerleri
herhangi bir güncelleştirme geçersiz kılar bir senaryoda sonuçlanır.
Aşağıdaki örnek iki yol parametreleri, tamsayı değeri görünümü SUM'ları oluşturma denetleyici yöntemi
varsayar myParam1 ve myParam2 ve tek bir model özelliği olarak toplamını döndürür. Bu toplam değiştiğinde,
önbellek etiketi Yardımcısı içeriğini oluşturulur ve tekrar önbelleğe alınmış.
Eylem:

public IActionResult Index(string myParam1, string myParam2, string myParam3)


{
int num1;
int num2;
int.TryParse(myParam1, out num1);
int.TryParse(myParam2, out num2);
return View(viewName, num1 + num2);
}

Index.cshtml:

<cache vary-by="@Model">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

öncelik
ÖZNITELIK TÜRÜ ÖRNEKLER VARSAYILAN

CacheItemPriority High , Low , NeverRemove , Normal Normal

priority Yerleşik önbelleği sağlayıcısı için önbellek çıkarma rehberlik sağlar. Web sunucusu çıkarır Low bellek
baskısı altında olduğunda girişleri ilk önbellek.
Örnek:
<cache priority="High">
Current Time Inside Cache Tag Helper: @DateTime.Now
</cache>

priority Özniteliği, belirli bir önbellek bekletme düzeyini garanti etmez. CacheItemPriority yalnızca bir
öneridir. Bu öznitelik ayarını NeverRemove önbelleğe alınmış öğeleri her zaman korunur garanti etmez. Konular,
bkz: ek kaynaklar bölümünde daha fazla bilgi için.
Önbellek etiketi Yardımcısı bağlıdır bellek önbellek hizmeti. Önbellek etiketi Yardımcısı eklenmemiş olan hizmet
ekler.

Ek kaynaklar
ASP.NET Core 'de önbellek belleği
ASP.NET Core kimliğe giriş
Dağıtılmış önbellek etiketi Yardımcısı ASP.NET
core'da
12.07.2019 • 2 minutes to read • Edit Online

Tarafından Peter Kellner ve Luke Latham


Dağıtılmış önbellek etiketi Yardımcısı, dağıtılmış önbellek kaynağına içeriği önbelleğe alarak ASP.NET Core
uygulamanızı performansını önemli ölçüde artırmak olanağı sağlar.
Etiket Yardımcıları genel bakış için bkz. ASP.NET Core etiket yardımcıları.
Dağıtılmış önbellek etiketi Yardımcısı, önbellek etiketi Yardımcısı olarak aynı temel sınıfından devralır. Tüm
önbellek etiketi Yardımcısı öznitelikleri dağıtılmış etiketi Yardımcısı için kullanılabilir.
Dağıtılmış önbellek etiketi Yardımcısı kullanan Oluşturucu ekleme. IDistributedCache Arabirimi, dağıtılmış
önbellek etiketi Yardımcısı'nın oluşturucuya geçirilir. Hiçbir somut uygulaması varsa IDistributedCache
oluşturulur Startup.ConfigureServices (Startup.cs), dağıtılmış önbellek etiketi Yardımcısı olarak önbelleğe
alınmış verileri depolamak için aynı bellek içi sağlayıcısı kullanan önbellek etiketi Yardımcısı.

Dağıtılmış önbellek etiketi Yardımcısı öznitelikleri


Önbellek etiketi Yardımcısı ile paylaşılan öznitelikleri
enabled
expires-on
expires-after
expires-sliding
vary-by-header
vary-by-query
vary-by-route
vary-by-cookie
vary-by-user
vary-by priority

Önbellek etiketi Yardımcısı aynı sınıfta dağıtılmış önbellek etiketi Yardımcısı devralır. Bu öznitelikler açıklaması
için bkz. önbellek etiketi Yardımcısı.
name
ÖZNITELIK TÜRÜ ÖRNEK

Dize my-distributed-cache-unique-key-101

name gerekli değildir. name Özniteliği, her depolanan önbellek örneği için bir anahtar olarak kullanılır. Önbellek
etiketi Razor sayfası adı ve Razor sayfası konuma göre her bir örneği için bir önbellek anahtarı atayan Yardımcısı,
dağıtılmış önbellek etiketi Yardımcısı yalnızca anahtarıyla özniteliğini tabanları name .
Örnek:
<distributed-cache name="my-distributed-cache-unique-key-101">
Time Inside Cache Tag Helper: @DateTime.Now
</distributed-cache>

Dağıtılmış önbellek etiketi Yardımcısı IDistributedCache uygulamaları


İki uygulamaları vardır IDistributedCache ASP.NET Core için yerleşik olarak bulunur. Bir SQL Sunucusu'nu
temel alır ve diğer Redis dayanır. Bu uygulamalar ayrıntıları bulunabilir ASP.NET Core 'de dağıtılmış önbelleğe
alma. Bir örneği her iki uygulamaları içeren IDistributedCache içinde Startup .
Tüm özel uygulanışı kullanmaya özellikle ilişkili hiçbir etiket öznitelik IDistributedCache .

Ek kaynaklar
Önbellek etiketi Yardımcısı, ASP.NET Core MVC
ASP.NET Core bağımlılık ekleme
ASP.NET Core 'de dağıtılmış önbelleğe alma
ASP.NET Core 'de önbellek belleği
ASP.NET Core kimliğe giriş
ASP.NET core'da ortam etiketi Yardımcısı
12.07.2019 • 2 minutes to read • Edit Online

Tarafından Peter Kellner, Hisham Bin Ateya, ve Luke Latham


Ortam etiketi Yardımcısı koşullu olarak geçerli göre kapalı içeriğini işler barındırma ortamı. Ortam etiketi
Yardımcısı'nın tek öznitelik names , ortam adlarının virgülle ayrılmış listesidir. Sağlanan ortam adları geçerli
ortamı hiçbiriyle, ekteki içeriğin işlenir.
Etiket Yardımcıları genel bakış için bkz. ASP.NET Core etiket yardımcıları.

Ortam etiketi Yardımcısı öznitelikleri


adlar
names Tek bir barındırma ortamı adı veya işleme ekteki içeriğin tetikleyen ortam adları barındırma virgülle
ayrılmış listesini kabul eder.
Tarafından döndürülen değeri, geçerli ortam değerlerini karşılaştırılır IHostingEnvironment.EnvironmentName.
Karşılaştırma çalışması yoksayar.
Aşağıdaki örnek, bir ortam etiketi Yardımcısı kullanır. Barındırma ortamı hazırlık veya üretim olması durumunda
içeriğinin işlenip:

<environment names="Staging,Production">
<strong>HostingEnvironment.EnvironmentName is Staging or Production</strong>
</environment>

dahil etme ve dışlama öznitelikleri


include & exclude dahil veya hariç tutulan barındırma ortamı adlarını temel alarak ekteki içeriğin işleme
öznitelikleri denetimi.
include
include Özelliği için benzer bir davranış gösteriyor names özniteliği. Listelenen bir ortam include öznitelik
değeri, uygulamanın barındırma ortamına eşleşmelidir (IHostingEnvironment.EnvironmentName) içeriği
işlemek için <environment> etiketi.

<environment include="Staging,Production">
<strong>HostingEnvironment.EnvironmentName is Staging or Production</strong>
</environment>

exclude
Tersine include özniteliği, içeriğini <environment> etiket listede bir ortam barındırma ortamı eşleşmediğinde
işlenir exclude öznitelik değeri.

<environment exclude="Development">
<strong>HostingEnvironment.EnvironmentName is not Development</strong>
</environment>
Ek kaynaklar
ASP.NET Core çoklu ortamları kullanma
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET core'da görüntü etiketi Yardımcısı
12.07.2019 • 2 minutes to read • Edit Online

Tarafından Peter Kellner


Görüntü etiketi Yardımcısı geliştirir <img> statik resim dosyaları için önbellek busting davranışı sağlamak için
etiket.
Bir önbellek busting dize varlığın URL'ye eklenen statik görüntü dosyasının bir karmasını temsil eden benzersiz
bir değerdir. Benzersiz bir dize istemciler (ve bazı Ara sunucular) konak web sunucusu ve istemci önbelleğinden
görüntü yeniden yüklemek ister.
Varsa resim kaynağını ( src ) konak web sunucusundaki bir statik dosya:
Önbellek busting benzersiz bir dize, görüntü kaynağı için bir sorgu parametresi olarak eklenir.
Konak web sunucusunda dosyayı değişirse, güncelleştirilmiş istek parametresi içeren bir benzersiz istek URL'si
oluşturulur.
Etiket Yardımcıları genel bakış için bkz. ASP.NET Core etiket yardımcıları.

Görüntü etiketi Yardımcısı öznitelikleri


src
Görüntü etiketi Yardımcısı, etkinleştirme src öznitelik gerekli <img> öğesi.
Resim kaynağını ( src ) statik fiziksel bir dosya sunucusuna işaret etmelidir. Varsa src uzak bir URI önbelleği
busting sorgu dizesi parametresi oluşturulmadığından.
ASP ekleme sürümü
Zaman asp-append-version ile belirtilen bir true değer ile birlikte bir src özniteliği, görüntü etiketi Yardımcısı
çağrılır.
Aşağıdaki örnek, bir görüntü etiketi Yardımcısı kullanır:

<img src="~/images/asplogo.png" asp-append-version="true">

Statik dosya dizininde bulunuyorsa /wwwroot/resimler/ , oluşturulan HTML (karma farklı olacaktır) aşağıdakine
benzer:

<img src="/images/asplogo.png?v=Kl_dqr9NVtnMdsM2MUg4qthUnWZm5T1fCEimBPWDNgM">

Parametresine atanan değer v karma değeri asplogo.png diskteki dosya. Web sunucusu statik dosya için okuma
erişimi alamadı ise hiçbir v parametresi eklenir src biçimlendirmenin özniteliği.

Karma önbelleğe alma davranışı


Görüntü etiketi Yardımcısı önbelleği sağlayıcısı hesaplanan depolamak için yerel web sunucusu üzerinde kullanır
Sha512 belirli bir dosya karması. Dosyanın birden çok kez istenirse, karma yeniden hesaplanması değil. Önbellek
dosyaya eklenmiş bir dosya İzleyicisi tarafından geçersiz olduğunda dosyanın Sha512 karma hesaplanır. Dosyanın
diskte değiştiğinde yeni bir karma hesaplanır ve önbelleğe alınmış.
Ek kaynaklar
ASP.NET Core 'de önbellek belleği
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core etiket Yardımcısı bağlantı
25.09.2019 • 3 minutes to read • Edit Online

Tarafından Rick Anderson


Bağlantı etiketi Yardımcısı , birincil veya GERI dönüş CSS dosyasına bir bağlantı oluşturur. Genellikle birincil CSS
dosyası Content Delivery Network (CDN ).
CDN:
, Varlığın Web uygulamasıyla barındırılmasına karşı çeşitli performans avantajları sağlar.
Varlık için tek kaynak olarak hiçbir şekilde güvenilmemelidir. CDNs her zaman kullanılabilir değildir, bu nedenle
güvenilir bir geri dönüş kullanılmalıdır. Genellikle geri dönüş, Web uygulamasını barındıran sitedir.
Bağlantı etiketi Yardımcısı, CSS dosyası için CDN ve CDN kullanılabilir olmadığında geri dönüş belirtmenize
olanak tanır. Bağlantı etiketi Yardımcısı, CDN 'nin performans avantajlarından yararlanarak yerel barındırma
sağlamlığı sağlar.
Aşağıdaki Razor biçimlendirmesinde, ASP.NET Core Web head uygulaması şablonuyla oluşturulan bir düzen
dosyasının öğesi gösterilmektedir:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebLinkTH</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position"
asp-fallback-test-value="absolute"
crossorigin="anonymous"
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" />
</environment>
<link rel="stylesheet" href="~/css/site.css" />
</head>

Aşağıdaki kod, önceki koddan (geliştirme olmayan bir ortamda) HTML olarak işlenir:
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Home page - WebLinkTH</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.1.3/css/bootstrap.min.css"
crossorigin="anonymous" integrity="sha256-eS<snip>BE=" />
<meta name="x-stylesheet-fallback-test" content="" class="sr-only" />
<script>
!function (a, b, c, d) {
var e, f = document,
g = f.getElementsByTagName("SCRIPT"),
h = g[g.length - 1].previousElementSibling,
i = f.defaultView && f.defaultView.getComputedStyle ? f.defaultView.getComputedStyle(h) :
h.currentStyle;
if (i && i[a] !== b) for (e = 0; e < c.length; e++)
f.write('<link href="' + c[e] + '" ' + d + "/>")
}
("position", "absolute", ["\/lib\/bootstrap\/dist\/css\/bootstrap.min.css"],
"rel=\u0022stylesheet\u0022 crossorigin=\u0022anonymous\u0022 integrity=\abc<snip>BE=\u0022
");
</script>

<link rel="stylesheet" href="/css/site.css" />


</head>

Önceki kodda, bağlantı etiketi Yardımcısı <meta name="x-stylesheet-fallback-test" content="" class="sr-only" />
öğesi ve istenen Bootstrap. min. css dosyasının CDN üzerinde kullanılabilir olduğunu doğrulamak için kullanılan
aşağıdaki JavaScript 'i oluşturdu. Bu durumda, CSS dosyası kullanılabilir olduğundan, etiket Yardımcısı CDN CSS
dosyası ile <link /> öğeyi üretti.

Yaygın olarak kullanılan bağlantı etiketi Yardımcısı öznitelikleri


Tüm bağlantı etiketi Yardımcısı öznitelikleri, özellikleri ve yöntemleri için bağlantı etiketi Yardımcısı ' na bakın.
değerini
Bağlı kaynağın tercih edilen adresi. Adres, her durumda oluşturulan HTML 'ye düşünce olarak iletilir.
ASP-geri dönüş-href
Birincil URL 'nin başarısız olması durumunda öğesine geri dönüş için CSS stil sayfasının URL 'SI.
ASP-geri dönüş-test sınıfı
Geri dönüş testi için kullanılacak stil sayfasında tanımlanan sınıf adı. Daha fazla bilgi için bkz. FallbackTestClass.
ASP-Fallback-test-özelliği
Geri dönüş testi için kullanılacak CSS özellik adı. Daha fazla bilgi için bkz. FallbackTestProperty.
ASP-geri dönüş-test-değeri
Geri dönüş testi için kullanılacak CSS özelliği değeri. Daha fazla bilgi için bkz. FallbackTestValue.
ASP-geri dönüş-test-değeri
Geri dönüş testi için kullanılacak CSS özelliği değeri. Daha fazla bilgi için bkz.FallbackTestValue

Ek kaynaklar
ASP.NET Core etiket yardımcıları
ASP.NET Core bölgeler
ASP.NET Core Razor Pages giriş
ASP.NET Core MVC için uyumluluk sürümü
ASP.NET Core kısmi etiket Yardımcısı
6.12.2019 • 4 minutes to read • Edit Online

Scott Ade tarafından


Etiket Yardımcıları hakkında genel bilgi için bkz. ASP.NET Core etiket yardımcıları.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Genel bakış
Kısmi etiket Yardımcısı Razor Pages ve MVC uygulamalarında kısmi bir Görünüm oluşturmak için kullanılır.
Bunu göz önünde bulundurun:
ASP.NET Core 2,1 veya üstünü gerektirir.
, HTML yardımcı söz diziminebir alternatiftir.
Kısmi görünümü zaman uyumsuz olarak işler.
Kısmi görünümü işlemeye yönelik HTML yardımcı seçenekleri şunlardır:
@await Html.PartialAsync
@await Html.RenderPartialAsync
@Html.Partial
@Html.RenderPartial

Ürün modeli bu belgenin tamamında örneklerde kullanılır:

namespace TagHelpersBuiltIn.Models
{
public class Product
{
public int Number { get; set; }

public string Name { get; set; }

public string Description { get; set; }


}
}

Kısmi etiket Yardımcısı özniteliklerinin bir stoku aşağıda verilmiştir.

{1>name<1}
name özniteliği gereklidir. İşlenecek kısmi görünümün adını veya yolunu gösterir. Kısmi bir görünüm adı
sağlandığında, görünüm bulma işlemi başlatılır. Açık bir yol sağlandığında bu işlem atlanır. Tüm kabul edilebilir
name değerleri için bkz. kısmi görünüm bulma.

Aşağıdaki biçimlendirme, _ProductPartial. cshtml 'nin paylaşılan klasörden yükleneceğini belirten açık bir yol
kullanır. For özniteliği kullanılarak, bağlama için kısmi görünüme bir model geçirilir.

<partial name="Shared/_ProductPartial.cshtml" for="Product">


for
for özniteliği, geçerli modele göre değerlendirilecek bir Modelexpression atar. Bir ModelExpression @Model.
söz dizimini anlar. Örneğin, for="Product" for="@Model.Product" yerine kullanılabilir. Bu varsayılan çıkarım
davranışı, bir satır içi ifade tanımlamak için @ simgesi kullanılarak geçersiz kılınır.
Aşağıdaki biçimlendirme _ProductPartial. cshtml'yi yükler:

<partial name="_ProductPartial" for="Product">

Kısmi görünüm, ilişkili sayfa modelinin Product özelliğine bağlanır:

using Microsoft.AspNetCore.Mvc.RazorPages;
using TagHelpersBuiltIn.Models;

namespace TagHelpersBuiltIn.Pages
{
public class ProductModel : PageModel
{
public Product Product { get; set; }

public void OnGet()


{
Product = new Product
{
Number = 1,
Name = "Test product",
Description = "This is a test product"
};
}
}
}

{1>model<1}
model özniteliği kısmi görünüme geçirilecek bir model örneği atar. model özniteliği for özniteliğiyle birlikte
kullanılamaz.
Aşağıdaki biçimlendirmede, yeni bir Product nesnesi oluşturulur ve bağlama için model özniteliğine geçirilir:

<partial name="_ProductPartial"
model='new Product { Number = 1, Name = "Test product", Description = "This is a test" }'>

verileri görüntüle
view-data özniteliği, kısmi görünüme geçirilecek bir ViewDataDictionary atar. Aşağıdaki biçimlendirme tüm
ViewData toplamasını kısmi görünüm için erişilebilir hale getirir:

@{
ViewData["IsNumberReadOnly"] = true;
}

<partial name="_ProductViewDataPartial" for="Product" view-data="ViewData">

Yukarıdaki kodda IsNumberReadOnly anahtar değeri true olarak ayarlanır ve ViewData koleksiyonuna eklenir.
Sonuç olarak, ViewData["IsNumberReadOnly"] aşağıdaki kısmi görünüm içinde erişilebilir hale getirilir:
@model TagHelpersBuiltIn.Models.Product

<div class="form-group">
<label asp-for="Number"></label>
@if ((bool)ViewData["IsNumberReadOnly"])
{
<input asp-for="Number" type="number" class="form-control" readonly />
}
else
{
<input asp-for="Number" type="number" class="form-control" />
}
</div>
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" type="text" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Description"></label>
<textarea asp-for="Description" rows="4" cols="50" class="form-control"></textarea>
</div>

Bu örnekte, ViewData["IsNumberReadOnly"] değeri, sayı alanının salt okunurdur olarak görüntülenip


görüntülenmeyeceğini belirler.

HTML yardımcısından geçiş yapma


Aşağıdaki zaman uyumsuz HTML Yardımcısı örneğini göz önünde bulundurun. Bir ürün koleksiyonu
tekrarlandırılır ve görüntülenir. PartialAsync yönteminin ilk parametresi başına, _ProductPartial. cshtml kısmi
görünümü yüklenir. Product modelinin bir örneği bağlama için kısmi görünüme geçirilir.

@foreach (var product in Model.Products)


{
@await Html.PartialAsync("_ProductPartial", product)
}

Aşağıdaki kısmi etiket Yardımcısı PartialAsync HTML Yardımcısı ile aynı zaman uyumsuz işleme davranışına
erişir. model özniteliğine, kısmi görünüme bağlama için bir Product model örneği atanır.

@foreach (var product in Model.Products)


{
<partial name="_ProductPartial" model="product" />
}

Ek kaynaklar
ASP.NET Core kısmi görünümler
ASP.NET Core MVC 'deki görünümler
ASP.NET Core 'de betik etiketi Yardımcısı
3.12.2019 • 2 minutes to read • Edit Online

Rick Anderson tarafından


Betik etiketi Yardımcısı , birincil veya geri dönüş betik dosyasına bir bağlantı oluşturur. Genellikle birincil betik
dosyası Content Delivery Network (CDN ).
CDN:
, Varlığın Web uygulamasıyla barındırılmasına karşı çeşitli performans avantajları sağlar.
Varlık için tek kaynak olarak hiçbir şekilde güvenilmemelidir. CDNs her zaman kullanılabilir değildir, bu nedenle
güvenilir bir geri dönüş kullanılmalıdır. Genellikle geri dönüş, Web uygulamasını barındıran sitedir.
Betik etiketi Yardımcısı, CDN kullanılabilir olmadığında betik dosyası ve geri dönüş için CDN belirtmenize olanak
tanır. Betik etiketi Yardımcısı, bir CDN 'nin performans avantajlarından yararlanarak yerel barındırma sağlamlığı
sağlar.
Aşağıdaki Razor biçimlendirmesinde geri dönüş içeren bir script öğesi gösterilmektedir:

<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>

CDN betiğini yüklemeyi ertelemek için <script> öğenin erteleme özniteliğini kullanmayın. Komut dosyası etiketi
Yardımcısı, ASP -Fallback-test ifadesini hemen yürüten JavaScript 'i işler. CDN betiği yükleme ertelenir ise ifade
başarısız olur.

Yaygın olarak kullanılan betik etiketi Yardımcısı öznitelikleri


Tüm betik etiketi Yardımcısı öznitelikleri, özellikleri ve yöntemleri için komut dosyası etiketi Yardımcısı ' na bakın.
ASP-geri dönüş-test
Geri dönüş testi için kullanılacak birincil betikte tanımlanan betik yöntemi. Daha fazla bilgi için bkz.
FallbackTestExpression.
ASP-geri dönüş-src
Birincil bir hata durumunda öğesine geri dönüş yapılacak bir betik etiketinin URL 'SI. Daha fazla bilgi için bkz.
FallbackSrc.

Ek kaynaklar
ASP.NET Core etiket yardımcıları
ASP.NET Core bölgeler
ASP.NET Core Razor Pages giriş
ASP.NET Core MVC için uyumluluk sürümü
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core formlardaki etiket yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı gösterir. HTML form öğesi,
Web uygulamalarının sunucuya veri geri göndermek için kullanacağı birincil mekanizmayı sağlar. Bu belgenin
çoğunda Etiket Yardımcıları ve BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım sağlar, ancak bu etiket
yardımcıların HTML yardımcılarını değiştirmez ve her HTML Yardımcısı için bir etiket Yardımcısı olmadığını bilmek
önemlidir. Bir HTML Yardımcısı alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci ÜRETIR (http post eylem
yönteminde [ValidateAntiForgeryToken] özniteliğiyle kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini sağlar. Html.BeginForm
ve Html.BeginRouteForm routeValues parametreleri benzer işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan action öznitelik değerini
oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek sahteciliği (HTTP POST eylem yönteminde
[ValidateAntiForgeryToken] özniteliğiyle kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci
oluşturur. Bir saf HTML formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme oluşturabilir. register adlı bir
uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi kullanabilir:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni bir Web uygulaması
oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği doğrulanmamış veya
yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya çalıştığınızda, güvenlik ara yazılımı sizi returnUrl
kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya <input type="image" ...>
etiketi üzerinde oluşturur. formaction özniteliği bir formun verilerini nereden gönderdiğini denetler. image ve
<düğme > öğeleri <giriş > öğelerine bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction
bağlantısının oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin: asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index eylemine gönderir:
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.

<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Giriş etiketi Yardımcısı
Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini üretir.
name
asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir. İfadenin adı, asp-for özniteliği
değeri için kullanılan şeydir. Ek bilgi için ifade adları bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE göre HTML type
öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama öznitelikleri oluşturur
Html.TextBoxForve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor. Ayrıntılar için bkz. giriş etiketi
Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını güncelleştirmezseniz aşağıdakine benzer bir
hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda bazı ortak .NET türleri
ve oluşturulan HTML türü listelenmekte (her .NET türü listelenmemiştir).

.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak veri ek açıklamaları (her
doğrulama özniteliği listelenmez) gösterilmektedir:
ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler oluşturur. Giriş etiketi
Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-* öznitelikleri üretir (bkz. model doğrulama). Bu
öznitelikler, giriş alanlarına iliştirilecek Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması
sağlar. Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural doğrulama kuralının adıdır
(örneğin, data-val-required , data-val-email , data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa,
data-val-rule özniteliği için değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile çakışan özelliklere
sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak ayarlar; Html.TextBox ve Html.TextBoxFor .
Html.Editor ve Html.EditorFor tanıtıcı koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok.
Giriş etiketi Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri kullanırlar);
Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar ).

HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes adlı özel bir
ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak additionalViewData parametreleri kullanılarak
genişletilebilir. "HtmlAttributes" anahtarı büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox()
gibi giriş yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu nedenle,
asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu nedenle Model ile önek gerektirmez. "@"
karakterini kullanarak bir satır içi ifadeyi başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak üzere çeşitli kaynakları
inceler. <input type="text" asp-for="@Name"> göz önünde bulundurun. Hesaplanan value özniteliği, öğesinden
gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt Address özelliği içeren daha
karmaşık bir model sınıfı düşünün.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:


@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:


@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse foreach kullanılmalıdır.
Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa, foreach daha iyidir (senaryo buna izin veriyorsa).
Ancak, bir LINQ ifadesinde bir dizin oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş
olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @ işleçle nasıl değiştirileceğini
gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of
&#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of
&#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen görünen ad zaman içinde
değişebilir ve Display özniteliği ve etiket etiketi Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik değerini oluşturdu. Etiket
Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for öğeleri oluşturur. Bu örnekteki başlık Display
özniteliğinden gelir. Modelde bir Display özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek bir özellik için bir
doğrulama iletisi görüntüler) ve Validation Summary Tag Helper (doğrulama hatalarının özetini görüntüler).
Input Tag Helper , model sınıflarınızda bulunan veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5
istemci tarafı doğrulama öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı,
bir doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan span öğesine HTML5
data-valmsg-for="property" özniteliğini ekler. İstemci tarafı doğrulama hatası oluştuğunda, jQuery <span>
öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış olabilir ve bazı doğrulamalar
yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper genellikle kullanırsınız.
Bunun yapılması, hataya neden olan girişin yakınında herhangi bir doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir görünümsiniz olmalıdır. Daha fazla bilgi
için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan veya istemci tarafı
doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span> öğesinin gövdesi olarak koyar.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır. asp-validation-summary
öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten DataAnnotation öznitelikleri
vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi Yardımcısı şu hata iletisini görüntüler:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):


<form action="/DemoReg/Register" method="post">
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items seçenek öğelerini belirtir.
Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:


[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):

<form method="post" action="/">


<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli, MVC meta verileri
sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket Yardımcısı öznitelikleri olur (
asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri oluşturmak için
kullanışlıdır.
Örnek:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:


<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup nesnesi içerdiğinde
oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı otomatik olarak birden çok =
"Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}

Aşağıdaki görünümle:
@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi yinelemeyi ortadan
kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin, aşağıdaki görünüm ve eylem
yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli Country değerine bağlı olarak doğru <option> öğesi seçilecek ( selected="selected" özniteliğini içerir).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core formlardaki etiket
yardımcıları
6.12.2019 • 27 minutes to read • Edit Online

By Rick Anderson, N. Taylor Mullen, Davve Patııve Jerrie Pelser


Bu belge, formlarda ve genellikle form üzerinde kullanılan HTML öğeleriyle çalışmayı
gösterir. HTML form öğesi, Web uygulamalarının sunucuya veri geri göndermek için
kullanacağı birincil mekanizmayı sağlar. Bu belgenin çoğunda Etiket Yardımcıları ve
BUNLARıN güçlü HTML formları oluşturma konusunda nasıl yardımcı olabilecekleri
açıklanmaktadır. Bu belgeyi okuyabilmeniz Için yardımcıları etiketleyerek okumanız önerilir.
Birçok durumda, HTML Yardımcıları belirli bir etiket Yardımcısı için alternatif bir yaklaşım
sağlar, ancak bu etiket yardımcıların HTML yardımcılarını değiştirmez ve her HTML
Yardımcısı için bir etiket Yardımcısı olmadığını bilmek önemlidir. Bir HTML Yardımcısı
alternatifi varsa, bu, bahsedilir.

Form etiketi Yardımcısı


Form etiketi Yardımcısı:
MVC denetleyicisi eylemi veya adlandırılmış yol için HTML <FORM > action
öznitelik değeri oluşturur
Siteler arası istek yasaklamasını engellemek için gizli bir Istek doğrulama belirteci
ÜRETIR (http post eylem yönteminde [ValidateAntiForgeryToken] özniteliğiyle
kullanıldığında)
Yol değerlerine <Parameter Name> eklendiği asp-route-<Parameter Name> özniteliğini
sağlar. Html.BeginForm ve Html.BeginRouteForm routeValues parametreleri benzer
işlevlere sahiptir.
Bir HTML Yardımcısı alternatifi Html.BeginForm ve Html.BeginRouteForm

Örnek:

<form asp-controller="Demo" asp-action="Register" method="post">


<!-- Input and Submit elements -->
</form>

Yukarıdaki form etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/Register">


<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

MVC çalışma zamanı, etiket Yardımcısı öznitelikleri asp-controller ve asp-action olan


action öznitelik değerini oluşturur. Form etiketi Yardımcısı ayrıca, siteler arası istek
sahteciliği (HTTP POST eylem yönteminde [ValidateAntiForgeryToken] özniteliğiyle
kullanıldığında) engellemek için gizli bir Istek doğrulama belirteci oluşturur. Bir saf HTML
formunun siteler arası istek sahteciliğini önleme 'den korunması zordur, form etiketi
Yardımcısı bu hizmeti sizin için sağlar.
Adlandırılmış yol kullanma
asp-route Tag Helper özniteliği, HTML action özniteliği için de biçimlendirme
oluşturabilir. register adlı bir uygulama, kayıt sayfası için aşağıdaki biçimlendirmeyi
kullanabilir:

<form asp-route="register" method="post">


<!-- Input and Submit elements -->
</form>

Görünümler/hesap klasöründeki görünümlerin birçoğu ( bireysel kullanıcı hesaplarıylayeni


bir Web uygulaması oluşturduğunuzda oluşturulur), ASP -Route-ReturnUrl özniteliğini
içerir:

<form asp-controller="Account" asp-action="Login"


asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">

NOTE
Yerleşik şablonlarla returnUrl , yalnızca yetkili bir kaynağa erişmeye çalıştığınızda ancak kimliği
doğrulanmamış veya yetkilendirilmeyen otomatik olarak doldurulur. Yetkisiz erişim yapmaya
çalıştığınızda, güvenlik ara yazılımı sizi returnUrl kümesi ile oturum açma sayfasına yönlendirir.

Form eylemi etiketi Yardımcısı


Form eylemi etiketi Yardımcısı, formaction özniteliği oluşturulan <button ...> veya
<input type="image" ...> etiketi üzerinde oluşturur. formaction özniteliği bir formun
verilerini nereden gönderdiğini denetler. image ve <düğme > öğeleri <giriş > öğelerine
bağlanır. Form eylemi etiketi Yardımcısı, karşılık gelen öğe için formaction bağlantısının
oluşturulduğunu denetlemek için birkaç AnchorTagHelper asp- özniteliği kullanımını
sağlar.
formaction değerini denetlemek için desteklenen AnchorTagHelper öznitelikleri:

ÖZNITELIK AÇIKLAMA

ASP-Controller Denetleyicinin adı.

ASP-eylem Eylem yönteminin adı.

ASP-alanı Alanın adı.

asp-sayfa Razor sayfasının adı.

ASP-Page-Handler Razor sayfası işleyicisinin adı.

ASP-Route Rotanın adı.


ÖZNITELIK AÇIKLAMA

ASP-Route-{Value} Tek bir URL yol değeri. Örneğin:


asp-route-id="1234" .

ASP-All-Route-Data Tüm rota değerleri.

ASP-Fragment URL parçası.

Denetleyiciye gönder örneği


Aşağıdaki biçimlendirme, giriş veya düğme seçildiğinde formu HomeController Index
eylemine gönderir:

<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Sayfa örneğine gönder


Aşağıdaki biçimlendirme formu About Razor sayfasına gönderir:

<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Yönlendirme örneğine gönder


/Home/Test uç noktasını göz önünde bulundurun:

public class HomeController : Controller


{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}

Aşağıdaki biçimlendirme formu /Home/Test uç noktasına gönderir.


<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Önceki biçimlendirme, aşağıdaki HTML 'yi oluşturur:

<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>

Giriş etiketi Yardımcısı


Giriş etiketi Yardımcısı, bir HTML <girişi > öğesini Razor görünüminizdeki bir model
ifadesine bağlar.
Sözdizimi:

<input asp-for="<Expression Name>">

Giriş etiketi Yardımcısı:


asp-for özniteliğinde belirtilen ifade adı için id ve HTML özniteliklerini
name
üretir. asp-for="Property1.Property2" m => m.Property1.Property2 eşdeğerdir.
İfadenin adı, asp-for özniteliği değeri için kullanılan şeydir. Ek bilgi için ifade adları
bölümüne bakın.
Model özelliğine uygulanan model türüne ve veri ek açıklaması ÖZNITELIKLERINE
göre HTML type öznitelik değerini ayarlar
Belirtilirse, HTML type öznitelik değerinin üzerine yazmaz
Model özelliklerine uygulanan veri ek açıklama özniteliklerinden HTML5 doğrulama
öznitelikleri oluşturur
Html.TextBoxFor ve Html.EditorFor bir HTML Yardımcısı özelliği örtüşüyor.
Ayrıntılar için bkz. giriş etiketi Yardımcısı Için HTML Yardımcısı alternatifleri .
Güçlü yazma sağlar. Özelliğin adı değişirse ve etiket yardımcısını
güncelleştirmezseniz aşağıdakine benzer bir hata alırsınız:

An error occurred during the compilation of a resource required to process


this request. Please review the following specific error details and modify
your source code appropriately.

Type expected
'RegisterViewModel' does not contain a definition for 'Email' and no
extension method 'Email' accepting a first argument of type 'RegisterViewModel'
could be found (are you missing a using directive or an assembly reference?)

Input Tag Yardımcısı, HTML type özniteliğini .NET türüne göre ayarlar. Aşağıdaki tabloda
bazı ortak .NET türleri ve oluşturulan HTML türü listelenmekte (her .NET türü
listelenmemiştir).
.NET TÜRÜ GIRIŞ TÜRÜ

Bool Type = "onay kutusu"

Dize Type = "metin"

DateTime Type ="TarihSaat-yerel"

Bayt Type = "Number"

int Type = "Number"

Tek, Çift Type = "Number"

Aşağıdaki tabloda, giriş etiketi Yardımcısı 'nın belirli giriş türleriyle eşleşecağı bazı ortak
veri ek açıklamaları (her doğrulama özniteliği listelenmez) gösterilmektedir:

ÖZNITELIK GIRIŞ TÜRÜ

EmailAddress Type = "e-posta"

'Deki Type = "URL"

[Hiddenınput] Type = "Hidden"

Numarası Type = "tel"

[DataType (DataType. Password)] Type = "Password"

[DataType (DataType. Date)] Type = "Date"

[DataType (DataType. Time)] yazın = "Time"

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

Yukarıdaki kod, aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Demo/RegisterInput">


Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

Email ve Password özelliklerine uygulanan veri ek açıklamaları modelde meta veriler


oluşturur. Giriş etiketi Yardımcısı, model meta verilerini kullanır ve HTML5 data-val-*
öznitelikleri üretir (bkz. model doğrulama). Bu öznitelikler, giriş alanlarına iliştirilecek
Doğrulayıcıları anlatmaktadır. Bu unobtrusive HTML5 ve jQuery doğrulaması sağlar.
Unobtrusive özniteliklerinin biçimi data-val-rule="Error Message" , burada kural
doğrulama kuralının adıdır (örneğin, data-val-required , data-val-email ,
data-val-maxlength vb.) Öznitelikte bir hata iletisi sağlanırsa, data-val-rule özniteliği için
değer olarak görüntülenir. Ayrıca, kuralla ilgili ek ayrıntılar sağlayan
data-val-ruleName-argumentName="argumentValue" form öznitelikleri de vardır, örneğin,
data-val-maxlength-max="1024" .

Giriş etiketi Yardımcısı için HTML Yardımcısı alternatifleri


Html.TextBox , Html.TextBoxFor , Html.Editor ve Html.EditorFor , giriş etiketi Yardımcısı ile
çakışan özelliklere sahiptir. Giriş etiketi Yardımcısı type özniteliğini otomatik olarak
ayarlar; Html.TextBox ve Html.TextBoxFor . Html.Editor ve Html.EditorFor tanıtıcı
koleksiyonları, karmaşık nesneler ve şablonlar; Giriş etiketi Yardımcısı yok. Giriş etiketi
Yardımcısı, Html.EditorFor ve Html.TextBoxFor kesin türdedir (lambda ifadeleri
kullanırlar); Html.TextBox ve Html.Editor değildir (ifade adlarını kullanırlar).
HtmlAttributes
@Html.Editor() ve @Html.EditorFor() , varsayılan şablonlarını yürütürken htmlAttributes
adlı özel bir ViewDataDictionary girişi kullanır. Bu davranış, isteğe bağlı olarak
additionalViewData parametreleri kullanılarak genişletilebilir. "HtmlAttributes" anahtarı
büyük/küçük harfe duyarlıdır. "HtmlAttributes" anahtarı, @Html.TextBox() gibi giriş
yardımcılarını geçirilmiş htmlAttributes nesnesine benzer şekilde işlenir.

@Html.EditorFor(model => model.YourProperty,


new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

İfade adları
asp-for öznitelik değeri, bir lambda ifadesinin bir ModelExpression ve sağ tarafıdır. Bu
nedenle, asp-for="Property1" oluşturulan kodda m => m.Property1 hale gelir ve bu
nedenle Model ile önek gerektirmez. "@" karakterini kullanarak bir satır içi ifadeyi
başlatabilir ve m. önce taşıyabilirsiniz:

@{
var joe = "Joe";
}
<input asp-for="@joe">

Şunları üretir:

<input type="text" id="joe" name="joe" value="Joe">

Koleksiyon özellikleriyle asp-for="CollectionProperty[23].Member" , i değer 23 olduğunda


asp-for="CollectionProperty[i].Member" aynı adı üretir.
ASP.NET Core MVC ModelExpression değerini hesapladığında ModelState dahil olmak
üzere çeşitli kaynakları inceler. <input type="text" asp-for="@Name"> göz önünde
bulundurun. Hesaplanan value özniteliği, öğesinden gelen ilk null olmayan değerdir:
"Name" anahtarına sahip giriş ModelState .
İfadenin sonucu Model.Name .
Alt özelliklerde gezinme
Ayrıca, görünüm modelinin özellik yolunu kullanarak alt Özellikler ' e gidebilirsiniz. Alt
Address özelliği içeren daha karmaşık bir model sınıfı düşünün.

public class AddressViewModel


{
public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel


{
public string Email { get; set; }

[DataType(DataType.Password)]
public string Password { get; set; }

public AddressViewModel Address { get; set; }


}

Görünümde Address.AddressLine1 bağlandık:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">


Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine1" /><br />
<button type="submit">Register</button>
</form>

Address.AddressLine1 için aşağıdaki HTML oluşturulmuştur:


<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

İfade adları ve koleksiyonlar


Örnek, bir dizi Colors içeren bir modeldir:

public class Person


{
public List<string> Colors { get; set; }

public int Age { get; set; }


}

Eylem yöntemi:

public IActionResult Edit(int id, int colorIndex)


{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}

Aşağıdaki Razor, belirli bir Color öğesine nasıl erişistediğinizi göstermektedir:

@model Person
@{
var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">


@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>

Views/Shared/EditorTemplates/String. cshtml şablonu:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

List<T> kullanarak örnek:

public class ToDoItem


{
public string Name { get; set; }

public bool IsDone { get; set; }


}

Aşağıdaki Razor, bir koleksiyonun üzerinde nasıl yineleme yapılacağını göstermektedir:


@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">


<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>

@for (int i = 0; i < Model.Count; i++)


{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}

</table>
<button type="submit">Save</button>
</form>

Views/Shared/EditorTemplates/TodoItem. cshtml şablonu:

@model ToDoItem

<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>

@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@

değer bir asp-for veya Html.DisplayFor denk bir bağlamda kullanılacaksa, mümkünse
foreach kullanılmalıdır. Genel olarak, for bir Numaralandırıcı ayırması gerekmiyorsa,
foreach daha iyidir (senaryo buna izin veriyorsa). Ancak, bir LINQ ifadesinde bir dizin
oluşturucuyu değerlendirmek pahalı olabilir ve simge durumuna küçültülmüş olmalıdır.

NOTE
Yukarıdaki açıklamalı örnek kod, listedeki her bir ToDoItem erişmek için lambda ifadesinin @
işleçle nasıl değiştirileceğini gösterir.

TextArea etiketi Yardımcısı


Textarea Tag Helper Tag Yardımcısı giriş etiketi Yardımcısı ile benzerdir.
id ve name özniteliklerini ve <textarea > öğesi için modelden veri doğrulama
özniteliklerini üretir.
Güçlü yazma sağlar.
HTML Yardımcısı alternatifi: Html.TextAreaFor

Örnek:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}

@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">


<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Demo/RegisterTextArea">


<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a
maximum length of &#x27;1024&#x27;."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a
minimum length of &#x27;5&#x27;."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket etiketi Yardımcısı


Bir ifade adı için bir <label > öğesinde etiket başlık yazısı ve for özniteliği oluşturur
HTML Yardımcısı alternatifi: Html.LabelFor .

Label Tag Helper , saf HTML etiket öğesi üzerinde aşağıdaki avantajları sağlar:
Display özniteliğinden açıklayıcı etiket değerini otomatik olarak alırsınız. İstenen
görünen ad zaman içinde değişebilir ve Display özniteliği ve etiket etiketi
Yardımcısı 'nın birleşimi, Display her yere uygular.
Kaynak kodunda daha az biçimlendirme
Model özelliğiyle güçlü yazma.
Örnek:
using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}

@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">


<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>

<label> öğesi için aşağıdaki HTML oluşturulur:

<label for="Email">Email Address</label>

Etiket etiketi Yardımcısı, <input> öğesiyle ilişkili KIMLIK olan "e-posta" for öznitelik
değerini oluşturdu. Etiket Yardımcıları, doğru ilişkilendirilebilen şekilde tutarlı id ve for
öğeleri oluşturur. Bu örnekteki başlık Display özniteliğinden gelir. Modelde bir Display
özniteliği yoksa, başlık ifadenin Özellik adı olacaktır.

Doğrulama etiketi yardımcıları


İki doğrulama etiketi yardımcıları vardır. Validation Message Tag Helper (modelinizdeki tek
bir özellik için bir doğrulama iletisi görüntüler) ve Validation Summary Tag Helper
(doğrulama hatalarının özetini görüntüler). Input Tag Helper , model sınıflarınızda bulunan
veri ek açıklaması özniteliklerini temel alan giriş öğelerine HTML5 istemci tarafı doğrulama
öznitelikleri ekler. Doğrulama de sunucuda gerçekleştirilir. Doğrulama etiketi Yardımcısı, bir
doğrulama hatası oluştuğunda bu hata iletilerini görüntüler.
Doğrulama Iletisi etiketi Yardımcısı
Belirtilen model özelliğinin giriş alanındaki doğrulama hatası mesajlarını bağlayan
span öğesine HTML5 data-valmsg-for="property" özniteliğini ekler. İstemci tarafı
doğrulama hatası oluştuğunda, jQuery <span> öğesinde hata iletisini görüntüler.
Doğrulama de sunucuda gerçekleşir. İstemciler JavaScript devre dışı bırakılmış
olabilir ve bazı doğrulamalar yalnızca sunucu tarafında yapılabilir.
HTML Yardımcısı alternatifi: Html.ValidationMessageFor

Validation Message Tag Helper , bir HTML span öğesinde asp-validation-for özniteliğiyle
kullanılır.

<span asp-validation-for="Email"></span>

Doğrulama Iletisi etiketi Yardımcısı aşağıdaki HTML 'yi oluşturur:


<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Aynı özellik için bir Input etiketi Yardımcısı sonrasında Validation Message Tag Helper
genellikle kullanırsınız. Bunun yapılması, hataya neden olan girişin yakınında herhangi bir
doğrulama hata iletisi görüntüler.

NOTE
İstemci tarafı doğrulaması için doğru JavaScript ve jQuery betik başvurularını içeren bir
görünümsiniz olmalıdır. Daha fazla bilgi için bkz. model doğrulaması .

Sunucu tarafı doğrulama hatası oluştuğunda (örneğin, özel sunucu tarafı doğrulamadan
veya istemci tarafı doğrulaması devre dışı bırakılmışsa), MVC bu hata iletisini <span>
öğesinin gövdesi olarak koyar.

<span class="field-validation-error" data-valmsg-for="Email"


data-valmsg-replace="true">
The Email Address field is required.
</span>

Doğrulama Özeti etiketi Yardımcısı


asp-validation-summary özniteliği olan öğeleri <div> hedefleri
HTML Yardımcısı alternatifi: @Html.ValidationSummary

Validation Summary Tag Helper , doğrulama iletilerinin özetini göstermek için kullanılır.
asp-validation-summary öznitelik değeri, aşağıdakilerden herhangi biri olabilir:

ASP-DOĞRULAMA-ÖZET GÖRÜNEN DOĞRULAMA ILETILERI

ValidationSummary. All Özellik ve model düzeyi

Yalnızca ValidationSummary. model Model

ValidationSummary. None Yok.

Örnek
Aşağıdaki örnekte, veri modelinde <input> öğesinde doğrulama hata iletileri üreten
DataAnnotation öznitelikleri vardır. Doğrulama hatası oluştuğunda, doğrulama etiketi
Yardımcısı şu hata iletisini görüntüler:
using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}

@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">


<div asp-validation-summary="ModelOnly"></div>
Email: <input asp-for="Email" /> <br />
<span asp-validation-for="Email"></span><br />
Password: <input asp-for="Password" /><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>

Oluşturulan HTML (model geçerli olduğunda):

<form action="/DemoReg/Register" method="post">


<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul></div>
Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Etiket Seç Yardımcısı


Modelinizin özellikleri için Select ve ilişkili seçenek öğeleri oluşturur.
Bir HTML Yardımcısı alternatifi Html.DropDownListFor ve Html.ListBoxFor

Select Tag Helper asp-for , Select öğesi için model özelliği adını belirtir ve asp-items
seçenek öğelerini belirtir. Örneğin:

<select asp-for="Country" asp-items="Model.Countries"></select>

Örnek:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}

Index yöntemi CountryViewModel başlatır, seçilen ülkeyi ayarlar ve Index görünümüne


geçirir.

public IActionResult Index()


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

HTTP POST Index yöntemi seçimi görüntüler:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}

// If we got this far, something failed; redisplay form.


return View(model);
}

Index görünümü:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">


<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi üreten ("CA" seçiliyken):


<form method="post" action="/">
<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

NOTE
Etiket Seç Yardımcısı ile ViewBag veya ViewData kullanmanızı önermiyoruz. Bir görünüm modeli,
MVC meta verileri sağlamaya ve genellikle daha az soruna neden olacak daha sağlamdır.

asp-for öznitelik değeri özel bir durumdur ve Model öneki gerektirmez, diğer etiket
Yardımcısı öznitelikleri olur ( asp-items gibi)

<select asp-for="Country" asp-items="Model.Countries"></select>

Sabit Listesi bağlama


<select> , enum bir özellik ile kullanmak ve enum değerlerinden SelectListItem öğeleri
oluşturmak için kullanışlıdır.
Örnek:

public class CountryEnumViewModel


{
public CountryEnum EnumCountry { get; set; }
}
}

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

GetEnumSelectList yöntemi bir numaralandırma için SelectList nesnesi oluşturur.


@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">


<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>

Daha zengin bir kullanıcı arabirimi almak için, Numaralandırıcı listenizi Display
özniteliğiyle işaretleyebilirsiniz:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}

Aşağıdaki HTML oluşturulur:

<form method="post" action="/Home/IndexEnum">


<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

Seçenek grubu
HTML <SeçenekGrubu > öğesi, görünüm modelinde bir veya daha fazla SelectListGroup
nesnesi içerdiğinde oluşturulur.
CountryViewModelGroup , SelectListItem öğelerini "Kuzey Amerika" ve "Avrupa" gruplarına
gruplandırır:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };

Countries = new List<SelectListItem>


{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}

public string Country { get; set; }

public List<SelectListItem> Countries { get; }

İki grup aşağıda gösterilmiştir:


Oluşturulan HTML:

<form method="post" action="/Home/IndexGroup">


<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

Çoklu seçim
asp-for özniteliğinde belirtilen özellik bir IEnumerable ise, select etiketi Yardımcısı
otomatik olarak birden çok = "Multiple" özniteliği oluşturacaktır. Örneğin, aşağıdaki model
verildiğinde:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }

public List<SelectListItem> Countries { get; } = new List<SelectListItem>


{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}
Aşağıdaki görünümle:

@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">


<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>

Aşağıdaki HTML 'yi oluşturur:

<form method="post" action="/Home/IndexMultiSelect">


<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Seçim yok
Birden çok sayfada "belirtilmemiş" seçeneğini kullanarak kendinizi bulursanız, HTML 'yi
yinelemeyi ortadan kaldırmak için bir şablon oluşturabilirsiniz:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>

Views/Shared/EditorTemplates/CountryViewModel. cshtml şablonu:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">


<option value="">--none--</option>
</select>

HTML <seçenek > öğeleri ekleme hiçbir seçim durumuyla sınırlı değildir. Örneğin,
aşağıdaki görünüm ve eylem yöntemi yukarıdaki koda benzer HTML oluşturur:

public IActionResult IndexNone()


{
var model = new CountryViewModel();
model.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">


<select asp-for="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>

Geçerli değerine bağlı olarak doğru


Country <option> öğesi seçilecek (
selected="selected" özniteliğini içerir ).

public IActionResult IndexOption(int id)


{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}

<form method="post" action="/Home/IndexEmpty">


<select id="Country" name="Country">
<option value="">&lt;none&gt;</option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for
brevity>">
</form>

Ek kaynaklar
ASP.NET Core etiket yardımcıları
HTML form öğesi
İstek doğrulama belirteci
ASP.NET Core 'de model bağlama
ASP.NET Core MVC 'de model doğrulaması
Iattributeadapter arabirimi
Bu belge için kod parçacıkları
ASP.NET Core bileşenleri görüntüleme
31.07.2019 • 18 minutes to read • Edit Online

Tarafından Rick Anderson


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Görünüm bileşenleri
Görünüm bileşenleri kısmi görünümlere benzerdir, ancak çok daha güçlüdür.Görüntüleme bileşenleri model
bağlama kullanmaz ve yalnızca içine çağrılırken belirtilen verilere bağımlıdır. Bu makale, denetleyiciler ve
görünümler kullanılarak yazılmıştır, ancak bileşenleri görüntüle Razor Pages ile de çalışır.
Bir görünüm bileşeni:
Tam yanıt yerine bir öbek işler.
, Bir denetleyici ve görünüm arasında aynı sorun ayrımı ve test edilebilirlik avantajları içerir.
Parametrelere ve iş mantığına sahip olabilir.
Genellikle bir düzen sayfasından çağrılır.
Görünüm bileşenleri, kısmi bir görünüm için çok karmaşık olan işleme mantığınızı her yerde, örneğin:
Dinamik gezinti menüleri
Etiket bulutu (veritabanını sorgular)
Oturum açma paneli
Alışveriş sepeti
Son yayımlanan makaleler
Normal blogdaki kenar çubuğu içeriği
Her sayfada işlenecek bir oturum açma paneli ve kullanıcının oturum açma durumuna bağlı olarak oturum
açma veya oturum açma bağlantılarını gösterme
Bir görünüm bileşeni iki bölümden oluşur: Sınıf (genellikle Viewcomponentöğesinden türetilir) ve
döndürdüğü sonuç (genellikle bir görünüm). Denetleyiciler gibi bir görünüm bileşeni de bir POCO olabilir,
ancak çoğu geliştirici, ' den ViewComponent türeterek kullanılabilir yöntemler ve özelliklerden faydalanmak ister.
Görünüm bileşenlerinin bir uygulamanın belirtimlerini karşılayıp karşılamadığını düşünürken, bunun yerine
Razor bileşenleri kullanmayı göz önünde bulundurun. Razor bileşenleri ayrıca yeniden kullanılabilir Kullanıcı
C# arabirimi birimleri oluşturmak için biçimlendirmeyi kodla birleştirir. Razor bileşenleri, istemci tarafı UI
mantığı ve kompozisyonu sağlarken geliştirici üretkenliği için tasarlanmıştır. Daha fazla bilgi için bkz.
ASP.NET Core Razor bileşenleri oluşturma ve kullanma.

Görünüm bileşeni oluşturma


Bu bölüm, bir görünüm bileşeni oluşturmak için üst düzey gereksinimleri içerir. Makalenin ilerleyen
kısımlarında, her adımı ayrıntılı olarak inceleyecek ve bir görünüm bileşeni oluşturacağız.
Görünüm bileşeni sınıfı
Bir görünüm bileşeni sınıfı, aşağıdakilerden herhangi biri tarafından oluşturulabilir:
Viewcomponent 'dan türetme
[ViewComponent] Özniteliği özniteliğiyle bir sınıfı dekorasyon veya [ViewComponent] özniteliği ile bir
sınıftan türetiliyor
Sonekin son ek Viewcomponent ile bittiği bir sınıf oluşturma
Denetleyiciler gibi, görünüm bileşenleri ortak, iç içe olmayan ve soyut olmayan sınıflar olmalıdır. Görünüm
bileşeni adı, "ViewComponent" sonekini kaldıran sınıf adıdır. Ayrıca ViewComponentAttribute.Name özelliği
kullanılarak açıkça belirtilebilir.
Bir görünüm bileşeni Sınıfı:
Oluşturucu bağımlılığı ekleme işlemini tamamen destekler
, Bir görünüm bileşeninde filtre kullanamayabilmeniz için denetleyicinin yaşam döngüsünde bir parçası
almaz
Bileşen yöntemlerini görüntüle
Bir InvokeAsync görünüm bileşeni, bir Task<IViewComponentResult> veya döndüren IViewComponentResult
zaman uyumlu Invoke bir yöntemde veya döndüren bir yöntemde mantığını tanımlar. Parametreler, model
bağlamalarından değil doğrudan görünüm bileşeni çağrısından gelir. Bir görünüm bileşeni hiçbir şekilde isteği
doğrudan işlemez. Genellikle, bir görünüm bileşeni bir modeli başlatır ve View yöntemini çağırarak bir
görünüme geçirir. Özet bölümünde bileşen yöntemlerini görüntüleyin:
Bir veya döndüren Invoke zamanuyumlu bir yöntem InvokeAsync Task<IViewComponentResult> döndüren
bir yöntem tanımlayın. IViewComponentResult
Genellikle bir modeli başlatır ve ViewComponent View yöntemini çağırarak bir görünüme geçirir.
Parametreler, HTTP değil çağırma yönteminden gelir. Model bağlama yok.
Doğrudan bir HTTP uç noktası olarak erişilemez. Bunlar, kodunuzun içinden çağrılır (genellikle bir
görünümde). Bir görünüm bileşeni hiçbir şekilde isteği hiçbir şekilde işlemez.
Geçerli HTTP isteğindeki tüm ayrıntılar yerine İmzada aşırı yüklendi.
Arama yolunu görüntüle
Çalışma zamanı, görünümü aşağıdaki yollarda arar:
/Views/{Controller adı}/Components/{View bileşen adı}/{View Name}
/Views/Shared/Components/{View bileşen adı}/{View Name}
/Pages/Shared/Components/{View bileşen adı}/{View Name}
Arama yolu, denetleyiciler + görünümler ve Razor Pages kullanan projeler için geçerlidir.
Bir görünüm bileşeni için varsayılan görünüm adı varsayılandır, yani görünüm dosyanız genellikle default.
cshtmlolarak adlandırılır. Görünüm bileşeni sonucunu oluştururken veya View yöntemini çağırırken farklı bir
görünüm adı belirtebilirsiniz.
Görünüm dosyasını default. cshtml olarak yazmanız ve görünümleri/paylaşılan/bileşenler/{görünüm bileşen
adı}/{View Name} yolunu kullanmanız önerilir. Bu örnekte kullanılan PriorityList görünüm bileşeni
görünüm bileşeni görünümü için Görünümler/paylaşılan/bileşenler/prioritylist/default. cshtml kullanır.

Bir görünüm bileşenini çağırma


Görünüm bileşenini kullanmak için, aşağıdakileri bir görünüm içinde çağırın:

@await Component.InvokeAsync("Name of view component", {Anonymous Type Containing Parameters})

Parametreleri InvokeAsync yöntemine geçirilir. Makalede geliştirilen görünüm bileşeni,


Görünümler/Todo/Index. cshtml görünüm dosyasından çağrılır. PriorityList Aşağıdaki şekilde, InvokeAsync
yöntemi iki parametreyle çağrılır:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Bir görünüm bileşenini etiket Yardımcısı olarak çağırma


ASP.NET Core 1,1 ve üzeri için bir görünüm bileşenini etiket Yardımcısıolarak çağırabilirsiniz:

<vc:priority-list max-priority="2" is-done="false">


</vc:priority-list>

Etiket Yardımcıları için Pascal özellikli sınıf ve Yöntem parametreleri, Kebab durumlarınaçevrilir. Bir görünüm
bileşenini çağırmak için etiket Yardımcısı <vc></vc> öğesini kullanır. Görünüm bileşeni aşağıdaki gibi belirtilir:

<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>

Bir görünüm bileşenini etiket Yardımcısı olarak kullanmak için, @addTagHelper yönergesini kullanarak
görünüm bileşenini içeren derlemeyi kaydedin. Görünüm bileşeniniz adlı MyWebApp bir derlemede yer alıyorsa,
_viewwimports. cshtml dosyasına aşağıdaki yönergeyi ekleyin:

@addTagHelper *, MyWebApp

Görünüm bileşenine başvuran herhangi bir dosyaya bir görünüm bileşenini etiket Yardımcısı olarak
kaydedebilirsiniz. Etiket yardımcılarını kaydetme hakkında daha fazla bilgi için bkz. etiket Yardımcısı kapsamını
yönetme .
Bu öğreticide kullanılan yöntem: InvokeAsync

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Etiket Yardımcısı biçimlendirmesinde:

<vc:priority-list max-priority="2" is-done="false">


</vc:priority-list>

Yukarıdaki örnekte, PriorityList görünüm bileşeni olur priority-list . Görünüm bileşenine yönelik
parametreler, Kebab durumunda öznitelik olarak geçirilir.
Bir görünüm bileşenini doğrudan bir denetleyiciden çağırma
Görünüm bileşenleri genellikle bir görünümden çağrılır, ancak bunları doğrudan bir denetleyici yönteminden
çağırabilirsiniz. Görüntüleme bileşenleri, denetleyiciler gibi uç noktaları tanımlamıyorsa, ' ın
ViewComponentResult içeriğini döndüren bir denetleyici eylemini kolayca uygulayabilirsiniz.

Bu örnekte, görünüm bileşeni doğrudan denetleyiciden çağrılır:

public IActionResult IndexVC()


{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
İzlenecek yol: Basit bir görünüm bileşeni oluşturma
Başlatıcı kodunu indirin, derleyin ve test edin. Bu, Yapılacaklar öğelerinin listesini görüntüleyen bir ToDo
denetleyiciyi olan basit bir projem .

ViewComponent sınıfı ekleme


Bir viewcomponents klasörü oluşturun ve aşağıdaki PriorityListViewComponent sınıfı ekleyin:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
public class PriorityListViewComponent : ViewComponent
{
private readonly ToDoContext db;

public PriorityListViewComponent(ToDoContext context)


{
db = context;
}

public async Task<IViewComponentResult> InvokeAsync(


int maxPriority, bool isDone)
{
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
}

Koda notlar:
Görünüm bileşen sınıfları projedeki herhangi bir klasörde bulunabilir.
PriorityListviewcomponent sınıf adı, son ek viewcomponentile sona ertiğinden, çalışma zamanı bir
görünümden sınıf bileşenine başvururken "prioritylist" dizesini kullanır. Daha sonra ayrıntılı olarak
açıklayacağım.
[ViewComponent] Özniteliği bir görünüm bileşenine başvurmak için kullanılan adı değiştirebilir.
Örneğin, sınıfını XYZ adlandırdık ve ViewComponent özniteliği uygulamış olduğumuz:

[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent

Yukarıdaki özniteliği görüntüle bileşen seçicisine bileşenle ilişkili görünümleri ararken adı
PriorityList kullanmasını ve bir görünümden sınıf bileşenine başvururken "prioritylist" dizesini
kullanmasını söyler. [ViewComponent] Daha sonra ayrıntılı olarak açıklayacağım.
Bileşen, veri bağlamını kullanılabilir hale getirmek için bağımlılık ekleme işlemini kullanır.
InvokeAsync bir görünümden çağrılabilen bir yöntemi gösterir ve rastgele sayıda bağımsız değişken
alabilir.
InvokeAsync ToDo Yöntemi isDone ve parametrelerinikarşılayanöğekümesinidöndürür maxPriority .
Görünüm bileşeni Razor görünümünü oluşturma
Görünümler/paylaşılan/bileşenler klasörünü oluşturun. Bu klasör, adlandırılmış Bileşenler olmalıdır .
Görünümler/paylaşılan/bileşenler/PriorityList klasörünü oluşturun. Bu klasör adı, görünüm bileşen
sınıfının adıyla ya da sınıfın adı eksi sonek ile eşleşmelidir (Bu kural izleniyorsa ve sınıf adında
Viewcomponent sonekini kullandıysanız). ViewComponent Özniteliğini kullandıysanız, sınıf adının
öznitelik atamasını eşleşmesi gerekir.
Bir Görünümler/paylaşılan/bileşenler/PriorityList/default. cshtml Razor görünümü oluşturun:

@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h3>Priority Items</h3>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>

Razor görünümü bir listesini TodoItem alır ve görüntüler. Görünüm bileşeni InvokeAsync yöntemi,
görünümün adını (örneğimizde olduğu gibi) geçirmezse, varsayılan olarak kurala göre görünüm adı
için kullanılır. Öğreticide daha sonra görünümün adının nasıl geçirileceğini göstereceğiz. Belirli bir
denetleyicinin varsayılan stilini geçersiz kılmak için denetleyiciye özgü görünüm klasörüne bir
görünüm ekleyin (örneğin, Görünümler/Todo/Components/PriorityList/default. cshtml) .
Görünüm bileşeni denetleyiciye özgü ise, denetleyiciyi denetleyiciye özgü klasöre ekleyebilirsiniz
(Görünümler/Todo/bileşenler/PriorityList/default. cshtml).
Priority listesi div bileşenine, Görünümler/Todo/index. cshtml dosyasının altına bir çağrı içeren bir
çağrı ekleyin:
</table>
<div>
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
</div>

Biçimlendirme @await Component.InvokeAsync , görünüm bileşenlerini çağırma söz dizimini gösterir. İlk
bağımsız değişken, çağırmak veya çağırmak istediğimiz bileşenin adıdır. Sonraki parametreler bileşene
geçirilir. InvokeAsync rastgele sayıda bağımsız değişken alabilir.
Uygulamayı test edin. Aşağıdaki görüntüde ToDo listesi ve öncelik öğeleri gösterilmektedir:

Görünüm bileşenini doğrudan denetleyiciden de çağırabilirsiniz:

public IActionResult IndexVC()


{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Bir görünüm adı belirtme
Karmaşık bir görünüm bileşeninin bazı koşullarda varsayılan olmayan bir görünüm belirtmesi gerekebilir.
Aşağıdaki kod, InvokeAsync yönteminden "PVC" görünümünün nasıl ekleneceğini gösterir.
PriorityListViewComponent Sınıfında InvokeAsync yöntemi güncelleştirin.

public async Task<IViewComponentResult> InvokeAsync(


int maxPriority, bool isDone)
{
string MyView = "Default";
// If asking for all completed tasks, render with the "PVC" view.
if (maxPriority > 3 && isDone == true)
{
MyView = "PVC";
}
var items = await GetItemsAsync(maxPriority, isDone);
return View(MyView, items);
}

Görünümleri/paylaşılan/bileşenler/prioritylist/default. cshtml dosyasını


views/Shared/Components/PRIORITYLIST/PVC. cshtmladlı bir görünüme kopyalayın. PVC görünümünün
kullanıldığını belirtmek için bir başlık ekleyin.

@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h2> PVC Named Priority Component View</h2>


<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>

Güncelleştirme görünümleri/Todo/Index. cshtml:

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Uygulamayı çalıştırın ve PVC görünümünü doğrulayın.


PVC görünümü işlenmemişse, görünüm bileşenini 4 veya daha yüksek bir önceliğe sahip olduğunuzu
doğrulayın.
Görünüm yolunu inceleyin
Öncelik görünümü döndürülmemesi için öncelik parametresini üç veya daha az olacak şekilde
değiştirin.
Views/Todo/Components/PriorityList/default. cshtml 'Yi 1default. cshtmlolarak geçici olarak yeniden
adlandırın.
Uygulamayı test edin, şu hatayı alırsınız:

An unhandled exception occurred while processing the request.


InvalidOperationException: The view 'Components/PriorityList/Default' wasn't found. The following
locations were searched:
/Views/ToDo/Components/PriorityList/Default.cshtml
/Views/Shared/Components/PriorityList/Default.cshtml
EnsureSuccessful

Görünümleri/ Todo/bileşenler/PriorityList/1Default. cshtml 'yi


views/Shared/Components/Prioritylist/default. cshtmlolarak kopyalayın.
Görünümün paylaşılan klasörden olduğunu göstermek için paylaşılan Todo görünümü bileşen
görünümüne bir biçimlendirme ekleyin.
Paylaşılan bileşen görünümünü test edin.
Sabit kodlanmış dizelerin önleme
Derleme zamanı güvenliğini istiyorsanız, sabit kodlanmış görünüm bileşeni adını sınıf adıyla değiştirebilirsiniz.
"ViewComponent" soneki olmadan görünüm bileşenini oluşturun:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
public class PriorityList : ViewComponent
{
private readonly ToDoContext db;

public PriorityList(ToDoContext context)


{
db = context;
}

public async Task<IViewComponentResult> InvokeAsync(


int maxPriority, bool isDone)
{
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
}

Razor görünümü using dosyanıza bir ifade ekleyin ve nameof işlecini kullanın:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>

<h2>ToDo nameof</h2>
<!-- Markup removed for brevity. -->

<div>

@*
Note:
To use the below line, you need to #define no_suffix in ViewComponents/PriorityList.cs or it
won't compile.
By doing so it will cause a problem to index as there will be multiple viewcomponents
with the same name after the compiler removes the suffix "ViewComponent"
*@

@*@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })*@


</div>

Zaman uyumlu iş gerçekleştirin


Zaman uyumsuz iş yapmanız gerekmiyorsa çerçeve Invoke zaman uyumlu bir yöntem çağırma işlemini
gerçekleştirir. Aşağıdaki yöntem, zaman uyumlu Invoke bir görünüm bileşeni oluşturur:

public class PriorityList : ViewComponent


{
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
return View(items);
}
}

Görünüm bileşeninin Razor dosyası Invoke yöntemine geçirilen dizeleri listeler


(Görünümler/giriş/bileşenler/prioritylist/default. cshtml):

@model List<string>

<h3>Priority Items</h3>
<ul>
@foreach (var item in Model)
{
<li>@item</li>
}
</ul>

Görünüm bileşeni, aşağıdaki yaklaşımlardan birini kullanarak bir Razor dosyasında (örneğin,
views/Home/Index. cshtml) çağrılır:
IViewComponentHelper
Etiket Yardımcısı
IViewComponentHelper Yaklaşımı kullanmak için şunu çağırın Component.InvokeAsync :
Görünüm bileşeni ile IViewComponentHelperRazor dosyası (örneğin, Görünümler/Home/Index. cshtml)
çağrılır.
Çağrı Component.InvokeAsync :
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })

Etiket Yardımcısını kullanmak için, @addTagHelper yönergesini kullanarak görünüm bileşenini içeren derlemeyi
kaydedin (görünüm bileşeni adlı MyWebApp bir derlemede):

@addTagHelper *, MyWebApp

Razor biçimlendirme dosyasında bileşen etiketini görüntüle yardımcısını kullanın:

<vc:priority-list max-priority="999" is-done="false">


</vc:priority-list>

Öğesinin PriorityList.InvokeYöntem imzası zaman uyumludur, ancak Razor, biçimlendirme dosyasında ile
Component.InvokeAsync metodunu bulur ve çağırır.

Tüm görünüm bileşeni parametreleri gereklidir


Bir görünüm bileşenindeki her bir parametre gerekli bir özniteliktir. Bu GitHub sorununabakın. Herhangi bir
parametre atlanırsa:
InvokeAsync Yöntem imzası eşleşmez, bu nedenle Yöntem yürütülmez.
ViewComponent hiçbir biçimlendirmeyi işlemez.
Hata oluşturulmayacak.

Ek kaynaklar
Görünümlere bağımlılık ekleme
ASP.NET Core 'de Razor dosyası derlemesi
6.12.2019 • 6 minutes to read • Edit Online

Tarafından Rick Anderson


Bir Razor dosyası, ilişkili MVC görünümü çağrıldığında çalışma zamanında derlenir. Derleme zamanı Razor
dosyası yayımlama desteklenmiyor. Razor dosyaları isteğe bağlı olarak yayımlama zamanında derlenebilir ve ön
derleme Aracı kullanılarak uygulama—dağıtılabilir.
Razor dosyası, ilişkili Razor sayfası veya MVC görünümü çağrıldığında çalışma zamanında derlenir. Derleme
zamanı Razor dosyası yayımlama desteklenmiyor. Razor dosyaları isteğe bağlı olarak yayımlama zamanında
derlenebilir ve ön derleme Aracı kullanılarak uygulama—dağıtılabilir.
Razor dosyası, ilişkili Razor sayfası veya MVC görünümü çağrıldığında çalışma zamanında derlenir. Razor
dosyaları, Razor SDKkullanılarak hem derlemede hem de yayımlama zamanında derlenir.
. Cshtml uzantılı Razor dosyaları, Razor SDKkullanılarak hem derlemede hem de yayımlama zamanında derlenir.
Çalışma zamanı derlemesi, uygulamanız yapılandırılarak isteğe bağlı olarak etkinleştirilebilir.

Razor derleme
Razor dosyalarının derleme ve yayımlama zamanı derlemesi, Razor SDK tarafından varsayılan olarak
etkinleştirilmiştir. Etkinleştirildiğinde, çalışma zamanı derlemesi derleme zamanı derlemesini tamamlar ve bunlar
düzenlendiklerinde, Razor dosyalarının güncelleştirilmesine izin verir.
Razor dosyalarının derleme ve yayımlama zamanı derlemesi, Razor SDK tarafından varsayılan olarak
etkinleştirilmiştir. Razor dosyalarını güncelleştirildikten sonra düzenlediğinizde derleme zamanında desteklenir.
Varsayılan olarak, yalnızca derlenen views. dll ve No . cshtml dosyaları ya da Razor dosyalarını derlemek için
gerekli derlemeler, uygulamanız ile dağıtılır.

IMPORTANT
Ön derleme aracı kullanım dışı bırakılmıştır ve ASP.NET Core 3,0 ' de kaldırılacak. Razor SDK'ya geçiş yapmanızı öneririz.
Razor SDK yalnızca proje dosyasında ön derleme özgü hiçbir özellik ayarlanmamışsa etkilidir. Örneğin, . csproj dosyasının
MvcRazorCompileOnPublish özelliğinin true olarak ayarlanması Razor SDK 'sını devre dışı bırakır.

Projeniz .NET Framework hedefliyorsa Microsoft. AspNetCore. Mvc. Razor. ViewCompilation NuGet paketini
yükler:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation"
Version="2.0.4"
PrivateAssets="All" />

Projeniz .NET Core 'u hedefliyorsa, hiçbir değişiklik yapılması gerekmez.


ASP.NET Core 2. x proje şablonları, varsayılan olarak MvcRazorCompileOnPublish özelliğini true olarak ayarlar.
Sonuç olarak, bu öğe . csproj dosyasından güvenle kaldırılabilir.
IMPORTANT
Ön derleme aracı kullanım dışı bırakılmıştır ve ASP.NET Core 3,0 ' de kaldırılacak. Razor SDK'ya geçiş yapmanızı öneririz.
ASP.NET Core 2,0 ' de otomatik olarak barındırılan bir dağıtım (SCD) gerçekleştirilirken Razor dosyası ön derlemesi
kullanılamaz.

özelliğini true olarak ayarlayın ve Microsoft. AspNetCore. Mvc. Razor.


MvcRazorCompileOnPublish
ViewCompilation NuGet paketini yükler. Aşağıdaki . csproj örneği bu ayarları vurgular:

<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="1.1.0-*" />
</ItemGroup>
</Project>

.NET Core CLI Publish komutuylauygulamayı çerçeveye bağlı bir dağıtım için hazırlayın. Örneğin, proje kökünde
aşağıdaki komutu yürütün:

dotnet publish -c Release

Bir <project_name >. Derlenen Razor dosyalarını içeren PrecompiledViews. dll dosyası, ön derleme başarılı
olduğunda üretilir. Örneğin, aşağıdaki ekran görüntüsünde WebApplication1. PrecompiledViews. dlliçindeki
Index. cshtml 'nin içerikleri gösterilmektedir:

Çalışma zamanı derlemesi


Yapı zamanı derlemesi, Razor dosyalarının çalışma zamanı derlemesi tarafından belirlenir. ASP.NET Core MVC,
bir . cshtml dosyasının Içeriği değiştiğinde Razor dosyalarını yeniden derleyerek.
Yapı zamanı derlemesi, Razor dosyalarının çalışma zamanı derlemesi tarafından belirlenir.
RazorViewEngineOptions AllowRecompilingViewsOnFileChange, Razor dosyalarının (Razor görünümleri ve
Razor Pages) yeniden derlendiğini ve dosyaların diskte değiştirilmesi durumunda güncelleştirilip
güncelleştirilmediğini belirleyen bir değer alır veya ayarlar.
Varsayılan değer için true :
Uygulamanın uyumluluk sürümü Version_2_1 veya daha önceki bir sürüme ayarlandıysa
Uygulamanın uyumluluk sürümü Version_2_2 veya üzeri olarak ayarlandıysa ve uygulama geliştirme
ortamındaysanız IsDevelopment. Diğer bir deyişle, AllowRecompilingViewsOnFileChange açıkça
ayarlanmamışsa Razor dosyaları geliştirme dışı ortamda yeniden derlenmemiş.
Uygulamanın uyumluluk sürümünü ayarlamaya yönelik rehberlik ve örnekler için bkz. ASP.NET Core MVC için
uyumluluk sürümü.
Tüm ortamlar ve yapılandırma modları için çalışma zamanı derlemesini etkinleştirmek için:
1. Microsoft. AspNetCore. Mvc. Razor. RuntimeCompilation NuGet paketini yükler.
2. Projenin Startup.ConfigureServices yöntemini AddRazorRuntimeCompilation çağrısı içerecek şekilde
güncelleştirin. Örneğin:

public void ConfigureServices(IServiceCollection services)


{
services.AddRazorPages()
.AddRazorRuntimeCompilation();

// code omitted for brevity


}

Çalışma zamanı derlemesini koşullu olarak etkinleştir


Çalışma zamanı derlemesi, yalnızca yerel geliştirme için kullanılabilir olacak şekilde etkinleştirilebilir. Bu şekilde
koşullu etkinleştirme, yayımlanan çıktının olmasını sağlar:
Derlenmiş görünümleri kullanır.
Boyutu küçüktür.
, İzleyicileri dosyasını üretimde etkinleştirmez.
Çalışma zamanı derlemesini ortam ve yapılandırma moduna göre etkinleştirmek için:
1. Etkin Configuration değerini temel alarak Microsoft. AspNetCore. Mvc. Razor. RuntimeCompilation
paketine koşullu olarak başvurun:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.0"


Condition="'$(Configuration)' == 'Debug'" />

2. Projenin Startup.ConfigureServices yöntemini AddRazorRuntimeCompilation çağrısı içerecek şekilde


güncelleştirin. AddRazorRuntimeCompilation , yalnızca ASPNETCORE_ENVIRONMENT değişkeni Development olarak
ayarlandığında hata ayıklama modunda çalışacak şekilde koşullu olarak yürütün:

public IWebHostEnvironment Env { get; set; }

public void ConfigureServices(IServiceCollection services)


{
IMvcBuilder builder = services.AddRazorPages();

#if DEBUG
if (Env.IsDevelopment())
{
builder.AddRazorRuntimeCompilation();
}
#endif

// code omitted for brevity


}
Ek kaynaklar
ASP.NET Core MVC 'deki görünümler
ASP.NET Core Razor Pages giriş
ASP.NET Core MVC 'deki görünümler
ASP.NET Core Razor Pages giriş
ASP.NET Core MVC 'deki görünümler
ASP.NET Core Razor SDK 'Sı
ASP.NET Core 'de uygulama modeliyle çalışma
6.12.2019 • 15 minutes to read • Edit Online

Steve Smith tarafından


ASP.NET Core MVC, MVC uygulamasının bileşenlerini temsil eden bir uygulama modeli tanımlar. MVC öğelerinin
nasıl davrandığını değiştirmek için bu modeli okuyabilir ve düzenleyebilirsiniz. Varsayılan olarak, MVC, hangi
sınıfların denetleyici olduğunu belirlemek için bazı kuralları izler, bu sınıfların hangi yöntemlerin eylem olduğunu ve
parametrelerin ve yönlendirmenin nasıl davranacağını sağlar. Kendi kurallarınızı oluşturarak ve bunları küresel
olarak veya öznitelik olarak uygulayarak, uygulamanızın gereksinimlerine uyacak şekilde bu davranışı
özelleştirebilirsiniz.

Modeller ve sağlayıcılar
ASP.NET Core MVC uygulama modeli, hem soyut arabirimleri hem de bir MVC uygulamasını tanımlayan somut
uygulama sınıflarını içerir. Bu model, uygulamanın denetleyicilerini, eylemlerini, eylem parametrelerini, yolları ve
filtreleri varsayılan kurallara göre bulma hakkında MVC 'nin sonucudur. Uygulama modeliyle çalışarak,
uygulamanızı varsayılan MVC davranışından farklı kurallara göre izlemek için değiştirebilirsiniz. Parametrelerin,
adların, yolların ve filtrelerin hepsi, Eylemler ve denetleyiciler için yapılandırma verileri olarak kullanılır.
ASP.NET Core MVC uygulama modeli aşağıdaki yapıya sahiptir:
ApplicationModel
Denetleyiciler (ControllerModel)
Eylemler (ActionModel)
Parametreler (ParameterModel)
Modelin her düzeyinin ortak bir Properties koleksiyonuna erişimi vardır ve alt düzeyler hiyerarşide daha yüksek
düzeyler tarafından ayarlanan özellik değerlerine erişebilir ve üzerine yazabilir. Eylemler oluşturulduğunda
Özellikler ActionDescriptor.Properties kalıcı hale getirilir. Bir istek işlenirken, bir kurala eklenen veya değiştirilen
tüm özelliklere ActionContext.ActionDescriptor.Properties aracılığıyla erişilebilir. Özellikleri kullanmak, filtrelerinizi,
model ciltlerinizi, vb. her eylem temelinde yapılandırmanın harika bir yoludur.

NOTE
Uygulama başlatma işlemi tamamlandıktan sonra ActionDescriptor.Properties koleksiyonu iş parçacığı güvenli değildir
(yazma işlemleri için). Kurallar, bu koleksiyona güvenle veri eklemenin en iyi yoludur.

Iapplicationmodelprovider
ASP.NET Core MVC, ıapplicationmodelprovider arabirimi tarafından tanımlanan bir sağlayıcı modeli kullanarak
uygulama modelini yükler. Bu bölümde, bu sağlayıcının nasıl çalıştığı hakkında bazı iç uygulama ayrıntıları ele
alınmaktadır. Bu gelişmiş bir konudur. uygulama modelinden yararlanan birçok uygulama, kurallara göre çalışır.
Her uygulamayla, Order özelliğine göre artan sırada OnProvidersExecuting arayan IApplicationModelProvider
arabiriminin "Wrap" uygulamaları diğeri. OnProvidersExecuted yöntemi daha sonra ters sırada çağrılır. Framework
çeşitli sağlayıcıları tanımlar:
İlk ( Order=-1000 ):
DefaultApplicationModelProvider
Sonra ( Order=-990 ):
AuthorizationApplicationModelProvider
CorsApplicationModelProvider

NOTE
Order için aynı değere sahip iki sağlayıcının çağrılmasıyla ilgili sıralama tanımsız ve bu nedenle güvenmemelidir.

NOTE
IApplicationModelProvider , çerçeve yazarlarının genişlemesine yönelik gelişmiş bir kavramdır. Genel olarak, uygulamalar,
sağlayıcıları kullanması gereken kuralları ve çerçeveleri kullanmalıdır. Anahtar ayrımı, sağlayıcıların kuralların önüne her zaman
çalıştırılacağı bir değer.

DefaultApplicationModelProvider , ASP.NET Core MVC tarafından kullanılan varsayılan davranışların çoğunu


belirler. Sorumlulukları şunları içerir:
Bağlama genel filtreler ekleme
Bağlama denetleyicilere ekleniyor
Genel denetleyici yöntemlerini eylem olarak ekleme
Bağlama eylem yöntemi parametreleri ekleme
Yol ve diğer öznitelikler uygulanıyor
Bazı yerleşik davranışlar DefaultApplicationModelProvider uygulanır. Bu sağlayıcı, ActionModel , PropertyModel ve
ParameterModel örneklerine başvuran ControllerModel oluşturmaktan sorumludur.
DefaultApplicationModelProvider sınıfı, gelecekte değiştirecek bir iç çerçeve uygulama ayrıntısıyla sonuçlanır.

AuthorizationApplicationModelProvider, AuthorizeFilter ve AllowAnonymousFilter öznitelikleriyle ilişkili davranışı


uygulamaktan sorumludur. Bu öznitelikler hakkında daha fazla bilgi edinin.
CorsApplicationModelProvider , IEnableCorsAttribute ve IDisableCorsAttribute ve DisableCorsAuthorizationFilter
ilişkili davranışı uygular. CORS hakkında daha fazla bilgi edinin.

Kurallar
Uygulama modeli, modellerin tüm model veya sağlayıcıyı geçersiz kılmasından daha basit bir yol sağlayan kural
soyutlamalarını tanımlar. Bu soyutlamalar, uygulamanızın davranışını değiştirmek için önerilen yoldur.Kurallar,
özelleştirmeleri dinamik olarak uygulayacak kodu yazmanız için bir yol sağlar. Filtreler çerçeve davranışının
değiştirilmesini sağlayan bir yol sağlarken, özelleştirmeler uygulamanın tamamının birlikte nasıl çalıştığını
denetlemenizi sağlar.
Aşağıdaki kurallar kullanılabilir:
IApplicationModelConvention
IControllerModelConvention
IActionModelConvention
IParameterModelConvention

Kurallar, MVC seçeneklerine eklenerek veya Attribute s uygulayarak ve bunları denetleyicilere, eylemlere veya
eylem parametrelerine uygulayarak ( Filters benzer şekilde) uygulanır. Filtrelerin aksine, kurallar yalnızca
uygulama başlatıldığında yürütülür, her isteğin bir parçası olarak değildir.
Örnek: ApplicationModel değiştirme
Aşağıdaki kural uygulama modeline bir özellik eklemek için kullanılır.

using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
public class ApplicationDescription : IApplicationModelConvention
{
private readonly string _description;

public ApplicationDescription(string description)


{
_description = description;
}

public void Apply(ApplicationModel application)


{
application.Properties["description"] = _description;
}
}
}

Startup``ConfigureServices MVC eklendiğinde, uygulama modeli kuralları seçenek olarak uygulanır.

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
//options.Conventions.Add(new IdsMustBeInRouteParameterModelConvention());
});
}

Özellikler, denetleyici eylemleri içindeki ActionDescriptor özellikleri koleksiyonundan erişilebilir:

public class AppModelController : Controller


{
public string Description()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}

Örnek: ControllerModel açıklamasını değiştirme


Önceki örnekte olduğu gibi, denetleyici modeli de özel özellikler içerecek şekilde değiştirilebilir. Bunlar, varolan
özellikleri uygulama modelinde belirtilen adla geçersiz kılar. Aşağıdaki kural özniteliği, denetleyici düzeyine bir
açıklama ekler:
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
public class ControllerDescriptionAttribute : Attribute, IControllerModelConvention
{
private readonly string _description;

public ControllerDescriptionAttribute(string description)


{
_description = description;
}

public void Apply(ControllerModel controllerModel)


{
controllerModel.Properties["description"] = _description;
}
}
}

Bu kural, bir denetleyiciye bir öznitelik olarak uygulanır.

[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}

"Description" özelliğine, önceki örneklerde olduğu gibi erişilir.


Örnek: ActionModel açıklamasını değiştirme
Ayrı bir öznitelik kuralı tek tek eylemlere uygulanabilir, uygulama veya denetleyici düzeyinde zaten uygulanmış
davranışı geçersiz kılar.

using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
public class ActionDescriptionAttribute : Attribute, IActionModelConvention
{
private readonly string _description;

public ActionDescriptionAttribute(string description)


{
_description = description;
}

public void Apply(ActionModel actionModel)


{
actionModel.Properties["description"] = _description;
}
}
}

Bu, önceki örnekte denetleyicinin içindeki bir eyleme uygulandığında, denetleyici düzeyi kuralı nasıl geçersiz
kılacağını gösterir:
[ControllerDescription("Controller Description")]
public class DescriptionAttributesController : Controller
{
public string Index()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}

[ActionDescription("Action Description")]
public string UseActionDescriptionAttribute()
{
return "Description: " + ControllerContext.ActionDescriptor.Properties["description"];
}
}

Örnek: ParameterModel değiştirme


Aşağıdaki kural, BindingInfo değiştirmek için eylem parametrelerine uygulanabilir. Aşağıdaki kural parametrenin
bir yol parametresi olmasını gerektirir; diğer olası bağlama kaynakları (sorgu dizesi değerleri gibi) yok sayılır.

using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace AppModelSample.Conventions
{
public class MustBeInRouteParameterModelConvention : Attribute, IParameterModelConvention
{
public void Apply(ParameterModel model)
{
if (model.BindingInfo == null)
{
model.BindingInfo = new BindingInfo();
}
model.BindingInfo.BindingSource = BindingSource.Path;
}
}
}

Öznitelik herhangi bir eylem parametresine uygulanabilir:

public class ParameterModelController : Controller


{
// Will bind: /ParameterModel/GetById/123
// WON'T bind: /ParameterModel/GetById?id=123
public string GetById([MustBeInRouteParameterModelConvention]int id)
{
return $"Bound to id: {id}";
}
}

Örnek: ActionModel adını değiştirme


Aşağıdaki kural, uygulandığı eylemin adını güncelleştirmek için ActionModel değiştirir. Yeni ad, özniteliğe bir
parametre olarak sağlanır. Bu yeni ad yönlendirme tarafından kullanılır, bu nedenle bu eylem yöntemine ulaşmak
için kullanılan yolu etkileyecektir.
using System;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
public class CustomActionNameAttribute : Attribute, IActionModelConvention
{
private readonly string _actionName;

public CustomActionNameAttribute(string actionName)


{
_actionName = actionName;
}

public void Apply(ActionModel actionModel)


{
// this name will be used by routing
actionModel.ActionName = _actionName;
}
}
}

Bu öznitelik HomeController bir eylem yöntemine uygulanır:

// Route: /Home/MyCoolAction
[CustomActionName("MyCoolAction")]
public string SomeName()
{
return ControllerContext.ActionDescriptor.ActionName;
}

Yöntem adı olsa da öznitelik, yöntem adını kullanmanın MVC kuralını geçersiz kılar ve eylem adını
SomeName
MyCoolAction olarak değiştirir. Bu nedenle, bu eyleme ulaşmak için kullanılan yol /Home/MyCoolAction .

NOTE
Bu örnek temelde, yerleşik ActionName özniteliği kullanılarak aynıdır.

Örnek: özel yönlendirme kuralı


Yönlendirmenin nasıl çalıştığını özelleştirmek için bir IApplicationModelConvention kullanabilirsiniz. Örneğin,
aşağıdaki kural, denetleyiciler ' ad alanlarını rotalarıyla birleştirir ve ad alanındaki . , rotadaki / olacak şekilde
değiştirir:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;

namespace AppModelSample.Conventions
{
public class NamespaceRoutingConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
var hasAttributeRouteModels = controller.Selectors
.Any(selector => selector.AttributeRouteModel != null);

if (!hasAttributeRouteModels
&& controller.ControllerName.Contains("Namespace")) // affect one controller in this sample
{
// Replace the . in the namespace with a / to create the attribute route
// Ex: MySite.Admin namespace will correspond to MySite/Admin attribute route
// Then attach [controller], [action] and optional {id?} token.
// [Controller] and [action] is replaced with the controller and action
// name to generate the final template
controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
{
Template = controller.ControllerType.Namespace.Replace('.', '/') +
"/[controller]/[action]/{id?}"
};
}
}

// You can continue to put attribute route templates for the controller actions depending on the
way you want them to behave
}
}
}

Kural başlangıçta bir seçenek olarak eklenir.

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("My Application Description"));
options.Conventions.Add(new NamespaceRoutingConvention());
//options.Conventions.Add(new IdsMustBeInRouteParameterModelConvention());
});
}

TIP
services.Configure<MvcOptions>(c => c.Conventions.Add(YOURCONVENTION)); kullanarak MvcOptions erişerek, Ara
yazılıma kurallar ekleyebilirsiniz

Bu örnek, denetleyicinin adında "namespace" özelliği bulunan öznitelik yönlendirme kullanmayan yollara bu kuralı
uygular. Aşağıdaki denetleyicide bu kural gösterilmektedir:
using Microsoft.AspNetCore.Mvc;

namespace AppModelSample.Controllers
{
public class NamespaceRoutingController : Controller
{
// using NamespaceRoutingConvention
// route: /AppModelSample/Controllers/NamespaceRouting/Index
public string Index()
{
return "This demonstrates namespace routing.";
}
}
}

WebApiCompatShim 'de uygulama modeli kullanımı


ASP.NET Core MVC, ASP.NET Web API 2 ' den farklı bir kural kümesi kullanır. Özel kuralları kullanarak, bir
ASP.NET Core MVC uygulamasının davranışını bir Web API uygulaması ile tutarlı olacak şekilde değiştirebilirsiniz.
Microsoft bu amaçla WebApiCompatShim 'i özel olarak sevk eder.

NOTE
ASP.NET Web API 'sinden geçişhakkında daha fazla bilgi edinin.

Web API 'SI uyumluluk dolgusu 'nı kullanmak için, paketi projenize eklemeniz ve sonra
Startup``AddWebApiConventions çağırarak kuralları MVC 'ye eklemeniz gerekir:

services.AddMvc().AddWebApiConventions();

Dolgu tarafından belirtilen kurallar yalnızca belirli özniteliklerin uygulanmış olduğu uygulamanın bölümlerine
uygulanır. Aşağıdaki dört öznitelik, hangi denetleyicilerin kendi kurallarını Shim 'in kuralları tarafından
değiştirildiğini denetlemek için kullanılır:
UseWebApiActionConventionsAttribute
UseWebApiOverloadingAttribute
UseWebApiParameterConventionsAttribute
UseWebApiRoutesAttribute
Eylem kuralları
UseWebApiActionConventionsAttribute , HTTP yöntemini adına göre eylemlerle eşlemek için kullanılır (örneğin, Get
HttpGet eşlenir ). Yalnızca öznitelik yönlendirme kullanmayan eylemler için geçerlidir.

Aşırı Yükleme
UseWebApiOverloadingAttribute , WebApiOverloadingApplicationModelConvention kuralını uygulamak için kullanılır. Bu
kural, aday eylemlerini isteğin tüm isteğe bağlı olmayan parametreleri karşılayan olanlarla sınırlayan eylem seçimi
işlemine bir OverloadActionConstraint ekler.
Parametre kuralları
UseWebApiParameterConventionsAttribute , WebApiParameterConventionsApplicationModelConvention eylem kuralını
uygulamak için kullanılır. Bu kural, eylem parametreleri olarak kullanılan basit türlerin varsayılan olarak URI 'den
bağlandığı, karmaşık türlerin istek gövdesinden bağlandığı bir şekilde belirtir.
Rotalar
UseWebApiRoutesAttribute , WebApiApplicationModelConvention denetleyicisi kuralının uygulanıp uygulanmadığını
denetler. Bu kural etkinleştirildiğinde, rotadaki alanlara yönelik destek eklemek için kullanılır.
Bir kural kümesine ek olarak, uyumluluk paketi, Web API 'SI tarafından sağlanarak yerine geçen bir
System.Web.Http.ApiController taban sınıfı içerir. Bu, denetleyicilerinizin Web API 'SI için yazılmasını ve
ApiController ASP.NET Core MVC üzerinde çalıştırılırken tasarlandıkları şekilde çalışmasını sağlar. Daha önce
listelenen tüm UseWebApi* öznitelikleri, temel denetleyici sınıfına uygulanır. ApiController , Web API 'sinde
bulunan özelliklerle uyumlu özellikleri, yöntemleri ve sonuç türlerini kullanıma sunar.

Uygulamanızı belgelemek için ApiExplorer kullanma


Uygulama modeli, uygulamanın yapısına çapraz geçiş için kullanılabilecek her düzeyde bir ApiExplorer özelliği
sunar. Bu, Swagger gibi araçları kullanarak Web API 'leriniz için yardım sayfaları oluşturmaküzere kullanılabilir.
ApiExplorer özelliği, uygulamanızın modelinin hangi bölümlerinin sunulduğunu belirtmek üzere ayarlanabilir bir
IsVisible özelliğini kullanıma sunar. Bu ayarı, bir kuralı kullanarak yapılandırabilirsiniz:

using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace AppModelSample.Conventions
{
public class EnableApiExplorerApplicationConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
application.ApiExplorer.IsVisible = true;
}
}
}

Bu yaklaşımı (ve gerekirse ek kuralları) kullanarak uygulamanızın içindeki herhangi bir düzeyde API görünürlüğünü
etkinleştirebilir veya devre dışı bırakabilirsiniz.
ASP.NET Core filtreler
23.11.2019 • 33 minutes to read • Edit Online

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 (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 döndürür).
Ç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, görünümler içeren Razor Pages, API denetleyicileri ve denetleyiciler için geçerlidir.
Ö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.

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 yetkisiz ise işlem hattı kısa devre dışı.
Kaynak filtreleri:
Yetkilendirmeden sonra çalıştırın.
OnResourceExecuting, filtre işlem hattının geri kalanının önüne kod çalıştırabilir. Örneğin
OnResourceExecuting , model bağlamadan önce kodu çalıştırabilir.
OnResourceExecuted, ardışık düzenin geri kalanı tamamlandıktan sonra kodu çalıştırabilir.
Eylem filtreleri , tek bir eylem yöntemi çağrıldıktan hemen önce ve sonra kodu çalıştırabilir. Bir eyleme
geçirilen bağımsız değişkenleri ve eylemden döndürülen sonucu işlemek için kullanılabilirler. Eylem
filtreleri Razor Pages desteklenmez.
Özel durum filtreleri , yanıt gövdesine hiçbir şey yazılmadan önce oluşan işlenmemiş özel durumlara
genel ilkeler uygulamak için kullanılır.
Sonuç filtreleri , tek tek eylem sonuçlarının yürütülmesinden hemen önce ve sonra kodu çalıştırabilir.
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.

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 ( On-Stage-Executing ) ve sonra kodu çalıştırabilir (
On-Stage-Executed ). Ö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.
}

public void OnActionExecuted(ActionExecutedContext context)


{
// Do something after the action executes.
}
}

Zaman uyumsuz filtreler bir On-Stage-ExecutionAsync yöntemi 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 yürüten bir ActionExecutionDelegate ( next )


sahiptir. On-Stage-ExecutionAsync yöntemlerinin her biri, filtrenin ardışık düzen aşamasını yürüten bir
FilterType-ExecutionDelegate alır.

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ı
IActionFilter , IResultFilter ve zaman uyumsuz eşdeğerlerini 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.
ActionFilterAttribute gibi soyut sınıflar kullanılırken, yalnızca zaman uyumlu yöntemleri veya her bir filtre
türü için zaman uyumsuz yöntemi 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", "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 arabirimlerinden birkaçı, özel uygulamalar için temel sınıflar olarak kullanılabilecek karşılık gelen
özniteliklere sahiptir.
Filtre öznitelikleri:
ActionFilterAttribute
ExceptionFilterAttribute
ResultFilterAttribute
FormatFilterAttribute
ServiceFilterAttribute
TypeFilterAttribute

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


Üç kapsamındanbirindeki işlem hattına bir filtre eklenebilir:
Bir eylem üzerinde bir öznitelik kullanma.
Bir denetleyicide bir özniteliği 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ı
İş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.
Denetleyici filtrelerinden önceki kod.
Eylem yöntemi filtrelerinden önceki kod.
Eylem yöntemi filtrelerinden sonraki kod.
Denetleyici filtrelerinden sonraki kod.
Genel filtrelerin sonraki kodu.
Zaman uyumlu eylem filtreleri için filtre yöntemlerinin çağrıldığı sırayı gösteren aşağıdaki örnek.

SEQUENCE FILTRE KAPSAMI FILTER YÖNTEMI

1 Global OnActionExecuting

2 Denetleyici OnActionExecuting

3 Yöntem OnActionExecuting

4 Yöntem OnActionExecuted

5 Denetleyici OnActionExecuted

6 Global OnActionExecuted

Bu sıra şunları gösterir:


Yöntem filtresi, denetleyici filtresi içinde iç içe geçmiş.
Denetleyici filtresi, genel filtrenin içinde iç içe geçmiş.
Denetleyici ve Razor sayfa düzeyi filtreleri
Controller temel sınıfından devralan her denetleyici Controller. OnActionExecuting, Controller.
OnActionExecutionAsyncve controller. onactionyürütülmüş OnActionExecuted yöntemlerini içerir. Bu
Yöntemler:
Belirli bir eylem için çalışan filtreleri sarın.
OnActionExecuting , eylemin filtrelerinden herhangi birinin önüne çağırılır.
OnActionExecuted tüm eylem filtrelerinden sonra çağrılır.
, eylemin filtrelerinden herhangi birinin önüne çağırılır.
OnActionExecutionAsync next sonra filtre içindeki
kod eylem yönteminden sonra çalışır.
Örneğin, indirme örneğinde MySampleActionFilter , başlangıçta genel olarak uygulanır.
TestController :
FilterTest2 eyleme SampleActionFilterAttribute ( [SampleActionFilter] ) uygular.
OnActionExecuting ve OnActionExecuted geçersiz kılar.

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);
}
}

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


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

Razor Pages için bkz. filtre yöntemlerini geçersiz kılarak Razor sayfası filtrelerini uygulama.
Varsayılan sırayı geçersiz kılma
Varsayılan yürütme sırası IOrderedFilteruygulayarak geçersiz kılınabilir. IOrderedFilter , yürütme sırasını
belirlemede kapsama göre öncelik alan Order özelliğini kullanıma sunar. Daha düşük bir Order değerine
sahip bir filtre:
Daha yüksek bir Order bir filtrenin önüne kodundan önce kodu çalıştırır.
Daha yüksek Order değerine sahip bir filtrenin sonrasında koddan sonra çalışır.

Order özelliği bir Oluşturucu parametresiyle ayarlanabilir:

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

Yukarıdaki örnekte gösterilen 3 eylem filtresini göz önünde bulundurun. Denetleyicinin ve genel filtrelerin
Order özelliği sırasıyla 1 ve 2 ' ye ayarlandıysa, yürütme sırası tersine çevrilir.
SEQUENCE FILTRE KAPSAMI ORDER ÖZELLIĞI FILTER YÖNTEMI

1 Yöntem 0 OnActionExecuting

2 Denetleyici 1 OnActionExecuting

3 Global 2 OnActionExecuting

4 Global 2 OnActionExecuted

5 Denetleyici 1 OnActionExecuted

6 Yöntem 0 OnActionExecuted

Order özelliği filtrelerin çalıştırıldığı sırayı belirlerken 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 tümü IOrderedFilter uygular ve
varsayılan Order değerini 0 olarak ayarlar. Yerleşik filtreler için, Order sıfır olmayan bir değere
ayarlanmadığı takdirde kapsam sıralamayı belirler.

İptal ve kısa devre dışı


Filtre işlem hattı, filtre yöntemine sunulan ResourceExecutingContext parametresindeki Result özelliği
ayarlanarak kısa devre dışı olabilir. Ö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, hem ShortCircuitingResourceFilter hem de AddHeader filtresi SomeResource Action


metodunu hedefleyin. ShortCircuitingResourceFilter :
Önce bir kaynak filtresi olduğundan ve AddHeader bir eylem filtresi olduğundan, önce çalışır.
Kısa süreli işlem hattının geri kalanı.
Bu nedenle AddHeader filtresi SomeResource eylemi için hiçbir şekilde çalışmamayacaktır. Her iki filtre de
eylem yöntemi düzeyinde uygulanırsa, ShortCircuitingResourceFilter ilk kez çalıştırıldıysa bu davranış aynı
olur. ShortCircuitingResourceFilter , filtre türü veya Order özelliğinin açık kullanımı nedeniyle önce çalışır.
[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:
ServiceFilterAttribute
TypeFilterAttribute
IFilterFactory özniteliğe uygulandı.
Ö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 ConfigureServices kaydedilir. ServiceFilterAttribute, bir filtrenin bir örneğini
dı öğesinden alır.
Aşağıdaki kod 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.
}
}

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

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 dı öğesinden AddHeaderResultServiceFilter filtrenin bir örneğini


alır:

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

ServiceFilterAttribute kullanırken, Servicefilterattribute. ısyeniden kullanılabilirolarak ayarlanıyor:


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 IFilterFactoryuygular. IFilterFactory , bir IFilterMetadata örneği oluşturmak için
CreateInstance yöntemini kullanıma sunar. CreateInstance , belirtilen türü DI 'dan yükler.
TypeFilterAttribute
TypeFilterAttribute ServiceFilterAttributebenzerdir, ancak türü doğrudan dı kapsayıcısından çözümlenmez.
Microsoft.Extensions.DependencyInjection.ObjectFactorykullanarak türü başlatır.
TypeFilterAttribute türler doğrudan dı kapsayıcısından çözümlenmediğinden:
TypeFilterAttribute kullanılarak başvurulan türlerin dı kapsayıcısına kaydedilmesi 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.

TypeFilterAttribute kullanırken Typefilterattribute. ıyeniden kullanılabilirolarak ayarlanıyor:


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 TypeFilterAttribute kullanarak bir türe bağımsız değişkenlerin nasıl geçirileceğini gösterir:

[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:
IResourceFilter ya da IAsyncResourceFilter arabirimini uygulayın.
Yürütme, filtre işlem hattının çoğunu sarmalar.
Kaynak filtrelerinden önce yalnızca Yetkilendirme filtreleri çalışır.
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:
Daha önce gösterilen kısa devre dışı kaynak filtresi .
Disableformvaluemodelbindingattribute:
Model bağlamanın form verilerine erişimini engeller.
Form verilerinin belleğe okunmasını engellemek için büyük dosya yüklemeleri için kullanılır.

Eylem filtreleri
IMPORTANT
Eylem filtreleri Razor Pages için uygulanmaz. Razor Pages IPageFilter ve IAsyncPageFilter destekler. Daha fazla bilgi
için bkz. Razor Pages Için filtre yöntemleri.

Eylem filtreleri:
IActionFilter ya da IAsyncActionFilter arabirimini uygulayın.
Yürütmesinin, eylem yöntemlerinin yürütülmesi çevreler.
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.
}

public void OnActionExecuted(ActionExecutedContext context)


{
// Do something after the action executes.
}
}
ActionExecutingContext aşağıdaki özellikleri sağlar:
ActionArguments-bir eylem yöntemine yönelik girişlerin okunmalarını sağlar.
Controller-denetleyici örneğinin işlenmesine izin vermez.
Result-eylem yönteminin ve sonraki eylem filtrelerinin Result kısa devre dışı yürütmesi.

Eylem yönteminde özel durum oluşturma:


Sonraki filtrelerin çalıştırılmasını önler.
Result ayarının aksine, 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 IAsyncActionFilter için ActionExecutionDelegateçağrısı:


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

Kısa devre dışı, bir sonuç örneğine Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result atayın


ve next çağırmayın ( ActionExecutionDelegate ).
Framework, alt sınıflı olabilecek bir soyut ActionFilterAttribute sağlar.
OnActionExecuting eylem 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);
}
}

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


Ve Result özelliği aracılığıyla eylemin sonuçlarını görebilir ve değiştirebilir.
eylem yürütmesi başka bir filtre tarafından kabul edilse, Canceled true olarak ayarlanır.
eylem veya sonraki eylem filtresi bir özel durum harekete geçirdi, Exception null olmayan bir değere
ayarlanır. Exception null olarak ayarlanıyor:
Bir özel durumu etkin bir şekilde işler.
ActionExecutedContext.Result , normal olarak eylem yönteminden 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:
IExceptionFilter veya IAsyncExceptionFilteruygulayın.
, Yaygın hata işleme ilkelerini uygulamak için kullanılabilir.
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 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:


Etkinlikden önceki ve sonraki olaylar yok.
OnException veya OnExceptionAsyncuygulayın.
Razor sayfası 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 veya bir yanıt 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:
Arabirim uygulama:
IResultFilter veya IAsyncResultFilter
IAlwaysRunResultFilter veya IAsyncAlwaysRunResultFilter
Yürütmesi, eylem sonuçlarının yürütülmesini çevreler.
IResultFilter ve ıasyncresultfilter
Aşağıdaki kod, bir HTTP üst bilgisi ekleyen bir sonuç filtresi 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 göre değişir. Bir görünüm döndüren bir eylem, yürütülen ViewResult bir
parçası olarak tüm Razor işlemlerini içerir. Bir API yöntemi, sonucun yürütülmesinin bir parçası olarak bazı
serileştirme işlemleri gerçekleştirebilir. Eylem sonuçlarıhakkında daha fazla bilgi edinin.
Sonuç filtreleri yalnızca bir eylem veya eylem filtresi bir eylem sonucu üretirse yürütülür. Şu durumlarda
sonuç filtreleri yürütülmez:
Bir yetkilendirme filtresi veya kaynak filtresi, işlem hattı için kısa süreli olarak devre dışı.
Bir özel durum filtresi, bir eylem sonucu üreterek özel durumu işler.
Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting yöntemi, eylem sonucunun ve sonraki
sonuç filtrelerinin true Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel ayarlanarak kısa
devre yürütülmesine neden olabilir. Boş bir yanıt oluşturmamaya kaçınmak için kısa devre dışı bırakıldığında
yanıt nesnesine yazın. IResultFilter.OnResultExecuting bir özel durum oluşturma şu şekilde yapılır:
Eylem sonucunun ve sonraki filtrelerin yürütülmesini önleyin.
Başarılı bir sonuç yerine hata olarak kabul edilir.
Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted yöntemi çalıştırıldığında, yanıt istemciye
zaten gönderilir. Yanıt istemciye zaten gönderildiyse, daha fazla değiştirilemez.
ResultExecutedContext.Canceled , eylem sonucu yürütmesi başka bir filtre tarafından kabul edilen kısa devre
ise true olarak ayarlanır.
eylem sonucu veya sonraki sonuç filtresi bir özel durum harekete geçirdi, ResultExecutedContext.Exception
null olmayan bir değere ayarlanır. Exception null olarak ayarlanması, bir özel durumu etkili bir şekilde işler
ve özel durumun, ardışık düzendeki ASP.NET Core daha sonra yeniden oluşturulmasını önler. Bir sonuç
filtresinde özel durum işlenirken yanıta veri yazmanın güvenilir bir yolu yoktur. Bir eylem sonucu bir özel
durum oluşturduğunda üstbilgiler istemciye temizleniyorsa, hata kodu göndermek için güvenilir bir
mekanizma yoktur.
Bir IAsyncResultFilteriçin, ResultExecutionDelegate bir await next çağrısı, sonraki sonuç filtrelerini ve
eylem sonucunu yürütür. Kısa devre dışı, ResultExecutingContext. Cancel true ve ResultExecutionDelegate
çağırmayın:
public class MyAsyncResponseFilter : IAsyncResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context,
ResultExecutionDelegate next)
{
if (!(context.Result is EmptyResult))
{
await next();
}
else
{
context.Cancel = true;
}

}
}

Framework, alt sınıflı olabilecek bir soyut ResultFilterAttribute sağlar. Daha önce gösterilen
Addheaderattribute sınıfı bir sonuç Filtresi özniteliği örneğidir.
Ialwaysrunresultfilter ve ıasyncalwaysrunresultfilter
IAlwaysRunResultFilter ve IAsyncAlwaysRunResultFilter arabirimleri, tüm eylem sonuçları için çalışan bir
IResultFilter uygulamasını 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 içerik anlaşması başarısız olduğunda 422 olmayan bir varlık
durum kodu ile bir eylem sonucu (ObjectResult) ayarlar:

public class UnprocessableResultFilter : Attribute, IAlwaysRunResultFilter


{
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result is StatusCodeResult statusCodeResult &&
statusCodeResult.StatusCode == 415)
{
context.Result = new ObjectResult("Can't process this!")
{
StatusCode = 422,
};
}
}

public void OnResultExecuted(ResultExecutedContext context)


{
}
}

IFilterFactory
IFilterFactory IFilterMetadatauygular. Bu nedenle, bir IFilterFactory örneği, filtre ardışık düzeninde
herhangi bir yerde IFilterMetadata bir örnek olarak kullanılabilir. Çalışma zamanı filtreyi çağırmayı
hazırlarken, bir IFilterFactory dönüştürmeyi dener. Bu atama başarılı olursa, çağrılan IFilterMetadata
örneğini oluşturmak için CreateInstance yöntemi çağırılır. 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://test-cors.org 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ı
IFilterFactory uygulayan filtreler ş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 IFilterFactoryuygular. IFilterFactory , bir IFilterMetadata örneği oluşturmak için
CreateInstance yöntemini kullanıma sunar. CreateInstance , belirtilen türü hizmetler kapsayıcısından (DI)
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 kodda [SampleActionFilter] uygulamak için üç yaklaşım gösterilmektedir:

[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 [SampleActionFilter] olarak dekorasyon, SampleActionFilter uygulamak için


tercih edilen yaklaşımdır.

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, filtre ardışık düzenine eklenecek olan ara yazılımı belirten
Configure yöntemi ile 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);
}
}

Ara yazılımı çalıştırmak için MiddlewareFilterAttribute 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.

Sonraki eylemler
Razor Pages Için filtre yöntemlerinebakın.
Filtrelerle denemek için GitHub örneğini indirin, test edin ve değiştirin.
ASP.NET Core bölgeler
6.12.2019 • 11 minutes to read • Edit Online

Dhananjay Rohan ve Rick Anderson


Bölgeler, ilgili işlevselliği ayrı bir ad alanı (yönlendirme için) ve klasör yapısı (görünümler için) olarak bir
grup içinde düzenlemek için kullanılan bir ASP.NET özelliğidir. Alanların kullanılması area , controller
ve action ya da Razor sayfası page başka bir rota parametresi ekleyerek yönlendirme amacına yönelik
bir hiyerarşi oluşturur.
Alanları, her biri kendi Razor Pages, denetleyiciler, görünümler ve modeller kümesine sahip bir ASP.NET
Core Web uygulamasını daha küçük işlevsel gruplar halinde bölümlemek için bir yol sağlar. Bir alan, bir
uygulamanın içindeki yapısı etkin bir şekilde. Bir ASP.NET Core Web projesinde, sayfalar, model,
denetleyici ve görünüm gibi mantıksal bileşenler farklı klasörlerde tutulur. ASP.NET Core çalışma
zamanı, bu bileşenler arasındaki ilişkiyi oluşturmak için adlandırma kurallarını kullanır. Büyük bir
uygulama için, uygulamayı işlevlerin ayrı üst düzey alanlarında bölümlemek avantajlı olabilir. Örneğin,
kullanıma alma, faturalandırma ve arama gibi birden çok iş birimi içeren bir e-ticaret uygulaması. Bu
birimlerin her birinin görünümleri, denetleyicileri, Razor Pages ve modelleri içermesi için kendi alanı
vardır.
Şu durumlarda bir projedeki alanı kullanmayı göz önünde bulundurun:
Uygulama, mantıksal olarak ayrılabilen birden çok üst düzey işlevsel bileşenden oluşur.
Her işlevsel alanın bağımsız olarak çalışabilmesi için uygulamayı bölümlemek istiyorsunuz.
Örnek kodu görüntüleyin veya indirin (nasıl indirilir). İndirme örneği, test bölgeleri için temel bir
uygulama sağlar.
Razor Pages kullanıyorsanız, bu belgede Razor Pages bulunan alanlara bakın.

Görünümlere sahip denetleyiciler için bölgeler


Alanları, denetleyicileri ve görünümleri kullanan tipik bir ASP.NET Core Web uygulaması şunları içerir:
Bir alan klasörü yapısı.
Denetleyiciyi alanla ilişkilendirmek için [Area] özniteliğine sahip denetleyiciler:

[Area("Products")]
public class ManageController : Controller
{

Başlangıç alanına eklenen alan yolu:


app.UseMvc(routes =>
{
routes.MapRoute(
name: "MyArea",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Alan klasörü yapısı


İki mantıksal grup, ürün ve hizmetiçeren bir uygulamayı düşünün. Alan kullanarak, klasör yapısı
aşağıdakine benzer olacaktır:
Proje adı
Alanlar
Ürünler
Denetleyiciler
HomeController.cs
ManageController.cs
Görünümler
Ana Sayfası
Index.cshtml
Yönet
Index.cshtml
. Cshtml hakkında
Hizmetler
Denetleyiciler
HomeController.cs
Görünümler
Ana Sayfası
Index.cshtml
Yukarıdaki düzen, alan kullanılırken tipik olsa da, bu klasör yapısını kullanmak için yalnızca görünüm
dosyaları gereklidir. Eşleşen bir alan görünümü dosyası için bulma aramalarını aşağıdaki sırayla
görüntüleyin:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

Denetleyiciyi bir alanla ilişkilendir


Alan denetleyicileri [alanı] özniteliğiyle belirlenir:
using Microsoft.AspNetCore.Mvc;

namespace MVCareas.Areas.Products.Controllers
{
[Area("Products")]
public class ManageController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult About()


{
return View();
}
}
}

Alan yolu Ekle


Alan rotaları genellikle öznitelik yönlendirme yerine geleneksel yönlendirmeyi kullanır. Geleneksel
yönlendirme sıra bağımlıdır. Genel olarak, alanlar içeren rotalar, alan olmayan rotalardan daha belirgin
olduklarından daha önce rota tablosuna yerleştirilmelidir.
{area:...} , URL alanı tüm alanlarda Tekdüzen ise yol şablonlarında bir belirteç olarak kullanılabilir:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "MyArea",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

Yukarıdaki kodda exists , yolun bir alanla eşleşmesi gereken bir kısıtlama uygular. {area:...}
kullanmak, alanlara yönlendirme eklemek için en az karmaşık mekanizmadır.
Aşağıdaki kod, iki adlandırılmış alan yolu oluşturmak için MapAreaRoute kullanır:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseMvc(routes =>
{
routes.MapAreaRoute(
name: "MyAreaProducts",
areaName:"Products",
template: "Products/{controller=Home}/{action=Index}/{id?}");

routes.MapAreaRoute(
name: "MyAreaServices",
areaName: "Services",
template: "Services/{controller=Home}/{action=Index}/{id?}");

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

ASP.NET Core 2,2 ile MapAreaRoute kullanırken, Bu GitHub sorununabakın.


Daha fazla bilgi için bkz. alan yönlendirme.
MVC alanlarıyla bağlantı oluşturma
Örnek indirmenin aşağıdaki kodu, belirtilen alanla birlikte bağlantı oluşturmayı gösterir:
<li>Anchor Tag Helper links</li>
<ul>
<li>
<a asp-area="Products" asp-controller="Home" asp-action="About">
Products/Home/About
</a>
</li>
<li>
<a asp-area="Services" asp-controller="Home" asp-action="About">
Services About
</a>
</li>
<li>
<a asp-area="" asp-controller="Home" asp-action="About">
/Home/About
</a>
</li>
</ul>
<li>Html.ActionLink generated links</li>
<ul>
<li>
@Html.ActionLink("Product/Manage/About", "About", "Manage",
new { area = "Products" })
</li>
</ul>
<li>Url.Action generated links</li>
<ul>
<li>
<a href='@Url.Action("About", "Manage", new { area = "Products" })'>
Products/Manage/About
</a>
</li>
</ul>

Yukarıdaki kodla oluşturulan bağlantılar, uygulamanın herhangi bir yerinde geçerlidir.


Örnek indirme, önceki bağlantıları içeren kısmi bir görünüm ve alanı belirtmeksizin aynı bağlantıları
içerir. Kısmi görünüme, Düzen dosyasındabaşvurulur, bu nedenle uygulamadaki her sayfa oluşturulan
bağlantıları görüntüler. Alanı belirtmeden oluşturulan bağlantılar yalnızca aynı alan ve denetleyicideki bir
sayfadan başvuruluyorsa geçerlidir.
Alan veya denetleyici belirtilmediğinde, yönlendirme ortam değerlerine göre değişir. Geçerli isteğin
geçerli yol değerleri, bağlantı oluşturma için çevresel değerler olarak kabul edilir. Örnek uygulama için
birçok durumda, ortam değerlerini kullanmak yanlış bağlantılar oluşturur.
Daha fazla bilgi için bkz. Denetleyici eylemlerine yönlendirme.
_ViewStart. cshtml dosyasını kullanan alanların paylaşılan düzeni
Uygulamanın tamamında ortak bir düzen paylaşmak için _ViewStart. cshtml 'yi uygulama kök klasörüne
taşıyın.
_ViewImports. cshtml
Standart konumunda /views/_ViewImports. cshtml , alanlara uygulanmaz. Bölgenizdeki ortak Etiket
Yardımcıları, @using veya @inject kullanmak için, uygun bir _ViewImports. cshtml dosyasının, alan
Görünümleriniz için geçerliolduğundan emin olun. Tüm görünümlerinizin aynı davranışını istiyorsanız,
/views/_ViewImports. cshtml öğesini uygulama köküne taşıyın.
Görünümlerin depolandığı varsayılan alan klasörünü değiştirme
Aşağıdaki kod, varsayılan alan klasörünü "Areas" "MyAreas" olarak değiştirir:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RazorViewEngineOptions>(options =>
{
options.AreaViewLocationFormats.Clear();
options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");
options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");
options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});

services.AddMvc();
}

Razor Pages alan bölgeler


Razor Pages olan alanlarda, uygulamanın kökünde bir alan//Pages klasörü gerekir. Aşağıdaki klasör
yapısı örnek uygulamaylabirlikte kullanılır:
Proje adı
Alanlar
Ürünler
Sayfalar
_ViewImports
hakkında
Dizin
Hizmetler
Sayfalar
Yönet
hakkında
Dizin
Razor Pages ve alanlarıyla bağlantı oluşturma
Örnek indirmenin aşağıdaki kodu, belirtilen alanla birlikte bağlantı oluşturmayı gösterir (örneğin,
asp-area="Products" ):
<li>Anchor Tag Helper links</li>
<ul>
<li>
<a asp-area="Products" asp-page="/About">
Products/About
</a>
</li>
<li>
<a asp-area="Services" asp-page="/Manage/About">
Services/Manage/About
</a>
</li>
<li>
<a asp-area="" asp-page="/About">
/About
</a>
</li>
</ul>
<li>Url.Page generated links</li>
<ul>
<li>
<a href='@Url.Page("/Manage/About", new { area = "Services" })'>
Services/Manage/About
</a>
</li>
<li>
<a href='@Url.Page("/About", new { area = "Products" })'>
Products/About
</a>
</li>
</ul>

Yukarıdaki kodla oluşturulan bağlantılar, uygulamanın herhangi bir yerinde geçerlidir.


Örnek indirme, önceki bağlantıları içeren kısmi bir görünüm ve alanı belirtmeksizin aynı bağlantıları
içerir. Kısmi görünüme, Düzen dosyasındabaşvurulur, bu nedenle uygulamadaki her sayfa oluşturulan
bağlantıları görüntüler. Alanı belirtmeden oluşturulan bağlantılar yalnızca aynı alandaki bir sayfadan
başvuruluyorsa geçerlidir.
Alan belirtilmediğinde, yönlendirme ortam değerlerine göre değişir. Geçerli isteğin geçerli yol değerleri,
bağlantı oluşturma için çevresel değerler olarak kabul edilir. Örnek uygulama için birçok durumda,
ortam değerlerini kullanmak yanlış bağlantılar oluşturur. Örneğin, aşağıdaki koddan oluşturulan
bağlantıları göz önünde bulundurun:

<li>
<a asp-page="/Manage/About">
Services/Manage/About
</a>
</li>
<li>
<a asp-page="/About">
/About
</a>
</li>

Önceki kod için:


<a asp-page="/Manage/About"> oluşturulan bağlantı, yalnızca son istek Services alanındaki bir sayfa
için olduğunda doğrudur. Örneğin, /Services/Manage/ , /Services/Manage/Index veya
/Services/Manage/About .
<a asp-page="/About"> oluşturulan bağlantı, yalnızca son istek /Home bir sayfa için olduğunda
doğrudur.
Kod, örnek indirden.
Ad alanı ve etiket yardımcıları _ViewImports dosya ile içeri aktarma
Bir _ViewImports. cshtml dosyası her bir alan sayfaları klasörüne eklenerek, ad alanı ve etiket
yardımcıları, klasördeki her bir Razor sayfasına içeri aktarabilir.
Örnek kodun bir _ViewImports. cshtml dosyası içermeyen Hizmetler alanını göz önünde bulundurun.
Aşağıdaki biçimlendirme /Services/Manage/about Razor sayfasını göstermektedir:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model RPareas.Areas.Services.Pages.Manage.AboutModel
@{
ViewData["Title"] = "Srv Mng About";
}

<h2>/Services/Manage/About</h2>

<a asp-area="Products" asp-page="/Index">


Products/Index
</a>

Önceki biçimlendirmede:
Modeli belirtmek için tam etki alanı adının kullanılması gerekir (
@model RPareas.Areas.Services.Pages.Manage.AboutModel ).
Etiket yardımcıları @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers tarafından etkinleştirilir

Örnek indirme sırasında, ürünler alanı aşağıdaki _ViewImports. cshtml dosyasını içerir:

@namespace RPareas.Areas.Products.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Aşağıdaki biçimlendirme /Products/about Razor sayfasını göstermektedir:

@page
@model AboutModel
@{
ViewData["Title"] = "Prod About";
}

<h2>Products/About</h2>

<a asp-area="Services" asp-page="/Manage/About">


Services/Manage/About
</a>

Önceki dosyada, ad alanı ve @addTagHelper yönergesi, alan/ürünler/Pages/_ViewImports. cshtml


dosyası tarafından dosyaya aktarılır.
Daha fazla bilgi için bkz. etiket Yardımcısı kapsamını yönetme ve paylaşılan yönergeleri içeri aktarma.
Razor Pages alanlarıyla ilgili paylaşılan düzen
Uygulamanın tamamında ortak bir düzen paylaşmak için _ViewStart. cshtml 'yi uygulama kök klasörüne
taşıyın.
Yayımlama alanı
Wwwroot dizinindeki tüm *. cshtml dosyaları ve dosyaları, <Project Sdk="Microsoft.NET.Sdk.Web"> *.
csproj dosyasına dahil edildiğinde çıktıya yayımlanır.
ASP.NET Core dosyaları karşıya yükleme
6.12.2019 • 68 minutes to read • Edit Online

Luke Latham, Steve Smithve Rutger fırtınası tarafından


ASP.NET Core, daha küçük dosyalar için arabellekli model bağlama ve daha büyük dosyalar için arabelleğe
alınmamış akış kullanarak bir veya daha fazla dosyanın yüklenmesini destekler
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Güvenlik konuları
Kullanıcılara bir sunucuya dosya yükleme yeteneği sağlarken dikkatli olun. Saldırganlar şunları deneyebilir:
Hizmet reddi saldırıları yürütün.
Virüsleri veya kötü amaçlı yazılımları karşıya yükleyin.
Ağları ve sunucuları diğer yollarla tehlikeye atabilir.
Başarılı bir saldırının olasılığını azaltan güvenlik adımları şunlardır:
Dosyaları, tercihen sistem dışı bir sürücüye, özel bir dosya yükleme alanına yükleyin. Ayrılmış bir konum, karşıya
yüklenen dosyalar üzerinde güvenlik kısıtlamaları yapmayı kolaylaştırır. Dosya yükleme konumunda yürütme
izinlerini devre dışı bırakın.†
Karşıya yüklenen dosyaları uygulamayla aynı dizin ağacında kalıcı yapma .†
Uygulama tarafından belirlenen bir güvenli dosya adı kullanın. Kullanıcı tarafından belirtilen bir dosya adı veya
karşıya yüklenen dosyanın güvenilmeyen dosya adı kullanmayın.† HTML 'yi görüntülerken güvenilmeyen dosya
adını kodlayın. Örneğin, dosya adını günlüğe kaydetme veya Kullanıcı arabiriminde görüntüleme (Razor
otomatik olarak HTML kodlama çıkışı).
Uygulamanın tasarım belirtimi için yalnızca onaylanan dosya uzantılarına izin verin.†
Sunucuda istemci tarafı denetimlerinin gerçekleştirildiğinden emin olun.† Istemci tarafı denetimleri kolayca
atlayabilirsiniz.
Karşıya yüklenen dosyanın boyutunu denetleyin. Büyük karşıya yüklemeleri engellemek için en büyük boyut
sınırını ayarlayın.†
Aynı ada sahip karşıya yüklenen bir dosya tarafından dosyaların üzerine yazılmaması gerektiğinde, dosyayı
karşıya yüklemeden önce dosya adını veritabanına veya fiziksel depolamaya göre denetleyin.
Dosya depolanmadan önce karşıya yüklenen içerik üzerinde bir virüs/kötü amaçlı yazılım tarayıcısı
çalıştırın.
örnek uygulama †ölçütleri karşılayan bir yaklaşımı gösterir.
WARNING
Kötü amaçlı bir kodun bir sisteme karşıya yükleme için kod yürütme için ilk adımı sık şöyledir:
Sistemin denetimini tamamen elde edin.
Sistemin kilitlenme sonucuyla bir sistemi aşırı yükleme.
Kullanıcı veya sistem verilerini tehlikeye.
Genel Kullanıcı arabirimine Graffiti uygulayın.
Kullanıcıların dosyaları kabul ederken saldırı yüzey alanı azaltma hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:
Sınırsız dosya karşıya yükleme
Azure güvenlik: uygun denetimleri kullanıcıların dosyaları kabul ederken karşılandığından emin

Örnek uygulamadaki örnekler de dahil olmak üzere güvenlik önlemlerini uygulama hakkında daha fazla bilgi için
doğrulama bölümüne bakın.

Depolama senaryoları
Dosyalar için ortak depolama seçenekleri şunlardır:
Veritabanı
Küçük dosya yüklemeleri için, bir veritabanı genellikle fiziksel depolama (dosya sistemi veya ağ
paylaşımından) seçeneklerinden daha hızlıdır.
Kullanıcı verileri için bir veritabanı kaydının alınması eşzamanlı olarak dosya içeriğini (örneğin, avatar
görüntüsü) sağlayabildiğinden, veritabanı genellikle fiziksel depolama seçeneklerine göre daha uygundur.
Bir veritabanı, veri depolama hizmeti kullanmaktan daha ucuz olabilir.
Fiziksel depolama (dosya sistemi veya ağ paylaşma)
Büyük dosya yüklemeleri için:
Veritabanı limitleri karşıya yükleme boyutunu kısıtlayabilir.
Fiziksel depolama genellikle bir veritabanındaki depolamadan daha az ekonomik olur.
Fiziksel depolama, veri depolama hizmeti kullanmaktan daha ucuz olabilir.
Uygulamanın işlemi, depolama konumu için okuma ve yazma izinlerine sahip olmalıdır. Hiçbir zaman
yürütme izni vermeyin.
Veri depolama hizmeti (örneğin, Azure Blob depolama)
Hizmetler genellikle tek hata noktalarına tabi olan şirket içi çözümler üzerinde geliştirilmiş
ölçeklenebilirlik ve esneklik sunar.
Hizmetler büyük depolama altyapısı senaryolarında düşük maliyetlidir.
Daha fazla bilgi için bkz. hızlı başlangıç: nesne depolamada blob oluşturmak için .NET kullanma. Konu
UploadFromFileAsyncgösterir, ancak UploadFromStreamAsync bir Streamçalışırken blob depolamaya
FileStream kaydetmek için kullanılabilir.

Karşıya dosya yükleme senaryoları


Dosyaları karşıya yüklemek için iki genel yaklaşım arabelleğe alınır ve akışlardır.
Ara
Dosyanın tamamı bir IFormFileokur, bu dosya dosyayı işlemek veya kaydetmek C# için kullanılan bir gösterimidir.
Dosya karşıya yüklemeleri tarafından kullanılan kaynaklar (disk, bellek), eşzamanlı dosya karşıya yüklemelerinin
sayısına ve boyutuna bağlıdır. Bir uygulama çok fazla karşıya yükleme arabelleğini denerse, bellek veya disk alanı
tükenirse site çöker. Karşıya dosya yükleme boyutu veya sıklığı uygulama kaynaklarını tüketme ise, akış ' ı kullanın.

NOTE
64 KB geçen tek bir arabelleğe alınmış dosya, bellekten diskte geçici bir dosyaya taşınır.

Dosya arabelleğe alma, bu konunun aşağıdaki bölümlerinde ele alınmıştır:


Fiziksel depolama alanı
Veritabanı
Akış
Dosya çok parçalı bir istekten alınır ve doğrudan uygulama tarafından işlenir veya kaydedilir. Akış performansı
önemli ölçüde iyileştirmez. Akış, dosya karşıya yüklenirken bellek veya disk alanı taleplerini azaltır.
Akış büyük dosyaları akış ile büyük dosyaları karşıya yükle bölümünde ele alınmıştır.
Fiziksel depolamaya arabellekli model bağlamaya sahip küçük dosyaları karşıya yükleme
Küçük dosyaları karşıya yüklemek için, çok parçalı bir form kullanın veya JavaScript kullanarak bir POST isteği
oluşturun.
Aşağıdaki örnek, tek bir dosyayı karşıya yüklemek için bir Razor Pages formunun kullanımını gösterir (örnek
uygulamadaPages/Bufferedsinglefileuploadfiziksel. cshtml ):

<form enctype="multipart/form-data" method="post">


<dl>
<dt>
<label asp-for="FileUpload.FormFile"></label>
</dt>
<dd>
<input asp-for="FileUpload.FormFile" type="file">
<span asp-validation-for="FileUpload.FormFile"></span>
</dd>
</dl>
<input asp-page-handler="Upload" class="btn" type="submit" value="Upload" />
</form>

Aşağıdaki örnek, önceki örneğe benzerdir, ancak şunları hariç:


Form verilerini göndermek için JavaScript (Fetch API) kullanılır.
Doğrulama yok.
<form action="BufferedSingleFileUploadPhysical/?handler=Upload"
enctype="multipart/form-data" onsubmit="AJAXSubmit(this);return false;"
method="post">
<dl>
<dt>
<label for="FileUpload_FormFile">File</label>
</dt>
<dd>
<input id="FileUpload_FormFile" type="file"
name="FileUpload.FormFile" />
</dd>
</dl>

<input class="btn" type="submit" value="Upload" />

<div style="margin-top:15px">
<output name="result"></output>
</div>
</form>

<script>
async function AJAXSubmit (oFormElement) {
var resultElement = oFormElement.elements.namedItem("result");
const formData = new FormData(oFormElement);

try {
const response = await fetch(oFormElement.action, {
method: 'POST',
body: formData
});

if (response.ok) {
window.location.href = '/';
}

resultElement.value = 'Result: ' + response.status + ' ' +


response.statusText;
} catch (error) {
console.error('Error:', error);
}
}
</script>

Fetch API 'sini desteklemeyenistemcilerde form gönderisini JavaScript 'te gerçekleştirmek için aşağıdaki
yaklaşımlardan birini kullanın:
Fetch Polyfill kullanın (örneğin, Window. Fetch (GitHub/fetch)).
XMLHttpRequest kullanın. Örneğin:

<script>
"use strict";

function AJAXSubmit (oFormElement) {


var oReq = new XMLHttpRequest();
oReq.onload = function(e) {
oFormElement.elements.namedItem("result").value =
'Result: ' + this.status + ' ' + this.statusText;
};
oReq.open("post", oFormElement.action);
oReq.send(new FormData(oFormElement));
}
</script>
Dosya yüklemelerini desteklemek için, HTML formları multipart/form-data bir kodlama türü ( enctype )
belirtmelidir.
Birden çok dosyayı karşıya yüklemeyi desteklemek için files giriş öğesi için, <input> öğesinde multiple
özniteliğini sağlayın:

<input asp-for="FileUpload.FormFiles" type="file" multiple>

Sunucuya yüklenen tek dosyalara IFormFilekullanılarak model bağlama yoluyla erişilebilir. Örnek uygulama,
veritabanı ve fiziksel depolama senaryoları için birden çok arabellekli dosya yüklemeyi gösterir.

WARNING
Görüntüleme ve günlüğe kaydetme için dışında IFormFile FileName özelliğini kullanmayın. Görüntüleme veya günlüğe
kaydetme sırasında, HTML dosya adını kodlayın. Saldırgan, tam yollar veya göreli yollar dahil olmak üzere kötü amaçlı bir
dosya adı sağlayabilir. Uygulamalar:
Kullanıcı tarafından sağlanan dosya adının yolunu kaldırın.
Kullanıcı arabirimi veya günlüğe kaydetme için HTML kodlu, yol tarafından kaldırılan dosya adını kaydedin.
Depolama için yeni bir rastgele dosya adı oluşturun.
Aşağıdaki kod, dosya adından yolu kaldırır:

string untrustedFileName = Path.GetFileName(pathName);

Bu nedenle, şu ana kadar dikkate alınması gereken örnekler aşağıda verilmiştir. Ek bilgiler aşağıdaki bölümler ve örnek
uygulamatarafından sağlanır:
Güvenlik konuları
Doğrulama

Model bağlama ve IFormFilekullanarak dosya karşıya yüklerken, eylem yöntemi şunları kabul edebilir:
Tek bir IFormFile.
Birkaç dosyayı temsil eden aşağıdaki koleksiyonlardan herhangi biri:
IFormFileCollection
IEnumerable<IFormFile>
Liste<IFormFile>

NOTE
Bağlama, form dosyaları adına göre eşleşir. Örneğin, <input type="file" name="formFile"> HTML name değeri C#
parametre/özellik ile ( FormFile ) eşleşmelidir. Daha fazla bilgi için, ad öznitelik DEĞERINI Post yönteminin parametre adına
eşleştirin bölümüne bakın.

Aşağıdaki örnek:
Karşıya yüklenen bir veya daha fazla dosya üzerinden döngü.
Dosya adı da dahil olmak üzere bir dosyanın tam yolunu döndürmek için Path. GetTempFileName kullanır.
Dosyalar, uygulama tarafından oluşturulan bir dosya adı kullanılarak yerel dosya sistemine kaydedilir.
Karşıya yüklenen dosyaların toplam sayısını ve boyutunu döndürür.
public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);

foreach (var formFile in files)


{
if (formFile.Length > 0)
{
var filePath = Path.GetTempFileName();

using (var stream = System.IO.File.Create(filePath))


{
await formFile.CopyToAsync(stream);
}
}
}

// Process uploaded files


// Don't rely on or trust the FileName property without validation.

return Ok(new { count = files.Count, size, filePath });


}

Yol olmadan bir dosya adı oluşturmak için Path.GetRandomFileName kullanın. Aşağıdaki örnekte, yol
yapılandırmadan alınır:

foreach (var formFile in files)


{
if (formFile.Length > 0)
{
var filePath = Path.Combine(_config["StoredFilesPath"],
Path.GetRandomFileName());

using (var stream = System.IO.File.Create(filePath))


{
await formFile.CopyToAsync(stream);
}
}
}

FileStream geçirilen yol, dosya adını içermelidir. Dosya adı sağlanmazsa, çalışma zamanında bir
UnauthorizedAccessException oluşturulur.
IFormFile tekniği kullanılarak yüklenen dosyalar, işlemeden önce sunucuda veya diskte bellek halinde arabelleğe
alınır. Eylem yönteminde, IFormFile içeriğe Streamolarak erişilebilir. Yerel dosya sistemine ek olarak, dosyalar bir ağ
paylaşımında veya Azure Blob depolamagibi bir dosya depolama hizmetine kaydedilebilir.
Karşıya yüklemek için birden çok dosya üzerinde döngü yapan ve güvenli dosya adları kullanan başka bir örnek
için, örnek uygulamadaki Pages/Bufferedmultiplefileuploadfiziksel. cshtml. cs dosyasına bakın.

WARNING
Path. GetTempFileName , önceki geçici dosyaları silmeden 65.535 'den fazla dosya oluşturulduysa bir IOException oluşturur.
65.535 dosya sınırının sunucu başına sınırı vardır. Windows işletim sistemi için bu sınır hakkında daha fazla bilgi için aşağıdaki
konulara bakın:
GetTempFileNameA işlevi
GetTempFileName

Bir veritabanına arabellekli model bağlamaya sahip küçük dosyaları karşıya yükleme
İkili dosya verilerini Entity Frameworkkullanarak bir veritabanında depolamak için, varlıkta bir Byte Array özelliği
tanımlayın:

public class AppFile


{
public int Id { get; set; }
public byte[] Content { get; set; }
}

Bir IFormFileiçeren sınıf için bir sayfa modeli özelliği belirtin:

public class BufferedSingleFileUploadDbModel : PageModel


{
...

[BindProperty]
public BufferedSingleFileUploadDb FileUpload { get; set; }

...
}

public class BufferedSingleFileUploadDb


{
[Required]
[Display(Name="File")]
public IFormFile FormFile { get; set; }
}

NOTE
IFormFile, doğrudan bir eylem yöntemi parametresi veya bir bağlantılı model özelliği olarak kullanılabilir. Önceki örnekte, bir
bağlantılı model özelliği kullanılmaktadır.

FileUpload Razor Pages formunda kullanılır:

<form enctype="multipart/form-data" method="post">


<dl>
<dt>
<label asp-for="FileUpload.FormFile"></label>
</dt>
<dd>
<input asp-for="FileUpload.FormFile" type="file">
</dd>
</dl>
<input asp-page-handler="Upload" class="btn" type="submit" value="Upload">
</form>

Form sunucuya gönderildiğinde, IFormFile bir akışa kopyalayın ve veritabanına bir bayt dizisi olarak kaydedin.
Aşağıdaki örnekte, uygulamanın veritabanı bağlamını _dbContext depolar:
public async Task<IActionResult> OnPostUploadAsync()
{
using (var memoryStream = new MemoryStream())
{
await FileUpload.FormFile.CopyToAsync(memoryStream);

// Upload the file if less than 2 MB


if (memoryStream.Length < 2097152)
{
var file = new AppFile()
{
Content = memoryStream.ToArray()
};

_dbContext.File.Add(file);

await _dbContext.SaveChangesAsync();
}
else
{
ModelState.AddModelError("File", "The file is too large.");
}
}

return Page();
}

Yukarıdaki örnek, örnek uygulamada gösterilen senaryoya benzerdir:


Pages/BufferedSingleFileUploadDb. cshtml
Pages/BufferedSingleFileUploadDb. cshtml. cs

WARNING
İkili verileri ilişkisel veritabanlarında depolarken dikkatli olun, çünkü performansı olumsuz etkileyebilir.
Doğrulaması olmadan IFormFile FileName özelliğine güvenmeyin veya güvenmeyin. FileName özelliği yalnızca
görüntüleme amacıyla ve yalnızca HTML kodlaması sonrasında kullanılmalıdır.
Belirtilen örneklerde dikkate alınması gereken önemli noktalar. Ek bilgiler aşağıdaki bölümler ve örnek uygulamatarafından
sağlanır:
Güvenlik konuları
Doğrulama

Akışa sahip büyük dosyaları karşıya yükleme


Aşağıdaki örnek, bir denetleyiciyi bir denetleyici eyleminde akışa almak için JavaScript 'in nasıl kullanılacağını
gösterir. Dosyanın antiforgery belirteci özel bir filtre özniteliği kullanılarak oluşturulur ve istek gövdesi yerine
istemci HTTP üst bilgilerine geçirilir. Eylem yöntemi karşıya yüklenen verileri doğrudan işlediğinden, form modeli
bağlama başka bir özel filtre tarafından devre dışı bırakıldı. Eylem içinde formun içerikleri, her bir MultipartSection
okuyan, dosyayı işleyen veya içeriği uygun şekilde depolayan bir MultipartReader kullanılarak okunur. Çok parçalı
bölümler okunduktan sonra eylem kendi model bağlamasını gerçekleştirir.
İlk sayfa yanıtı formu yükler ve bir tanımlama bilgisine ( GenerateAntiforgeryTokenCookieAttribute özniteliği
aracılığıyla) bir antiforgery belirteci kaydeder. Öznitelik, bir istek belirtecine sahip bir tanımlama bilgisi ayarlamak
için ASP.NET Core yerleşik antiforgery desteğini kullanır:
public class GenerateAntiforgeryTokenCookieAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var antiforgery = context.HttpContext.RequestServices.GetService<IAntiforgery>();

// Send the request token as a JavaScript-readable cookie


var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);

context.HttpContext.Response.Cookies.Append(
"RequestVerificationToken",
tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}

public override void OnResultExecuted(ResultExecutedContext context)


{
}
}

Model bağlamayı devre dışı bırakmak için DisableFormValueModelBindingAttribute kullanılır:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}

public void OnResourceExecuted(ResourceExecutedContext context)


{
}
}

Örnek uygulamada GenerateAntiforgeryTokenCookieAttribute ve DisableFormValueModelBindingAttribute ,


Startup.ConfigureServices kurallarıkullanılarak Razor Pages /StreamedSingleFileUploadDb ve
/StreamedSingleFileUploadPhysical sayfa uygulama modellerine filtre olarak uygulanır:
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/StreamedSingleFileUploadDb",
model =>
{
model.Filters.Add(
new GenerateAntiforgeryTokenCookieAttribute());
model.Filters.Add(
new DisableFormValueModelBindingAttribute());
});
options.Conventions
.AddPageApplicationModelConvention("/StreamedSingleFileUploadPhysical",
model =>
{
model.Filters.Add(
new GenerateAntiforgeryTokenCookieAttribute());
model.Filters.Add(
new DisableFormValueModelBindingAttribute());
});
});

Model bağlama formu okumadığından formdan bağlanan parametreler bağlanamaz (sorgu, yol ve başlık çalışmaya
devam eder). Action yöntemi doğrudan Request özelliği ile birlikte çalışabilir. Her bölümü okumak için bir
MultipartReader kullanılır. Anahtar/değer verileri bir KeyValueAccumulator depolanır. Çok parçalı bölümler
okunduktan sonra, KeyValueAccumulator içeriği form verilerini bir model türüne bağlamak için kullanılır.
EF Core ile bir veritabanına akışa yönelik tüm StreamingController.UploadDatabase yöntemi:

[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadDatabase()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error

return BadRequest(ModelState);
}

// Accumulate the form data key-value pairs in the request (formAccumulator).


var formAccumulator = new KeyValueAccumulator();
var trustedFileNameForDisplay = string.Empty;
var untrustedFileNameForStorage = string.Empty;
var streamedFileContent = new byte[0];

var boundary = MultipartRequestHelper.GetBoundary(


MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);

var section = await reader.ReadNextSectionAsync();

while (section != null)


{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);

if (hasContentDispositionHeader)
{
{
if (MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
untrustedFileNameForStorage = contentDisposition.FileName.Value;
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);

streamedFileContent =
await FileHelpers.ProcessStreamedFile(section, contentDisposition,
ModelState, _permittedExtensions, _fileSizeLimit);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
}
else if (MultipartRequestHelper
.HasFormDataContentDisposition(contentDisposition))
{
// Don't limit the key name length because the
// multipart headers length limit is already in effect.
var key = HeaderUtilities
.RemoveQuotes(contentDisposition.Name).Value;
var encoding = GetEncoding(section);

if (encoding == null)
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error

return BadRequest(ModelState);
}

using (var streamReader = new StreamReader(


section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
// The value length limit is enforced by
// MultipartBodyLengthLimit
var value = await streamReader.ReadToEndAsync();

if (string.Equals(value, "undefined",
StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}

formAccumulator.Append(key, value);

if (formAccumulator.ValueCount >
_defaultFormOptions.ValueCountLimit)
{
// Form key count limit of
// _defaultFormOptions.ValueCountLimit
// is exceeded.
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 3).");
// Log error

return BadRequest(ModelState);
}
}
}
}
}

// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}

// Bind form data to the model


var formData = new FormData();
var formValueProvider = new FormValueProvider(
BindingSource.Form,
new FormCollection(formAccumulator.GetResults()),
CultureInfo.CurrentCulture);
var bindingSuccessful = await TryUpdateModelAsync(formData, prefix: "",
valueProvider: formValueProvider);

if (!bindingSuccessful)
{
ModelState.AddModelError("File",
"The request couldn't be processed (Error 5).");
// Log error

return BadRequest(ModelState);
}

// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample app.

var file = new AppFile()


{
Content = streamedFileContent,
UntrustedName = untrustedFileNameForStorage,
Note = formData.Note,
Size = streamedFileContent.Length,
UploadDT = DateTime.UtcNow
};

_context.File.Add(file);
await _context.SaveChangesAsync();

return Created(nameof(StreamingController), null);


}

MultipartRequestHelper (Utilities/MultipartRequestHelper. cs):


using System;
using System.IO;
using Microsoft.Net.Http.Headers;

namespace SampleApp.Utilities
{
public static class MultipartRequestHelper
{
// Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq"
// The spec at https://tools.ietf.org/html/rfc2046#section-5.1 states that 70 characters is a
reasonable limit.
public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
{
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;

if (string.IsNullOrWhiteSpace(boundary))
{
throw new InvalidDataException("Missing content-type boundary.");
}

if (boundary.Length > lengthLimit)


{
throw new InvalidDataException(
$"Multipart boundary length limit {lengthLimit} exceeded.");
}

return boundary;
}

public static bool IsMultipartContentType(string contentType)


{
return !string.IsNullOrEmpty(contentType)
&& contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}

public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition)


{
// Content-Disposition: form-data; name="key";
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& string.IsNullOrEmpty(contentDisposition.FileName.Value)
&& string.IsNullOrEmpty(contentDisposition.FileNameStar.Value);
}

public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)


{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
|| !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
}
}
}

Fiziksel bir konuma akışa yönelik tüm StreamingController.UploadPhysical yöntemi:

[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadPhysical()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error

return BadRequest(ModelState);
}

var boundary = MultipartRequestHelper.GetBoundary(


MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();

while (section != null)


{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);

if (hasContentDispositionHeader)
{
// This check assumes that there's a file
// present without form data. If form data
// is present, this method immediately fails
// and returns the model error.
if (!MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error

return BadRequest(ModelState);
}
else
{
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);
var trustedFileNameForFileStorage = Path.GetRandomFileName();

// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample.

var streamedFileContent = await FileHelpers.ProcessStreamedFile(


section, contentDisposition, ModelState,
_permittedExtensions, _fileSizeLimit);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

using (var targetStream = System.IO.File.Create(


Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);

_logger.LogInformation(
"Uploaded file '{TrustedFileNameForDisplay}' saved to " +
"'{TargetFilePath}' as {TrustedFileNameForFileStorage}",
trustedFileNameForDisplay, _targetFilePath,
trustedFileNameForFileStorage);
}
}
}
}

// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}

return Created(nameof(StreamingController), null);


}

Örnek uygulamada, doğrulama denetimleri FileHelpers.ProcessStreamedFile tarafından işlenir.

Doğrulama
Örnek uygulamanın FileHelpers sınıfı, arabelleğe alınmış IFormFile ve akış dosya yüklemeleri için birkaç denetim
gösterir. Örnek uygulamada arabelleğe alınmış IFormFile dosya yüklemelerini işlemek için, Utilities/Fileyardımcılar.
cs dosyasındaki ProcessFormFile yöntemine bakın. Akış dosyalarını işlemek için aynı dosyadaki
ProcessStreamedFile yöntemine bakın.

WARNING
Örnek uygulamada gösterilen doğrulama işleme yöntemleri karşıya yüklenen dosyaların içeriğini taramaz. Çoğu üretim
senaryosunda, dosyanın kullanıcılara veya diğer sistemlere kullanılabilir hale getirilmesi için dosya üzerinde bir virüs/kötü
amaçlı yazılım tarayıcı API 'SI kullanılır.
Konu örneği, doğrulama tekniklerine yönelik çalışan bir örnek sağlasa da şunları gerçekleştirmediğiniz takdirde bir üretim
uygulamasında FileHelpers sınıfını uygulamayın:
Uygulamayı tam olarak anlayın.
Uygulamayı uygulamanın ortamı ve belirtimleri için uygun şekilde değiştirin.
Bu gereksinimleri bilmeden bir uygulamada güvenlik kodunu hiçbir şekilde sayısının fark gözetmeden uygulayın.

İçerik doğrulama
Karşıya yüklenen içerikte üçüncü taraf bir virüs/kötü amaçlı yazılım tarama API 'SI kullanın.
Dosyaları tarama, yüksek hacimli senaryolarda sunucu kaynaklarında yoğun bir şekilde yapılır. Dosya tarama
nedeniyle istek işleme performansı azaldığında, tarama işini, muhtemelen uygulamanın sunucusundan farklı bir
sunucuda çalışan bir arka plan hizmetinedevredere göz önünde bulundurun. Genellikle, arka plan virüs tarayıcısı
tarafından denetlene kadar karşıya yüklenen dosyalar karantinaya alınmış bir alanda tutulur. Bir dosya geçtiğinde
dosya normal dosya depolama konumuna taşınır. Bu adımlar genellikle bir dosyanın tarama durumunu gösteren
bir veritabanı kaydıyla birlikte gerçekleştirilir. Böyle bir yaklaşım kullanarak, uygulama ve uygulama sunucusu
isteklere yanıt vermeye odaklanmaya devam eder.
Dosya Uzantısı doğrulaması
Karşıya yüklenen dosyanın uzantısı izin verilen uzantılar listesine göre denetlenmelidir. Örneğin:

private string[] permittedExtensions = { ".txt", ".pdf" };

var ext = Path.GetExtension(uploadedFileName).ToLowerInvariant();

if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext))
{
// The extension is invalid ... discontinue processing the file
}
Dosya imzası doğrulaması
Bir dosyanın imzası, bir dosyanın başlangıcında ilk birkaç bayta göre belirlenir. Bu baytlar, uzantının dosyanın
içeriğiyle eşleşip eşleşmediğini göstermek için kullanılabilir. Örnek uygulama, birkaç ortak dosya türü için dosya
imzalarını denetler. Aşağıdaki örnekte, bir JPEG görüntüsünün dosya imzası, dosyaya karşı denetlenir:

private static readonly Dictionary<string, List<byte[]>> _fileSignature =


new Dictionary<string, List<byte[]>>
{
{ ".jpeg", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 },
}
},
};

using (var reader = new BinaryReader(uploadedFileData))


{
var signatures = _fileSignature[ext];
var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length));

return signatures.Any(signature =>


headerBytes.Take(signature.Length).SequenceEqual(signature));
}

Ek dosya imzaları almak için Dosya Imzaları veritabanı ve resmi dosya belirtimleri bölümüne bakın.
Dosya adı güvenliği
Fiziksel depolamaya bir dosyayı kaydetmek için hiçbir şekilde istemci tarafından sağlanan dosya adı kullanmayın.
Geçici depolama için tam yol (dosya adı da dahil olmak üzere) oluşturmak için Path. GetRandomFileName veya
Path. GetTempFileName kullanarak dosya için güvenli bir dosya adı oluşturun.
Razor otomatik olarak HTML, görüntüleme için özellik değerlerini kodlar. Aşağıdaki kodun kullanımı güvenlidir:

@foreach (var file in Model.DatabaseFiles) {


<tr>
<td>
@file.UntrustedName
</td>
</tr>
}

Razor dışında, her zaman bir kullanıcının isteğinden dosya adı içeriği HtmlEncode.
Birçok uygulama, dosyanın var olduğunu bir denetim içermelidir; Aksi takdirde, dosyanın üzerine aynı ada sahip bir
dosya yazılır. Uygulamanızın belirtimlerini karşılamak için ek mantık sağlayın.
Boyut doğrulaması
Karşıya yüklenen dosyaların boyutunu sınırlayın.
Örnek uygulamada, dosyanın boyutu 2 MB ile sınırlıdır (bayt cinsinden gösterilir). Sınır, appSettings. JSON
dosyasındaki yapılandırma yoluyla sağlanır:

{
"FileSizeLimit": 2097152
}

FileSizeLimit PageModel sınıflarına eklenmiş:


public class BufferedSingleFileUploadPhysicalModel : PageModel
{
private readonly long _fileSizeLimit;

public BufferedSingleFileUploadPhysicalModel(IConfiguration config)


{
_fileSizeLimit = config.GetValue<long>("FileSizeLimit");
}

...
}

Dosya boyutu sınırı aştığında, dosya reddedilir:

if (formFile.Length > _fileSizeLimit)


{
// The file is too large ... discontinue processing the file
}

Name öznitelik değerini POST yönteminin Parameter adı ile Eşleştir


Form verileri oluşturan veya JavaScript 'in FormData doğrudan kullanan Razor olmayan formlarda, formun
öğesinde veya FormData belirtilen adın, denetleyicinin eyleminde parametrenin adıyla eşleşmesi gerekir.
Aşağıdaki örnekte:
Bir <input> öğesi kullanılırken, name özniteliği battlePlans değere ayarlanır:

<input type="file" name="battlePlans" multiple>

JavaScript içinde FormData kullanırken ad, battlePlans değer olarak ayarlanır:

var formData = new FormData();

for (var file in files) {


formData.append("battlePlans", file, file.name);
}

C# Yöntemin parametresi için eşleşen bir ad kullanın ( battlePlans ):


Upload adlı Razor Pages sayfa işleyicisi yöntemi için:

public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> battlePlans)

MVC POST denetleyicisi eylem yöntemi için:

public async Task<IActionResult> Post(List<IFormFile> battlePlans)

Sunucu ve uygulama yapılandırması


Çok parçalı gövde uzunluğu sınırı
MultipartBodyLengthLimit her bir çok parçalı gövdenin uzunluğu için sınır ayarlar. Bu sınırı aşan form bölümleri
ayrıştırıldığında bir InvalidDataException oluşturur. Varsayılan değer 134.217.728 ' dir (128 MB ).
Startup.ConfigureServices MultipartBodyLengthLimit ayarını kullanarak sınırı özelleştirin:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<FormOptions>(options =>
{
// Set the limit to 256 MB
options.MultipartBodyLengthLimit = 268435456;
});
}

RequestFormLimitsAttribute, tek sayfa veya eylem için MultipartBodyLengthLimit ayarlamak üzere kullanılır.
Razor Pages bir uygulamada, filtreyi Startup.ConfigureServices bir kurala uygulayın:

services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/FileUploadPage",
model.Filters.Add(
new RequestFormLimitsAttribute()
{
// Set the limit to 256 MB
MultipartBodyLengthLimit = 268435456
});
});

Razor Pages bir uygulamada veya bir MVC uygulamasında, filtreyi sayfa modeline veya eylem yöntemine
uygulayın:

// Set the limit to 256 MB


[RequestFormLimits(MultipartBodyLengthLimit = 268435456)]
public class BufferedSingleFileUploadPhysicalModel : PageModel
{
...
}

Kestrel maksimum istek gövdesi boyutu


Kestrel tarafından barındırılan uygulamalar için, varsayılan en büyük istek gövdesi boyutu 30.000.000 bayttır ve bu,
yaklaşık 28,6 MB 'tır. MaxRequestBodySize Kestrel Server seçeneğini kullanarak sınırı özelleştirin:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureKestrel((context, options) =>
{
// Handle requests up to 50 MB
options.Limits.MaxRequestBodySize = 52428800;
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

RequestSizeLimitAttribute, tek sayfa veya eylem için MaxRequestBodySize ayarlamak üzere kullanılır.
Razor Pages bir uygulamada, filtreyi Startup.ConfigureServices bir kurala uygulayın:
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/FileUploadPage",
model =>
{
// Handle requests up to 50 MB
model.Filters.Add(
new RequestSizeLimitAttribute(52428800));
});
});

Bir Razor sayfaları uygulamasında veya bir MVC uygulamasında, filtreyi sayfa işleyici sınıfına veya eylem
yöntemine uygulayın:

// Handle requests up to 50 MB
[RequestSizeLimit(52428800)]
public class BufferedSingleFileUploadPhysicalModel : PageModel
{
...
}

RequestSizeLimitAttribute , @attribute Razor yönergesi kullanılarak da uygulanabilir:

@attribute [RequestSizeLimitAttribute(52428800)]

Diğer Kestrel limitleri


Kestrel tarafından barındırılan uygulamalar için diğer Kestrel limitleri de uygulanabilir:
İstemci bağlantıları üst sınırı
İstek ve yanıt veri ücretleri
IIS içerik uzunluğu sınırı
Varsayılan istek sınırı ( maxAllowedContentLength ), yaklaşık 28.6 MB olan 30.000.000 bayttır. Web. config dosyasında
sınırı özelleştirin:

<system.webServer>
<security>
<requestFiltering>
<!-- Handle requests up to 50 MB -->
<requestLimits maxAllowedContentLength="52428800" />
</requestFiltering>
</security>
</system.webServer>

Bu ayar yalnızca IIS için geçerlidir. Kestrel üzerinde barındırırken davranış varsayılan olarak gerçekleşmez. Daha
fazla bilgi için bkz. Istek limitleri <requestLimits >.
ASP.NET Core modülündeki sınırlamalar veya IIS Istek filtreleme modülünün varlığı, karşıya yüklemeleri 2 veya 4
GB ile sınırlandırabilir. Daha fazla bilgi için bkz. 2 GB 'tan büyük dosya karşıya yüklenemiyor
(ASPNET/AspNetCore #2711).

Sorunları Gider
Dosyaları karşıya yükleme ve olası çözümleri ile çalışırken karşılaşılan bazı yaygın sorunlar aşağıda verilmiştir.
Bir IIS sunucusuna dağıtılırken bulunamadı hatası
Aşağıdaki hata karşıya yüklenen dosyanın, sunucunun yapılandırılmış içerik uzunluğunu aştığını gösterir:

HTTP 404.13 - Not Found


The request filtering module is configured to deny a request that exceeds the request content length.

Limiti artırma hakkında daha fazla bilgi için bkz. IIS içerik uzunluğu sınırı bölümü.
Bağlantı hatası
Bir bağlantı hatası ve bir sıfırlama sunucu bağlantısı büyük olasılıkla karşıya yüklenen dosyanın Kestrel 'in en büyük
istek gövdesi boyutunu aştığını gösterir. Daha fazla bilgi için, Kestrel maksimum istek gövdesi boyutu bölümüne
bakın. Kestrel istemci bağlantı limitleri de ayarlama gerektirebilir.
Iformfile ile null başvuru özel durumu
Denetleyici IFormFile kullanarak karşıya yüklenen dosyaları kabul ediyorsanız, ancak değer null , HTML
formunun multipart/form-data``enctype değerini belirtdiğini doğrulayın. Bu öznitelik <form> öğesinde
ayarlanmamışsa, dosya karşıya yükleme gerçekleşmez ve herhangi bir bağlı IFormFile bağımsız değişken null .
Ayrıca, form verilerinde karşıya yükleme adlandırmasının uygulamanın adlandırmayla eşleştiğindenemin olun.
Akış çok uzun
Bu konudaki örneklerde karşıya yüklenen dosyanın içeriğini tutmak için MemoryStream bağımlıdır. Bir
MemoryStream boyut limiti int.MaxValue . Uygulamanın dosya yükleme senaryosu, dosya içeriğinin 50 MB 'tan
büyük olmasını gerektiriyorsa, karşıya yüklenen dosyanın içeriğini tutmak için tek bir MemoryStream kullanmayan
alternatif bir yaklaşım kullanın.
ASP.NET Core, daha küçük dosyalar için arabellekli model bağlama ve daha büyük dosyalar için arabelleğe
alınmamış akış kullanarak bir veya daha fazla dosyanın yüklenmesini destekler
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Güvenlik konuları
Kullanıcılara bir sunucuya dosya yükleme yeteneği sağlarken dikkatli olun. Saldırganlar şunları deneyebilir:
Hizmet reddi saldırıları yürütün.
Virüsleri veya kötü amaçlı yazılımları karşıya yükleyin.
Ağları ve sunucuları diğer yollarla tehlikeye atabilir.
Başarılı bir saldırının olasılığını azaltan güvenlik adımları şunlardır:
Dosyaları, tercihen sistem dışı bir sürücüye, özel bir dosya yükleme alanına yükleyin. Ayrılmış bir konum, karşıya
yüklenen dosyalar üzerinde güvenlik kısıtlamaları yapmayı kolaylaştırır. Dosya yükleme konumunda yürütme
izinlerini devre dışı bırakın.†
Karşıya yüklenen dosyaları uygulamayla aynı dizin ağacında kalıcı yapma .†
Uygulama tarafından belirlenen bir güvenli dosya adı kullanın. Kullanıcı tarafından belirtilen bir dosya adı veya
karşıya yüklenen dosyanın güvenilmeyen dosya adı kullanmayın.† HTML 'yi görüntülerken güvenilmeyen dosya
adını kodlayın. Örneğin, dosya adını günlüğe kaydetme veya Kullanıcı arabiriminde görüntüleme (Razor
otomatik olarak HTML kodlama çıkışı).
Uygulamanın tasarım belirtimi için yalnızca onaylanan dosya uzantılarına izin verin.†
Sunucuda istemci tarafı denetimlerinin gerçekleştirildiğinden emin olun.† Istemci tarafı denetimleri kolayca
atlayabilirsiniz.
Karşıya yüklenen dosyanın boyutunu denetleyin. Büyük karşıya yüklemeleri engellemek için en büyük boyut
sınırını ayarlayın.†
Aynı ada sahip karşıya yüklenen bir dosya tarafından dosyaların üzerine yazılmaması gerektiğinde, dosyayı
karşıya yüklemeden önce dosya adını veritabanına veya fiziksel depolamaya göre denetleyin.
Dosya depolanmadan önce karşıya yüklenen içerik üzerinde bir virüs/kötü amaçlı yazılım tarayıcısı
çalıştırın.
örnek uygulama †ölçütleri karşılayan bir yaklaşımı gösterir.

WARNING
Kötü amaçlı bir kodun bir sisteme karşıya yükleme için kod yürütme için ilk adımı sık şöyledir:
Sistemin denetimini tamamen elde edin.
Sistemin kilitlenme sonucuyla bir sistemi aşırı yükleme.
Kullanıcı veya sistem verilerini tehlikeye.
Genel Kullanıcı arabirimine Graffiti uygulayın.
Kullanıcıların dosyaları kabul ederken saldırı yüzey alanı azaltma hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:
Sınırsız dosya karşıya yükleme
Azure güvenlik: uygun denetimleri kullanıcıların dosyaları kabul ederken karşılandığından emin

Örnek uygulamadaki örnekler de dahil olmak üzere güvenlik önlemlerini uygulama hakkında daha fazla bilgi için
doğrulama bölümüne bakın.

Depolama senaryoları
Dosyalar için ortak depolama seçenekleri şunlardır:
Veritabanı
Küçük dosya yüklemeleri için, bir veritabanı genellikle fiziksel depolama (dosya sistemi veya ağ
paylaşımından) seçeneklerinden daha hızlıdır.
Kullanıcı verileri için bir veritabanı kaydının alınması eşzamanlı olarak dosya içeriğini (örneğin, avatar
görüntüsü) sağlayabildiğinden, veritabanı genellikle fiziksel depolama seçeneklerine göre daha uygundur.
Bir veritabanı, veri depolama hizmeti kullanmaktan daha ucuz olabilir.
Fiziksel depolama (dosya sistemi veya ağ paylaşma)
Büyük dosya yüklemeleri için:
Veritabanı limitleri karşıya yükleme boyutunu kısıtlayabilir.
Fiziksel depolama genellikle bir veritabanındaki depolamadan daha az ekonomik olur.
Fiziksel depolama, veri depolama hizmeti kullanmaktan daha ucuz olabilir.
Uygulamanın işlemi, depolama konumu için okuma ve yazma izinlerine sahip olmalıdır. Hiçbir zaman
yürütme izni vermeyin.
Veri depolama hizmeti (örneğin, Azure Blob depolama)
Hizmetler genellikle tek hata noktalarına tabi olan şirket içi çözümler üzerinde geliştirilmiş
ölçeklenebilirlik ve esneklik sunar.
Hizmetler büyük depolama altyapısı senaryolarında düşük maliyetlidir.
Daha fazla bilgi için bkz. hızlı başlangıç: nesne depolamada blob oluşturmak için .NET kullanma. Konu
UploadFromFileAsyncgösterir, ancak UploadFromStreamAsync bir Streamçalışırken blob depolamaya
FileStream kaydetmek için kullanılabilir.

Karşıya dosya yükleme senaryoları


Dosyaları karşıya yüklemek için iki genel yaklaşım arabelleğe alınır ve akışlardır.
Ara
Dosyanın tamamı bir IFormFileokur, bu dosya dosyayı işlemek veya kaydetmek C# için kullanılan bir gösterimidir.
Dosya karşıya yüklemeleri tarafından kullanılan kaynaklar (disk, bellek), eşzamanlı dosya karşıya yüklemelerinin
sayısına ve boyutuna bağlıdır. Bir uygulama çok fazla karşıya yükleme arabelleğini denerse, bellek veya disk alanı
tükenirse site çöker. Karşıya dosya yükleme boyutu veya sıklığı uygulama kaynaklarını tüketme ise, akış ' ı kullanın.

NOTE
64 KB geçen tek bir arabelleğe alınmış dosya, bellekten diskte geçici bir dosyaya taşınır.

Dosya arabelleğe alma, bu konunun aşağıdaki bölümlerinde ele alınmıştır:


Fiziksel depolama alanı
Veritabanı
Akış
Dosya çok parçalı bir istekten alınır ve doğrudan uygulama tarafından işlenir veya kaydedilir. Akış performansı
önemli ölçüde iyileştirmez. Akış, dosya karşıya yüklenirken bellek veya disk alanı taleplerini azaltır.
Akış büyük dosyaları akış ile büyük dosyaları karşıya yükle bölümünde ele alınmıştır.
Fiziksel depolamaya arabellekli model bağlamaya sahip küçük dosyaları karşıya yükleme
Küçük dosyaları karşıya yüklemek için, çok parçalı bir form kullanın veya JavaScript kullanarak bir POST isteği
oluşturun.
Aşağıdaki örnek, tek bir dosyayı karşıya yüklemek için bir Razor Pages formunun kullanımını gösterir (örnek
uygulamadaPages/Bufferedsinglefileuploadfiziksel. cshtml ):

<form enctype="multipart/form-data" method="post">


<dl>
<dt>
<label asp-for="FileUpload.FormFile"></label>
</dt>
<dd>
<input asp-for="FileUpload.FormFile" type="file">
<span asp-validation-for="FileUpload.FormFile"></span>
</dd>
</dl>
<input asp-page-handler="Upload" class="btn" type="submit" value="Upload" />
</form>

Aşağıdaki örnek, önceki örneğe benzerdir, ancak şunları hariç:


Form verilerini göndermek için JavaScript (Fetch API) kullanılır.
Doğrulama yok.
<form action="BufferedSingleFileUploadPhysical/?handler=Upload"
enctype="multipart/form-data" onsubmit="AJAXSubmit(this);return false;"
method="post">
<dl>
<dt>
<label for="FileUpload_FormFile">File</label>
</dt>
<dd>
<input id="FileUpload_FormFile" type="file"
name="FileUpload.FormFile" />
</dd>
</dl>

<input class="btn" type="submit" value="Upload" />

<div style="margin-top:15px">
<output name="result"></output>
</div>
</form>

<script>
async function AJAXSubmit (oFormElement) {
var resultElement = oFormElement.elements.namedItem("result");
const formData = new FormData(oFormElement);

try {
const response = await fetch(oFormElement.action, {
method: 'POST',
body: formData
});

if (response.ok) {
window.location.href = '/';
}

resultElement.value = 'Result: ' + response.status + ' ' +


response.statusText;
} catch (error) {
console.error('Error:', error);
}
}
</script>

Fetch API 'sini desteklemeyenistemcilerde form gönderisini JavaScript 'te gerçekleştirmek için aşağıdaki
yaklaşımlardan birini kullanın:
Fetch Polyfill kullanın (örneğin, Window. Fetch (GitHub/fetch)).
XMLHttpRequest kullanın. Örneğin:

<script>
"use strict";

function AJAXSubmit (oFormElement) {


var oReq = new XMLHttpRequest();
oReq.onload = function(e) {
oFormElement.elements.namedItem("result").value =
'Result: ' + this.status + ' ' + this.statusText;
};
oReq.open("post", oFormElement.action);
oReq.send(new FormData(oFormElement));
}
</script>
Dosya yüklemelerini desteklemek için, HTML formları multipart/form-data bir kodlama türü ( enctype )
belirtmelidir.
Birden çok dosyayı karşıya yüklemeyi desteklemek için files giriş öğesi için, <input> öğesinde multiple
özniteliğini sağlayın:

<input asp-for="FileUpload.FormFiles" type="file" multiple>

Sunucuya yüklenen tek dosyalara IFormFilekullanılarak model bağlama yoluyla erişilebilir. Örnek uygulama,
veritabanı ve fiziksel depolama senaryoları için birden çok arabellekli dosya yüklemeyi gösterir.

WARNING
Görüntüleme ve günlüğe kaydetme için dışında IFormFile FileName özelliğini kullanmayın. Görüntüleme veya günlüğe
kaydetme sırasında, HTML dosya adını kodlayın. Saldırgan, tam yollar veya göreli yollar dahil olmak üzere kötü amaçlı bir
dosya adı sağlayabilir. Uygulamalar:
Kullanıcı tarafından sağlanan dosya adının yolunu kaldırın.
Kullanıcı arabirimi veya günlüğe kaydetme için HTML kodlu, yol tarafından kaldırılan dosya adını kaydedin.
Depolama için yeni bir rastgele dosya adı oluşturun.
Aşağıdaki kod, dosya adından yolu kaldırır:

string untrustedFileName = Path.GetFileName(pathName);

Bu nedenle, şu ana kadar dikkate alınması gereken örnekler aşağıda verilmiştir. Ek bilgiler aşağıdaki bölümler ve örnek
uygulamatarafından sağlanır:
Güvenlik konuları
Doğrulama

Model bağlama ve IFormFilekullanarak dosya karşıya yüklerken, eylem yöntemi şunları kabul edebilir:
Tek bir IFormFile.
Birkaç dosyayı temsil eden aşağıdaki koleksiyonlardan herhangi biri:
IFormFileCollection
IEnumerable<IFormFile>
Liste<IFormFile>

NOTE
Bağlama, form dosyaları adına göre eşleşir. Örneğin, <input type="file" name="formFile"> HTML name değeri C#
parametre/özellik ile ( FormFile ) eşleşmelidir. Daha fazla bilgi için, ad öznitelik DEĞERINI Post yönteminin parametre adına
eşleştirin bölümüne bakın.

Aşağıdaki örnek:
Karşıya yüklenen bir veya daha fazla dosya üzerinden döngü.
Dosya adı da dahil olmak üzere bir dosyanın tam yolunu döndürmek için Path. GetTempFileName kullanır.
Dosyalar, uygulama tarafından oluşturulan bir dosya adı kullanılarak yerel dosya sistemine kaydedilir.
Karşıya yüklenen dosyaların toplam sayısını ve boyutunu döndürür.
public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);

foreach (var formFile in files)


{
if (formFile.Length > 0)
{
var filePath = Path.GetTempFileName();

using (var stream = System.IO.File.Create(filePath))


{
await formFile.CopyToAsync(stream);
}
}
}

// Process uploaded files


// Don't rely on or trust the FileName property without validation.

return Ok(new { count = files.Count, size, filePath });


}

Yol olmadan bir dosya adı oluşturmak için Path.GetRandomFileName kullanın. Aşağıdaki örnekte, yol
yapılandırmadan alınır:

foreach (var formFile in files)


{
if (formFile.Length > 0)
{
var filePath = Path.Combine(_config["StoredFilesPath"],
Path.GetRandomFileName());

using (var stream = System.IO.File.Create(filePath))


{
await formFile.CopyToAsync(stream);
}
}
}

FileStream geçirilen yol, dosya adını içermelidir. Dosya adı sağlanmazsa, çalışma zamanında bir
UnauthorizedAccessException oluşturulur.
IFormFile tekniği kullanılarak yüklenen dosyalar, işlemeden önce sunucuda veya diskte bellek halinde arabelleğe
alınır. Eylem yönteminde, IFormFile içeriğe Streamolarak erişilebilir. Yerel dosya sistemine ek olarak, dosyalar bir ağ
paylaşımında veya Azure Blob depolamagibi bir dosya depolama hizmetine kaydedilebilir.
Karşıya yüklemek için birden çok dosya üzerinde döngü yapan ve güvenli dosya adları kullanan başka bir örnek
için, örnek uygulamadaki Pages/Bufferedmultiplefileuploadfiziksel. cshtml. cs dosyasına bakın.

WARNING
Path. GetTempFileName , önceki geçici dosyaları silmeden 65.535 'den fazla dosya oluşturulduysa bir IOException oluşturur.
65.535 dosya sınırının sunucu başına sınırı vardır. Windows işletim sistemi için bu sınır hakkında daha fazla bilgi için aşağıdaki
konulara bakın:
GetTempFileNameA işlevi
GetTempFileName

Bir veritabanına arabellekli model bağlamaya sahip küçük dosyaları karşıya yükleme
İkili dosya verilerini Entity Frameworkkullanarak bir veritabanında depolamak için, varlıkta bir Byte Array özelliği
tanımlayın:

public class AppFile


{
public int Id { get; set; }
public byte[] Content { get; set; }
}

Bir IFormFileiçeren sınıf için bir sayfa modeli özelliği belirtin:

public class BufferedSingleFileUploadDbModel : PageModel


{
...

[BindProperty]
public BufferedSingleFileUploadDb FileUpload { get; set; }

...
}

public class BufferedSingleFileUploadDb


{
[Required]
[Display(Name="File")]
public IFormFile FormFile { get; set; }
}

NOTE
IFormFile, doğrudan bir eylem yöntemi parametresi veya bir bağlantılı model özelliği olarak kullanılabilir. Önceki örnekte, bir
bağlantılı model özelliği kullanılmaktadır.

FileUpload Razor Pages formunda kullanılır:

<form enctype="multipart/form-data" method="post">


<dl>
<dt>
<label asp-for="FileUpload.FormFile"></label>
</dt>
<dd>
<input asp-for="FileUpload.FormFile" type="file">
</dd>
</dl>
<input asp-page-handler="Upload" class="btn" type="submit" value="Upload">
</form>

Form sunucuya gönderildiğinde, IFormFile bir akışa kopyalayın ve veritabanına bir bayt dizisi olarak kaydedin.
Aşağıdaki örnekte, uygulamanın veritabanı bağlamını _dbContext depolar:
public async Task<IActionResult> OnPostUploadAsync()
{
using (var memoryStream = new MemoryStream())
{
await FileUpload.FormFile.CopyToAsync(memoryStream);

// Upload the file if less than 2 MB


if (memoryStream.Length < 2097152)
{
var file = new AppFile()
{
Content = memoryStream.ToArray()
};

_dbContext.File.Add(file);

await _dbContext.SaveChangesAsync();
}
else
{
ModelState.AddModelError("File", "The file is too large.");
}
}

return Page();
}

Yukarıdaki örnek, örnek uygulamada gösterilen senaryoya benzerdir:


Pages/BufferedSingleFileUploadDb. cshtml
Pages/BufferedSingleFileUploadDb. cshtml. cs

WARNING
İkili verileri ilişkisel veritabanlarında depolarken dikkatli olun, çünkü performansı olumsuz etkileyebilir.
Doğrulaması olmadan IFormFile FileName özelliğine güvenmeyin veya güvenmeyin. FileName özelliği yalnızca
görüntüleme amacıyla ve yalnızca HTML kodlaması sonrasında kullanılmalıdır.
Belirtilen örneklerde dikkate alınması gereken önemli noktalar. Ek bilgiler aşağıdaki bölümler ve örnek uygulamatarafından
sağlanır:
Güvenlik konuları
Doğrulama

Akışa sahip büyük dosyaları karşıya yükleme


Aşağıdaki örnek, bir denetleyiciyi bir denetleyici eyleminde akışa almak için JavaScript 'in nasıl kullanılacağını
gösterir. Dosyanın antiforgery belirteci özel bir filtre özniteliği kullanılarak oluşturulur ve istek gövdesi yerine
istemci HTTP üst bilgilerine geçirilir. Eylem yöntemi karşıya yüklenen verileri doğrudan işlediğinden, form modeli
bağlama başka bir özel filtre tarafından devre dışı bırakıldı. Eylem içinde formun içerikleri, her bir MultipartSection
okuyan, dosyayı işleyen veya içeriği uygun şekilde depolayan bir MultipartReader kullanılarak okunur. Çok parçalı
bölümler okunduktan sonra eylem kendi model bağlamasını gerçekleştirir.
İlk sayfa yanıtı formu yükler ve bir tanımlama bilgisine ( GenerateAntiforgeryTokenCookieAttribute özniteliği
aracılığıyla) bir antiforgery belirteci kaydeder. Öznitelik, bir istek belirtecine sahip bir tanımlama bilgisi ayarlamak
için ASP.NET Core yerleşik antiforgery desteğini kullanır:
public class GenerateAntiforgeryTokenCookieAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var antiforgery = context.HttpContext.RequestServices.GetService<IAntiforgery>();

// Send the request token as a JavaScript-readable cookie


var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);

context.HttpContext.Response.Cookies.Append(
"RequestVerificationToken",
tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}

public override void OnResultExecuted(ResultExecutedContext context)


{
}
}

Model bağlamayı devre dışı bırakmak için DisableFormValueModelBindingAttribute kullanılır:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}

public void OnResourceExecuted(ResourceExecutedContext context)


{
}
}

Örnek uygulamada GenerateAntiforgeryTokenCookieAttribute ve DisableFormValueModelBindingAttribute ,


Startup.ConfigureServices kurallarıkullanılarak Razor Pages /StreamedSingleFileUploadDb ve
/StreamedSingleFileUploadPhysical sayfa uygulama modellerine filtre olarak uygulanır:
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/StreamedSingleFileUploadDb",
model =>
{
model.Filters.Add(
new GenerateAntiforgeryTokenCookieAttribute());
model.Filters.Add(
new DisableFormValueModelBindingAttribute());
});
options.Conventions
.AddPageApplicationModelConvention("/StreamedSingleFileUploadPhysical",
model =>
{
model.Filters.Add(
new GenerateAntiforgeryTokenCookieAttribute());
model.Filters.Add(
new DisableFormValueModelBindingAttribute());
});
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Model bağlama formu okumadığından formdan bağlanan parametreler bağlanamaz (sorgu, yol ve başlık çalışmaya
devam eder). Action yöntemi doğrudan Request özelliği ile birlikte çalışabilir. Her bölümü okumak için bir
MultipartReader kullanılır. Anahtar/değer verileri bir KeyValueAccumulator depolanır. Çok parçalı bölümler
okunduktan sonra, KeyValueAccumulator içeriği form verilerini bir model türüne bağlamak için kullanılır.
EF Core ile bir veritabanına akışa yönelik tüm StreamingController.UploadDatabase yöntemi:

[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadDatabase()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error

return BadRequest(ModelState);
}

// Accumulate the form data key-value pairs in the request (formAccumulator).


var formAccumulator = new KeyValueAccumulator();
var trustedFileNameForDisplay = string.Empty;
var untrustedFileNameForStorage = string.Empty;
var streamedFileContent = new byte[0];

var boundary = MultipartRequestHelper.GetBoundary(


MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);

var section = await reader.ReadNextSectionAsync();

while (section != null)


{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);

if (hasContentDispositionHeader)
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
untrustedFileNameForStorage = contentDisposition.FileName.Value;
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);

streamedFileContent =
await FileHelpers.ProcessStreamedFile(section, contentDisposition,
ModelState, _permittedExtensions, _fileSizeLimit);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
}
else if (MultipartRequestHelper
.HasFormDataContentDisposition(contentDisposition))
{
// Don't limit the key name length because the
// multipart headers length limit is already in effect.
var key = HeaderUtilities
.RemoveQuotes(contentDisposition.Name).Value;
var encoding = GetEncoding(section);

if (encoding == null)
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error

return BadRequest(ModelState);
}

using (var streamReader = new StreamReader(


section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
// The value length limit is enforced by
// MultipartBodyLengthLimit
var value = await streamReader.ReadToEndAsync();

if (string.Equals(value, "undefined",
StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}

formAccumulator.Append(key, value);

if (formAccumulator.ValueCount >
_defaultFormOptions.ValueCountLimit)
{
// Form key count limit of
// _defaultFormOptions.ValueCountLimit
// is exceeded.
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 3).");
// Log error

return BadRequest(ModelState);
}
}
}
}
}

// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}

// Bind form data to the model


var formData = new FormData();
var formValueProvider = new FormValueProvider(
BindingSource.Form,
new FormCollection(formAccumulator.GetResults()),
CultureInfo.CurrentCulture);
var bindingSuccessful = await TryUpdateModelAsync(formData, prefix: "",
valueProvider: formValueProvider);

if (!bindingSuccessful)
{
ModelState.AddModelError("File",
"The request couldn't be processed (Error 5).");
// Log error

return BadRequest(ModelState);
}

// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample app.

var file = new AppFile()


{
Content = streamedFileContent,
UntrustedName = untrustedFileNameForStorage,
Note = formData.Note,
Size = streamedFileContent.Length,
UploadDT = DateTime.UtcNow
};

_context.File.Add(file);
await _context.SaveChangesAsync();

return Created(nameof(StreamingController), null);


}

MultipartRequestHelper (Utilities/MultipartRequestHelper. cs):


using System;
using System.IO;
using Microsoft.Net.Http.Headers;

namespace SampleApp.Utilities
{
public static class MultipartRequestHelper
{
// Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq"
// The spec at https://tools.ietf.org/html/rfc2046#section-5.1 states that 70 characters is a
reasonable limit.
public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
{
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;

if (string.IsNullOrWhiteSpace(boundary))
{
throw new InvalidDataException("Missing content-type boundary.");
}

if (boundary.Length > lengthLimit)


{
throw new InvalidDataException(
$"Multipart boundary length limit {lengthLimit} exceeded.");
}

return boundary;
}

public static bool IsMultipartContentType(string contentType)


{
return !string.IsNullOrEmpty(contentType)
&& contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}

public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition)


{
// Content-Disposition: form-data; name="key";
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& string.IsNullOrEmpty(contentDisposition.FileName.Value)
&& string.IsNullOrEmpty(contentDisposition.FileNameStar.Value);
}

public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)


{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
|| !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
}
}
}

Fiziksel bir konuma akışa yönelik tüm StreamingController.UploadPhysical yöntemi:

[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadPhysical()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error

return BadRequest(ModelState);
}

var boundary = MultipartRequestHelper.GetBoundary(


MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();

while (section != null)


{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);

if (hasContentDispositionHeader)
{
// This check assumes that there's a file
// present without form data. If form data
// is present, this method immediately fails
// and returns the model error.
if (!MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error

return BadRequest(ModelState);
}
else
{
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);
var trustedFileNameForFileStorage = Path.GetRandomFileName();

// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample.

var streamedFileContent = await FileHelpers.ProcessStreamedFile(


section, contentDisposition, ModelState,
_permittedExtensions, _fileSizeLimit);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

using (var targetStream = System.IO.File.Create(


Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);

_logger.LogInformation(
"Uploaded file '{TrustedFileNameForDisplay}' saved to " +
"'{TargetFilePath}' as {TrustedFileNameForFileStorage}",
trustedFileNameForDisplay, _targetFilePath,
trustedFileNameForFileStorage);
}
}
}
}

// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}

return Created(nameof(StreamingController), null);


}

Örnek uygulamada, doğrulama denetimleri FileHelpers.ProcessStreamedFile tarafından işlenir.

Doğrulama
Örnek uygulamanın FileHelpers sınıfı, arabelleğe alınmış IFormFile ve akış dosya yüklemeleri için birkaç denetim
gösterir. Örnek uygulamada arabelleğe alınmış IFormFile dosya yüklemelerini işlemek için, Utilities/Fileyardımcılar.
cs dosyasındaki ProcessFormFile yöntemine bakın. Akış dosyalarını işlemek için aynı dosyadaki
ProcessStreamedFile yöntemine bakın.

WARNING
Örnek uygulamada gösterilen doğrulama işleme yöntemleri karşıya yüklenen dosyaların içeriğini taramaz. Çoğu üretim
senaryosunda, dosyanın kullanıcılara veya diğer sistemlere kullanılabilir hale getirilmesi için dosya üzerinde bir virüs/kötü
amaçlı yazılım tarayıcı API 'SI kullanılır.
Konu örneği, doğrulama tekniklerine yönelik çalışan bir örnek sağlasa da şunları gerçekleştirmediğiniz takdirde bir üretim
uygulamasında FileHelpers sınıfını uygulamayın:
Uygulamayı tam olarak anlayın.
Uygulamayı uygulamanın ortamı ve belirtimleri için uygun şekilde değiştirin.
Bu gereksinimleri bilmeden bir uygulamada güvenlik kodunu hiçbir şekilde sayısının fark gözetmeden uygulayın.

İçerik doğrulama
Karşıya yüklenen içerikte üçüncü taraf bir virüs/kötü amaçlı yazılım tarama API 'SI kullanın.
Dosyaları tarama, yüksek hacimli senaryolarda sunucu kaynaklarında yoğun bir şekilde yapılır. Dosya tarama
nedeniyle istek işleme performansı azaldığında, tarama işini, muhtemelen uygulamanın sunucusundan farklı bir
sunucuda çalışan bir arka plan hizmetinedevredere göz önünde bulundurun. Genellikle, arka plan virüs tarayıcısı
tarafından denetlene kadar karşıya yüklenen dosyalar karantinaya alınmış bir alanda tutulur. Bir dosya geçtiğinde
dosya normal dosya depolama konumuna taşınır. Bu adımlar genellikle bir dosyanın tarama durumunu gösteren
bir veritabanı kaydıyla birlikte gerçekleştirilir. Böyle bir yaklaşım kullanarak, uygulama ve uygulama sunucusu
isteklere yanıt vermeye odaklanmaya devam eder.
Dosya Uzantısı doğrulaması
Karşıya yüklenen dosyanın uzantısı izin verilen uzantılar listesine göre denetlenmelidir. Örneğin:

private string[] permittedExtensions = { ".txt", ".pdf" };

var ext = Path.GetExtension(uploadedFileName).ToLowerInvariant();

if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext))
{
// The extension is invalid ... discontinue processing the file
}
Dosya imzası doğrulaması
Bir dosyanın imzası, bir dosyanın başlangıcında ilk birkaç bayta göre belirlenir. Bu baytlar, uzantının dosyanın
içeriğiyle eşleşip eşleşmediğini göstermek için kullanılabilir. Örnek uygulama, birkaç ortak dosya türü için dosya
imzalarını denetler. Aşağıdaki örnekte, bir JPEG görüntüsünün dosya imzası, dosyaya karşı denetlenir:

private static readonly Dictionary<string, List<byte[]>> _fileSignature =


new Dictionary<string, List<byte[]>>
{
{ ".jpeg", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 },
}
},
};

using (var reader = new BinaryReader(uploadedFileData))


{
var signatures = _fileSignature[ext];
var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length));

return signatures.Any(signature =>


headerBytes.Take(signature.Length).SequenceEqual(signature));
}

Ek dosya imzaları almak için Dosya Imzaları veritabanı ve resmi dosya belirtimleri bölümüne bakın.
Dosya adı güvenliği
Fiziksel depolamaya bir dosyayı kaydetmek için hiçbir şekilde istemci tarafından sağlanan dosya adı kullanmayın.
Geçici depolama için tam yol (dosya adı da dahil olmak üzere) oluşturmak için Path. GetRandomFileName veya
Path. GetTempFileName kullanarak dosya için güvenli bir dosya adı oluşturun.
Razor otomatik olarak HTML, görüntüleme için özellik değerlerini kodlar. Aşağıdaki kodun kullanımı güvenlidir:

@foreach (var file in Model.DatabaseFiles) {


<tr>
<td>
@file.UntrustedName
</td>
</tr>
}

Razor dışında, her zaman bir kullanıcının isteğinden dosya adı içeriği HtmlEncode.
Birçok uygulama, dosyanın var olduğunu bir denetim içermelidir; Aksi takdirde, dosyanın üzerine aynı ada sahip bir
dosya yazılır. Uygulamanızın belirtimlerini karşılamak için ek mantık sağlayın.
Boyut doğrulaması
Karşıya yüklenen dosyaların boyutunu sınırlayın.
Örnek uygulamada, dosyanın boyutu 2 MB ile sınırlıdır (bayt cinsinden gösterilir). Sınır, appSettings. JSON
dosyasındaki yapılandırma yoluyla sağlanır:

{
"FileSizeLimit": 2097152
}

FileSizeLimit PageModel sınıflarına eklenmiş:


public class BufferedSingleFileUploadPhysicalModel : PageModel
{
private readonly long _fileSizeLimit;

public BufferedSingleFileUploadPhysicalModel(IConfiguration config)


{
_fileSizeLimit = config.GetValue<long>("FileSizeLimit");
}

...
}

Dosya boyutu sınırı aştığında, dosya reddedilir:

if (formFile.Length > _fileSizeLimit)


{
// The file is too large ... discontinue processing the file
}

Name öznitelik değerini POST yönteminin Parameter adı ile Eşleştir


Form verileri oluşturan veya JavaScript 'in FormData doğrudan kullanan Razor olmayan formlarda, formun
öğesinde veya FormData belirtilen adın, denetleyicinin eyleminde parametrenin adıyla eşleşmesi gerekir.
Aşağıdaki örnekte:
Bir <input> öğesi kullanılırken, name özniteliği battlePlans değere ayarlanır:

<input type="file" name="battlePlans" multiple>

JavaScript içinde FormData kullanırken ad, battlePlans değer olarak ayarlanır:

var formData = new FormData();

for (var file in files) {


formData.append("battlePlans", file, file.name);
}

C# Yöntemin parametresi için eşleşen bir ad kullanın ( battlePlans ):


Upload adlı Razor Pages sayfa işleyicisi yöntemi için:

public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> battlePlans)

MVC POST denetleyicisi eylem yöntemi için:

public async Task<IActionResult> Post(List<IFormFile> battlePlans)

Sunucu ve uygulama yapılandırması


Çok parçalı gövde uzunluğu sınırı
MultipartBodyLengthLimit her bir çok parçalı gövdenin uzunluğu için sınır ayarlar. Bu sınırı aşan form bölümleri
ayrıştırıldığında bir InvalidDataException oluşturur. Varsayılan değer 134.217.728 ' dir (128 MB ).
Startup.ConfigureServices MultipartBodyLengthLimit ayarını kullanarak sınırı özelleştirin:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<FormOptions>(options =>
{
// Set the limit to 256 MB
options.MultipartBodyLengthLimit = 268435456;
});
}

RequestFormLimitsAttribute, tek sayfa veya eylem için MultipartBodyLengthLimit ayarlamak üzere kullanılır.
Razor Pages bir uygulamada, filtreyi Startup.ConfigureServices bir kurala uygulayın:

services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/FileUploadPage",
model.Filters.Add(
new RequestFormLimitsAttribute()
{
// Set the limit to 256 MB
MultipartBodyLengthLimit = 268435456
});
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Razor Pages bir uygulamada veya bir MVC uygulamasında, filtreyi sayfa modeline veya eylem yöntemine
uygulayın:

// Set the limit to 256 MB


[RequestFormLimits(MultipartBodyLengthLimit = 268435456)]
public class BufferedSingleFileUploadPhysicalModel : PageModel
{
...
}

Kestrel maksimum istek gövdesi boyutu


Kestrel tarafından barındırılan uygulamalar için, varsayılan en büyük istek gövdesi boyutu 30.000.000 bayttır ve bu,
yaklaşık 28,6 MB 'tır. MaxRequestBodySize Kestrel Server seçeneğini kullanarak sınırı özelleştirin:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
// Handle requests up to 50 MB
options.Limits.MaxRequestBodySize = 52428800;
});

RequestSizeLimitAttribute, tek sayfa veya eylem için MaxRequestBodySize ayarlamak üzere kullanılır.
Razor Pages bir uygulamada, filtreyi Startup.ConfigureServices bir kurala uygulayın:
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions
.AddPageApplicationModelConvention("/FileUploadPage",
model =>
{
// Handle requests up to 50 MB
model.Filters.Add(
new RequestSizeLimitAttribute(52428800));
});
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Bir Razor sayfaları uygulamasında veya bir MVC uygulamasında, filtreyi sayfa işleyici sınıfına veya eylem
yöntemine uygulayın:

// Handle requests up to 50 MB
[RequestSizeLimit(52428800)]
public class BufferedSingleFileUploadPhysicalModel : PageModel
{
...
}

Diğer Kestrel limitleri


Kestrel tarafından barındırılan uygulamalar için diğer Kestrel limitleri de uygulanabilir:
İstemci bağlantıları üst sınırı
İstek ve yanıt veri ücretleri
IIS içerik uzunluğu sınırı
Varsayılan istek sınırı ( maxAllowedContentLength ), yaklaşık 28.6 MB olan 30.000.000 bayttır. Web. config dosyasında
sınırı özelleştirin:

<system.webServer>
<security>
<requestFiltering>
<!-- Handle requests up to 50 MB -->
<requestLimits maxAllowedContentLength="52428800" />
</requestFiltering>
</security>
</system.webServer>

Bu ayar yalnızca IIS için geçerlidir. Kestrel üzerinde barındırırken davranış varsayılan olarak gerçekleşmez. Daha
fazla bilgi için bkz. Istek limitleri <requestLimits >.
ASP.NET Core modülündeki sınırlamalar veya IIS Istek filtreleme modülünün varlığı, karşıya yüklemeleri 2 veya 4
GB ile sınırlandırabilir. Daha fazla bilgi için bkz. 2 GB 'tan büyük dosya karşıya yüklenemiyor
(ASPNET/AspNetCore #2711).

Sorunları Gider
Dosyaları karşıya yükleme ve olası çözümleri ile çalışırken karşılaşılan bazı yaygın sorunlar aşağıda verilmiştir.
Bir IIS sunucusuna dağıtılırken bulunamadı hatası
Aşağıdaki hata karşıya yüklenen dosyanın, sunucunun yapılandırılmış içerik uzunluğunu aştığını gösterir:
HTTP 404.13 - Not Found
The request filtering module is configured to deny a request that exceeds the request content length.

Limiti artırma hakkında daha fazla bilgi için bkz. IIS içerik uzunluğu sınırı bölümü.
Bağlantı hatası
Bir bağlantı hatası ve bir sıfırlama sunucu bağlantısı büyük olasılıkla karşıya yüklenen dosyanın Kestrel 'in en büyük
istek gövdesi boyutunu aştığını gösterir. Daha fazla bilgi için, Kestrel maksimum istek gövdesi boyutu bölümüne
bakın. Kestrel istemci bağlantı limitleri de ayarlama gerektirebilir.
Iformfile ile null başvuru özel durumu
Denetleyici IFormFile kullanarak karşıya yüklenen dosyaları kabul ediyorsanız, ancak değer null , HTML
formunun multipart/form-data``enctype değerini belirtdiğini doğrulayın. Bu öznitelik <form> öğesinde
ayarlanmamışsa, dosya karşıya yükleme gerçekleşmez ve herhangi bir bağlı IFormFile bağımsız değişken null .
Ayrıca, form verilerinde karşıya yükleme adlandırmasının uygulamanın adlandırmayla eşleştiğindenemin olun.
Akış çok uzun
Bu konudaki örneklerde karşıya yüklenen dosyanın içeriğini tutmak için MemoryStream bağımlıdır. Bir
MemoryStream boyut limiti int.MaxValue . Uygulamanın dosya yükleme senaryosu, dosya içeriğinin 50 MB 'tan
büyük olmasını gerektiriyorsa, karşıya yüklenen dosyanın içeriğini tutmak için tek bir MemoryStream kullanmayan
alternatif bir yaklaşım kullanın.

Ek kaynaklar
Sınırsız dosya karşıya yükleme
Azure güvenliği: güvenlik çerçevesi: giriş doğrulaması | Karşı
Azure bulut tasarım desenleri: Valet anahtar düzeni
Uygulama parçalarıyla denetleyiciler, görünümler,
Razor Pages ve daha fazlasını paylaşma
10.12.2019 • 11 minutes to read • Edit Online

Tarafından Rick Anderson


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Uygulama bölümü , bir uygulamanın kaynakları üzerinde soyutlamadır. Uygulama bölümleri ASP.NET Core
denetleyicileri bulmasına, bileşenleri, etiket yardımcılarını, Razor Pages, Razor derleme kaynaklarını ve daha
fazlasını bulmasına olanak tanır. AssemblyPart bir uygulama bölümüdür. AssemblyPart bir derleme başvurusunu
kapsüller ve türleri ve derleme başvurularını ortaya koyar.
Özellik sağlayıcıları , uygulama bölümleriyle birlikte çalışarak bir ASP.NET Core uygulamasının özelliklerini
doldurur. Uygulama bölümleri için ana kullanım örneği, bir derlemeyi, bir derlemeden ASP.NET Core özellikleri
bulacak (ya da yüklemeden kaçınacak) şekilde yapılandırmaktır. Örneğin, birden çok uygulama arasında ortak
işlevselliği paylaşmak isteyebilirsiniz. Uygulama parçalarını kullanarak, birden çok uygulamayla denetleyiciler,
görünümler, Razor Pages, Razor derleme kaynakları, etiket yardımcıları ve daha fazlasını içeren bir derlemeyi (DLL )
paylaşabilirsiniz. Birden çok projedeki kodu çoğaltmak için bir derlemeyi paylaşma tercih edilir.
ASP.NET Core uygulamalar ApplicationPartözellikleri yükler. AssemblyPart sınıfı, bir derleme tarafından
desteklenen bir uygulama bölümünü temsil eder.

ASP.NET Core özellikleri yükle


ASP.NET Core özelliklerini (denetleyiciler, görünüm bileşenleri vb.) bulup yüklemek için
Microsoft.AspNetCore.Mvc.ApplicationParts ve AssemblyPart sınıflarını kullanın. ApplicationPartManager,
kullanılabilir uygulama parçalarını ve özellik sağlayıcılarını izler. ApplicationPartManager Startup.ConfigureServices
yapılandırılır:

// Requires using System.Reflection;


public void ConfigureServices(IServiceCollection services)
{
var assembly = typeof(MySharedController).Assembly;
services.AddControllersWithViews()
.AddApplicationPart(assembly);
}

Aşağıdaki kod, AssemblyPart kullanarak ApplicationPartManager yapılandırmaya yönelik alternatif bir yaklaşım
sağlar:

// Requires using System.Reflection;


// Requires using Microsoft.AspNetCore.Mvc.ApplicationParts;
public void ConfigureServices(IServiceCollection services)
{
var assembly = typeof(MySharedController).GetTypeInfo().Assembly;
// This creates an AssemblyPart, but does not create any related parts for items such as views.
var part = new AssemblyPart(assembly);
services.AddControllersWithViews()
.ConfigureApplicationPartManager(apm => apm.ApplicationParts.Add(part));
}
Önceki iki kod örneği bir derlemeden SharedController yükler. SharedController , uygulamanın projesinde değil.
Bkz. Webappparts çözüm örneği indirmesi.
Görünümleri dahil et
Derlemeye görünümler eklemek için Razor sınıf kitaplığı kullanın.
Kaynakları yüklemeyi engelle
Uygulama bölümleri, belirli bir derleme veya konumdaki kaynakları yüklemeyi önlemek için kullanılabilir.
Kullanılabilir kaynakları gizlemek veya mevcut hale getirmek için Microsoft.AspNetCore.Mvc.ApplicationParts
koleksiyonun üyelerini ekleyin veya kaldırın. ApplicationParts koleksiyonundaki girdilerin sırası önemli değildir.
Kapsayıcıdaki hizmetleri yapılandırmak için kullanmadan önce ApplicationPartManager yapılandırın. Örneğin,
AddControllersAsServices çağırmadan önce ApplicationPartManager yapılandırın. Bir kaynağı kaldırmak için
ApplicationParts koleksiyonundaki Remove çağırın.

ApplicationPartManager şunlar için parçalar içerir:


Uygulamanın derlemesi ve bağımlı derlemeleri.
Microsoft.AspNetCore.Mvc.ApplicationParts.CompiledRazorAssemblyPart
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
Microsoft.AspNetCore.Mvc.TagHelpers .
Microsoft.AspNetCore.Mvc.Razor .

Özellik sağlayıcıları
Uygulama özelliği sağlayıcıları uygulama parçalarını inceler ve bu parçalar için özellikler sağlar. Aşağıdaki ASP.NET
Core özellikleri için yerleşik özellik sağlayıcıları vardır:
ControllerFeatureProvider
TagHelperFeatureProvider
MetadataReferenceFeatureProvider
ViewsFeatureProvider
internal class RazorCompiledItemFeatureProvider

Özellik sağlayıcıları, T özelliğin türü olduğu IApplicationFeatureProvider<TFeature>devralınır. Özellik


sağlayıcıları, daha önce listelenen özellik türlerinden herhangi biri için uygulanabilir.
ApplicationPartManager.FeatureProviders özellik sağlayıcılarının sırası çalışma zamanı davranışını etkileyebilir. Daha
sonra eklenen sağlayıcılar, daha önce eklenen sağlayıcıların yaptığı eylemlere yanıt verebilir.
Kullanılabilir özellikleri görüntüle
Bir uygulama için kullanılabilen özellikler, bağımlılık eklemeyoluyla bir ApplicationPartManager isteyerek
numaralandırılabilir:
using AppPartsSample.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewComponents;

namespace AppPartsSample.Controllers
{
public class FeaturesController : Controller
{
private readonly ApplicationPartManager _partManager;

public FeaturesController(ApplicationPartManager partManager)


{
_partManager = partManager;
}

public IActionResult Index()


{
var viewModel = new FeaturesViewModel();

var controllerFeature = new ControllerFeature();


_partManager.PopulateFeature(controllerFeature);
viewModel.Controllers = controllerFeature.Controllers.ToList();

var tagHelperFeature = new TagHelperFeature();


_partManager.PopulateFeature(tagHelperFeature);
viewModel.TagHelpers = tagHelperFeature.TagHelpers.ToList();

var viewComponentFeature = new ViewComponentFeature();


_partManager.PopulateFeature(viewComponentFeature);
viewModel.ViewComponents = viewComponentFeature.ViewComponents.ToList();

return View(viewModel);
}
}
}

Yükleme örneği , uygulama özelliklerini göstermek için yukarıdaki kodu kullanır:

Controllers:
- FeaturesController
- HomeController
- HelloController
- GenericController`1
- GenericController`1
Tag Helpers:
- PrerenderTagHelper
- AnchorTagHelper
- CacheTagHelper
- DistributedCacheTagHelper
- EnvironmentTagHelper
- Additional Tag Helpers omitted for brevity.
View Components:
- SampleViewComponent

Uygulama bölümlerinde bulma


HTTP 404 hataları, uygulama parçalarıyla geliştirme sırasında sık karşılaşılan bir durumdur. Bu hatalar genellikle
uygulamaların bölümlerinin nasıl keşfedildiği konusunda önemli bir gereksinimin eksik olmasından kaynaklanır.
Uygulamanız bir HTTP 404 hatası döndürürse, aşağıdaki gereksinimlerin karşılandığından emin olun:
applicationName ayarının, bulma için kullanılan kök derlemeye ayarlanması gerekir. Bulma için kullanılan kök
derleme normalde giriş noktası derlemesidir.
Kök derlemenin, bulma için kullanılan bölümlere bir başvuruya sahip olması gerekir. Başvuru doğrudan veya
geçişli olabilir.
Kök derlemenin Web SDK 'sına başvurması gerekiyor. Çerçevede, öznitelikleri bulma için kullanılan kök
derlemeye damgalayan mantık vardır.
Tarafından Rick Anderson
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Uygulama bölümü , bir uygulamanın kaynakları üzerinde soyutlamadır. Uygulama bölümleri ASP.NET Core
denetleyicileri bulmasına, bileşenleri, etiket yardımcılarını, Razor Pages, Razor derleme kaynaklarını ve daha
fazlasını bulmasına olanak tanır. AssemblyPart bir uygulama bölümüdür. AssemblyPart bir derleme başvurusunu
kapsüller ve türleri ve derleme başvurularını ortaya koyar.
Özellik sağlayıcıları , uygulama bölümleriyle birlikte çalışarak bir ASP.NET Core uygulamasının özelliklerini
doldurur. Uygulama bölümleri için ana kullanım örneği, bir derlemeyi, bir derlemeden ASP.NET Core özellikleri
bulacak (ya da yüklemeden kaçınacak) şekilde yapılandırmaktır. Örneğin, birden çok uygulama arasında ortak
işlevselliği paylaşmak isteyebilirsiniz. Uygulama parçalarını kullanarak, birden çok uygulamayla denetleyiciler,
görünümler, Razor Pages, Razor derleme kaynakları, etiket yardımcıları ve daha fazlasını içeren bir derlemeyi (DLL )
paylaşabilirsiniz. Birden çok projedeki kodu çoğaltmak için bir derlemeyi paylaşma tercih edilir.
ASP.NET Core uygulamalar ApplicationPartözellikleri yükler. AssemblyPart sınıfı, bir derleme tarafından
desteklenen bir uygulama bölümünü temsil eder.

ASP.NET Core özellikleri yükle


ASP.NET Core özelliklerini (denetleyiciler, görünüm bileşenleri vb.) bulup yüklemek için ApplicationPart ve
AssemblyPart sınıflarını kullanın. ApplicationPartManager, kullanılabilir uygulama parçalarını ve özellik
sağlayıcılarını izler. ApplicationPartManager Startup.ConfigureServices yapılandırılır:

public void ConfigureServices(IServiceCollection services)


{
// Requires using System.Reflection;
var assembly = typeof(MySharedController).GetTypeInfo().Assembly;
services.AddMvc()
.AddApplicationPart(assembly)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Aşağıdaki kod, AssemblyPart kullanarak ApplicationPartManager yapılandırmaya yönelik alternatif bir yaklaşım
sağlar:

public void ConfigureServices(IServiceCollection services)


{
// Requires using System.Reflection;
// Requires using Microsoft.AspNetCore.Mvc.ApplicationParts;
var assembly = typeof(MySharedController).GetTypeInfo().Assembly;
var part = new AssemblyPart(assembly);
services.AddMvc()
.ConfigureApplicationPartManager(apm => apm.ApplicationParts.Add(part))
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Önceki iki kod örneği bir derlemeden SharedController yükler. SharedController , uygulamanın projesinde değil.
Bkz. Webappparts çözüm örneği indirmesi.
Görünümleri dahil et
Derlemeye görünümler eklemek için Razor sınıf kitaplığı kullanın.
Kaynakları yüklemeyi engelle
Uygulama bölümleri, belirli bir derleme veya konumdaki kaynakları yüklemeyi önlemek için kullanılabilir.
Kullanılabilir kaynakları gizlemek veya mevcut hale getirmek için Microsoft.AspNetCore.Mvc.ApplicationParts
koleksiyonun üyelerini ekleyin veya kaldırın. ApplicationParts koleksiyonundaki girdilerin sırası önemli değildir.
Kapsayıcıdaki hizmetleri yapılandırmak için kullanmadan önce ApplicationPartManager yapılandırın. Örneğin,
AddControllersAsServices çağırmadan önce ApplicationPartManager yapılandırın. Bir kaynağı kaldırmak için
ApplicationParts koleksiyonundaki Remove çağırın.

Aşağıdaki kod uygulamadan MyDependentLibrary kaldırmak için Microsoft.AspNetCore.Mvc.ApplicationParts


kullanır: [!code-csharp]
ApplicationPartManager şunlar için parçalar içerir:
Uygulamanın derlemesi ve bağımlı derlemeleri.
Microsoft.AspNetCore.Mvc.TagHelpers .
Microsoft.AspNetCore.Mvc.Razor .

Uygulama özelliği sağlayıcıları


Uygulama özelliği sağlayıcıları uygulama parçalarını inceler ve bu parçalar için özellikler sağlar. Aşağıdaki ASP.NET
Core özellikleri için yerleşik özellik sağlayıcıları vardır:
Denetleyiciler
Etiket Yardımcıları
Bileşenleri görüntüle
Özellik sağlayıcıları, T özelliğin türü olduğu IApplicationFeatureProvider<TFeature>devralınır. Özellik
sağlayıcıları, daha önce listelenen özellik türlerinden herhangi biri için uygulanabilir.
ApplicationPartManager.FeatureProviders özellik sağlayıcılarının sırası çalışma zamanı davranışını etkileyebilir. Daha
sonra eklenen sağlayıcılar, daha önce eklenen sağlayıcıların yaptığı eylemlere yanıt verebilir.
Kullanılabilir özellikleri görüntüle
Bir uygulama için kullanılabilen özellikler, bağımlılık eklemeyoluyla bir ApplicationPartManager isteyerek
numaralandırılabilir:
using AppPartsSample.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewComponents;

namespace AppPartsSample.Controllers
{
public class FeaturesController : Controller
{
private readonly ApplicationPartManager _partManager;

public FeaturesController(ApplicationPartManager partManager)


{
_partManager = partManager;
}

public IActionResult Index()


{
var viewModel = new FeaturesViewModel();

var controllerFeature = new ControllerFeature();


_partManager.PopulateFeature(controllerFeature);
viewModel.Controllers = controllerFeature.Controllers.ToList();

var tagHelperFeature = new TagHelperFeature();


_partManager.PopulateFeature(tagHelperFeature);
viewModel.TagHelpers = tagHelperFeature.TagHelpers.ToList();

var viewComponentFeature = new ViewComponentFeature();


_partManager.PopulateFeature(viewComponentFeature);
viewModel.ViewComponents = viewComponentFeature.ViewComponents.ToList();

return View(viewModel);
}
}
}

Yükleme örneği , uygulama özelliklerini göstermek için yukarıdaki kodu kullanır:

Controllers:
- FeaturesController
- HomeController
- HelloController
- GenericController`1
- GenericController`1
Tag Helpers:
- PrerenderTagHelper
- AnchorTagHelper
- CacheTagHelper
- DistributedCacheTagHelper
- EnvironmentTagHelper
- Additional Tag Helpers omitted for brevity.
View Components:
- SampleViewComponent

Uygulama bölümlerinde bulma


HTTP 404 hataları, uygulama parçalarıyla geliştirme sırasında sık karşılaşılan bir durumdur. Bu hatalar genellikle
uygulamaların bölümlerinin nasıl keşfedildiği konusunda önemli bir gereksinimin eksik olmasından kaynaklanır.
Uygulamanız bir HTTP 404 hatası döndürürse, aşağıdaki gereksinimlerin karşılandığından emin olun:
applicationName ayarının, bulma için kullanılan kök derlemeye ayarlanması gerekir. Bulma için kullanılan kök
derleme normalde giriş noktası derlemesidir.
Kök derlemenin, bulma için kullanılan bölümlere bir başvuruya sahip olması gerekir. Başvuru doğrudan veya
geçişli olabilir.
Kök derlemenin Web SDK 'sına başvurması gerekiyor.
ASP.NET Core Framework 'te, bulma için kullanılan kök derlemeye öznitelikleri damgalayan özel yapı
mantığı vardır.
DotNet ASPNET-CodeGenerator
19.09.2019 • 7 minutes to read • Edit Online

Tarafından Rick Anderson


dotnet aspnet-codegenerator -ASP.NET Core scafkatlama altyapısını çalıştırır.
dotnet aspnet-codegenerator yalnızca komut satırından yapı iskelesi sağlamak için gereklidir, Visual
Studio ile scafkatlamayı kullanmak gerekli değildir.
Bu makale .NET Core 2,1 SDK ve üzeri için geçerlidir.

ASPNET-CodeGenerator yükleniyor
dotnet-aspnet-codegenerator yüklenmesi gereken küresel bir araçtır . Aşağıdaki komut
dotnet-aspnet-codegenerator aracın en son kararlı sürümünü yüklüyor:

dotnet tool install -g dotnet-aspnet-codegenerator

Aşağıdaki komut, yüklü dotnet-aspnet-codegenerator .NET Core SDK 'larında kullanılabilen en son
kararlı sürümü güncelleştirir:

dotnet tool update -g dotnet-aspnet-codegenerator

Özeti
dotnet aspnet-codegenerator [arguments] [-p|--project] [-n|--nuget-package-dir] [-c|--
configuration] [-tfm|--target-framework] [-b|--build-base-path] [--no-build]
dotnet aspnet-codegenerator [-h|--help]

Açıklama
dotnet aspnet-codegenerator Genel komut ASP.NET Core kod Oluşturucu ve yapı iskelesi
altyapısını çalıştırır.

Arguments
generator

Çalıştırılacak kod Oluşturucu. Aşağıdaki oluşturucular kullanılabilir:

OLUŞTURUCU ÇALIŞMA

Alan Bir alanı dolandırın

denetleyici Bir denetleyiciyi yapı iskelesi

kimlik Yapı iskelesi kimliği


OLUŞTURUCU ÇALIŞMA

razorpage Yapı iskelesi Razor Pages

Görünümü Bir görünümü dolandırın

Seçenekler
-n|--nuget-package-dir

NuGet paket dizinini belirtir.


-c|--configuration {Debug|Release}

Yapı yapılandırmasını tanımlar. Varsayılan değer Debug şeklindedir.


-tfm|--target-framework

Kullanılacak hedef çerçeve . Örneğin: net46 .


-b|--build-base-path

Yapı temel yolu.


-h|--help

Komut için kısa bir yardım yazdırır.


--no-build

Çalıştırmadan önce projeyi oluşturmaz. Ayrıca --no-restore bayrağı örtülü olarak ayarlar.
-p|--project <PATH>

Çalıştırılacak proje dosyasının yolunu belirtir (klasör adı veya tam yol). Belirtilmezse, varsayılan
olarak geçerli dizini alır.

Oluşturucu seçenekleri
Aşağıdaki bölümler, desteklenen oluşturucular için kullanılabilen seçenekleri ayrıntılandırır:
Alan
Kumandasını
Kimlik
Razorpage
Görüntüle
Alan seçenekleri
Bu araç, denetleyiciler ve görünümler içeren ASP.NET Core Web projelerine yöneliktir. Razor Pages
uygulamalarına yönelik değildir.
Kullanım: dotnet aspnet-codegenerator area AreaNameToGenerate

Yukarıdaki komut aşağıdaki klasörleri oluşturur:


Alanlar
AreaNameToGenerate
Denetleyiciler
Veri
Modelde
Görünümler
Denetleyici Seçenekleri
Aşağıdaki tabloda aspnet-codegenerator controller ve seçeneklerilistelenmiştir: razorpage

SEÇENEK AÇIKLAMA

--model veya -m Kullanılacak model sınıfı.

--dataContext or -dc DbContext Kullanılacak sınıfı.

--bootstrapVersion veya -b Önyükleme sürümünü belirtir. Geçerli değerler 3


veya 4 . Varsayılan değer 4 . Gerekli ve mevcut bir
wwwroot dizin belirtilen sürümü önyükleme dosyaları
içeren oluşturulur.

--referenceScriptLibraries veya - betikleri Oluşturulan görünümler, betik kitaplıkları başvuru.


Ekler _ValidationScriptsPartial düzenleyip
sayfaları oluşturun.

--düzeni veya -m Kullanılacak özel düzen sayfası.

--useDefaultLayout veya - udl Varsayılan düzen görünümleri kullanın.

--force veya -f Varolan dosyaların üzerine yaz.

--relativeFolderPath veya - outDir Klasör yolu göreli çıkış projesi dosyası burada
oluşturulur. Belirtilmezse, dosyalar proje klasöründe
oluşturulur.

Aşağıdaki tabloda aşağıdakiler için aspnet-codegenerator controller benzersiz seçenekler


listelenmektedir:

SEÇENEK AÇIKLAMA

--controllerName veya-Name Denetleyicinin adı.

--Kullanılan Asyncactions veya-async Zaman uyumsuz denetleyici eylemleri oluştur.

--noViews veya-NV Hiçbir görünüm oluşturun.

--restWithNoViews veya-API REST stili API ile bir denetleyici oluşturun. noViews
varsayılır ve tüm görünümle ilgili seçenekler yok
sayılır.

--readWriteActions veya-Actions Model olmadan okuma/yazma eylemleri ile denetleyici


oluşturun.

Komutuyla ilgili yardım için -h aspnet-codegenerator controller anahtarı kullanın:

dotnet aspnet-codegenerator controller -h


Bir örneği dotnet aspnet-codegenerator controller için bkz. film modelini yapı iskelesi .
Razorpage
Razor Pages yeni sayfanın adı ve kullanılacak şablon belirtilerek tek tek iskele alınabilir. Desteklenen
şablonlar şunlardır:
Empty
Create
Edit
Delete
Details
List

Örneğin, aşağıdaki komut myedit. cshtml ve MyEdit.cshtml.csoluşturmak için düzenleme şablonunu


kullanır:

dotnet aspnet-codegenerator razorpage MyEdit Edit -m Movie -dc RazorPagesMovieContext -outDir


Pages/Movies

Genellikle, şablon ve oluşturulan dosya adı belirtilmez ve aşağıdaki şablonlar oluşturulur:


Create
Edit
Delete
Details
List

Aşağıdaki tabloda aspnet-codegenerator razorpage ve seçeneklerilistelenmiştir: controller

SEÇENEK AÇIKLAMA

--model veya -m Kullanılacak model sınıfı.

--dataContext or -dc DbContext Kullanılacak sınıfı.

--bootstrapVersion veya -b Önyükleme sürümünü belirtir. Geçerli değerler 3


veya 4 . Varsayılan değer 4 . Gerekli ve mevcut bir
wwwroot dizin belirtilen sürümü önyükleme dosyaları
içeren oluşturulur.

--referenceScriptLibraries veya - betikleri Oluşturulan görünümler, betik kitaplıkları başvuru.


Ekler _ValidationScriptsPartial düzenleyip
sayfaları oluşturun.

--düzeni veya -m Kullanılacak özel düzen sayfası.

--useDefaultLayout veya - udl Varsayılan düzen görünümleri kullanın.

--force veya -f Varolan dosyaların üzerine yaz.

--relativeFolderPath veya - outDir Klasör yolu göreli çıkış projesi dosyası burada
oluşturulur. Belirtilmezse, dosyalar proje klasöründe
oluşturulur.
Aşağıdaki tabloda aşağıdakiler için aspnet-codegenerator razorpage benzersiz seçenekler
listelenmektedir:

SEÇENEK AÇIKLAMA

--namespaceName veya-Namespace Oluşturulan PageModel için kullanılacak ad alanının


adı

--partialView veya-Partial Kısmi bir görünüm oluşturun. Bu belirtilirse, düzen


seçenekleri-l ve-UDL yok sayılır.

--noPageModel veya-NPM Boş şablon için bir PageModel sınıfı oluşturmamı geç

Komutuyla ilgili yardım için -h aspnet-codegenerator razorpage anahtarı kullanın:

dotnet aspnet-codegenerator razorpage -h

Bir örneği dotnet aspnet-codegenerator razorpage için bkz. film modelini yapı iskelesi .
Kimlik
Bkz. Yapı Iskelesi kimliği
ASP.NET Core ile Web API 'Leri oluşturma
6.12.2019 • 13 minutes to read • Edit Online

Scott Ade ve Tom Dykstra tarafından


ASP.NET Core, web API'leri olarak da bilinen RESTful hizmetleri oluşturulmasını C# kullanarak
desteklemektedir. İstekleri işlemek için, bir Web API 'SI denetleyicileri kullanır. Bir Web API 'sindeki
denetleyiciler ControllerBase türetilen sınıflardır. Bu makalede, Web API isteklerini işlemek için denetleyicilerin
nasıl kullanılacağı gösterilmektedir.
Görüntüleme veya indirme örnek kodu. (İndirme).

ControllerBase sınıfı
Bir Web API 'SI ControllerBasetüretilen bir veya daha fazla denetleyici sınıfından oluşur. Web API proje şablonu
bir başlatıcı denetleyicisi sağlar:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Controller sınıfından türeterek bir Web API denetleyicisi oluşturmayın. Controller ControllerBase türetilir ve
görünümler için destek ekler, bu nedenle Web API istekleri için değil Web sayfalarını işlemeye yöneliktir. Bu
kural için bir özel durum var: aynı denetleyiciyi hem görünümler hem de Web API 'Leri için kullanmayı
planlıyorsanız, Controller türetirsiniz.
ControllerBase sınıfı, HTTP isteklerini işlemek için yararlı olan çok sayıda özellik ve yöntem sağlar. Örneğin,
ControllerBase.CreatedAtAction 201 durum kodu döndürür:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
pet.Id = _petsInMemoryStore.Any() ?
_petsInMemoryStore.Max(p => p.Id) + 1 : 1;
_petsInMemoryStore.Add(pet);

return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);


}

ControllerBase sağladığı yöntemlere ilişkin bazı örnekler aşağıda verilmiştir.

YÖNTEM NOTLAR

BadRequest 400 durum kodunu döndürür.


YÖNTEM NOTLAR

NotFound 404 durum kodunu döndürür.

PhysicalFile Bir dosya döndürür.

TryUpdateModelAsync Model bağlamasınıçağırır.

TryValidateModel Model doğrulamasınıçağırır.

Tüm kullanılabilir yöntemlerin ve özelliklerin listesi için bkz. ControllerBase.

{1>{2>Öznitelikler<2}<1}
Microsoft.AspNetCore.Mvc ad alanı, Web API denetleyicileri ve eylem yöntemlerinin davranışını yapılandırmak
için kullanılabilen öznitelikleri sağlar. Aşağıdaki örnek, desteklenen HTTP eylem fiilini ve döndürülebilecek
bilinen HTTP durum kodlarını belirtmek için özniteliklerini kullanır:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
pet.Id = _petsInMemoryStore.Any() ?
_petsInMemoryStore.Max(p => p.Id) + 1 : 1;
_petsInMemoryStore.Add(pet);

return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);


}

Aşağıda, kullanılabilecek özniteliklerin daha fazla örneği verilmiştir.

ÖZNITELIK NOTLAR

[Route] Bir denetleyicinin veya eylemin URL modelini belirtir.

[Bind] Model bağlama için dahil edilecek öneki ve özellikleri belirtir.

[HttpGet] HTTP GET ACTION fiilini destekleyen bir eylemi tanımlar.

[Consumes] Bir eylemin kabul ettiği veri türlerini belirtir.

[Produces] Bir eylemin döndürdüğü veri türlerini belirtir.

Kullanılabilir öznitelikleri içeren bir liste için Microsoft.AspNetCore.Mvc ad alanına bakın.

ApiController özniteliği
[ApiController] özniteliği, AŞAĞıDAKI, API 'ye özgü davranışları etkinleştirmek üzere bir denetleyici sınıfına
uygulanabilir:
Öznitelik yönlendirme gereksinimi
Otomatik HTTP 400 yanıtları
Bağlama kaynak parametresi çıkarımı
Multipart/form-veri isteği çıkarımı
Hata durum kodları için sorun ayrıntıları
Bu özellikler, 2,1 veya üzeri bir Uyumluluk sürümü gerektirir.
Belirli denetleyicilerde öznitelik
[ApiController] özniteliği, proje şablonundan aşağıdaki örnekte olduğu gibi belirli denetleyicilere
uygulanabilir:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Birden çok denetleyicilerde öznitelik


Özniteliği birden fazla denetleyicide kullanmanın bir yaklaşımı, [ApiController] özniteliğiyle açıklanmış bir özel
temel denetleyici sınıfı oluşturmaktır. Aşağıdaki örnekte, özel bir temel sınıf ve ondan türetilen bir denetleyici
gösterilmektedir:

[ApiController]
public class MyControllerBase : ControllerBase
{
}

[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase

[Produces(MediaTypeNames.Application.Json)]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

Bir derlemedeki öznitelik


Uyumluluk sürümü 2,2 veya üzeri bir sürüme ayarlandıysa, [ApiController] özniteliği bir derlemeye
uygulanabilir. Bu şekilde ek açıklama, derlemedeki tüm denetleyicilere Web API davranışını uygular. Tek tek
denetleyiciler için geri alma yöntemi yoktur. Derleme düzeyi özniteliğini Startup sınıfını çevreleyen ad alanı
bildirimine uygulayın:

[assembly: ApiController]
namespace WebApiSample
{
public class Startup
{
...
}
}

Öznitelik yönlendirme gereksinimi


[ApiController] özniteliği öznitelik yönlendirme bir gereksinim yapar. Örneğin:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Eylemler Startup.Configure içinde UseEndpoints , UseMvcveya UseMvcWithDefaultRoute tarafından


tanımlanan geleneksel yollar aracılığıyla erişilemez.

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Eylemler Startup.Configure UseMvc veya UseMvcWithDefaultRoute tarafından tanımlanan geleneksel yollar


aracılığıyla erişilemez.

Otomatik HTTP 400 yanıtları


[ApiController] özniteliği, model doğrulama hatalarının otomatik olarak bir HTTP 400 yanıtı tetiklenmesine
neden olur. Sonuç olarak, aşağıdaki kod bir eylem yönteminde gereksizdir:

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

ASP.NET Core MVC, önceki denetimi yapmak için ModelStateInvalidFilter eylem filtresini kullanır.
Varsayılan BadRequest yanıtı
2,1 uyumluluk sürümü ile bir HTTP 400 yanıtı için varsayılan yanıt türü SerializableError. Aşağıdaki istek
gövdesi, serileştirilmiş türün bir örneğidir:

{
"": [
"A non-empty request body is required."
]
}

2,2 veya üzeri bir uyumluluk sürümü ile, bir HTTP 400 yanıtı için varsayılan yanıt türü
ValidationProblemDetails. Aşağıdaki istek gövdesi, serileştirilmiş türün bir örneğidir:

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors": {
"": [
"A non-empty request body is required."
]
}
}

ValidationProblemDetails türü:
Web API yanıtlarında hata belirtmek için makine tarafından okunabilen bir biçim sağlar.
RFC 7807 belirtimineuyar.
Otomatik 400 yanıtlarını günlüğe kaydet
Bkz. otomatik 400 yanıtlarını model doğrulama hatalarında günlüğe kaydetme (ASPNET/AspNetCore. Docs
#12157).
Otomatik 400 yanıtını devre dışı bırak
Otomatik 400 davranışını devre dışı bırakmak için SuppressModelStateInvalidFilter özelliğini true olarak
ayarlayın. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});

Bağlama kaynak parametresi çıkarımı


Bağlama kaynak özniteliği, bir eylem parametresi değerinin bulunduğu konumu tanımlar. Aşağıdaki bağlama
kaynak öznitelikleri var:

ÖZNITELIK BAĞLAMA KAYNAĞI

[FromBody] İstek gövdesi

[FromForm] İstek gövdesinde form verileri

[FromHeader] İstek üst bilgisi

[FromQuery] İstek sorgusu dize parametresi


ÖZNITELIK BAĞLAMA KAYNAĞI

[FromRoute] Geçerli istekten veri yönlendir

[FromServices] Eylem parametresi olarak eklenen istek hizmeti

WARNING
Değerler %2f ( / ) içerdiğinde [FromRoute] kullanmayın. %2f / atlanmaz. Değer %2f içeriyorsa [FromQuery]
kullanın.

[FromQuery] gibi [ApiController] özniteliği veya bağlama kaynağı öznitelikleri olmadan ASP.NET Core çalışma
zamanı karmaşık nesne modeli Ciltçi kullanmaya çalışır. Karmaşık nesne modeli Ciltçi, verileri değer
sağlayıcılarından tanımlı bir düzende çeker.
Aşağıdaki örnekte [FromQuery] özniteliği, istek URL 'sinin sorgu dizesinde discontinuedOnly parametre
değerinin sağlandığını belirtir:

[HttpGet]
public ActionResult<List<Product>> Get(
[FromQuery] bool discontinuedOnly = false)
{
List<Product> products = null;

if (discontinuedOnly)
{
products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
}
else
{
products = _productsInMemoryStore;
}

return products;
}

[ApiController] özniteliği, eylem parametrelerinin varsayılan veri kaynakları için çıkarım kuralları uygular. Bu
kurallar, eylem parametrelerine öznitelikleri uygulayarak bağlama kaynaklarını el ile tanımlamak zorunda
kalmadan sizi kaydeder. Bağlama kaynak çıkarımı kuralları aşağıdaki gibi davranır:
karmaşık tür parametreleri için [FromBody] algılanır. [FromBody] çıkarım kuralı için bir özel durum,
IFormCollection ve CancellationTokengibi özel bir anlamı olan karmaşık, yerleşik bir türdür. Bağlama kaynak
çıkarımı kodu bu özel türleri yoksayar.
IFormFile ve IFormFileCollectiontüründeki eylem parametreleri için [FromForm] algılanır. Bu, herhangi bir
basit veya Kullanıcı tanımlı tür için çıkarsanamıyor.
yol şablonundaki bir parametreyle eşleşen herhangi bir eylem parametresi adı için [FromRoute] algılanır.
Birden fazla yol bir eylem parametresiyle eşleştiğinde, herhangi bir rota değeri [FromRoute] olarak
değerlendirilir.
[FromQuery] diğer eylem parametreleri için algılanır.

FromBody çıkarım notları


string veya int gibi basit türler için [FromBody] çıkarsanamıyor. Bu nedenle, bu işlev gerektiğinde basit türler
için [FromBody] özniteliği kullanılmalıdır.
Bir eylem, istek gövdesinden birden fazla parametre bağlamışsa, bir özel durum oluşturulur. Örneğin, aşağıdaki
eylem yöntemi imzalarının tümü bir özel duruma neden olur:
karmaşık türler olduklarından her ikisi de [FromBody] .

[HttpPost]
public IActionResult Action1(Product product, Order order)

karmaşık bir tür olduğundan, başka bir üzerinde [FromBody] özniteliği.

[HttpPost]
public IActionResult Action2(Product product, [FromBody] Order order)

her ikisinde de [FromBody] özniteliği.

[HttpPost]
public IActionResult Action3([FromBody] Product product, [FromBody] Order order)

NOTE
ASP.NET Core 2,1 ' de, listeler ve diziler gibi koleksiyon türü parametreleri [FromQuery] olarak yanlış şekilde algılanır.
[FromBody] özniteliği, istek gövdesinden bağlanmaları durumunda bu parametreler için kullanılmalıdır. Bu davranış
ASP.NET Core 2,2 veya sonraki bir sürümde düzeltilir. burada, koleksiyon türü parametrelerinin varsayılan olarak gövdeden
bağlanacak şekilde çıkarsandır.

Çıkarım kurallarını devre dışı bırak


Bağlama kaynak çıkarımını devre dışı bırakmak için SuppressInferBindingSourcesForParameters true olarak
ayarlayın. Aşağıdaki kodu Startup.ConfigureServices ekleyin:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});

Multipart/form-veri isteği çıkarımı


[FromForm] özniteliğiyle bir eylem parametresine ek açıklama eklendiğinde [ApiController] özniteliği bir
çıkarım kuralı uygular. multipart/form-data isteği içerik türü algılanır.
Varsayılan davranışı devre dışı bırakmak için SuppressConsumesConstraintForFormFileParameters özelliğini
Startup.ConfigureServices``true olarak ayarlayın:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});

Hata durum kodları için sorun ayrıntıları


Uyumluluk sürümü 2,2 veya üzeri olduğunda, MVC bir hata sonucunu (durum kodu 400 veya üzeri olan bir
sonuç) ProblemDetailsbir sonuçla dönüştürür. ProblemDetails türü, bir HTTP yanıtında makine tarafından
okunabilen hata ayrıntılarını sağlamak için RFC 7807 belirtimine dayanır.
Bir denetleyici eyleminde aşağıdaki kodu göz önünde bulundurun:
if (pet == null)
{
return NotFound();
}

NotFound yöntemi ProblemDetails gövde içeren bir HTTP 404 durum kodu üretir. Örneğin:

{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}

ProblemDetails yanıtını devre dışı bırak


SuppressMapClientErrors özelliği true olarak ayarlandığında ProblemDetails örneğinin otomatik olarak
oluşturulması devre dışıdır. Aşağıdaki kodu Startup.ConfigureServices ekleyin:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

Ek kaynaklar
ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri
ASP.NET Core Web API 'Lerinde hataları işleme
ASP.NET Core Web API 'sindeki özel formatıcılar
ASP.NET Core Web API 'sindeki yanıt verilerini biçimlendirme
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core denetleyici eylemlerine yönlendirme
Öğretici: ASP.NET Core bir Web API 'SI oluşturma
10.12.2019 • 47 minutes to read • Edit Online

Tarafından Rick Anderson ve Mike Wasson


Bu öğretici, bir web API ASP.NET Core ile oluşturmaya ilişkin temel bilgileri öğretir.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
Bir Web API projesi oluşturun.
Bir model sınıfı ve bir veritabanı bağlamı ekleyin.
CRUD yöntemleriyle bir denetleyiciyi dolandırın.
Yönlendirmeyi, URL yollarını ve dönüş değerlerini yapılandırın.
Web API'si Postman ile çağırın.
Sonunda, bir veritabanında depolanan "yapılacaklar" öğelerini yönetebilmek için bir Web API 'SI vardır.

Genel bakış
Bu öğretici yandaki API oluşturur:

API AÇIKLAMA İSTEK GÖVDESI YANIT GÖVDESI

/Api/TodoItems al Tüm yapılacak iş öğeleri al Yok. Yapılacaklar öğelerinin bir


dizisi

/Api/TodoItems/{id} al Bir öğeyi Kimliğine göre Al Yok. Yapılacak iş öğesi

POST/api/TodoItems Yeni Öğe Ekle Yapılacak iş öğesi Yapılacak iş öğesi

/Api/TodoItems/{id} koy Mevcut öğeyi güncelleştirin Yapılacak iş öğesi Yok.

/Api/TodoItems/{id} SIL Öğeyi Sil Yok. Yok.

Aşağıdaki diyagramda, bu uygulamanın tasarımını gösterir.


Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019 16,4 veya üzeri
.NET Core 3,1 SDK veya üzeri

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması şablonunu seçin ve İleri' ye tıklayın.
Projeyi TodoApi olarak adlandırın ve Oluştur' a tıklayın.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda, .net Core ve ASP.NET Core 3,1 '
un seçili olduğunu doğrulayın. API şablonunu seçin ve Oluştur' a tıklayın.

API'yi test etme


Proje şablonu oluşturur bir WeatherForecast API. Çağrı Get uygulamayı test etmek için bir tarayıcıdan
yöntemi.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı çalıştırmak için CTRL + F5 tuşlarına basın. Visual Studio bir tarayıcı ile başlatarak
https://localhost:<port>/WeatherForecast burada <port> bir rastgele seçilen bağlantı noktası numarasıdır.
IIS Express sertifika güven varsa soran bir iletişim kutusu alırsanız seçin Evet. İçinde Güvenlik Uyarısı
ardından, görüntülenen iletişim seçin Evet.
Aşağıdakine benzer bir JSON döndürülür:

[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]

Bir model sınıfı ekleme


A modeli uygulamayı yöneten verilerini temsil eden sınıflar kümesidir. Tek bir modeldir bu uygulama için
TodoItem sınıfı.

Visual Studio
Visual Studio Code
Mac için Visual Studio
İçinde Çözüm Gezgini, projeye sağ tıklayın. Seçin ekleme > yeni klasör. Klasör adı modelleri.
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı Todoıtem seçip Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
}

Id Özelliği işlevlerinin bir ilişkisel veritabanında benzersiz anahtar.


Model sınıfları herhangi bir projede gidip ancak modelleri klasörü, kural olarak kullanılır.

Veritabanı bağlamı Ekle


Veritabanı bağlamı koordine eden bir veri modeli için Entity Framework işlevsellik ana sınıftır. Bu sınıf türetme
tarafından oluşturulan Microsoft.EntityFrameworkCore.DbContext sınıfı.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Microsoft. EntityFrameworkCore. SqlServer ekleyin
Araçlar menüsünde nuget Paket Yöneticisi > çözüm Için NuGet Paketlerini Yönet' i seçin.
Araştır sekmesini seçin ve arama kutusuna Microsoft. Entityframeworkcore. SqlServer yazın.
Sol bölmedeki Microsoft. EntityFrameworkCore. SqlServer öğesini seçin.
Sağ bölmedeki Proje onay kutusunu seçin ve ardından Install' ı seçin.
Microsoft.EntityFrameworkCore.InMemory NuGet paketini eklemek için yukarıdaki yönergeleri kullanın.

TodoContext veritabanı bağlamını ekleme


Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı TodoContext tıklatıp Ekle.
Aşağıdaki kodu girin:

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}

public DbSet<TodoItem> TodoItems { get; set; }


}
}

Veritabanı bağlamı Kaydet


ASP.NET Core DB bağlamı gibi hizmetler ile kaydedilmelidir bağımlılık ekleme (dı) kapsayıcı. Kapsayıcı hizmeti
denetleyicilerine sağlar.
Güncelleştirme Startup.cs aşağıdaki vurgulanmış kodu:
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

Yukarıdaki kod:
Kullanılmayan kaldırır using bildirimleri.
Veritabanı bağlamı DI kapsayıcıya ekler.
Veritabanı bağlamı bir bellek içi veritabanına kullanacağını belirtir.

Denetleyiciyi bir denetleyiciye katlama


Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ denetleyicileri klasör.
> yeni yapı Iskelesi öğesi Ekle ' yi seçin.
Entity Framework kullanarak ve eylemler Içeren API denetleyicisi' ni seçin ve ardından Ekle' yi
seçin.
API denetleyiciyi eylemler Ile Ekle ' de Entity Framework iletişim kutusunu kullanarak:
Model sınıfında TodoItem (TodoApi. modeller) öğesini seçin.
Veri bağlamı sınıfında TodoContext (TodoApi. modeller) öğesini seçin.
Add (Ekle) seçeneğini belirleyin.
Oluşturulan kod:
Bir API denetleyicisi sınıfı yöntemleri olmadan tanımlar.
Sınıfı [ApiController] özniteliğiyle işaretler. Bu öznitelik, denetleyicinin web API'si isteklerine yanıt verdiğini
gösterir. Özniteliğin izin aldığı belirli davranışlar hakkında daha fazla bilgi için bkz. ASP.NET Core ile Web
API 'Leri oluşturma.
Veritabanı bağlamı eklemesine DI kullanır ( TodoContext ) içine denetleyici. Her bir veritabanı bağlamı
kullanılan CRUD denetleyici yöntemleri.

PostTodoItem Create metodunu inceleyin


PostTodoItem ' deki return ifadesini, NameOf işlecini kullanacak şekilde değiştirin:

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();

//return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);


return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

Yukarıdaki kod, [HttpPost] özniteliğiyle gösterildiği gıbı bır http post yöntemidir. Yöntemi, HTTP isteği
gövdesinden Yapılacaklar öğenin değerini alır.
CreatedAtAction Yöntemi:
Başarılı olursa bir HTTP 201 durum kodu döndürür. HTTP 201 sunucuda yeni bir kaynak oluşturan bir HTTP
POST yöntemi için standart yanıttır.
Yanıta bir konum üst bilgisi ekler. Location üstbilgisi, yeni oluşturulan Yapılacaklar öğesinin URI 'sini belirtir.
Daha fazla bilgi için 10.2.2 201 oluşturuldu.
Location üst bilgisinin URI 'sini oluşturmak için GetTodoItem eyleme başvurur. C# nameof anahtar sözcüğü,
CreatedAtAction çağrısında eylem adının sabit kodlanmasını önlemek için kullanılır.

Postman yükleme
Bu öğreticide Postman web API'si test etmek için kullanılır.
Yükleme Postman
Web uygulaması başlatın.
Postman'i başlatın.
Devre dışı SSL sertifika doğrulama
Dosya > ayarları ' ndan (genel sekmesinden) SSL sertifikası doğrulamasınıdevre dışı bırakın.
WARNING
Test denetleyicisi sonra SSL sertifika doğrulamasını yeniden etkinleştirin.

Postman ile test PostTodoItem


Yeni bir istek oluşturun.
HTTP yöntemini POST olarak ayarlayın.
Seçin gövdesi sekmesi.
Seçin ham radyo düğmesi.
Tür kümesine JSON (application/json) .
İstek gövdesinde bir yapılacak iş öğesi için JSON girin:

{
"name":"walk dog",
"isComplete":true
}

Gönder’i seçin.

Konum üst bilgisi URI test


Seçin üstbilgileri sekmesinde yanıt bölmesi.
Kopyalama konumu üst bilgi değeri:
Yöntemini GET öğesine Ayarla.
URI 'yi yapıştırın (örneğin, https://localhost:5001/api/TodoItems/1 ).
Gönder’i seçin.

GET yöntemlerini inceleyin


İki GET uç noktası bu yöntemleri uygulayın:
GET /api/TodoItems
GET /api/TodoItems/{id}

Tarayıcıdan veya Postman 'dan iki uç noktayı çağırarak uygulamayı test edin. Örneğin:
https://localhost:5001/api/TodoItems
https://localhost:5001/api/TodoItems/1
Aşağıdakine benzer bir yanıt, GetTodoItems çağrısı tarafından üretilir:

[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]

Postman ile test al


Yeni bir istek oluşturun.
HTTP yöntemi kümesine alma.
İstek URL'si kümesine https://localhost:<port>/api/TodoItems . Örneğin:
https://localhost:5001/api/TodoItems .
Ayarlama iki bölme görünümü postman'deki.
Gönder’i seçin.
Bu uygulama, bellek içi bir veritabanını kullanır. Uygulama durdurulup başlatılırsa, önceki GET isteği herhangi
bir veri döndürmez. Hiçbir veri döndürülmezse, verileri uygulamaya gönderin .

URL Yönlendirme ve yolları


[HttpGet] Özniteliği bir HTTP GET isteğine yanıt vermeden bir yöntemi gösterir. Her yöntem için URL yolu şu
şekilde oluşturulur:
Denetleyicinin şablonu dizesi ile başlayıp Route özniteliği:

[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;

public TodoItemsController(TodoContext context)


{
_context = context;
}

Değiştirin [controller] denetleyicinin adı ile kural tarafından olduğu "Controller" soneki eksi denetleyici
sınıfı adı. Bu örnek için denetleyici sınıfı adı todoıtemsdenetleyicisidir, bu nedenle denetleyicinin adı
"todoıtems" olur. ASP.NET Core yönlendirme büyük/küçük harfe duyarlıdır.
[HttpGet] özniteliğinin bir yol şablonu varsa (örneğin, [HttpGet("products")] ), yola ekleyin. Bu örnek,
bir şablon kullanmaz. Daha fazla bilgi için özniteliği Http [eylem] özniteliği ile yönlendirme.
Aşağıdaki GetTodoItem yöntemi "{id}" yapılacak iş öğesi benzersiz tanımlayıcısı için bir yer tutucu
değişkendir. GetTodoItem çağrıldığında, URL 'deki "{id}" değeri id parametresindeki yöntemine sağlanır.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Döndürülen değerler
Dönüş türünü GetTodoItems ve GetTodoItem yöntemler actionresult öğesini<T > türü. ASP.NET Core, nesneyi
otomatik olarak serileştiren JSON ve yanıt iletisinin gövdesine JSON yazar. Yanıt kodu 200 bu dönüş türü için
olduğu varsayılırsa işlenmeyen özel durumlar vardır. İşlenmeyen özel durumları 5xx hatalarla karşılaşırsanız
çevrilir.
ActionResult dönüş türleri, geniş HTTP durum kodları temsil edebilir. Örneğin, GetTodoItem iki farklı durum
değerleri döndürebilir:
Öğe istenen kimliği eşleşirse, yöntem bir 404 döndürür NotFound hata kodu.
Aksi takdirde yöntem bir JSON yanıt gövdesine 200 döndürür. Döndüren item sonuçları bir HTTP 200
yanıtı.
PutTodoItem yöntemi
PutTodoItem yöntemini inceleyin:

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}

_context.Entry(todoItem).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}

return NoContent();
}

PutTodoItem benzer PostTodoItem , HTTP PUT kullanır. Yanıt 204 (içerik yok). HTTP belirtimine göre bir PUT
İsteği tüm güncelleştirilmiş varlık yalnızca değişiklikler değil göndermek istemci gerektirir. Kısmi
güncelleştirmeleri desteklemek için kullanma HTTP PATCH.
PutTodoItem çağırırken bir hata alırsanız, veritabanında bir öğe olduğundan emin olmak için GET çağırın.
Test PutTodoItem yöntemi
Bu örnek, uygulama her başlatıldığında başlatılmış olması gereken bellek içi bir veritabanını kullanır. Bir PUT
çağrısı yapmadan önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe
olduğundan emin olmak için GET çağrısı yapın.
ID = 1 olan Yapılacaklar öğesini güncelleştirin ve adını "Feed balık" olarak ayarlayın:

{
"ID":1,
"name":"feed fish",
"isComplete":true
}

Aşağıdaki görüntüde, Postman güncelleştirme gösterilmektedir:


DeleteTodoItem yöntemi
DeleteTodoItem yöntemini inceleyin:

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}

_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();

return todoItem;
}

DeleteTodoItem Yanıt 204 (içerik yok).


Test DeleteTodoItem yöntemi
Postman bir yapılacak iş öğesini silmek için kullanın:
Yöntem kümesine DELETE .
Silinecek nesnenin URI 'sini ayarlayın (örneğin https://localhost:5001/api/TodoItems/1 ).
Gönder’i seçin.

JavaScript ile Web API 'sini çağırma


Bkz. öğretici: JavaScript ile ASP.NET Core Web API 'Si çağırma.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
Bir Web API projesi oluşturun.
Bir model sınıfı ve bir veritabanı bağlamı ekleyin.
Bir denetleyici ekleyeceksiniz.
CRUD yöntemleri ekleyin.
Yönlendirmeyi Yapılandırma ve URL yolu.
Dönüş değerleri belirtin.
Web API'si Postman ile çağırın.
JavaScript ile Web API 'sini çağırın.
Sonunda, web API'si "Yapılacaklar" öğelerini ilişkisel bir veritabanında depolanan yönetebileceği sahip.

Genel bakış
Bu öğretici yandaki API oluşturur:

API AÇIKLAMA İSTEK GÖVDESI YANIT GÖVDESI

/Api/TodoItems al Tüm yapılacak iş öğeleri al Yok. Yapılacaklar öğelerinin bir


dizisi

/Api/TodoItems/{id} al Bir öğeyi Kimliğine göre Al Yok. Yapılacak iş öğesi

POST/api/TodoItems Yeni Öğe Ekle Yapılacak iş öğesi Yapılacak iş öğesi

/Api/TodoItems/{id} koy Mevcut öğeyi güncelleştirin Yapılacak iş öğesi Yok.

/Api/TodoItems/{id} SIL Öğeyi Sil Yok. Yok.

Aşağıdaki diyagramda, bu uygulamanın tasarımını gösterir.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2019 ile ASP.NET ve web geliştirme iş yükü
.NET core SDK 2.2 veya üzeri
WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Dosya menüsünden Yeni > Proje' yi seçin.
ASP.NET Core Web uygulaması şablonunu seçin ve İleri' ye tıklayın.
Projeyi TodoApi olarak adlandırın ve Oluştur' a tıklayın.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda, .net Core ve ASP.NET Core 2,2 '
un seçili olduğunu doğrulayın. API şablonunu seçin ve Oluştur' a tıklayın. Docker desteğini etkinleştir ' i
seçmeyin .

API'yi test etme


Proje şablonu oluşturur bir values API. Çağrı Get uygulamayı test etmek için bir tarayıcıdan yöntemi.
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı çalıştırmak için CTRL + F5 tuşlarına basın. Visual Studio bir tarayıcı ile başlatarak
https://localhost:<port>/api/values burada <port> bir rastgele seçilen bağlantı noktası numarasıdır.

IIS Express sertifika güven varsa soran bir iletişim kutusu alırsanız seçin Evet. İçinde Güvenlik Uyarısı
ardından, görüntülenen iletişim seçin Evet.
Aşağıdaki JSON döndürülür:

["value1","value2"]

Bir model sınıfı ekleme


A modeli uygulamayı yöneten verilerini temsil eden sınıflar kümesidir. Tek bir modeldir bu uygulama için
TodoItem sınıfı.

Visual Studio
Visual Studio Code
Mac için Visual Studio
İçinde Çözüm Gezgini, projeye sağ tıklayın. Seçin ekleme > yeni klasör. Klasör adı modelleri.
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı Todoıtem seçip Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:

namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
}

Id Özelliği işlevlerinin bir ilişkisel veritabanında benzersiz anahtar.


Model sınıfları herhangi bir projede gidip ancak modelleri klasörü, kural olarak kullanılır.

Veritabanı bağlamı Ekle


Veritabanı bağlamı koordine eden bir veri modeli için Entity Framework işlevsellik ana sınıftır. Bu sınıf türetme
tarafından oluşturulan Microsoft.EntityFrameworkCore.DbContext sınıfı.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ modelleri klasörü ve select Ekle > sınıfı. Sınıf adı TodoContext tıklatıp Ekle.
Şablon kodunu aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}

public DbSet<TodoItem> TodoItems { get; set; }


}
}

Veritabanı bağlamı Kaydet


ASP.NET Core DB bağlamı gibi hizmetler ile kaydedilmelidir bağımlılık ekleme (dı) kapsayıcı. Kapsayıcı hizmeti
denetleyicilerine sağlar.
Güncelleştirme Startup.cs aşağıdaki vurgulanmış kodu:
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the
//container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

// This method gets called by the runtime. Use this method to configure the HTTP
//request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseMvc();
}
}
}

Yukarıdaki kod:
Kullanılmayan kaldırır using bildirimleri.
Veritabanı bağlamı DI kapsayıcıya ekler.
Veritabanı bağlamı bir bellek içi veritabanına kullanacağını belirtir.

Denetleyici ekleme
Visual Studio
Visual Studio Code/Mac için Visual Studio
Sağ denetleyicileri klasör.
> Yeni öğe Ekle ' yi seçin.
İçinde Yeni Öğe Ekle iletişim kutusunda API denetleyici sınıfı şablonu.
Sınıf adı TodoControllerseçip Ekle.

Şablon kodunu aşağıdaki kodla değiştirin:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TodoApi.Models;

namespace TodoApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

public TodoController(TodoContext context)


{
_context = context;

if (_context.TodoItems.Count() == 0)
{
// Create a new TodoItem if collection is empty,
// which means you can't delete all TodoItems.
_context.TodoItems.Add(new TodoItem { Name = "Item1" });
_context.SaveChanges();
}
}
}
}

Yukarıdaki kod:
Bir API denetleyicisi sınıfı yöntemleri olmadan tanımlar.
Sınıfı [ApiController] özniteliğiyle işaretler. Bu öznitelik, denetleyicinin web API'si isteklerine yanıt verdiğini
gösterir. Özniteliğin izin aldığı belirli davranışlar hakkında daha fazla bilgi için bkz. ASP.NET Core ile Web
API 'Leri oluşturma.
Veritabanı bağlamı eklemesine DI kullanır ( TodoContext ) içine denetleyici. Her bir veritabanı bağlamı
kullanılan CRUD denetleyici yöntemleri.
Adlı bir öğe ekler Item1 veritabanı boşsa veritabanı. Her çalıştığında bu kod oluşturucusunun içinde yeni bir
HTTP isteği olduğundan. Tüm öğeleri silerseniz, oluşturucu oluşturur Item1 API yöntemi çağrıldığında
tekrar başlattığınızda. Bu nedenle, gerçekten işe yaradı silme işlemi işe yaramadı gibi görünebilir.

Get yöntemleri ekleyin


Yapılacak iş öğeleri alır bir API sağlamak için aşağıdaki yöntemi ekleyin. TodoController sınıfı:

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

İki GET uç noktası bu yöntemleri uygulayın:


GET /api/todo
GET /api/todo/{id}

Hala çalışıyorsa uygulamayı durdurun. Ardından, en son değişiklikleri dahil etmek için yeniden çalıştırın.
Bir tarayıcıdan iki uç nokta çağırarak uygulamayı test edin. Örneğin:
https://localhost:<port>/api/todo
https://localhost:<port>/api/todo/1

Şu HTTP yanıtı çağrısı tarafından üretilen GetTodoItems :

[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
URL Yönlendirme ve yolları
[HttpGet] Özniteliği bir HTTP GET isteğine yanıt vermeden bir yöntemi gösterir. Her yöntem için URL yolu şu
şekilde oluşturulur:
Denetleyicinin şablonu dizesi ile başlayıp Route özniteliği:

namespace TodoApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

Değiştirin [controller] denetleyicinin adı ile kural tarafından olduğu "Controller" soneki eksi denetleyici
sınıfı adı. Bu örnek, denetleyici sınıfı adı olan TodoDenetleyici adı "todo" Bu nedenle denetleyicisi.
ASP.NET Core yönlendirme büyük/küçük harfe duyarlıdır.
[HttpGet] özniteliğinin bir yol şablonu varsa (örneğin, [HttpGet("products")] ), yola ekleyin. Bu örnek,
bir şablon kullanmaz. Daha fazla bilgi için özniteliği Http [eylem] özniteliği ile yönlendirme.
Aşağıdaki GetTodoItem yöntemi "{id}" yapılacak iş öğesi benzersiz tanımlayıcısı için bir yer tutucu
değişkendir. Zaman GetTodoItem çağrılır, değerini "{id}" yöntemine URL'de sağlanan kendi id parametresi.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Döndürülen değerler
Dönüş türünü GetTodoItems ve GetTodoItem yöntemler actionresult öğesini<T > türü. ASP.NET Core, nesneyi
otomatik olarak serileştiren JSON ve yanıt iletisinin gövdesine JSON yazar. Yanıt kodu 200 bu dönüş türü için
olduğu varsayılırsa işlenmeyen özel durumlar vardır. İşlenmeyen özel durumları 5xx hatalarla karşılaşırsanız
çevrilir.
ActionResult dönüş türleri, geniş HTTP durum kodları temsil edebilir. Örneğin, GetTodoItem iki farklı durum
değerleri döndürebilir:
Öğe istenen kimliği eşleşirse, yöntem bir 404 döndürür NotFound hata kodu.
Aksi takdirde yöntem bir JSON yanıt gövdesine 200 döndürür. Döndüren item sonuçları bir HTTP 200
yanıtı.

Test GetTodoItems yöntemi


Bu öğreticide Postman web API'si test etmek için kullanılır.
Postman'yi yükleme.
Web uygulaması başlatın.
Postman'i başlatın.
SSL sertifikası doğrulamasınıdevre dışı bırakın.
Visual Studio
Visual Studio Code/Mac için Visual Studio
Dosya > ayarları ' ndan (genel sekmesinden) SSL sertifikası doğrulamasınıdevre dışı bırakın.

WARNING
Test denetleyicisi sonra SSL sertifika doğrulamasını yeniden etkinleştirin.

Yeni bir istek oluşturun.


HTTP yöntemi kümesine alma.
İstek URL'si kümesine https://localhost:<port>/api/todo . Örneğin: https://localhost:5001/api/todo
.
Ayarlama iki bölme görünümü postman'deki.
Gönder’i seçin.

Create yöntemi ekleme


Aşağıdaki PostTodoItem yöntemini Controllers/TodoController. csiçine ekleyin:
// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
_context.TodoItems.Add(item);
await _context.SaveChangesAsync();

return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);


}

Yukarıdaki kod, [HttpPost] özniteliğiyle gösterildiği gıbı bır http post yöntemidir. Yöntemi, HTTP isteği
gövdesinden Yapılacaklar öğenin değerini alır.
CreatedAtAction Yöntemi:
Başarılı olursa bir HTTP 201 durum kodu döndürür. HTTP 201 sunucuda yeni bir kaynak oluşturan bir
HTTP POST yöntemi için standart yanıttır.
Yanıta bir Location üst bilgisi ekler. Location üstbilgisi, yeni oluşturulan Yapılacaklar öğesinin URI 'sini
belirtir. Daha fazla bilgi için 10.2.2 201 oluşturuldu.
Locationüst bilgisinin URI 'sini oluşturmak için GetTodoItem eyleme başvurur. C# nameof anahtar
sözcüğü, CreatedAtAction çağrısında eylem adının sabit kodlanmasını önlemek için kullanılır.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

return todoItem;
}

Test PostTodoItem yöntemi


Projeyi oluşturun.
Postman HTTP yöntemi kümesine POST .
Seçin gövdesi sekmesi.
Seçin ham radyo düğmesi.
Tür kümesine JSON (application/json) .
İstek gövdesinde bir yapılacak iş öğesi için JSON girin:

{
"name":"walk dog",
"isComplete":true
}

Gönder’i seçin.
Bir 405 yöntemine Izin verilmiyor hatası alırsanız, PostTodoItem yöntemi eklendikten sonra projenin
derlenmesinin sonucu büyük olasılıkla oluşur.
Konum üst bilgisi URI test
Seçin üstbilgileri sekmesinde yanıt bölmesi.
Kopyalama konumu üst bilgi değeri:

Yöntemini GET öğesine Ayarla.


URI 'yi yapıştırın (örneğin, https://localhost:5001/api/Todo/2 ).
Gönder’i seçin.

PutTodoItem yöntemi ekleme


Aşağıdaki PutTodoItem yöntemi:
// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
if (id != item.Id)
{
return BadRequest();
}

_context.Entry(item).State = EntityState.Modified;
await _context.SaveChangesAsync();

return NoContent();
}

PutTodoItem benzer PostTodoItem , HTTP PUT kullanır. Yanıt 204 (içerik yok). HTTP belirtimine göre bir PUT
İsteği tüm güncelleştirilmiş varlık yalnızca değişiklikler değil göndermek istemci gerektirir. Kısmi
güncelleştirmeleri desteklemek için kullanma HTTP PATCH.
PutTodoItem çağırırken bir hata alırsanız, veritabanında bir öğe olduğundan emin olmak için GET çağırın.
Test PutTodoItem yöntemi
Bu örnek, uygulama her başlatıldığında başlatılmış olması gereken bellek içi bir veritabanını kullanır. Bir PUT
çağrısı yapmadan önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe
olduğundan emin olmak için GET çağrısı yapın.
Kimliğine sahip bir yapılacak iş öğesi güncelleştirme = 1 ve "balık akış için" adını girin:

{
"ID":1,
"name":"feed fish",
"isComplete":true
}

Aşağıdaki görüntüde, Postman güncelleştirme gösterilmektedir:


DeleteTodoItem yöntemi ekleme
Aşağıdaki DeleteTodoItem yöntemi:

// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
return NotFound();
}

_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();

return NoContent();
}

DeleteTodoItem Yanıt 204 (içerik yok).


Test DeleteTodoItem yöntemi
Postman bir yapılacak iş öğesini silmek için kullanın:
Yöntem kümesine DELETE .
Silinecek nesnenin URI 'sini ayarlayın (örneğin https://localhost:5001/api/todo/1 ).
Gönder’i seçin.
Örnek uygulama, tüm öğeleri silmenizi sağlar. Ancak, son öğe silindiğinde, API 'nin bir sonraki çağrılışında
model sınıfı Oluşturucu tarafından yeni bir tane oluşturulur.

JavaScript ile Web API 'sini çağırma


Bu bölümde, Web API 'sini çağırmak için JavaScript kullanan bir HTML sayfası eklenir.jQuery isteği başlatır.
JavaScript, sayfayı Web API 'sinin yanıtından alınan ayrıntılarla güncelleştirir.
Uygulamayı statik dosyalara sunacak şekilde yapılandırın ve aşağıdaki vurgulanmış kodla Startup.cs
güncelleştirerek varsayılan dosya eşlemesini etkinleştirin :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseMvc();
}
Oluşturma bir wwwroot proje dizininde klasör.
Adlı bir HTML dosyası ekleyin index.html için wwwroot dizin. Dosyanın içeriğini aşağıdaki biçimlendirme ile
değiştirin:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>To-do CRUD</title>
<style>
input[type='submit'], button, [aria-label] {
cursor: pointer;
}

#spoiler {
display: none;
}

table {
font-family: Arial, sans-serif;
border: 1px solid;
border-collapse: collapse;
}

th {
background-color: #0066CC;
color: white;
}

td {
border: 1px solid;
padding: 5px;
}
</style>
</head>
<body>
<h1>To-do CRUD</h1>
<h3>Add</h3>
<form action="javascript:void(0);" method="POST" onsubmit="addItem()">
<input type="text" id="add-name" placeholder="New to-do">
<input type="submit" value="Add">
</form>

<div id="spoiler">
<h3>Edit</h3>
<form class="my-form">
<input type="hidden" id="edit-id">
<input type="checkbox" id="edit-isComplete">
<input type="text" id="edit-name">
<input type="submit" value="Save">
<a onclick="closeInput()" aria-label="Close">&#10006;</a>
</form>
</div>

<p id="counter"></p>

<table>
<tr>
<th>Is Complete</th>
<th>Name</th>
<th></th>
<th></th>
</tr>
<tbody id="todos"></tbody>
</table>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="site.js"></script>
</body>
</html>

Adlı bir JavaScript dosyası ekleyin site.js için wwwroot dizin. Dosyanın içeriğini aşağıdaki kodla değiştirin:

const uri = "api/todo";


let todos = null;
function getCount(data) {
const el = $("#counter");
let name = "to-do";
if (data) {
if (data > 1) {
name = "to-dos";
}
el.text(data + " " + name);
} else {
el.text("No " + name);
}
}

$(document).ready(function() {
getData();
});

function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
success: function(data) {
const tBody = $("#todos");

$(tBody).empty();

getCount(data.length);

$.each(data, function(key, item) {


const tr = $("<tr></tr>")
.append(
$("<td></td>").append(
$("<input/>", {
type: "checkbox",
disabled: true,
checked: item.isComplete
})
)
)
.append($("<td></td>").text(item.name))
.append(
$("<td></td>").append(
$("<button>Edit</button>").on("click", function() {
editItem(item.id);
})
)
)
.append(
$("<td></td>").append(
$("<button>Delete</button>").on("click", function() {
deleteItem(item.id);
})
)
);

tr.appendTo(tBody);
tr.appendTo(tBody);
});

todos = data;
}
});
}

function addItem() {
const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}

function deleteItem(id) {
$.ajax({
url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});
}

function editItem(id) {
$.each(todos, function(key, item) {
if (item.id === id) {
$("#edit-name").val(item.name);
$("#edit-id").val(item.id);
$("#edit-isComplete")[0].checked = item.isComplete;
}
});
$("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
const item = {
name: $("#edit-name").val(),
isComplete: $("#edit-isComplete").is(":checked"),
id: $("#edit-id").val()
};

$.ajax({
url: uri + "/" + $("#edit-id").val(),
type: "PUT",
accepts: "application/json",
contentType: "application/json",
data: JSON.stringify(item),
success: function(result) {
getData();
}
});

closeInput();
closeInput();
return false;
});

function closeInput() {
$("#spoiler").css({ display: "none" });
}

ASP.NET Core proje başlatma ayarlarında bir değişiklik HTML sayfasını yerel olarak test etmek için gerekli:
Açık Properties\launchSettings.json.
Kaldırma launchUrl , açmak için uygulamayı zorlamak için özellik index.html—projenin varsayılan dosya.

Bu örnek, Web API 'sinin tüm CRUD yöntemlerini çağırır. API çağrıları açıklamaları aşağıda verilmiştir.
Yapılacaklar öğelerinin bir listesini alın
jQuery, bir to-do öğesi dizisini temsil eden JSON döndüren Web API 'sine bir HTTP GET isteği gönderir.
success İstek başarılı olursa geri çağırma işlevi çağrılır. Geri çağırma içinde DOM Yapılacaklar bilgilerle
güncelleştirilir.
$(document).ready(function() {
getData();
});

function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
success: function(data) {
const tBody = $("#todos");

$(tBody).empty();

getCount(data.length);

$.each(data, function(key, item) {


const tr = $("<tr></tr>")
.append(
$("<td></td>").append(
$("<input/>", {
type: "checkbox",
disabled: true,
checked: item.isComplete
})
)
)
.append($("<td></td>").text(item.name))
.append(
$("<td></td>").append(
$("<button>Edit</button>").on("click", function() {
editItem(item.id);
})
)
)
.append(
$("<td></td>").append(
$("<button>Delete</button>").on("click", function() {
deleteItem(item.id);
})
)
);

tr.appendTo(tBody);
});

todos = data;
}
});
}

Yapılacak İş Öğesi Ekle


jQuery, istek gövdesinde Yapılacaklar öğesiyle bir HTTP POST isteği gönderir. accepts Ve contentType
seçeneklerini ayarlamak application/json gönderilen ve alınan medya türü belirtmek için. Yapılacak iş öğesi
kullanarak JSON'a dönüştürülür JSON.stringify. API'yi bir başarılı durum kodu döndürdüğünde getData işlevi
HTML tablosu güncelleştirmek için çağrılır.
function addItem() {
const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}

Yapılacak iş öğesini güncelleştirme


Yapılacak iş öğesi güncelleştirilirken bir eklemeye benzerdir. url Öğenin benzersiz tanıtıcısı eklemek için
değişiklikleri ve type olduğu PUT .

$.ajax({
url: uri + "/" + $("#edit-id").val(),
type: "PUT",
accepts: "application/json",
contentType: "application/json",
data: JSON.stringify(item),
success: function(result) {
getData();
}
});

Yapılacak iş öğesi silme


Yapılacak iş öğesi silme gerçekleştirilir ayarlayarak type AJAX çağrısı hedefi üzerinde DELETE ve öğenin
benzersiz tanıtıcısı URL'yi belirterek.

$.ajax({
url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});

Web API 'sine kimlik doğrulama desteği ekleme


ASP.NET Core kimlik, ASP.NET Core Web uygulamalarına Kullanıcı arabirimi (UI) oturum açma işlevselliği
ekler. Web API 'Leri ve maça 'ları güvenli hale getirmek için aşağıdakilerden birini kullanın:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C )]
Identityserver4
Identityserver4, ASP.NET Core 3,0 için bir OpenID Connect ve OAuth 2,0 çerçevesidir. Identityserver4 aşağıdaki
güvenlik özelliklerini sunar:
Hizmet olarak kimlik doğrulaması (AaaS )
Birden çok uygulama türü üzerinde çoklu oturum açma/kapatma (SSO )
API 'Ler için erişim denetimi
Federasyon ağ geçidi
Daha fazla bilgi için bkz. ıdentityserver4 to Welcome.

Ek kaynaklar
Görüntülemek veya Bu öğretici için örnek kodu indirdikten. Bkz: nasıl indirileceğini.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
ASP.NET Core ile Web API 'Leri oluşturma
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core - Öğreticisi 1. 8'de Entity Framework Core ile Razor sayfaları
ASP.NET Core denetleyici eylemlerine yönlendirme
ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri
ASP.NET Core uygulamalarını Azure App Service dağıtma
ASP.NET Core barındırma ve dağıtma
Bu öğreticinin YouTube sürümü
MongoDB ile ASP.NET Core ile web API'si oluşturma
6.12.2019 • 33 minutes to read • Edit Online

Tarafından Pratik Khandelwal ve Scott Addie


Bu öğreticide web API'si temel oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemleri gerçekleştiren
oluşturur bir MongoDB NoSQL veritabanı.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
MongoDB yapılandırın
MongoDB veritabanı oluşturma
MongoDB koleksiyonu ve şema tanımlayın
Bir web API'sini MongoDB CRUD işlemleri gerçekleştirme
JSON serileştirmesini özelleştirme
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core SDK 3.0 veya üzeri
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
MongoDB

MongoDB yapılandırın
Windows kullanıyorsanız MongoDB, varsayılan olarak mongodb\C:\Program Files 'a yüklenir. \Program
Files\MongoDB\Server\ <Version_Number >\ Path ) ortam değişkenine ekleyin. Bu değişiklik yerden MongoDB
erişim sağlar, geliştirme makinenizde.
Mongo kabuğunu veritabanı oluşturma, koleksiyonları yapın ve belgeleri depolamak için aşağıdaki adımları
kullanın. Mongo Kabuğu komutları hakkında daha fazla bilgi için bkz. mongo kabuğunu çalışma.
1. Geliştirme makinenizde verilerin depolanması için bir dizin seçin. Örneğin, C: Windows üzerinde\BooksData
. Yoksa dizini oluşturun. Mongo kabuğunu yeni dizinleri oluşturmaz.
2. Bir komut kabuğunu açın. Varsayılan bağlantı noktası 27017 mongodb'ye bağlanmak için aşağıdaki komutu
çalıştırın. Değiştirmeyi unutmayın <data_directory_path> önceki adımda seçtiğiniz dizini.

mongod --dbpath <data_directory_path>

3. Başka bir komut kabuğu örneği açın. Aşağıdaki komutu çalıştırarak varsayılan test veritabanı'na bağlanma:

mongo

4. Bir komut kabuğu'nda aşağıdaki komutu çalıştırın:


use BookstoreDb

Adlı bir veritabanı zaten mevcut olmayan halinde BookstoreDb oluşturulur. Veritabanı mevcut değilse,
bağlantı işlemleri için açılır.
5. Oluşturma bir Books koleksiyon aşağıdaki komutu kullanarak:

db.createCollection('Books')

Aşağıdaki sonucu görüntülenir:

{ "ok" : 1 }

6. İçin bir şema tanımlayabilir Books toplama ve ekleme iki belge aşağıdaki komutu kullanarak:

db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph
Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])

Aşağıdaki sonucu görüntülenir:

{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5bfd996f7b8e48dc15ff215d"),
ObjectId("5bfd996f7b8e48dc15ff215e")
]
}

NOTE
Bu makalede gösterilen KIMLIK, bu örneği çalıştırdığınızda kimliklerle eşleşmeyecektir.

7. Aşağıdaki komutu kullanarak veritabanında belgelerini görüntüleyin:

db.Books.find({}).pretty()

Aşağıdaki sonucu görüntülenir:

{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
"Name" : "Design Patterns",
"Price" : 54.93,
"Category" : "Computers",
"Author" : "Ralph Johnson"
}
{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
"Name" : "Clean Code",
"Price" : 43.15,
"Category" : "Computers",
"Author" : "Robert C. Martin"
}
Şema girmiş ekler _id türünün özelliği ObjectId her belge için.

Veritabanı hazırdır. ASP.NET Core web API'si oluşturmaya başlayabilirsiniz.

ASP.NET Core web API projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
1. Dosya > Yeni > projesi' ne gidin.
2. ASP.NET Core Web uygulaması proje türünü seçin ve İleri' yi seçin.
3. Projeyi Booksapıolarak adlandırın ve Oluştur' u seçin.
4. .NET Core hedef çerçevesini ve 3,0 ASP.NET Coreseçin. API proje şablonunu seçin ve Oluştur' u seçin.
5. MongoDB için .NET sürücüsünün en son kararlı sürümünü öğrenmek üzere NuGet galerisini ziyaret edin:
MongoDB. Driver . İçinde Paket Yöneticisi Konsolu penceresinde proje kök dizinine gidin. MongoDB için
.NET sürücüsünü yüklemek için aşağıdaki komutu çalıştırın:

Install-Package MongoDB.Driver -Version {VERSION}

Varlık modeli ekleme


1. Ekleme bir modelleri proje kök dizini.
2. Ekleme bir Book sınıfının modelleri aşağıdaki kod ile dizin:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models
{
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

[BsonElement("Name")]
public string BookName { get; set; }

public decimal Price { get; set; }

public string Category { get; set; }

public string Author { get; set; }


}
}

Önceki sınıfta Id özelliği:


Ortak dil çalışma zamanı (CLR ) nesnesini MongoDB koleksiyonuna eşlemek için gereklidir.
, Bu özelliği belgenin birincil anahtarı olarak belirlemek için [BsonId] ile açıklama eklenir.
, Parametreyi ObjectID yapısı yerine tür string olarak geçirmeyi sağlayan
[BsonRepresentation(BsonType.ObjectId)] ile açıklama eklenir. Mongo, string dönüştürmeyi ObjectId
olarak işler.
BookName özelliğine [BsonElement] özniteliğiyle açıklama eklenir. Özniteliğin Name değeri, MongoDB
koleksiyonundaki özellik adını temsil eder.

Yapılandırma modeli ekleme


1. Aşağıdaki veritabanı yapılandırma değerlerini appSettings. JSONöğesine ekleyin:

{
"BookstoreDatabaseSettings": {
"BooksCollectionName": "Books",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookstoreDb"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}

2. Modeller dizinine aşağıdaki kodla bir BookstoreDatabaseSettings.cs dosyası ekleyin:

namespace BooksApi.Models
{
public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
{
public string BooksCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}

public interface IBookstoreDatabaseSettings


{
string BooksCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
}

Yukarıdaki BookstoreDatabaseSettings sınıfı, appSettings. JSON dosyasının BookstoreDatabaseSettings


özellik değerlerini depolamak için kullanılır. JSON ve C# Özellik adları, eşleme sürecini kolaylaştırmak için
aynı şekilde adlandırılır.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:
public void ConfigureServices(IServiceCollection services)
{
// requires using Microsoft.Extensions.Options
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddControllers();
}

Yukarıdaki kodda:
AppSettings. JSON dosyasının BookstoreDatabaseSettings bölüm bağlandığı yapılandırma örneği,
bağımlılık ekleme (dı) kapsayıcısına kaydedilir. Örneğin, bir BookstoreDatabaseSettings nesnesinin
ConnectionString özelliği appSettings. JSONiçindeki BookstoreDatabaseSettings:ConnectionString
özelliği ile doldurulur.
IBookstoreDatabaseSettings arabirimi, tek bir hizmet ömrüile dı 'ye kaydedilir. Eklerken, arabirim örneği
bir BookstoreDatabaseSettings nesnesine çözümlenir.
4. BookstoreDatabaseSettings ve IBookstoreDatabaseSettings başvurularını çözümlemek için aşağıdaki kodu
en üst kısmına ekleyin :

using BooksApi.Models;

CRUD işlemleri hizmeti ekleme


1. Ekleme bir Hizmetleri proje kök dizini.
2. Ekleme bir BookService sınıfının Hizmetleri aşağıdaki kod ile dizin:
using BooksApi.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;

namespace BooksApi.Services
{
public class BookService
{
private readonly IMongoCollection<Book> _books;

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

public List<Book> Get() =>


_books.Find(book => true).ToList();

public Book Get(string id) =>


_books.Find<Book>(book => book.Id == id).FirstOrDefault();

public Book Create(Book book)


{
_books.InsertOne(book);
return book;
}

public void Update(string id, Book bookIn) =>


_books.ReplaceOne(book => book.Id == id, bookIn);

public void Remove(Book bookIn) =>


_books.DeleteOne(book => book.Id == bookIn.Id);

public void Remove(string id) =>


_books.DeleteOne(book => book.Id == id);
}
}

Yukarıdaki kodda, Oluşturucu ekleme yoluyla dı 'den bir IBookstoreDatabaseSettings örneği alınır. Bu teknik,
yapılandırma modeli ekleme bölümüne eklenen appSettings. JSON yapılandırma değerlerine erişim sağlar.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddControllers();
}

Önceki kodda, BookService sınıfı, tüketen sınıflarda Oluşturucu ekleme işlemini desteklemek için DI ile
kaydedilir. BookService , MongoClient doğrudan bağımlılığı sağladığından, tek hizmet ömrü en uygundur.
Resmi Mongo istemci yeniden kullanım yönergeleritemelinde MongoClient , tek bir hizmet ömrü ile birlikte
kaydedilmelidir.
4. BookService başvurusunu çözümlemek için aşağıdaki kodu Startup.cs 'un en üstüne ekleyin:

using BooksApi.Services;

BookService Sınıfını kullanan aşağıdaki MongoDB.Driver veritabanında CRUD işlemleri gerçekleştirmek için
üyeleri:
Mongoclient –, veritabanı işlemlerini gerçekleştirmek için sunucu örneğini okur. Bu sınıfın oluşturucusu,
MongoDB bağlantı dizesini sağlanır:

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

Imongodatabase – işlemleri gerçekleştirmek Için Mongo veritabanını temsil eder. Bu öğretici, belirli bir
koleksiyondaki verilere erişim kazanmak için arabirimindeki genel GetCollection<TDocument >
(koleksiyon) yöntemini kullanır. Bu yöntem çağrıldıktan sonra, koleksiyonda CRUD işlemleri gerçekleştirin.
İçinde GetCollection<TDocument>(collection) yöntem çağrısı:
collection Koleksiyon adını temsil eder.
TDocument Bir koleksiyonda depolanan CLR nesne türünü temsil eder.
GetCollection<TDocument>(collection) , koleksiyonu temsil eden bir Mongocollection nesnesi döndürür. Bu
öğreticide, aşağıdaki yöntemlerden koleksiyonunda çağrılır:
Deleteone –, belirtilen arama ölçütleriyle eşleşen tek bir belgeyi siler.
<TDocument > bul –, koleksiyonda belirtilen arama ölçütleriyle eşleşen tüm belgeleri döndürür.
Insertone –, belirtilen nesneyi koleksiyondaki yeni bir belge olarak ekler.
Replaceone –, belirtilen arama ölçütleriyle eşleşen tek belgeyi, belirtilen nesneyle değiştirir.

Denetleyici ekleme
Ekleme bir BooksController sınıfının denetleyicileri aşağıdaki kod ile dizin:

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;

public BooksController(BookService bookService)


{
_bookService = bookService;
}

[HttpGet]
[HttpGet]
public ActionResult<List<Book>> Get() =>
_bookService.Get();

[HttpGet("{id:length(24)}", Name = "GetBook")]


public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

return book;
}

[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);

return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);


}

[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Update(id, bookIn);

return NoContent();
}

[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Remove(book.Id);

return NoContent();
}
}
}

Önceki web API denetleyicisi:


Kullanan BookService CRUD işlemleri gerçekleştirmek için sınıf.
GET, POST, PUT ve DELETE HTTP isteklerini desteklemek için eylem yöntemleri içerir.
Bir HTTP 201 yanıtı döndürmek için Create eylemi yönteminde CreatedAtRoute çağırır. Durum kodu 201,
sunucuda yeni bir kaynak oluşturan HTTP POST yöntemi için standart yanıttır. CreatedAtRoute Ayrıca yanıta bir
Location üst bilgisi ekler. Location üstbilgisi yeni oluşturulan kitabın URI 'sini belirtir.
Web API 'sini test etme
1. Uygulamayı derleyin ve çalıştırın.
2. Denetleyicinin parametresiz Get eylem yöntemini sınamak için http://localhost:<port>/api/books gidin.
Aşağıdaki JSON yanıtı gösterilir:

[
{
"id":"5bfd996f7b8e48dc15ff215d",
"bookName":"Design Patterns",
"price":54.93,
"category":"Computers",
"author":"Ralph Johnson"
},
{
"id":"5bfd996f7b8e48dc15ff215e",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}
]

3. Denetleyicinin aşırı yüklenmiş eylem yöntemini sınamak için


Get
http://localhost:<port>/api/books/{id here} gidin. Aşağıdaki JSON yanıtı gösterilir:

{
"id":"{ID}",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}

JSON serileştirme seçeneklerini yapılandırma


Web API 'Sini test etme bölümünde döndürülen JSON yanıtları hakkında iki ayrıntı vardır:
' Varsayılan ortası büyük/küçük harf özelliği, CLR nesnesinin özellik adlarının Pascal büyük küçük harfleriyle
eşleşecek şekilde değiştirilmelidir.
bookName özelliği Name olarak döndürülmelidir.

Önceki gereksinimleri karşılamak için aşağıdaki değişiklikleri yapın:


1. JSON.NET, ASP.NET paylaşılan çerçevesinden kaldırılmıştır. Microsoft. AspNetCore. Mvc.
NewtonsoftJsonöğesine bir paket başvurusu ekleyin.
2. Startup.ConfigureServices ' de, aşağıdaki vurgulanmış kodu AddMvc yöntemi çağrısına zincirle:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddControllers()
.AddNewtonsoftJson(options => options.UseMemberCasing());
}

Önceki değişiklik ile, Web API 'sinin seri hale getirilmiş JSON yanıtındaki Özellik adları CLR nesne
türündeki ilgili özellik adlarıyla eşleşir. Örneğin, Book sınıfının Author özelliği Author olarak serileştirir.
3. Modeller/Book. cs' de, BookName özelliğine aşağıdaki [JsonProperty] özniteliğiyle açıklama ekleyin:

[BsonElement("Name")]
[JsonProperty("Name")]
public string BookName { get; set; }

[JsonProperty] özniteliğinin değeri Name , Web API 'sinin serileştirilmiş JSON yanıtında özellik adını temsil
eder.
4. [JsonProperty] öznitelik başvurusunu çözümlemek için modeller/Book. cs ' nin en üstüne aşağıdaki kodu
ekleyin:

using Newtonsoft.Json;

5. Web API 'Sini test etme bölümünde tanımlanan adımları yineleyin. JSON Özellik adlarındaki farka dikkat
edin.
Bu öğreticide web API'si temel oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemleri gerçekleştiren
oluşturur bir MongoDB NoSQL veritabanı.
Bu öğreticide şunların nasıl yapıladığını öğreneceksiniz:
MongoDB yapılandırın
MongoDB veritabanı oluşturma
MongoDB koleksiyonu ve şema tanımlayın
Bir web API'sini MongoDB CRUD işlemleri gerçekleştirme
JSON serileştirmesini özelleştirme
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
.NET Core SDK 2,2
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
MongoDB
MongoDB yapılandırın
Windows kullanıyorsanız MongoDB, varsayılan olarak mongodb\C:\Program Files 'a yüklenir. \Program
Files\MongoDB\Server\ <Version_Number >\ Path ) ortam değişkenine ekleyin. Bu değişiklik yerden MongoDB
erişim sağlar, geliştirme makinenizde.
Mongo kabuğunu veritabanı oluşturma, koleksiyonları yapın ve belgeleri depolamak için aşağıdaki adımları
kullanın. Mongo Kabuğu komutları hakkında daha fazla bilgi için bkz. mongo kabuğunu çalışma.
1. Geliştirme makinenizde verilerin depolanması için bir dizin seçin. Örneğin, C: Windows üzerinde\BooksData
. Yoksa dizini oluşturun. Mongo kabuğunu yeni dizinleri oluşturmaz.
2. Bir komut kabuğunu açın. Varsayılan bağlantı noktası 27017 mongodb'ye bağlanmak için aşağıdaki komutu
çalıştırın. Değiştirmeyi unutmayın <data_directory_path> önceki adımda seçtiğiniz dizini.

mongod --dbpath <data_directory_path>

3. Başka bir komut kabuğu örneği açın. Aşağıdaki komutu çalıştırarak varsayılan test veritabanı'na bağlanma:

mongo

4. Bir komut kabuğu'nda aşağıdaki komutu çalıştırın:

use BookstoreDb

Adlı bir veritabanı zaten mevcut olmayan halinde BookstoreDb oluşturulur. Veritabanı mevcut değilse,
bağlantı işlemleri için açılır.
5. Oluşturma bir Books koleksiyon aşağıdaki komutu kullanarak:

db.createCollection('Books')

Aşağıdaki sonucu görüntülenir:

{ "ok" : 1 }

6. İçin bir şema tanımlayabilir Books toplama ve ekleme iki belge aşağıdaki komutu kullanarak:

db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph
Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])

Aşağıdaki sonucu görüntülenir:

{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5bfd996f7b8e48dc15ff215d"),
ObjectId("5bfd996f7b8e48dc15ff215e")
]
}
NOTE
Bu makalede gösterilen KIMLIK, bu örneği çalıştırdığınızda kimliklerle eşleşmeyecektir.

7. Aşağıdaki komutu kullanarak veritabanında belgelerini görüntüleyin:

db.Books.find({}).pretty()

Aşağıdaki sonucu görüntülenir:

{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
"Name" : "Design Patterns",
"Price" : 54.93,
"Category" : "Computers",
"Author" : "Ralph Johnson"
}
{
"_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
"Name" : "Clean Code",
"Price" : 43.15,
"Category" : "Computers",
"Author" : "Robert C. Martin"
}

Şema girmiş ekler _id türünün özelliği ObjectId her belge için.
Veritabanı hazırdır. ASP.NET Core web API'si oluşturmaya başlayabilirsiniz.

ASP.NET Core web API projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
1. Dosya > Yeni > projesi' ne gidin.
2. ASP.NET Core Web uygulaması proje türünü seçin ve İleri' yi seçin.
3. Projeyi Booksapıolarak adlandırın ve Oluştur' u seçin.
4. .NET Core hedef çerçevesini ve 2,2 ASP.NET Coreseçin. API proje şablonunu seçin ve Oluştur' u seçin.
5. MongoDB için .NET sürücüsünün en son kararlı sürümünü öğrenmek üzere NuGet galerisini ziyaret edin:
MongoDB. Driver . İçinde Paket Yöneticisi Konsolu penceresinde proje kök dizinine gidin. MongoDB için
.NET sürücüsünü yüklemek için aşağıdaki komutu çalıştırın:

Install-Package MongoDB.Driver -Version {VERSION}

Varlık modeli ekleme


1. Ekleme bir modelleri proje kök dizini.
2. Ekleme bir Book sınıfının modelleri aşağıdaki kod ile dizin:
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models
{
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

[BsonElement("Name")]
public string BookName { get; set; }

public decimal Price { get; set; }

public string Category { get; set; }

public string Author { get; set; }


}
}

Önceki sınıfta Id özelliği:


Ortak dil çalışma zamanı (CLR ) nesnesini MongoDB koleksiyonuna eşlemek için gereklidir.
, Bu özelliği belgenin birincil anahtarı olarak belirlemek için [BsonId] ile açıklama eklenir.
, Parametreyi ObjectID yapısı yerine tür string olarak geçirmeyi sağlayan
[BsonRepresentation(BsonType.ObjectId)] ile açıklama eklenir. Mongo, string dönüştürmeyi ObjectId
olarak işler.
BookName özelliğine [BsonElement] özniteliğiyle açıklama eklenir. Özniteliğin Name değeri, MongoDB
koleksiyonundaki özellik adını temsil eder.

Yapılandırma modeli ekleme


1. Aşağıdaki veritabanı yapılandırma değerlerini appSettings. JSONöğesine ekleyin:

{
"BookstoreDatabaseSettings": {
"BooksCollectionName": "Books",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookstoreDb"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}

2. Modeller dizinine aşağıdaki kodla bir BookstoreDatabaseSettings.cs dosyası ekleyin:


namespace BooksApi.Models
{
public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
{
public string BooksCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}

public interface IBookstoreDatabaseSettings


{
string BooksCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
}

Yukarıdaki BookstoreDatabaseSettings sınıfı, appSettings. JSON dosyasının BookstoreDatabaseSettings


özellik değerlerini depolamak için kullanılır. JSON ve C# Özellik adları, eşleme sürecini kolaylaştırmak için
aynı şekilde adlandırılır.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Yukarıdaki kodda:
AppSettings. JSON dosyasının BookstoreDatabaseSettings bölüm bağlandığı yapılandırma örneği,
bağımlılık ekleme (dı) kapsayıcısına kaydedilir. Örneğin, bir BookstoreDatabaseSettings nesnesinin
ConnectionString özelliği appSettings. JSONiçindeki BookstoreDatabaseSettings:ConnectionString
özelliği ile doldurulur.
IBookstoreDatabaseSettings arabirimi, tek bir hizmet ömrüile dı 'ye kaydedilir. Eklerken, arabirim örneği
bir BookstoreDatabaseSettings nesnesine çözümlenir.
4. BookstoreDatabaseSettings ve IBookstoreDatabaseSettings başvurularını çözümlemek için aşağıdaki kodu
en üst kısmına ekleyin :

using BooksApi.Models;

CRUD işlemleri hizmeti ekleme


1. Ekleme bir Hizmetleri proje kök dizini.
2. Ekleme bir BookService sınıfının Hizmetleri aşağıdaki kod ile dizin:
using BooksApi.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;

namespace BooksApi.Services
{
public class BookService
{
private readonly IMongoCollection<Book> _books;

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

public List<Book> Get() =>


_books.Find(book => true).ToList();

public Book Get(string id) =>


_books.Find<Book>(book => book.Id == id).FirstOrDefault();

public Book Create(Book book)


{
_books.InsertOne(book);
return book;
}

public void Update(string id, Book bookIn) =>


_books.ReplaceOne(book => book.Id == id, bookIn);

public void Remove(Book bookIn) =>


_books.DeleteOne(book => book.Id == bookIn.Id);

public void Remove(string id) =>


_books.DeleteOne(book => book.Id == id);
}
}

Yukarıdaki kodda, Oluşturucu ekleme yoluyla dı 'den bir IBookstoreDatabaseSettings örneği alınır. Bu teknik,
yapılandırma modeli ekleme bölümüne eklenen appSettings. JSON yapılandırma değerlerine erişim sağlar.
3. Aşağıdaki Vurgulanan kodu Startup.ConfigureServices ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Önceki kodda, BookService sınıfı, tüketen sınıflarda Oluşturucu ekleme işlemini desteklemek için DI ile
kaydedilir. BookService , MongoClient doğrudan bağımlılığı sağladığından, tek hizmet ömrü en uygundur.
Resmi Mongo istemci yeniden kullanım yönergeleritemelinde MongoClient , tek bir hizmet ömrü ile birlikte
kaydedilmelidir.
4. BookService başvurusunu çözümlemek için aşağıdaki kodu Startup.cs 'un en üstüne ekleyin:

using BooksApi.Services;

BookService Sınıfını kullanan aşağıdaki MongoDB.Driver veritabanında CRUD işlemleri gerçekleştirmek için
üyeleri:
Mongoclient –, veritabanı işlemlerini gerçekleştirmek için sunucu örneğini okur. Bu sınıfın oluşturucusu,
MongoDB bağlantı dizesini sağlanır:

public BookService(IBookstoreDatabaseSettings settings)


{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);

_books = database.GetCollection<Book>(settings.BooksCollectionName);
}

Imongodatabase – işlemleri gerçekleştirmek Için Mongo veritabanını temsil eder. Bu öğretici, belirli bir
koleksiyondaki verilere erişim kazanmak için arabirimindeki genel GetCollection<TDocument >
(koleksiyon) yöntemini kullanır. Bu yöntem çağrıldıktan sonra, koleksiyonda CRUD işlemleri gerçekleştirin.
İçinde GetCollection<TDocument>(collection) yöntem çağrısı:
collection Koleksiyon adını temsil eder.
TDocument Bir koleksiyonda depolanan CLR nesne türünü temsil eder.
GetCollection<TDocument>(collection) , koleksiyonu temsil eden bir Mongocollection nesnesi döndürür. Bu
öğreticide, aşağıdaki yöntemlerden koleksiyonunda çağrılır:
Deleteone –, belirtilen arama ölçütleriyle eşleşen tek bir belgeyi siler.
<TDocument > bul –, koleksiyonda belirtilen arama ölçütleriyle eşleşen tüm belgeleri döndürür.
Insertone –, belirtilen nesneyi koleksiyondaki yeni bir belge olarak ekler.
Replaceone –, belirtilen arama ölçütleriyle eşleşen tek belgeyi, belirtilen nesneyle değiştirir.

Denetleyici ekleme
Ekleme bir BooksController sınıfının denetleyicileri aşağıdaki kod ile dizin:

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;

public BooksController(BookService bookService)


{
_bookService = bookService;
}
[HttpGet]
public ActionResult<List<Book>> Get() =>
_bookService.Get();

[HttpGet("{id:length(24)}", Name = "GetBook")]


public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

return book;
}

[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);

return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);


}

[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Update(id, bookIn);

return NoContent();
}

[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);

if (book == null)
{
return NotFound();
}

_bookService.Remove(book.Id);

return NoContent();
}
}
}

Önceki web API denetleyicisi:


Kullanan BookService CRUD işlemleri gerçekleştirmek için sınıf.
GET, POST, PUT ve DELETE HTTP isteklerini desteklemek için eylem yöntemleri içerir.
Bir HTTP 201 yanıtı döndürmek için Create eylemi yönteminde CreatedAtRoute çağırır. Durum kodu 201,
sunucuda yeni bir kaynak oluşturan HTTP POST yöntemi için standart yanıttır. CreatedAtRoute Ayrıca yanıta bir
Location üst bilgisi ekler. Location üstbilgisi yeni oluşturulan kitabın URI 'sini belirtir.
Web API 'sini test etme
1. Uygulamayı derleyin ve çalıştırın.
2. Denetleyicinin parametresiz Get eylem yöntemini sınamak için http://localhost:<port>/api/books gidin.
Aşağıdaki JSON yanıtı gösterilir:

[
{
"id":"5bfd996f7b8e48dc15ff215d",
"bookName":"Design Patterns",
"price":54.93,
"category":"Computers",
"author":"Ralph Johnson"
},
{
"id":"5bfd996f7b8e48dc15ff215e",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}
]

3. Denetleyicinin aşırı yüklenmiş eylem yöntemini sınamak için


Get
http://localhost:<port>/api/books/{id here} gidin. Aşağıdaki JSON yanıtı gösterilir:

{
"id":"{ID}",
"bookName":"Clean Code",
"price":43.15,
"category":"Computers",
"author":"Robert C. Martin"
}

JSON serileştirme seçeneklerini yapılandırma


Web API 'Sini test etme bölümünde döndürülen JSON yanıtları hakkında iki ayrıntı vardır:
' Varsayılan ortası büyük/küçük harf özelliği, CLR nesnesinin özellik adlarının Pascal büyük küçük harfleriyle
eşleşecek şekilde değiştirilmelidir.
bookName özelliği Name olarak döndürülmelidir.

Önceki gereksinimleri karşılamak için aşağıdaki değişiklikleri yapın:


1. Startup.ConfigureServices ' de, aşağıdaki vurgulanmış kodu AddMvc yöntemi çağrısına zincirle:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

services.AddSingleton<BookService>();

services.AddMvc()
.AddJsonOptions(options => options.UseMemberCasing())
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Önceki değişiklik ile, Web API 'sinin seri hale getirilmiş JSON yanıtındaki Özellik adları CLR nesne
türündeki ilgili özellik adlarıyla eşleşir. Örneğin, Book sınıfının Author özelliği Author olarak serileştirir.
2. Modeller/Book. cs' de, BookName özelliğine aşağıdaki [JsonProperty] özniteliğiyle açıklama ekleyin:

[BsonElement("Name")]
[JsonProperty("Name")]
public string BookName { get; set; }

[JsonProperty] özniteliğinin değeri Name , Web API 'sinin serileştirilmiş JSON yanıtında özellik adını temsil
eder.
3. [JsonProperty] öznitelik başvurusunu çözümlemek için modeller/Book. cs ' nin en üstüne aşağıdaki kodu
ekleyin:

using Newtonsoft.Json;

4. Web API 'Sini test etme bölümünde tanımlanan adımları yineleyin. JSON Özellik adlarındaki farka dikkat
edin.

Web API 'sine kimlik doğrulama desteği ekleme


ASP.NET Core kimlik, ASP.NET Core Web uygulamalarına Kullanıcı arabirimi (UI) oturum açma işlevselliği ekler.
Web API 'Leri ve maça 'ları güvenli hale getirmek için aşağıdakilerden birini kullanın:
Azure Active Directory
Azure Active Directory B2C (Azure AD B2C )]
Identityserver4
Identityserver4, ASP.NET Core 3,0 için bir OpenID Connect ve OAuth 2,0 çerçevesidir. Identityserver4 aşağıdaki
güvenlik özelliklerini sunar:
Hizmet olarak kimlik doğrulaması (AaaS )
Birden çok uygulama türü üzerinde çoklu oturum açma/kapatma (SSO )
API 'Ler için erişim denetimi
Federasyon ağ geçidi
Daha fazla bilgi için bkz. ıdentityserver4 to Welcome.

Sonraki adımlar
ASP.NET Core web API'leri oluşturmaya daha fazla bilgi için aşağıdaki kaynaklara bakın:
Bu makalenin YouTube sürümü
ASP.NET Core ile Web API 'Leri oluşturma
ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri
ASP.NET Core web API Yardım sayfaları ile Swagger
/ Openapı
9.12.2019 • 4 minutes to read • Edit Online

Tarafından Christoph Nienaber ve Riko Suter


Bir Web API'si kullanılırken, çeşitli metotlarını anlama bir geliştirici için zor olabilir. Swaggerolarak da bilinen
Openapı, Web API'leri için kullanışlı belgeler ve Yardım sayfaları oluşturma sorununu çözer. Bu, etkileşimli
belgeleri, istemci SDK oluşturma ve API keşfedilebilirliğini gibi avantajlar sağlar.
Bu makalede, Swashbuckle.AspNetCore ve NSwag uygulamaları .NET Swagger büyütmüş:
Swashbuckle.AspNetCore Swagger belgeler için ASP.NET Core Web API'leri oluşturmak için açık
kaynak bir projedir.
NSwag Swagger belgeler oluşturmak ve tümleştirme için başka bir açık kaynaklı proje Swagger kullanıcı
arabirimini veya ReDoc içinde ASP.NET Core web API'leri. Ayrıca, NSwag API'niz için C# ve TypeScript
istemci kodu oluşturmak için bir yaklaşım sunar.

Swagger nedir / Openapı?


Swagger belirtimidir tanımlamak için bir dilden REST API'leri. Swagger proje için üzerinde Bağış Openapı
girişim, burada, artık Openapı adlandırılır. Her iki birbirinin yerine kullanılır; Ancak, Openapı tercih edilir. Bu hem
bilgisayarları hem de bir hizmet uygulaması (kaynak kodu, ağ erişimi, belgeleri) doğrudan erişim olmadan
yeteneklerini anlamalarına insanlar sağlar. İlişkisi kaldırılan Hizmetleri bağlanmak için gerekli çalışma miktarını
en aza bir hedeftir. Başka bir hedefe doğru bir şekilde bir hizmet belgesi için gereken süreyi azaltmaktır.

Swagger belirtimi (swagger.json)


Swagger akışa çekirdek Swagger belirtimidir—varsayılan olarak, bir belge adlı swagger.json. Hizmet tabanlı
Swagger araç zinciri (veya bu üçüncü taraf uygulamaları) tarafından oluşturulur. Bu, API'nizi ve HTTP ile erişmek
nasıl yeteneklerini açıklar. Swagger kullanıcı arabirimini yönlendirir ve araç zinciri tarafından bulma ve istemci
kodu oluşturmayı etkinleştirme için kullanılır. Konuyu uzatmamak amacıyla sınırlı bir Swagger belirtimi bir örnek
aşağıda verilmiştir:
{
"swagger": "2.0",
"info": {
"version": "v1",
"title": "API V1"
},
"basePath": "/",
"paths": {
"/api/Todo": {
"get": {
"tags": [
"Todo"
],
"operationId": "ApiTodoGet",
"consumes": [],
"produces": [
"text/plain",
"application/json",
"text/json"
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/TodoItem"
}
}
}
}
},
"post": {
...
}
},
"/api/Todo/{id}": {
"get": {
...
},
"put": {
...
},
"delete": {
...
},
"definitions": {
"TodoItem": {
"type": "object",
"properties": {
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
},
"isComplete": {
"default": false,
"type": "boolean"
}
}
}
},
"securityDefinitions": {}
}
Swagger kullanıcı Arabirimi
Swagger kullanıcı Arabirimi oluşturulan Swagger belirtimi kullanarak hizmeti hakkında bilgi sağlayan bir web
tabanlı bir kullanıcı Arabirimi sunar. ASP.NET Core uygulamanızı bir ara yazılım kayıt çağrısı kullanarak
barındırılan Swashbuckle hem NSwag Swagger kullanıcı arabirimini, katıştırılmış bir sürümünü içerir. Web
kullanıcı Arabirimi şöyle görünür:

Kullanıcı Arabiriminden denetleyicilerinizi her genel bir eylem yöntemi test edilebilir. Bir yöntem adı bölümü
genişletmek için tıklayın. Gerekli tüm parametreleri ekleyin ve deneyin! .
NOTE
Ekran görüntüleri için kullanılan Swagger kullanıcı arabirimini sürüm sürüm 2 ' dir. Sürüm 3 örnek için bkz: Petstore örnek.

Sonraki adımlar
Swashbuckle kullanmaya başlama
NSwag Kullanmaya Başlama
Swashbuckle ve ASP.NET Core kullanmaya başlayın
6.12.2019 • 20 minutes to read • Edit Online

, Shayne Boyer ve Scott Ade tarafından


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Swashbuckle'ın üç temel bileşeni vardır:
Swashbuckle. AspNetCore. Swagger: nesneleri JSON uç noktaları olarak SwaggerDocument göstermek için
Swagger nesne modeli ve ara yazılımı.
Swashbuckle. AspNetCore. SwaggerGen: doğrudan rotalarınız, Denetleyicilerinizden ve modellerinizde
SwaggerDocument nesneleri oluşturan bir Swagger Oluşturucu. Bu genellikle Swagger JSON uç noktasını
otomatik olarak kullanıma sunmak için Swagger uç noktası ara katmanıyla birlikte kullanılır.
Swashbuckle. AspNetCore. SwaggerUI: Swagger Kullanıcı arabirimi aracının gömülü bir sürümü. Swagger
JSON uç noktasını yorumlayarak web API'sinin işlevlerini tanımlayan zengin ve özelleştirilebilir bir
deneyim oluşturur. Genel yöntemler için yerleşik test kuluçkaları içerir.

Paket yüklemesi
Aşağıdaki yaklaşımlar ile swashbuckle eklenebilir:
Visual Studio
Mac için Visual Studio
Visual Studio Code
.NET Core CLI
Paket Yöneticisi konsol penceresinde:
Diğer Windows > paket Yöneticisi konsolu > görüntüle ' ye gidin
TodoApi. csproj dosyasının bulunduğu dizine gidin
Aşağıdaki komutu yürütün:

Install-Package Swashbuckle.AspNetCore -Version 5.0.0-rc4

NuGet Paketlerini Yönet iletişim kutusunda:


NuGet paketlerini yönetmek > Çözüm Gezgini ' de projeye sağ tıklayın
Paket kaynağını "NuGet.org" olarak ayarlayın
"Ön sürümü dahil et" seçeneğinin etkinleştirildiğinden emin olun
Arama kutusuna "swashbuckle. AspNetCore" yazın
Araştır sekmesinden en son "swashbuckle. aspnetcore" paketini seçin ve sonra da yüklensin ' e tıklayın.

Swagger ara yazılım ekleme ve yapılandırma


Startup sınıfında, OpenApiInfo sınıfını kullanmak için aşağıdaki ad alanını içeri aktarın:
using Microsoft.OpenApi.Models;

Swagger oluşturucuyu Startup.ConfigureServices yöntemindeki Services koleksiyonuna ekleyin:

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc();

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
}

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
}

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
}

Startup.Configure yönteminde, oluşturulan JSON belgesine ve Swagger Kullanıcı arabirimine hizmet veren ara
yazılımı etkinleştirin:
public void Configure(IApplicationBuilder app)
{
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),


// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

app.UseMvc();
}

public void Configure(IApplicationBuilder app)


{
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),


// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

Yukarıdaki UseSwaggerUI yöntemi çağrısı statik dosya ara yazılımınısunar. .NET Framework veya .NET Core 1. x 'i
hedefliyorsanız, projeye Microsoft. AspNetCore. StaticFiles NuGet paketini ekleyin.
Uygulamayı başlatın ve http://localhost:<port>/swagger/v1/swagger.json gidin. Uç noktaları tanımlayan
oluşturulan belge, Swagger belirtiminde (Swagger. JSON ) gösterildiği gibi görünür.
Swagger Kullanıcı arabirimi http://localhost:<port>/swagger ' de bulunabilir. Swagger Kullanıcı arabirimi
aracılığıyla API 'YI keşfet ve diğer programlarda birleştirme.

TIP
Swagger Kullanıcı arabirimine uygulamanın kökünde ( http://localhost:<port>/ ) hizmeti sağlamak için RoutePrefix
özelliğini boş bir dize olarak ayarlayın:

app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.RoutePrefix = string.Empty;
});

IIS veya ters proxy ile dizin kullanıyorsanız, Swagger uç noktasını ./ önekini kullanarak göreli bir yol olarak
ayarlayın. Örneğin: ./swagger/v1/swagger.json . /swagger/v1/swagger.json kullanmak, uygulamayı URL 'nin gerçek
kökünde (artı kullanılıyorsa rota öneki), JSON dosyasını aramasını söyler. Örneğin,
http://localhost:<port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json yerine
http://localhost:<port>/<route_prefix>/swagger/v1/swagger.json kullanın.
Özelleştirme ve genişletme
Swagger, nesne modelini belgeleme ve Kullanıcı arabirimini temanızla eşleşecek şekilde özelleştirme seçenekleri
sağlar.
Startup sınıfında, aşağıdaki ad alanlarını ekleyin:

using System;
using System.Reflection;
using System.IO;

API bilgisi ve açıklaması


AddSwaggerGen yöntemine geçirilen yapılandırma eylemi yazar, lisans ve açıklama gibi bilgileri ekler:

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});
});

Swagger Kullanıcı arabirimi, sürümün bilgilerini görüntüler:

XML açıklamaları
XML açıklamaları aşağıdaki yaklaşımlar ile etkinleştirilebilir:
Visual Studio
Mac için Visual Studio
Visual Studio Code
.NET Core CLI
Çözüm Gezgini projeye sağ tıklayın ve >. csproj Project_Name < Düzenle' yi seçin.
Vurgulanan satırları . csproj dosyasına el ile ekleyin:

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Projeye sağ Çözüm Gezgini seçip özellikleri.


Build sekmesinin output bölümünün altındaki XML belge dosyası kutusunu işaretleyin.
XML açıklamalarını etkinleştirmek, belgelenmemiş ortak türler ve Üyeler için hata ayıklama bilgileri sağlar.
Belgelenmemiş türler ve Üyeler uyarı iletisiyle belirtilir. Örneğin, aşağıdaki ileti 1591 uyarı kodunu ihlal eder:

warning CS1591: Missing XML comment for publicly visible type or member 'TodoController.GetAll()'

Uyarıları proje genelinde gizlemek için, proje dosyasında yoksayılacak uyarı kodlarının noktalı virgülle ayrılmış bir
listesini tanımlayın. Uyarı kodlarının $(NoWarn); eklenmesi, C# varsayılan değerleri de uygular.

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<PropertyGroup>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Yalnızca belirli Üyeler için uyarıları gizlemek için, kodu #pragma uyarı Önişlemci yönergeleri arasına alın. Bu
yaklaşım, API belgeleri aracılığıyla sunulmaması gereken kod için yararlıdır. Aşağıdaki örnekte, tüm Program sınıfı
için uyarı kodu CS1591 yok sayılır. Uyarı kodu zorlaması sınıf tanımının kapandığına geri yüklenir. Virgülle ayrılmış
bir liste ile birden çok uyarı kodu belirtin.

namespace TodoApi
{
#pragma warning disable CS1591
public class Program
{
public static void Main(string[] args) =>
BuildWebHost(args).Run();

public static IWebHost BuildWebHost(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
#pragma warning restore CS1591
}
Swagger 'yi yukarıdaki yönergelerle oluşturulan XML dosyasını kullanacak şekilde yapılandırın. Linux veya
Windows dışı işletim sistemleri için dosya adları ve yolları büyük/küçük harfe duyarlı olabilir. Örneğin, TodoApi.
xml dosyası Windows üzerinde geçerlidir ancak CentOS değildir.

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc();

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc();

// Register the Swagger generator, defining 1 or more Swagger documents


services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}

Yukarıdaki kodda, yansıma , Web API projesi ile eşleşen bir XML dosya adı oluşturmak için kullanılır. AppContext.
BaseDirectory ÖZELLIĞI, XML dosyasının yolunu oluşturmak için kullanılır. Bazı Swagger özellikleri (örneğin, bir
XML belge dosyası kullanılmadan, giriş parametrelerinin veya HTTP yöntemlerinin ve yanıt kodlarının) bir bölümü
çalışır. Çoğu özellik için, yöntem özetleri ve parametrelerin ve yanıt kodlarının açıklamaları, bir XML dosyası
kullanımı zorunludur.
Bir eyleme üç eğik çizgiyle açıklama eklediğinizde bölüm üst bilgisine açıklama eklenir ve Swagger UI geliştirilir.
Delete eyleminin üstüne bir <summary > öğesi ekleyin:

/// <summary>
/// Deletes a specific TodoItem.
/// </summary>
/// <param name="id"></param>
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
var todo = _context.TodoItems.Find(id);

if (todo == null)
{
return NotFound();
}

_context.TodoItems.Remove(todo);
_context.SaveChanges();

return NoContent();
}
Swagger Kullanıcı arabirimi, önceki kodun <summary> öğesinin iç metnini görüntüler:

Kullanıcı arabirimi, oluşturulan JSON şeması tarafından çalıştırılır:

"delete": {
"tags": [
"Todo"
],
"summary": "Deletes a specific TodoItem.",
"operationId": "ApiTodoByIdDelete",
"consumes": [],
"produces": [],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "Success"
}
}
}

Create Action yöntemi belgelerine bir <açıklamaları > öğesi ekleyin. <summary> öğesinde belirtilen bilgileri
tamamlar ve daha sağlam bir Swagger Kullanıcı arabirimi sağlar. <remarks> öğesi içeriği metin, JSON veya XML
içerebilir.
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public IActionResult Create([FromBody] TodoItem item)
{
if (item == null)
{
return BadRequest();
}

_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

Bu ek açıklamalarla UI geliştirmelerini göz unutmayın:

Veri açıklamaları
Swagger Kullanıcı Arabirimi bileşenlerini sağlamaya yardımcı olmak için System. ComponentModel.
Dataaçıklamalarda ad alanında bulunan öznitelikleri olan modeli işaretleyin.
TodoItem sınıfının Name özelliğine [Required] özniteliğini ekleyin:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }

[Required]
public string Name { get; set; }

[DefaultValue(false)]
public bool IsComplete { get; set; }
}
}

Bu özniteliğin varlığı, Kullanıcı arabirimi davranışını değiştirir ve temel alınan JSON şemasını değiştirir:

"definitions": {
"TodoItem": {
"required": [
"name"
],
"type": "object",
"properties": {
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
},
"isComplete": {
"default": false,
"type": "boolean"
}
}
}
},

API denetleyicisine [Produces("application/json")] özniteliğini ekleyin. Amaç, denetleyicinin eylemlerinin bir


uygulama/JSONyanıt içerik türünü desteklediğini bildirsağlamaktır:

[Produces("application/json")]
[Route("api/[controller]")]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

[Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;
[Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
private readonly TodoContext _context;

Yanıt Içerik türü açılan liste, denetleyicinin al eylemleri için varsayılan olarak bu içerik türünü seçer:

Web API 'sindeki veri ek açıklamaların kullanımı arttıkça, UI ve API Yardım sayfaları daha açıklayıcı ve yararlı hale
gelir.
Yanıt türlerini açıkla
Web API kullanan geliştiriciler, özellikle yanıt türleri ve hata kodları (Standart değilse)—döndürülmesiyle ilgilidir.
Yanıt türleri ve hata kodları XML açıklamaları ve veri ek açıklamalarında gösterilir.
Create eylemi başarılı olduğunda bir HTTP 201 durum kodu döndürür. Postalanan istek gövdesi null olduğunda
bir HTTP 400 durum kodu döndürülür. Swagger Kullanıcı arabiriminde doğru belgeler olmadan, tüketici beklenen
bu sonuçlar hakkında bilgi sahibi yoktur. Aşağıdaki örneğe vurgulanan satırları ekleyerek bu sorunu
giderebilirsiniz:
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public IActionResult Create([FromBody] TodoItem item)
{
if (item == null)
{
return BadRequest();
}

_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

Swagger Kullanıcı arabirimi artık beklenen HTTP yanıt kodlarını açıkça belgelemektedir:

ASP.NET Core 2,2 veya üzeri sürümlerde, kurallar [ProducesResponseType] ile tek tek eylemleri açıkça dekorasyon
alternatif olarak kullanılabilir. Daha fazla bilgi için bkz. Web API 'SI kurallarını kullanma.
Kullanıcı arabirimini özelleştirme
Hisse senedi Kullanıcı arabirimi hem işlevsel hem de edileni. Ancak, API belge sayfaları markanızı veya temanızı
temsil etmelidir. Marka, swashbuckle bileşenleri, statik dosyalara ve bu dosyaları barındırmak için klasör yapısını
oluşturmaya yönelik kaynakların eklenmesini gerektirir.
.NET Framework veya .NET Core 1. x 'i hedefliyorsanız, Microsoft. AspNetCore. StaticFiles NuGet paketini projeye
ekleyin:
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />

Önceki NuGet paketi, .NET Core 2. x hedefleniyorsa ve metapackagekullanılarak zaten yüklüdür.


Statik dosya ara yazılımını etkinleştir:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles();

// Enable middleware to serve generated Swagger as a JSON endpoint.


app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),


// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

app.UseMvc();
}

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles();

// Enable middleware to serve generated Swagger as a JSON endpoint.


app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),


// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

Swagger Kullanıcı arabirimi GitHub deposundan Dist klasörünün içeriğini alın. Bu klasör, Swagger Kullanıcı
arabirimi sayfası için gerekli varlıkları içerir.
Bir Wwwroot/Swagger/UI klasörü oluşturun ve bunu Dist klasörünün içeriğine kopyalayın.
Sayfa üstbilgisini özelleştirmek için aşağıdaki CSS ile Wwwroot/Swagger/UIiçinde özel bir. css dosyası oluşturun:

.swagger-ui .topbar {
background-color: #000;
border-bottom: 3px solid #547f00;
}

Diğer CSS dosyalarından sonra, Kullanıcı arabirimi klasörünün içindeki index. html dosyasında Custom. css
dosyasına başvurun:
<link href="https://fonts.googleapis.com/css?
family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
<link rel="stylesheet" type="text/css" href="custom.css">

http://localhost:<port>/swagger/ui/index.html adresindeki index. html sayfasına gidin. Üstbilginin metin kutusuna


https://localhost:<port>/swagger/v1/swagger.json girin ve ardından keşfet düğmesine tıklayın. Elde edilen sayfa
şu şekilde görünür:

Sayfada yapabileceğiniz çok daha fazla şey vardır. Swagger Kullanıcı arabirimi GitHub DEPOSUNDAKIUI
kaynakları için tam yeteneklere bakın.
NSwag ve ASP.NET Core kullanmaya başlayın
9.12.2019 • 10 minutes to read • Edit Online

, Christoph Nienaber, Riko Suterve bave Brock tarafından


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
NSwag aşağıdaki özellikleri sunar:
Swagger Kullanıcı arabirimi ve Swagger oluşturucuyu kullanma özelliği.
Esnek kod oluşturma özellikleri.
NSwag ile, var olan bir API 'ye ihtiyacınız yoktur—Swagger içeren üçüncü taraf API 'Leri kullanabilir ve bir istemci
uygulamasını oluşturabilirsiniz. NSwag, geliştirme döngüsünü hızlandırın ve API değişikliklerine kolayca uyum
sağlar.

NSwag ara yazılımını kaydetme


NSwag ara yazılımını şu şekilde kaydedin:
Uygulanan Web API 'SI için Swagger belirtimini oluşturun.
Web API 'sini taramak ve test etmek için Swagger Kullanıcı arabirimini sunar.
Nswag ASP.NET Core ara yazılımını kullanmak Için nswag. aspnetcore NuGet paketini yüklemelisiniz. Bu paket
Swagger belirtimini oluşturma ve sunma ara yazılımını, Swagger Kullanıcı arabirimini (v2 ve v3) ve Redoc Kullanıcı
arabiriminiiçerir.
NSwag NuGet paketini yüklemek için aşağıdaki yaklaşımlardan birini kullanın:
Visual Studio
Mac için Visual Studio
.NET Core CLI
Paket Yöneticisi konsol penceresinde:
Diğer Windows > paket Yöneticisi konsolu > görüntüle ' ye gidin
TodoApi. csproj dosyasının bulunduğu dizine gidin
Aşağıdaki komutu yürütün:

Install-Package NSwag.AspNetCore

NuGet Paketlerini Yönet iletişim kutusunda:


NuGet paketlerini yönetmek > Çözüm Gezgini ' de projeye sağ tıklayın
Paket kaynağını "NuGet.org" olarak ayarlayın
Arama kutusuna "NSwag. AspNetCore" yazın
Araştır sekmesinden "NSwag. aspnetcore" paketini seçin ve sonra da yüklensin ' e tıklayın.

Swagger ara yazılım ekleme ve yapılandırma


Aşağıdaki adımları gerçekleştirerek ASP.NET Core uygulamanızda Swagger ekleyin ve yapılandırın:
Startup.ConfigureServices yönteminde, gerekli Swagger hizmetlerini kaydedin:

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc();

// Register the Swagger services


services.AddSwaggerDocument();
}

Startup.Configure yönteminde, oluşturulan Swagger belirtimini ve Swagger Kullanıcı arabirimini sunan ara
yazılımı etkinleştirin:

public void Configure(IApplicationBuilder app)


{
app.UseStaticFiles();

// Register the Swagger generator and the Swagger UI middlewares


app.UseOpenApi();
app.UseSwaggerUi3();

app.UseMvc();
}

Uygulamayı başlatma. Şuraya gidin:


Swagger Kullanıcı arabirimini görüntülemek için http://localhost:<port>/swagger .
Swagger belirtimini görüntülemek için http://localhost:<port>/swagger/v1/swagger.json .

Kod oluşturma
Aşağıdaki seçeneklerden birini seçerek NSwag 'nin kod oluşturma özelliğinden yararlanabilirsiniz:
NSwagStudio , veya TYPESCRIPT içinde C# API istemci kodu oluşturmak için bir Windows masaüstü
uygulaması –.
Projenizin içindeki kod üretimi için Nswag. CodeGeneration. CSharp veya Nswag. CodeGeneration. TypeScript
NuGet paketleri.
Komut satırındanNSwag.
Nswag. MSBuild NuGet paketi.
Unchase Openapı (Swagger) bağlı hizmeti , veya TYPESCRIPT içinde C# API istemci kodu oluşturmak Için bir
Visual Studio bağlı hizmeti –. Ayrıca, C# NSwag Ile openapı Hizmetleri için denetleyiciler oluşturur.
NSwagStudio ile kod oluşturma
NSwagStudio GitHub deposundakiyönergeleri izleyerek NSwagStudio 'i yükler. NSwag Release sayfasında,
yükleme ve yönetici ayrıcalıkları olmadan başlatılabilen bir Xcopy sürümü indirebilirsiniz.
NSwagStudio başlatın ve Swagger BELIRTIM URL 'si metin kutusuna Swagger. JSON dosya URL 'sini
girin. Örneğin, http://localhost:44354/swagger/v1/swagger.json .
Swagger belirtimin bir JSON gösterimini oluşturmak için Yerel kopya oluştur düğmesine tıklayın.
Çıktılar alanında, CSharp Client onay kutusuna tıklayın. Projenize bağlı olarak, TypeScript Client veya
CSharp Web API Controller' ı da seçebilirsiniz. CSharp Web API denetleyicisi' ni seçerseniz, bir hizmet
belirtimi hizmeti yeniden oluşturur ve bu da ters bir oluşturma görevi görür.
TodoApi. NSwag projesinin tüm C# Istemci uygulamasını oluşturmak için çıkış oluştur ' a tıklayın.
Oluşturulan istemci kodunu görmek için CSharp istemci sekmesine tıklayın:
//----------------------
// <auto-generated>
// Generated using the NSwag toolchain v12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json v11.0.0.0))
(http://NSwag.org)
// </auto-generated>
//----------------------

namespace MyNamespace
{
#pragma warning disable

[System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json


v11.0.0.0))")]
public partial class TodoClient
{
private string _baseUrl = "https://localhost:44354";
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;

public TodoClient(System.Net.Http.HttpClient httpClient)


{
_httpClient = httpClient;
_settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(() =>
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
});
}

public string BaseUrl


{
get { return _baseUrl; }
set { _baseUrl = value; }
}

// code omitted for brevity

TIP
C# İstemci kodu, Ayarlar sekmesindeki seçimlere göre oluşturulur. varsayılan ad alanı yeniden adlandırma ve zaman uyumlu
yöntem oluşturma gibi görevleri gerçekleştirmek için ayarları değiştirin.

Oluşturulan C# kodu, istemci projesindeki bir dosyaya, API 'yi kullanacak şekilde kopyalayın.
Web API 'sini kullanmayı Başlat:

var todoClient = new TodoClient();

// Gets all to-dos from the API


var allTodos = await todoClient.GetAllAsync();

// Create a new TodoItem, and save it via the API.


var createdTodo = await todoClient.CreateAsync(new TodoItem());

// Get a single to-do by ID


var foundTodo = await todoClient.GetByIdAsync(1);

API belgelerini özelleştirme


Swagger, Web API 'sinin kullanımını kolaylaştırmak için nesne modelini belgeleme seçeneklerini sağlar.
API bilgisi ve açıklaması
Startup.ConfigureServices yönteminde, AddSwaggerDocument yöntemine geçirilen bir yapılandırma eylemi yazar,
lisans ve açıklama gibi bilgileri ekler:

services.AddSwaggerDocument(config =>
{
config.PostProcess = document =>
{
document.Info.Version = "v1";
document.Info.Title = "ToDo API";
document.Info.Description = "A simple ASP.NET Core web API";
document.Info.TermsOfService = "None";
document.Info.Contact = new NSwag.OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = "https://twitter.com/spboyer"
};
document.Info.License = new NSwag.OpenApiLicense
{
Name = "Use under LICX",
Url = "https://example.com/license"
};
};
});

Swagger Kullanıcı arabirimi, sürümün bilgilerini görüntüler:

XML açıklamaları
XML açıklamalarını etkinleştirmek için aşağıdaki adımları uygulayın:
Visual Studio
Mac için Visual Studio
.NET Core CLI
Çözüm Gezgini projeye sağ tıklayın ve >. csproj Project_Name < Düzenle' yi seçin.
Vurgulanan satırları . csproj dosyasına el ile ekleyin:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Çözüm Gezgini ' de projeye sağ tıklayın ve Özellikler ' i seçin


Build sekmesinin output bölümünün altındaki XML belge dosyası kutusunu işaretleyin
Veri açıklamaları
NSwag yansımakullandığından ve Web API 'si eylemleri için önerilen dönüş türü ıactionresultolduğundan,
eyleminiz ne yaptığını ve döndürdüğü şeyi çıkarmaz.
Aşağıdaki örnek göz önünde bulundurun:

[HttpPost]
public IActionResult Create([FromBody] TodoItem item)
{
if (item == null)
{
return BadRequest();
}

_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

Önceki eylem IActionResult döndürüyor, ancak eylemin içinde Createdatroute veya BadRequestdöndürüyor.
İstemcilere bu eylemin hangi HTTP durum kodlarına geri dönebileceği bilinmektedir olduğunu bildirmek için veri
açıklamalarını kullanın. Eylemi aşağıdaki özniteliklerle işaretleyin:

[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)] // Created


[ProducesResponseType(StatusCodes.Status400BadRequest)] // BadRequest

NSwag yansımakullandığından ve Web API eylemleri için önerilen dönüş türü ActionResult<t >olduğundan,
yalnızca T tarafından tanımlanan dönüş türünü çıkarabilir. Diğer olası dönüş türlerini otomatik olarak
çıkarsanamıyor.
Aşağıdaki örnek göz önünde bulundurun:

[HttpPost]
public ActionResult<TodoItem> Create(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();

return CreatedAtRoute("GetTodo", new { id = item.Id }, item);


}

Önceki eylem ActionResult<T> döndürür. Eylemin içinde, Createdatroutedöndürüyor. Denetleyicinin


[ApiController] özniteliği olduğundan, bir BadRequest yanıtı da mümkündür. Daha fazla bilgi için bkz. OTOMATIK
HTTP 400 yanıtları. İstemcilere bu eylemin hangi HTTP durum kodlarına geri dönebileceği bilinmektedir olduğunu
bildirmek için veri açıklamalarını kullanın. Eylemi aşağıdaki özniteliklerle işaretleyin:
[ProducesResponseType(StatusCodes.Status201Created)] // Created
[ProducesResponseType(StatusCodes.Status400BadRequest)] // BadRequest

ASP.NET Core 2,2 veya üzeri sürümlerde, tek tek eylemleri [ProducesResponseType] birlikte açıkça dekorasyon
yerine kuralları kullanabilirsiniz. Daha fazla bilgi için bkz. Web API 'SI kurallarını kullanma.
Swagger Oluşturucusu artık bu eylemi doğru bir şekilde tanımlayabilir ve üretilen istemciler, uç noktayı çağırırken
ne elde ettikleri hakkında bilgi alabilir. Öneri olarak tüm eylemleri bu özniteliklerle işaretleyin.
API eylemlerinizin dönmesi gereken HTTP yanıtlarının hakkında yönergeler için bkz. RFC 7231 belirtimi.
Openapı araçlarını kullanarak ASP.NET Core
uygulamaları geliştirme
27.09.2019 • 4 minutes to read • Edit Online

İle Ryan Brandenburg


Microsoft. DotNet-openapı , bir proje Içindeki openapı başvurularını yönetmek için .NET Core küresel bir araçtır .

Yükleme
Yüklemek Microsoft.dotnet-openapi için şu komutu çalıştırın:

dotnet tool install -g Microsoft.dotnet-openapi

Ekle
Bu sayfadaki komutlardan herhangi birini kullanarak bir openapı başvurusu eklemek, . csproj dosyasına
<OpenApiReference /> aşağıdakine benzer bir öğe ekler:

<OpenApiReference Include="openapi.json" />

Uygulamanın oluşturulan istemci kodunu çağırması için önceki başvuru gereklidir.


Dosya Ekle
Seçenekler

SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA ÖRNEK

-v --ayrıntılı Ayrıntılı çıktıyı göster. DotNet openapı dosya Ekle -


v .\Openapi.exe

-p --updateProject Üzerinde çalışılacak proje. DotNet openapı dosya Ekle -


-updateproject .\Ref.exe
.\Openapi.exe

-c --Code-Generator Başvuruya uygulanacak kod DotNet openapı Add dosyası


Oluşturucu. Seçenekler ve .\Openapi.exe JSON--Code-
NSwagCSharp ' Generator
NSwagTypeScript dir.
Belirtilmemişse, araçları
varsayılan olarak
NSwagCSharp ayarlanır.
--code-generator

-h --yardım Yardım bilgilerini göster DotNet openapı dosya Ekle--


yardım

Bağımsız Değişkenler
BAĞIMSIZ DEĞIŞKEN AÇIKLAMA ÖRNEK

Kaynak dosya Başvuru oluşturulacak kaynak. Bir DotNet openapı dosya ekleme
Openapı dosyası olmalıdır. .\Openapi.exe

URL ekle
Seçenekler

SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA ÖRNEK

-v --ayrıntılı Ayrıntılı çıktıyı göster. DotNet openapı URL 'si Ekle


-v
https://contoso.com/openapi.json

-p --updateProject Üzerinde çalışılacak proje. DotNet openapı Add URL --


updateproject .\Ref.exe
https://contoso.com/openapi.json

-o --Çıkış-dosya Openapı dosyasının yerel DotNet openapı Add URL


kopyasının yerleştirileceği yer. https://contoso.com/openapi.json
--çıktı-File MyClient. JSON

-c --Code-Generator Başvuruya uygulanacak kod DotNet openapı Add dosyası


Oluşturucu. Seçenekler ve .\Openapi.exe JSON--Code-
NSwagCSharp ' Generator
NSwagTypeScript dir.

-h --yardım Yardım bilgilerini göster DotNet openapı URL


ekleme--Yardım

Bağımsız Değişkenler

BAĞIMSIZ DEĞIŞKEN AÇIKLAMA ÖRNEK

Kaynak-URL Başvuru oluşturulacak kaynak. Bir URL DotNet openapı URL 'si Ekle
olmalıdır. https://contoso.com/openapi.json

Kaldır
Verilen dosya adıyla eşleşen Openapı başvurusunu . csproj dosyasından kaldırır. Openapı başvurusu kaldırıldığında,
istemciler oluşturulmaz. Local . JSON ve . YAML dosyaları silinir.
Seçenekler
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA ÖRNEK

-v --ayrıntılı Ayrıntılı çıktıyı göster. DotNet openapı Remove -v

-p --updateProject Üzerinde çalışılacak proje. DotNet openapı Remove --


updateproject .\ref. csproj
.\openapi.exe

-h --yardım Yardım bilgilerini göster DotNet openapı Remove--


Help

Bağımsız Değişkenler
BAĞIMSIZ DEĞIŞKEN AÇIKLAMA ÖRNEK

Kaynak dosya Başvurunun kaldırılacağı kaynak. DotNet openapı kaldırma .\Openapi.exe

Yenile
İndirme URL 'sindeki en son içerik kullanılarak indirilen bir dosyanın yerel sürümünü yeniler.
Seçenekler
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA ÖRNEK

-v --ayrıntılı Ayrıntılı çıktıyı göster. DotNet openapı yenileme -v


https://contoso.com/openapi.json

-p --updateProject Üzerinde çalışılacak proje. DotNet openapı yenileme --


updateproject .\ref.exe
https://contoso.com/openapi.json

-h --yardım Yardım bilgilerini göster DotNet openapı yenilemesi--


yardım

Bağımsız Değişkenler
BAĞIMSIZ DEĞIŞKEN AÇIKLAMA ÖRNEK

Kaynak-URL Başvurunun yenileneceği URL. DotNet openapı yenilemesi


https://contoso.com/openapi.json
ASP.NET Core Web API 'sindeki denetleyici eylemi
dönüş türleri
6.12.2019 • 10 minutes to read • Edit Online

Scott Ade tarafından


Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
ASP.NET Core Web API denetleyicisi eylem dönüş türleri için aşağıdaki seçenekleri sunar:
Belirli tür
Iactionresult
ActionResult<T >
Belirli tür
Iactionresult
Bu belgede, her dönüş türünü kullanmak için en uygun olan bilgiler açıklanmaktadır.

Belirli tür
En basit eylem, basit veya karmaşık bir veri türü döndürür (örneğin, string veya özel nesne türü). Özel Product
nesnelerinin bir koleksiyonunu döndüren aşağıdaki eylemi göz önünde bulundurun:

[HttpGet]
public List<Product> Get() =>
_repository.GetProducts();

Eylem yürütme sırasında korunmak üzere bilinen koşullar olmadan, belirli bir türü döndürmek yeterli olabilir.
Önceki eylem hiçbir parametre kabul etmez, bu nedenle parametre kısıtlamaları doğrulaması gerekli değildir.
Bir eylemde, bilinen koşulların ne zaman hesaba katılması gerektiği olduğunda, birden fazla dönüş yolu
tanıtılmıştır. Böyle bir durumda, basit veya karmaşık dönüş türüyle ActionResult bir dönüş türü karıştırmak
yaygındır. Bu tür eyleme uyum sağlamak için ıactionresult veya ActionResult<t > gereklidir.
IEnumerable<T > veya ıasyncenumerable<T > döndürün
ASP.NET Core 2,2 ve önceki sürümlerde, bir eylemden IEnumerable<T> döndürmek seri hale getirici tarafından
zaman uyumlu koleksiyon yinelemesi ile sonuçlanır. Sonuç olarak, çağrı engelleme ve iş parçacığı havuzu için
olası bir olasılık vardır. Göstermek için, Web API 'sinin veri erişimi ihtiyaçları için Entity Framework (EF ) Core
kullanıldığını düşünün. Aşağıdaki eylemin dönüş türü serileştirme sırasında zaman uyumlu olarak
numaralandırılır:

public IEnumerable<Product> GetOnSaleProducts() =>


_context.Products.Where(p => p.IsOnSale);

Zaman uyumlu numaralandırmayı önlemek ve engellemeyi ASP.NET Core 2,2 ve önceki sürümlerde veritabanı
üzerinde bekleyip, ToListAsync çağırın:
public IEnumerable<Product> GetOnSaleProducts() =>
_context.Products.Where(p => p.IsOnSale).ToListAsync();

ASP.NET Core 3,0 ve üzeri sürümlerde IAsyncEnumerable<T> bir eylemden geri döndürülüyor:
Zaman uyumlu yineleme ile sonuçlanmayacaktır.
IEnumerable<T>döndüren etkin hale gelir.
ASP.NET Core 3,0 ve üzeri, serileştiriciye sağlamadan önce aşağıdaki eylemin sonucunu arabelleğe alır:

public IEnumerable<Product> GetOnSaleProducts() =>


_context.Products.Where(p => p.IsOnSale);

Zaman uyumsuz yinelemeyi garantilemek için eylem imzasının dönüş türünü IAsyncEnumerable<T> olarak
bildirmeyi düşünün. Sonuç olarak, yineleme modu döndürülmekte olan temel somut türü temel alır. MVC,
IAsyncEnumerable<T> uygulayan herhangi bir somut türü otomatik olarak arabelleğe alır.

IEnumerable<Product> olarak satış fiyatlı ürün kayıtları döndüren aşağıdaki eylemi göz önünde bulundurun:

[HttpGet("syncsale")]
public IEnumerable<Product> GetOnSaleProducts()
{
var products = _repository.GetProducts();

foreach (var product in products)


{
if (product.IsOnSale)
{
yield return product;
}
}
}

Önceki eylemin IAsyncEnumerable<Product> eşdeğeri şunlardır:

[HttpGet("asyncsale")]
public async IAsyncEnumerable<Product> GetOnSaleProductsAsync()
{
var products = _repository.GetProductsAsync();

await foreach (var product in products)


{
if (product.IsOnSale)
{
yield return product;
}
}
}

Yukarıdaki eylemlerin her ikisi de ASP.NET Core 3,0 itibariyle engellenmeyen bir işlem değildir.

Iactionresult türü
IActionResult dönüş türü, bir eylemde birden çok ActionResult dönüş türü mümkün olduğunda uygundur.
ActionResult türleri çeşitli HTTP durum kodlarını temsil eder. ActionResult türetilen Özet olmayan herhangi bir
sınıf, geçerli bir dönüş türü olarak nitelendirir. Bu kategorideki bazı yaygın dönüş türleri BadRequestResult (400),
NotFoundResult (404) ve OkObjectResult (200). Alternatif olarak, ControllerBase sınıfındaki kullanışlı yöntemler
bir eylemden ActionResult türlerini döndürmek için kullanılabilir. Örneğin, return BadRequest();
return new BadRequestResult(); toplu bir biçimidir.

Bu tür bir eylemde birden çok dönüş türü ve yolu olduğundan, [ProducesResponseType] özniteliğin serbest
kullanımı gereklidir. Bu öznitelik, Swaggergibi araçlar tarafından oluşturulan Web API Yardım sayfaları için daha
açıklayıcı yanıt ayrıntıları üretir. [ProducesResponseType] , eylem tarafından döndürülecek bilinen türleri ve HTTP
durum kodlarını gösterir.
Zaman uyumlu eylem
İki olası dönüş türü olan aşağıdaki zaman uyumlu eylemi göz önünde bulundurun:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}

return Ok(product);
}

[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}

return Ok(product);
}

Önceki eylemde:
Temel alınan veri deposunda id tarafından temsil edilen ürün yoksa 404 durum kodu döndürülür. NotFound
kolaylığı yöntemi return new NotFoundResult(); için toplu olarak çağrılır.
Ürün mevcut olduğunda Product nesnesi ile bir 200 durum kodu döndürülür. Ok kolaylığı yöntemi
return new OkObjectResult(product); için toplu olarak çağrılır.

Zaman uyumsuz eylem


İki olası dönüş türü olan aşağıdaki zaman uyumsuz eylemi göz önünde bulundurun:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}

await _repository.AddProductAsync(product);

return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);


}

[HttpPost]
[Consumes("application/json")]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync([FromBody] Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}

await _repository.AddProductAsync(product);

return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);


}

Önceki eylemde:
Ürün açıklaması "XYZ pencere öğesi" içerdiğinde 400 durum kodu döndürülür. BadRequest kolaylığı yöntemi
return new BadRequestResult(); için toplu olarak çağrılır.
Bir ürün oluşturulduğunda CreatedAtAction kullanışlı yöntem tarafından bir 201 durum kodu oluşturulur.
CreatedAtAction çağırma alternatifi
return new CreatedAtActionResult(nameof(GetById), "Products", new { id = product.Id }, product); . Bu kod
yolunda, Product nesnesi yanıt gövdesinde sağlanır. Yeni oluşturulan ürünün URL 'sini içeren Location bir
yanıt üst bilgisi sağlanır.
Örneğin, aşağıdaki model isteklerin Name ve Description özelliklerini içermesi gerektiğini gösterir. Name
sağlama hatası ve istekte Description , model doğrulamasının başarısız olmasına neden oluyor.

public class Product


{
public int Id { get; set; }

[Required]
public string Name { get; set; }

[Required]
public string Description { get; set; }
}

ASP.NET Core 2,1 veya sonraki bir sürümde [ApiController] özniteliği uygulanırsa, model doğrulama hataları
400 durum koduna neden olur. Daha fazla bilgi için bkz. OTOMATIK HTTP 400 yanıtları.
ActionResult<T > türü
ASP.NET Core 2,1, Web API denetleyicisi eylemleri için <t > geri dönüş türünü sunmuştur. ActionResult
türettikten veya belirli bir türdöndürmenize olanak sağlar. ActionResult<T> , ıactionresult türüüzerinde aşağıdaki
avantajları sunmaktadır:
[ProducesResponseType] özniteliğin Type özelliği dışarıda bırakılabilirler. Örneğin,
[ProducesResponseType(200, Type = typeof(Product))] [ProducesResponseType(200)] basitleştirilmiştir. Eylemin
beklenen dönüş türü, ActionResult<T>``T çıkarsandı.
Örtük atama işleçleri hem T hem de ActionResult<T>``ActionResult dönüştürmeyi destekler. T
ObjectResultdönüştürür, bu, return new ObjectResult(T); return T; olarak basitleşdüğü anlamına gelir.
C#arabirimlerde örtük atama işleçlerini desteklemez. Sonuç olarak, ActionResult<T> kullanmak için arabirimin
somut bir türe dönüştürülmesi gerekir. Örneğin, aşağıdaki örnekte IEnumerable kullanımı çalışmaz:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get() =>
_repository.GetProducts();

Önceki kodu gidermeye yönelik bir seçenek _repository.GetProducts().ToList(); döndürmemelidir.


Çoğu eylemin belirli bir dönüş türü vardır. Eylem yürütme sırasında beklenmeyen koşullar gerçekleşebilir, bu
durumda belirli tür döndürülmez. Örneğin, bir eylemin giriş parametresi, model doğrulamasının başarısız
olmasına neden olabilir. Böyle bir durumda, belirli tür yerine uygun ActionResult türünü döndürmek yaygın bir
durumdur.
Zaman uyumlu eylem
İki olası dönüş türü olan zaman uyumlu bir eylem düşünün:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}

return product;
}

Önceki eylemde:
Ürün veritabanında mevcut olmadığında bir 404 durum kodu döndürülür.
Ürün mevcut olduğunda karşılık gelen Product nesnesiyle bir 200 durum kodu döndürülür. 2,1 ASP.NET
Core önce return product; satırının return Ok(product); olması gerekiyordu.
Zaman uyumsuz eylem
İki olası dönüş türü olan zaman uyumsuz bir eylem düşünün:
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}

await _repository.AddProductAsync(product);

return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);


}

Önceki eylemde:
Bir 400 durum kodu (BadRequest), şu durumlarda ASP.NET Core çalışma zamanı tarafından döndürülür:
[ApiController] özniteliği uygulandı ve model doğrulaması başarısız oluyor.
Ürün açıklaması "XYZ pencere öğesi" içerir.
Bir ürün oluşturulduğunda CreatedAtAction yöntemi tarafından 201 durum kodu oluşturulur. Bu kod yolunda,
Product nesnesi yanıt gövdesinde sağlanır. Yeni oluşturulan ürünün URL 'sini içeren Location bir yanıt üst
bilgisi sağlanır.

Ek kaynaklar
ASP.NET Core MVC 'de denetleyicilerle istekleri işleme
ASP.NET Core MVC 'de model doğrulaması
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core Web API JsonPatch
11.07.2019 • 10 minutes to read • Edit Online

tarafından Tom Dykstra


Bu makalede, bir ASP.NET Core web API'si, JSON Patch isteklerinin nasıl işleneceğini açıklar.

PATCH HTTP istek yöntemi


KOY ve düzeltme eki yöntemleri, mevcut bir kaynağı güncelleştirmek için kullanılır. Aralarındaki fark, düzeltme eki
yalnızca değişiklikleri belirtirken PUT tüm kaynak değiştirir ' dir.

JSON yaması
JSON yaması bir kaynağa uygulanacak güncelleştirmeleri belirtmek için bir biçimidir. Bir dizi JSON yama belgesi
sahip operations. Her bir işlemin belirli bir değişiklik türünü tanımlar, gibi bir dizi öğesine eklemek veya bir özellik
değeri değiştirin.
Örneğin, aşağıdaki JSON belgelerini bir kaynak, kaynak ve patch işlemleri sonucu için JSON patch belgenin
gösterir.
Kaynak örneği

{
"customerName": "John",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
}
]
}

JSON patch örneği

[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]

Yukarıdaki JSON:
op Özelliği işlem türünü belirtir.
path Güncelleştirilecek öğe özelliği belirtir.
value Özelliğinin yeni değeri sağlar.

Düzeltme eki sonra kaynak


Yukarıdaki JSON yama belgesi uyguladıktan sonra kaynak şöyledir:

{
"customerName": "Barry",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
},
{
"orderName": "Order2",
"orderType": null
}
]
}

Kaynak JSON yama belgesi uygulayarak yapılan değişiklikler atomiktir: listedeki herhangi bir işlem başarısız
olursa, listedeki işlem uygulanır.

Yolu sözdizimi
Yolu işlem nesnesi özelliğine düzeyleri arasında eğik çizgi sahiptir. Örneğin: "/address/zipCode" .
Sıfır tabanlı dizin, dizi öğeleri belirtmek için kullanılır. İlk öğesi addresses dizi konumunda olacak /addresses/0 .
İçin add bir dizinin sonuna bir tire (-) yerine bir dizin numarasını kullanın: /addresses/- .
İşlemler
Aşağıdaki tablo desteklenen gösterir işlemleri sınıfında tanımlandığı gibi JSON Patch belirtimi:

ÇALIŞMA NOTLAR

add Bir özellik ya da dizi öğesini ekleyin. Var olan bir özellik için:
değeri ayarlayın.

remove Bir özellik ya da dizi öğesini kaldırın.

replace Aynı remove ardından add aynı konumda.

move Aynı remove ardından kaynağından add değerini kullanarak


bir kaynaktan bir hedefe.

copy Aynı add değerini kullanarak bir kaynaktan bir hedefe.

test Başarılı durum kodu döndürür değerini path sağlanan =


value .

ASP.NET core'da JsonPatch


JSON yaması ASP.NET Core uygulaması sağlanan Microsoft.AspNetCore.JsonPatch NuGet paketi. Paket dahil
Microsoft.AspnetCore.App metapackage.

Eylem yöntemi kodu


API denetleyicisi içinde bir eylem yöntemi için JSON Patch:
İle açıklanıyor HttpPatch özniteliği.
Kabul eden bir JsonPatchDocument<T> , genellikle [FromBody] ile.
Çağrıları ApplyTo üzerindeki değişiklikleri uygulamak için yama belgesi.

Örnek buradadır:

[HttpPatch]
public IActionResult JsonPatchWithModelState(
[FromBody] JsonPatchDocument<Customer> patchDoc)
{
if (patchDoc != null)
{
var customer = CreateCustomer();

patchDoc.ApplyTo(customer, ModelState);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

return new ObjectResult(customer);


}
else
{
return BadRequest(ModelState);
}
}

Bu örnek uygulama kodundan aşağıdakilerle çalışır Customer modeli.

public class Customer


{
public string CustomerName { get; set; }
public List<Order> Orders { get; set; }
}

public class Order


{
public string OrderName { get; set; }
public string OrderType { get; set; }
}

Örnek eylem yöntemi:


Oluşturur bir Customer .
Düzeltme eki uygular.
Yanıt gövdesinde sonucunu döndürür.
Gerçek bir uygulamada kod bir veritabanı gibi bir depolama alanından verileri almak ve düzeltme eki
uygulandıktan sonra veritabanı güncelleştirmesi.
Model durumu
Önceki eylem yöntemi örneği bir aşırı yüklemesini çağırır ApplyTo , parametrelerinden biri olarak model
durumunu alır. Bu seçenek belirtilmişse, hata iletileri yanıtlarını alabilirsiniz. Aşağıdaki örnek, bir 400 Hatalı istek
yanıt gövdesinin gösterir. bir test işlemi:

{
"Customer": [
"The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
]
}

Dinamik nesneler
Eylem yöntemi aşağıda dinamik bir nesne için bir düzeltme eki uygulama işlemini gösterir.

[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
dynamic obj = new ExpandoObject();
patch.ApplyTo(obj);

return Ok(obj);
}

Ekleme işlemi
Varsa path bir dizi öğesine işaret eder: tarafından belirtilen bir önce yeni bir öğe ekler path .
Varsa path gösteren bir özelliğe: özellik değeri ayarlar.
Varsa path varolmayan bir konuma işaret eder:
Düzeltme eki kaynağa dinamik bir nesne ise: bir özellik ekler.
Kaynak düzeltme eki için statik bir nesneyse: istek başarısız olur.
Aşağıdaki örnek yama belgesi değerini ayarlar CustomerName ve ekler bir Order nesnesinin sonuna Orders dizisi.

[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]

Kaldırma işlemi
Varsa path bir dizi öğesine işaret eder: öğeyi kaldırır.
Varsa path işaret eden bir özellik için:
Kaynak düzeltme eki için dinamik bir nesne ise: özelliği kaldırır.
Kaynak düzeltme eki için statik bir nesne ise:
Özellik boş değer atanabilir ise: null olarak ayarlar.
NULL olmayan bir özelliğidir, bu ayarlar default<T> .
Aşağıdaki örnek, düzeltme eki belge kümeleri CustomerName null ve silmeleri Orders[0] .

[
{
"op": "remove",
"path": "/customerName"
},
{
"op": "remove",
"path": "/orders/0",
}
]

Değiştirme işlemi
Bu işlem işlevsel olarak aynıdır bir remove arkasından bir add .
Aşağıdaki örnek yama belgesi değerini ayarlar CustomerName ve değiştirir Orders[0] yeni bir Order nesne.

[
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]

Taşıma işlemi
Varsa bir dizi öğesine işaret: kopyalar from konumunu öğesine path öğesi, daha sonra çalışan bir
path
remove işlemi from öğesi.
Varsa path gösteren bir özelliğe: kopyalar değerini from özelliğini path özelliği, daha sonra çalışan bir
remove işlemi from özelliği.
Varsa path işaret varolmayan bir özellik için:
Kaynak düzeltme eki için statik bir nesneyse: istek başarısız olur.
Yama kaynak dinamik bir nesne ise: kopyaları from özelliği tarafından belirtilen konuma path , sonra
çalışan bir remove işlemi from özelliği.
Aşağıdaki örnek yama belgesi:
Değerini kopyalar Orders[0].OrderName için CustomerName .
Kümeleri Orders[0].OrderName null.
Taşır Orders[1] için önce Orders[0] .
[
{
"op": "move",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "move",
"from": "/orders/1",
"path": "/orders/0"
}
]

Kopyalama işlemi
Bu işlem işlevsel olarak aynıdır bir move son olmadan işlemi remove adım.
Aşağıdaki örnek yama belgesi:
Değerini kopyalar Orders[0].OrderName için CustomerName .
Bir kopyasını ekler Orders[1] önce Orders[0] .

[
{
"op": "copy",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "copy",
"from": "/orders/0",
"path": "/orders/1"
}
]

Test işlemi
Bu konumdaki değeri tarafından belirtilmişse path sağlanan değerinden farklı value , istek başarısız olur. Bu
durumda bile yama belgesindeki tüm diğer işlemler, aksi takdirde başarılı olabilir tüm PATCH isteği başarısız olur.
test İşlemi bir eşzamanlılık çakışması olduğunda, bir güncelleştirme önlemek için yaygın olarak kullanılır.
Aşağıdaki örnek yama belgesi etkisizdir başlangıç değeri oluşan CustomerName "John", test başarısız çünkü:

[
{
"op": "test",
"path": "/customerName",
"value": "Nancy"
},
{
"op": "add",
"path": "/customerName",
"value": "Barry"
}
]

Kodu alma
Görüntüleme veya indirme örnek kodu. (Nasıl indirileceğini).
Örnek test etmek için uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri göndermek için:
URL: http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
HTTP yöntemi: PATCH
Üst bilgi: Content-Type: application/json-patch+json
Gövdesi: JSON patch belge örneklerinden birini kopyalayıp JSON proje klasörü.

Ek kaynaklar
IETF RFC 5789 düzeltme eki yöntemi belirtimi
IETF RFC 6902 JSON Patch belirtimi
IETF RFC 6901 JSON Patch yolu biçim belirtimi
JSON yaması belgeleri. JSON yaması belgeleri oluşturmak için kaynakların bağlantılarını içerir.
ASP.NET Core JSON Patch kaynak kodu
ASP.NET Core Web API 'sindeki yanıt verilerini
biçimlendirme
10.12.2019 • 12 minutes to read • Edit Online

By Rick Anderson ve Steve Smith


ASP.NET Core MVC, yanıt verilerini biçimlendirme desteğine sahiptir. Yanıt verileri, belirli biçimler kullanılarak
veya istemci tarafından istenen biçime yanıt olarak biçimlendirilebilir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Formata özgü eylem sonuçları


Bazı eylem sonuç türleri, JsonResult ve ContentResultgibi belirli bir biçime özgüdür. Eylemler, istemci
tercihlerinden bağımsız olarak belirli bir biçimde biçimlendirilen sonuçları döndürebilir. Örneğin, döndürme
JsonResult JSON biçimli verileri döndürür. ContentResult veya dize döndürüldüğünde düz metin biçimli dize
verileri döndürülür.
Belirli bir tür döndürmek için bir eylem gerekli değildir. ASP.NET Core, tüm nesne dönüş değerlerini destekler.
IActionResult türler olmayan nesneleri döndüren eylemlerin sonuçları, uygun IOutputFormatter uygulamasını
kullanarak serileştirilir. Daha fazla bilgi için bkz. ASP.NET Core Web API 'sindeki denetleyici eylemi dönüş türleri.
Yerleşik yardımcı yöntem Ok JSON biçimli verileri döndürür: [!code-csharp ]
Örnek indirme, yazarların listesini döndürür. Önceki kodla F12 tarayıcı geliştirici araçları veya Postman kullanma:
Content-Type: application/json; charset=utf-8 içeren yanıt üst bilgisi görüntülenir.
İstek üst bilgileri görüntülenir. Örneğin, Accept üst bilgisi. Accept üst bilgisi, önceki kod tarafından yok
sayılır.
Düz metin biçimli verileri döndürmek için Content ve Content yardımcısını kullanın:

// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}

Yukarıdaki kodda, döndürülen Content-Type text/plain . Bir dize döndürmek text/plain``Content-Type sağlar:

// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}

Birden çok dönüş türüne sahip eylemler için IActionResult döndürün. Örneğin, gerçekleştirilen işlemlerin
sonucuna göre farklı HTTP durum kodları döndürülüyor.

İçerik anlaşması
İstemci bir Accept üst bilgisibelirttiğinde içerik anlaşması oluşur. ASP.NET Core tarafından kullanılan varsayılan
biçim JSON'dir. İçerik anlaşması:
ObjectResulttarafından uygulandı.
Yardımcı metotlarından döndürülen durum koduna özgü eylem sonuçlarına yerleşik olarak. Eylem sonuçları
yardımcı yöntemleri ObjectResult tabanlıdır.
Bir model türü döndürüldüğünde, dönüş türü ObjectResult .
Aşağıdaki eylem yöntemi Ok ve NotFound yardımcı yöntemlerini kullanır:

// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authors.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}

Varsayılan olarak, ASP.NET Core application/json , text/json ve text/plain medya türlerini destekler. Fiddler
veya Postman gibi araçlar, dönüş biçimini belirtmek için Accept istek üst bilgisini ayarlayabilir. Accept üst bilgisi
sunucunun desteklediği bir tür içerdiğinde, bu tür döndürülür. Sonraki bölümde, ek Biçimlendiriciler ekleme
gösterilmektedir.
Denetleyici eylemleri POCOs (düz eski CLR nesneleri) döndürebilir. POCO döndürüldüğünde, çalışma zamanı
otomatik olarak nesneyi sarmalayan bir ObjectResult oluşturur. İstemci, biçimlendirilen serileştirilmiş nesneyi
alır. Döndürülen nesne null , bir 204 No Content yanıtı döndürülür.
Nesne türü döndürülüyor:

// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authors.GetByAlias(alias);
}

Önceki kodda, geçerli bir yazar diğer adı için bir istek yazarın verileriyle 200 OK bir yanıt döndürür. Geçersiz bir
diğer ad isteği bir 204 No Content yanıtı döndürüyor.
Accept üstbilgisi
İstekte bir Accept üst bilgisi göründüğünde içerik anlaşması gerçekleşir. Bir istek bir Accept üst bilgisi
içerdiğinde ASP.NET Core:
Kabul üst bilgisindeki medya türlerini tercih sırasına göre numaralandırır.
Belirtilen biçimlerden birinde yanıt üretemeyen bir biçimlendirici bulmaya çalışır.
İstemcinin isteğini karşılayabilen bir biçimlendirici bulunmazsa ASP.NET Core:
MvcOptions ayarlandıysa 406 Not Acceptable döndürür veya-
Yanıt üreten ilk biçimlendirici bulmayı dener.
İstenen biçim için bir biçimlendirici yapılandırılmamışsa, nesneyi biçimlendirebileceğini ilk biçimlendirici
kullanılır. İstekte hiçbir Accept üstbilgisi görünürse:
Nesneyi işleyebilen ilk biçimlendirici, yanıtı seri hale getirmek için kullanılır.
Hiçbir anlaşma gerçekleşmiyor. Sunucu hangi biçimin döneceğine karar verir.
Accept üst bilgisi */* içeriyorsa, MvcOptions RespectBrowserAcceptHeader true olarak ayarlanmadığı takdirde
başlık yok sayılır.
Tarayıcılar ve içerik anlaşması
Tipik API istemcilerinin aksine Web tarayıcıları Accept üst bilgileri sağlar. Web tarayıcısı, joker karakterler dahil
olmak üzere birçok biçim belirtir. Varsayılan olarak, Framework isteğin bir tarayıcıdan geldiğini algıladığında:
Accept üst bilgisi yok sayılır.
Aksi yapılandırılmadığı takdirde içerik JSON içinde döndürülür.
Bu, API 'Leri tükettiren tarayıcılarda daha tutarlı bir deneyim sağlar.
Bir uygulamayı tarayıcı onay üstbilgilerini kabul edecek şekilde yapılandırmak için RespectBrowserAcceptHeader
true olarak ayarlayın:

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});
}

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Biçimleri yapılandırma
Ek biçimleri desteklemesi gereken uygulamalar uygun NuGet paketlerini ekleyebilir ve desteği yapılandırabilir.
Giriş ve çıkış için ayrı biçimlendirme vardır. Giriş formatlayıcıları model bağlamatarafından kullanılır. Çıkış
biçimleri, yanıtları biçimlendirmek için kullanılır. Özel bir biçimlendirici oluşturma hakkında daha fazla bilgi için
bkz. özel Formatlayıcılar.
XML biçimi desteği ekle
XmlSerializer kullanılarak uygulanan XML formatlayıcıları AddXmlSerializerFormattersçağırarak yapılandırılır:

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers()
.AddXmlSerializerFormatters();
}

Yukarıdaki kod, XmlSerializer kullanarak sonuçları seri hale getirir.


Önceki kodu kullanırken, denetleyici yöntemleri isteğin Accept üst bilgisine göre uygun biçimi döndürür.
System. Text. JSON tabanlı formatlayıcıları yapılandırma
System.Text.Json tabanlı formatlayıcılar için özellikler, Microsoft.AspNetCore.Mvc.JsonOptions.SerializerOptions
kullanılarak yapılandırılabilir.

services.AddControllers().AddJsonOptions(options =>
{
// Use the default property (Pascal) casing.
options.SerializerOptions.PropertyNamingPolicy = null;

// Configure a custom converter.


options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

Çıkış serileştirme seçenekleri, eylem başına temelinde, JsonResult kullanılarak yapılandırılabilir. Örneğin:

public IActionResult Get()


{
return Json(model, new JsonSerializerOptions
{
options.WriteIndented = true,
});
}

Newtonsoft. JSON tabanlı JSON biçimi desteği ekleyin


ASP.NET Core 3,0 ' dan önce, varsayılan olarak kullanılan JSON formatlayıcıları Newtonsoft.Json paketi
kullanılarak uygulanır. ASP.NET Core 3,0 veya üzeri sürümlerde, varsayılan JSON biçimleri System.Text.Json
temel alır. Newtonsoft.Json tabanlı formatlayıcılar ve özellikler için destek, Microsoft. AspNetCore. Mvc.
NewtonsoftJson NuGet paketini yükleyerek ve Startup.ConfigureServices yapılandırılarak kullanılabilir.

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers()
.AddNewtonsoftJson();
}

Bazı özellikler System.Text.Json tabanlı formatlayıcılar ile iyi çalışmayabilir ve Newtonsoft.Json tabanlı
Biçimlendiriciler için bir başvuru gerektirir. Uygulama şu durumlarda Newtonsoft.Json tabanlı formatlayıcıları
kullanmaya devam edin:
Newtonsoft.Json özniteliklerini kullanır. Örneğin, [JsonProperty] veya [JsonIgnore] .
Serileştirme ayarlarını özelleştirir.
Newtonsoft.Json sağladığı özellikleri kullanır.
Microsoft.AspNetCore.Mvc.JsonResult.SerializerSettingsyapılandırır. ASP.NET Core 3,0 ' dan önce
JsonResult.SerializerSettings , Newtonsoft.Json özgü bir JsonSerializerSettings örneğini kabul eder.
Openapı belgeleri oluşturur.
Newtonsoft.Json tabanlı formatlayıcılar için özellikler
Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings kullanılarak yapılandırılabilir:
services.AddControllers().AddNewtonsoftJson(options =>
{
// Use the default property (Pascal) casing
options.SerializerSettings.ContractResolver = new DefaultContractResolver();

// Configure a custom converter


options.SerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

Çıkış serileştirme seçenekleri, eylem başına temelinde, JsonResult kullanılarak yapılandırılabilir. Örneğin:

public IActionResult Get()


{
return Json(model, new JsonSerializerSettings
{
options.Formatting = Formatting.Indented,
});
}

XML biçimi desteği ekle


XML biçimlendirme, Microsoft. AspNetCore. Mvc. Formatters. xml NuGet paketini gerektirir.
XmlSerializer kullanılarak uygulanan XML formatlayıcıları AddXmlSerializerFormattersçağırarak yapılandırılır:

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddXmlSerializerFormatters();
}

Yukarıdaki kod, XmlSerializer kullanarak sonuçları seri hale getirir.


Önceki kodu kullanırken, denetleyici yöntemleri isteğin Accept üst bilgisine göre uygun biçimi döndürmelidir.
Biçim belirtin
Yanıt biçimlerini kısıtlamak için [Produces] filtresini uygulayın. Çoğu filtregibi [Produces] eylem, denetleyici
veya genel kapsamda uygulanabilir:

[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{

Önceki [Produces] filtresi:


Denetleyici içindeki tüm eylemleri JSON biçimli yanıtları döndürecek şekilde zorlar.
Diğer formatlayıcılar yapılandırıldıysa ve istemci farklı bir biçim belirtiyorsa JSON döndürülür.
Daha fazla bilgi için bkz. Filtreler.
Özel durum formatları
Bazı özel durumlar, yerleşik formatlayıcılar kullanılarak uygulanır. string dönüş türleri varsayılan olarak
metin/düz ( Accept üst bilgisi ile isteniyorsametin/html ) olarak biçimlendirilir. Bu davranış,
StringOutputFormatterkaldırılarak silinebilir. Biçimlendiriciler ConfigureServices yönteminde kaldırılır. Model
nesne dönüş türü olan eylemler null döndürürken 204 No Content döndürür. Bu davranış,
HttpNoContentOutputFormatterkaldırılarak silinebilir. Aşağıdaki kod StringOutputFormatter ve
HttpNoContentOutputFormatter kaldırır.

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
}

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

StringOutputFormatter olmadan, yerleşik JSON biçimlendirici string dönüş türlerini biçimlendirir. Yerleşik
JSON biçimlendiricisi kaldırılırsa ve bir XML biçimlendirici varsa, XML biçimlendirici string dönüş türlerini
biçimlendirir. Aksi takdirde, string dönüş türleri 406 Not Acceptable döndürür.
HttpNoContentOutputFormatter olmadan, null nesneler yapılandırılmış biçimlendirici kullanılarak biçimlendirilir.
Örneğin:
JSON biçimlendiricisi null gövdesiyle bir yanıt döndürür.
XML biçimlendiricisi, xsi:nil="true" ayarlanan özniteliğe sahip boş bir XML öğesi döndürür.

Yanıt biçimi URL eşlemeleri


İstemciler URL 'nin bir parçası olarak belirli bir biçim talep edebilir, örneğin:
Sorgu dizesinde veya yolun bir bölümünde.
. Xml veya. JSON gibi formata özgü bir dosya uzantısı kullanarak.
İstek yolundan eşleme, API 'nin kullandığı rotada belirtilmelidir. Örneğin:

[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
[HttpGet("{id}.{format?}")]
public Product Get(int id)
{

Önceki yol, istenen biçimin isteğe bağlı bir dosya uzantısı olarak belirtilmesini sağlar. [FormatFilter] özniteliği,
RouteData biçim değerinin varlığını denetler ve yanıt oluşturulduğu zaman yanıt biçimini uygun biçimlendirici ile
eşler.
YOL BIÇIMLENDIRICI

/api/products/5 Varsayılan çıkış biçimlendiricisi

/api/products/5.json JSON biçimlendiricisi (yapılandırıldıysa)

/api/products/5.xml XML biçimlendiricisi (yapılandırıldıysa)


ASP.NET Core Web API 'sindeki özel formatıcılar
13.09.2019 • 7 minutes to read • Edit Online

Tom Dykstra tarafından


ASP.NET Core MVC, giriş ve çıkış formatlayıcıları kullanılarak Web API 'Lerinde veri değişimini destekler. Giriş
formatlayıcıları model bağlamatarafından kullanılır. Çıkış biçimleri, yanıtları biçimlendirmekiçin kullanılır.
Framework, JSON ve XML için yerleşik giriş ve çıkış biçimleri sağlar. Düz metin için yerleşik bir çıkış
biçimlendiricisi sağlar, ancak düz metin için bir giriş biçimlendiricisi sağlamaz.
Bu makalede, özel formatlayıcılar oluşturarak ek biçimler için nasıl destek ekleneceği gösterilmektedir. Düz metin
için özel bir giriş biçimlendirici örneği için GitHub 'da Textplainınputformatter bölümüne bakın.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Özel formatlayıcılar ne zaman kullanılır?


İçerik anlaşma işleminin yerleşik biçimleri tarafından desteklenmeyen bir içerik türünü desteklemesini
istediğinizde, özel bir biçimlendirici kullanın.
Örneğin, Web API 'niz için bazı istemciler prototip biçimini işleyebildiğinden, daha verimli olduğundan bu
istemcilerle prototip kullanmak isteyebilirsiniz. Ya da Web API 'nizin kişi adlarını ve adresleri, kişi verilerini değiş
tokuş için sık kullanılan bir biçimde, vCard biçiminde göndermesini isteyebilirsiniz. Bu makalede belirtilen örnek
uygulama, basit bir vCard biçimlendiricisi uygular.

Özel biçimlendirici kullanma konusuna genel bakış


Özel bir biçimlendirici oluşturma ve kullanma adımları aşağıda verilmiştir:
İstemciye göndermek için veri serileştirmek istiyorsanız çıkış biçimlendirici sınıfı oluşturun.
İstemciden alınan verilerin serisini kaldırmak istiyorsanız bir giriş biçimlendirici sınıfı oluşturun.
InputFormatters Mvcoptionsiçindeki ve OutputFormatters koleksiyonlarına Biçimlendiriciler örneklerini
ekleyin.
Aşağıdaki bölümlerde, bu adımların her biri için rehberlik ve kod örnekleri sağlanmaktadır.

Özel bir biçimlendirici sınıfı oluşturma


Bir biçimlendirici oluşturmak için:
Sınıfı uygun temel sınıftan türet.
Oluşturucuda geçerli medya türleri ve kodlamalar belirtin.
Geçersiz CanReadType kılma / yöntemleri CanWriteType
Geçersiz ReadRequestBodyAsync kılma / yöntemleri WriteResponseBodyAsync
Uygun taban sınıftan türet
Metin medya türleri (örneğin, vCard) için, Textinputformatter veya Textoutputformatter temel sınıfından
türetirsiniz.

public class VcardOutputFormatter : TextOutputFormatter


Bir giriş biçimlendirici örneği için bkz. örnek uygulama.
İkili türler için inputformatter veya outputformatter temel sınıfından türetirsiniz.
Geçerli medya türlerini ve kodlamaları belirtin
Oluşturucuda, SupportedMediaTypes ve SupportedEncodings koleksiyonlarına ekleyerek geçerli medya türlerini ve
kodlamaları belirtin.

public VcardOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard"));

SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}

Bir giriş biçimlendirici örneği için bkz. örnek uygulama.

NOTE
Bir biçimlendirici sınıfında Oluşturucu bağımlılığı ekleme yapamazsınız. Örneğin, oluşturucuya bir günlükçü parametresi
ekleyerek günlükçü alamazsınız. Hizmetlere erişmek için yöntemlerinize geçirilen bağlam nesnesini kullanmanız gerekir.
Aşağıdaki kod örneği bunun nasıl yapılacağını gösterir.

CanReadType/CanWriteType geçersiz kıl


CanReadType Veya CanWriteType yöntemlerini geçersiz kılarak seri durumdan çıkarabilen veya seri hale
getirekullanabileceğiniz türü belirtin. Örneğin, yalnızca bir Contact türden vCard metni oluşturabileceğiniz gibi,
tam tersi de olabilir.

protected override bool CanWriteType(Type type)


{
if (typeof(Contact).IsAssignableFrom(type)
|| typeof(IEnumerable<Contact>).IsAssignableFrom(type))
{
return base.CanWriteType(type);
}
return false;
}

Bir giriş biçimlendirici örneği için bkz. örnek uygulama.


CanWriteResult yöntemi
Bazı senaryolarda CanWriteResult CanWriteType yerine geçersiz kılmanız gerekir. Aşağıdaki CanWriteResult
koşullar doğruysa kullanın:
Eylem yönteminiz bir model sınıfı döndürür.
Çalışma zamanında döndürülebilecek türetilmiş sınıflar var.
Eylem tarafından türetilen sınıfın döndürüldüğü çalışma zamanında bilmeniz gerekir.
Örneğin, eylem yöntemi Person imzanızın bir tür döndürdüğünden, ancak ondan Person türetilen bir Student
veya Instructor türü döndürebildiğini varsayalım. Biçimlendiricinin yalnızca Student nesneleri işlemesini
istiyorsanız, CanWriteResult metoduna sunulan bağlam nesnesindeki nesne türünü denetleyin. Eylem
CanWriteResult yöntemidöndürüldüğünde CanWriteType kullanılması gerekmediğini unutmayın
;Budurumdayöntemçalışmazamanıtürünüalır. IActionResult
ReadRequestBodyAsync/WriteResponseBodyAsync geçersiz kıl
ReadRequestBodyAsync Ya WriteResponseBodyAsync da ' de serileştirilin veya serileştirme fiili işi yapabilirsiniz.
Aşağıdaki örnekte vurgulanan satırlarda, bağımlılık ekleme kapsayıcısından hizmetlerin nasıl alınacağı
gösterilmektedir (Bu parametreleri Oluşturucu parametrelerinden alamazsınız).

public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding


selectedEncoding)
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices;
var logger = serviceProvider.GetService(typeof(ILogger<VcardOutputFormatter>)) as ILogger;

var response = context.HttpContext.Response;

var buffer = new StringBuilder();


if (context.Object is IEnumerable<Contact>)
{
foreach (Contact contact in context.Object as IEnumerable<Contact>)
{
FormatVcard(buffer, contact, logger);
}
}
else
{
var contact = context.Object as Contact;
FormatVcard(buffer, contact, logger);
}
await response.WriteAsync(buffer.ToString());
}

private static void FormatVcard(StringBuilder buffer, Contact contact, ILogger logger)


{
buffer.AppendLine("BEGIN:VCARD");
buffer.AppendLine("VERSION:2.1");
buffer.AppendFormat($"N:{contact.LastName};{contact.FirstName}\r\n");
buffer.AppendFormat($"FN:{contact.FirstName} {contact.LastName}\r\n");
buffer.AppendFormat($"UID:{contact.ID}\r\n");
buffer.AppendLine("END:VCARD");
logger.LogInformation("Writing {FirstName} {LastName}", contact.FirstName, contact.LastName);
}

Bir giriş biçimlendirici örneği için bkz. örnek uygulama.

MVC 'yi özel bir biçimlendirici kullanacak şekilde yapılandırma


Özel bir biçimlendirici kullanmak için, InputFormatters veya OutputFormatters koleksiyonuna biçimlendirici
sınıfının bir örneğini ekleyin.

services.AddMvc(options =>
{
options.InputFormatters.Insert(0, new VcardInputFormatter());
options.OutputFormatters.Insert(0, new VcardOutputFormatter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Biçimlendiriciler, eklediğiniz sırada değerlendirilir. Birincisi bir öncelik alır.

Sonraki adımlar
Bu belge içinbasit vCard giriş ve çıkış biçimleri uygulayan örnek uygulama. Uygulamalar aşağıdaki örnekteki
gibi görünen vCard 'ları okur ve yazar:
BEGIN:VCARD
VERSION:2.1
N:Davolio;Nancy
FN:Nancy Davolio
UID:20293482-9240-4d68-b475-325df4a83728
END:VCARD

VCard çıktısını görmek için, uygulamayı çalıştırın ve "metin/vCard" http://localhost:63313/api/contacts/ onay


üst bilgisine sahip bir get isteği gönderin (Visual Studio 'dan çalıştırıldığında) veya
http://localhost:5000/api/contacts/ (komut satırından çalıştırıldığında).

Bir vCard 'ı bellek içi kişiler koleksiyonuna eklemek için, Içerik türü üst bilgisi "metin/vCard" ile aynı URL 'ye bir
post isteği gönderin ve gövdesinde örnek olarak biçimlendirilen vCard metni yazın.
Web API Çözümleyicileri kullanma
19.09.2019 • 3 minutes to read • Edit Online

ASP.NET Core 2,2 ve üzeri, Web API projeleriyle kullanılması amaçlanan bir MVC Çözümleyicileri paketi sağlar.
Çözümleyiciler, Web API kurallarıüzerinde oluşturma sırasında ApiControllerAttributeile açıklanmış olan
denetleyicilerle birlikte çalışır.
Çözümleyiciler paketi şu şekilde bir denetleyici eylemi bildirir:
Bildirilmemiş bir durum kodu döndürür.
Bildirilmemiş başarı sonucunu döndürür.
Döndürülen bir durum kodunu belgeler.
Açık model doğrulama denetimi içerir.

Çözümleyici paketine başvur


ASP.NET Core 3,0 veya sonraki sürümlerde, çözümleyiciler .NET Core SDK dahil edilmiştir. Projenizdeki
çözümleyici 'yi etkinleştirmek için, proje dosyasına IncludeOpenAPIAnalyzers özelliği ekleyin:

<PropertyGroup>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
</PropertyGroup>

Paket yüklemesi
Aşağıdaki yaklaşımlardan biriyle Microsoft. AspNetCore. Mvc. api. çözümleyiciler NuGet paketini yükler:
Visual Studio
Mac için Visual Studio
Visual Studio Code
.NET Core CLI
Paket Yöneticisi konsol penceresinde:
> Diğer Windows paket> Yöneticisi konsolunugörüntüle ' ye gidin.
Apiconventions. csproj dosyasının bulunduğu dizine gidin.
Aşağıdaki komutu yürütün:

Install-Package Microsoft.AspNetCore.Mvc.Api.Analyzers

Web API kuralları için çözümleyiciler


Openapı belgeleri, bir eylemin döndürebildiği durum kodlarını ve yanıt türlerini içerir. ASP.NET Core MVC 'de,
ProducesResponseTypeAttribute ve ProducesAttribute gibi öznitelikler bir eylemi belgelemek için kullanılır.
ASP.NET Core Web API Yardım sayfaları ile Swagger / OpenapıWeb API 'nizi belgeleme hakkında daha fazla
ayrıntıya gider.
Paketteki çözümleyicilerden biri ile ApiControllerAttribute açıklanmış denetimleri inceler ve yanıtlarını tamamen
belgemeyen eylemleri tanımlar. Aşağıdaki örnek göz önünde bulundurun:

// GET api/contacts/{guid}
[HttpGet("{id}", Name = "GetById")]
[ProducesResponseType(typeof(Contact), StatusCodes.Status200OK)]
public IActionResult Get(string id)
{
var contact = _contacts.Get(id);

if (contact == null)
{
return NotFound();
}

return Ok(contact);
}

Yukarıdaki eylem HTTP 200 başarılı dönüş türünü belgeler, ancak HTTP 404 hata durumu kodunu belgeetmez.
Çözümleyici, HTTP 404 durum kodu için eksik belgeleri uyarı olarak bildirir. Sorunu gidermeye yönelik bir seçenek
sağlanır.

Ek kaynaklar
Web API 'SI kurallarını kullanma
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core ile Web API 'Leri oluşturma
Web API 'SI kurallarını kullanma
6.12.2019 • 5 minutes to read • Edit Online

, Pranav Krishnamoorthy ve Scott Ade tarafından


ASP.NET Core 2,2 ve üzeri, ortak API belgelerini ayıklamanızı ve bunu birden çok eyleme, denetleyiciye veya bir
derleme içindeki tüm denetleyicilere uygulamanıza yönelik bir yol içerir. Web API kuralları,
[ProducesResponseType] tek tek eylemleri dekorasyon bir yerdir.

Bir kural şunları yapmanıza olanak sağlar:


Belirli bir eylem türünden döndürülen en yaygın dönüş türlerini ve durum kodlarını tanımlayın.
Tanımlanan standartta saptacak eylemleri belirler.
ASP.NET Core MVC 2,2 ve üzeri, Microsoft.AspNetCore.Mvc.DefaultApiConventionsbir dizi varsayılan kural
içerir. Kurallar ASP.NET Core API proje şablonunda belirtilen denetleyiciyi ( ValuesController.cs) temel alır.
Eylemleriniz şablondaki desenleri izledikten sonra varsayılan kuralları kullanarak başarılı olmanız gerekir.
Varsayılan kurallar ihtiyaçlarınızı karşılamıyorsa, bkz. Web API kuralları oluşturma.
Çalışma zamanında Microsoft.AspNetCore.Mvc.ApiExplorer kuralları anlamıştır. ApiExplorer , Openapı (Swagger
olarak da bilinir) belge oluşturucuları ile iletişim kurmak için MVC 'nin soyutlamasıdır. Uygulanan kuraldaki
öznitelikler bir eylemle ilişkilendirilir ve eylemin Openapı belgelerine dahil edilir. API Çözümleyicileri , kuralları da
anlalar. Eyleminiz geleneksel değilse (örneğin, uygulanan kural tarafından belgelenmemiş bir durum kodu
döndürürse), durum kodunu belgeleyerek bir uyarı görürsünüz.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Web API 'SI kurallarını Uygula


Kurallar oluşturma; Her eylem, tam olarak bir kurala göre ilişkilendirilebilir. Daha belirgin kuralların daha az
belirli kurallara göre daha fazla olması. Aynı önceliğe sahip iki veya daha fazla kural bir eyleme uygulandığınızda
seçim belirleyici değildir. Aşağıdaki seçenekler, en çok belirli olan en az belirli bir eyleme bir kural uygulamak için
mevcuttur:
1. Microsoft.AspNetCore.Mvc.ApiConventionMethodAttribute — tek tek eylemler için geçerlidir ve kural türünü
ve uygulanan kural yöntemini belirtir.
Aşağıdaki örnekte, varsayılan kural türünün Microsoft.AspNetCore.Mvc.DefaultApiConventions.Put kuralı
yöntemi Update eylemine uygulanır:
// PUT api/contactsconvention/{guid}
[HttpPut("{id}")]
[ApiConventionMethod(typeof(DefaultApiConventions),
nameof(DefaultApiConventions.Put))]
public IActionResult Update(string id, Contact contact)
{
var contactToUpdate = _contacts.Get(id);

if (contactToUpdate == null)
{
return NotFound();
}

_contacts.Update(contact);

return NoContent();
}

Microsoft.AspNetCore.Mvc.DefaultApiConventions.Put Convention yöntemi eyleme aşağıdaki öznitelikleri


uygular:

[ProducesDefaultResponseType]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]

[ProducesDefaultResponseType] hakkında daha fazla bilgi için bkz. Varsayılan Yanıt.


2. bir denetleyiciye uygulanan Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute , belirtilen kural türünü
denetleyicideki tüm eylemlere uygular —. Kural yöntemi, kural yönteminin uygulandığı eylemleri
belirleyen ipuçlarıyla işaretlenir. İpuçları hakkında daha fazla bilgi için bkz. Web API kuralları oluşturma).
Aşağıdaki örnekte, varsayılan kurallar kümesi ContactsConventionControlleriçindeki tüm eylemlere
uygulanır:

[ApiController]
[ApiConventionType(typeof(DefaultApiConventions))]
[Route("api/[controller]")]
public class ContactsConventionController : ControllerBase
{

3. bir derlemeye uygulanan Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute , belirtilen kural türünü


geçerli derlemedeki tüm denetleyicilere uygular —. Öneri olarak, Startup.cs dosyasına derleme düzeyi
öznitelikleri uygulayın.
Aşağıdaki örnekte, varsayılan kural kümesi derlemedeki tüm denetleyicilere uygulanır:

[assembly: ApiConventionType(typeof(DefaultApiConventions))]
namespace ApiConventions
{
public class Startup
{

Web API kuralları oluşturma


Varsayılan API kuralları gereksinimlerinizi karşılamıyorsa, kendi kurallarınızı oluşturun. Bir kural:
Metotları olan statik bir tür.
Eylemlerde Yanıt türleri ve adlandırma gereksinimleri tanımlama özelliğine sahiptir.
Yanıt türleri
Bu yöntemlere [ProducesResponseType] veya [ProducesDefaultResponseType] öznitelikleriyle açıklama eklenir.
Örneğin:

public static class MyAppConventions


{
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public static void Find(int id)
{
}
}

Daha özel meta veri öznitelikleri yoksa, bu kuralı bir derlemeye uygulamak şunları uygular:
Kural yöntemi, Find adlı tüm eylemler için geçerlidir.
Find eyleminde id adlı bir parametre var.

Adlandırma gereksinimleri
[ApiConventionNameMatch] ve [ApiConventionTypeMatch] öznitelikleri, uygulandıkları eylemleri belirleyen kural
yöntemine uygulanabilir. Örneğin:

[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
public static void Find(
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
int id)
{ }

Yukarıdaki örnekte:
Yöntemine uygulanan Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior.Prefix seçeneği,
kuralının "Find" önekini ön eki eklenmiş herhangi bir eylem ile eşleştiğini gösterir. Eşleşen eylemlere örnek
olarak Find , FindPet ve FindById verilebilir.
Parametreye uygulanan Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior.Suffix ,
yöntemin sonek tanımlayıcısında biten tek bir parametreye sahip yöntemlerle eşleştiğini gösterir. Örnekler
id veya petId gibi parametreleri içerir. parametre türünü kısıtlamak için ApiConventionTypeMatch benzer
şekilde türlere uygulanabilir. params[] bağımsız değişkeni, açıkça eşleştirilmesinin gerekli olmadığı kalan
parametreleri gösterir.

Ek kaynaklar
Web API Çözümleyicileri kullanma
ASP.NET Core Web API Yardım sayfaları ile Swagger / Openapı
ASP.NET Core Web API 'Lerinde hataları işleme
10.12.2019 • 9 minutes to read • Edit Online

Bu makalede, ASP.NET Core Web API 'Leriyle hata işlemenin nasıl işleneceği ve özelleştirileceği açıklanır.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Geliştirici özel durum sayfası


Geliştirici özel durum sayfası , sunucu hataları için ayrıntılı yığın izlemeleri almak için kullanışlı bir araçtır. HTTP
ardışık düzeninde zaman uyumlu ve zaman uyumsuz özel durumları yakalamak ve hata yanıtları oluşturmak için
DeveloperExceptionPageMiddleware kullanır. Göstermek için aşağıdaki denetleyici eylemini göz önünde
bulundurun:

[HttpGet("{city}")]
public WeatherForecast Get(string city)
{
if (!string.Equals(city?.TrimEnd(), "Redmond", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(
$"We don't offer a weather forecast for {city}.", nameof(city));
}

return GetWeather().First();
}

Önceki eylemi test etmek için aşağıdaki curl komutunu çalıştırın:

curl -i https://localhost:5001/weatherforecast/chicago

ASP.NET Core 3,0 ve üzeri sürümlerde geliştirici özel durum sayfasında, istemci HTML biçimli çıkış isteğinde
yoksa bir düz metin yanıtı görüntülenir. Şu çıktı görünür:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/plain
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:13:16 GMT

System.ArgumentException: We don't offer a weather forecast for chicago. (Parameter 'city')


at WebApiSample.Controllers.WeatherForecastController.Get(String city) in
C:\working_folder\aspnet\AspNetCore.Docs\aspnetcore\web-api\handle-
errors\samples\3.x\Controllers\WeatherForecastController.cs:line 34
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTyp
eMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.
<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.
<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope
scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed
context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object&
state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope,
Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker
invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task
requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Host: localhost:44312
User-Agent: curl/7.55.1

Bunun yerine HTML biçimli bir yanıt göstermek için Accept HTTP istek üst bilgisini text/html medya türüne
ayarlayın. Örneğin:

curl -i -H "Accept: text/html" https://localhost:5001/weatherforecast/chicago

HTTP yanıtından aşağıdaki alıntıyı göz önünde bulundurun:


ASP.NET Core 2,2 ve önceki sürümlerde, geliştirici özel durum sayfasında HTML biçimli bir yanıt görüntülenir.
Örneğin, HTTP yanıtından aşağıdaki alıntıyı göz önünde bulundurun:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:55:37 GMT

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
background-color: #fff;
}

HTML biçimli yanıt Postman gibi araçlar aracılığıyla test edilirken yararlı olur. Aşağıdaki ekran yakalama, Postman
'daki düz metin ve HTML biçimli yanıtları gösterir:

WARNING
Geliştirici özel durum sayfasını yalnızca uygulama geliştirme ortamında çalışırkenetkinleştirin. Uygulama üretimde
çalıştırıldığında ayrıntılı özel durum bilgilerini herkese açık bir şekilde paylaşmak istemezsiniz. Ortamları yapılandırma hakkında
daha fazla bilgi için bkz. ASP.NET Core çoklu ortamları kullanma.

Özel durum işleyicisi


Geliştirme dışı ortamlarda, özel durum Işleme ara yazılımı bir hata yükü oluşturmak için kullanılabilir:
1. Startup.Configure ' de, ara yazılımı kullanmak için UseExceptionHandler çağırın:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}

app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseMvc();
}

2. /error yoluna yanıt vermek için bir denetleyici eylemi yapılandırın:

[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error")]
public IActionResult Error() => Problem();
}
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error")]
public ActionResult Error([FromServices] IHostingEnvironment webHostEnvironment)
{
var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
var ex = feature?.Error;
var isDev = webHostEnvironment.IsDevelopment();
var problemDetails = new ProblemDetails
{
Status = (int)HttpStatusCode.InternalServerError,
Instance = feature?.Path,
Title = isDev ? $"{ex.GetType().Name}: {ex.Message}" : "An error occurred.",
Detail = isDev ? ex.StackTrace : null,
};

return StatusCode(problemDetails.Status.Value, problemDetails);


}
}

Yukarıdaki Error eylemi istemciye RFC 7807ile uyumlu bir yük gönderir.
Özel durum Işleme ara yazılımı, yerel geliştirme ortamında daha ayrıntılı içerik üzerinde anlaşılan çıkış de
sağlayabilir. Geliştirme ve üretim ortamları genelinde tutarlı bir yük biçimi oluşturmak için aşağıdaki adımları
kullanın:
1. Startup.Configure , ortama özgü özel durum Işleme ara yazılım örneklerini kaydedin:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseExceptionHandler("/error-local-development");
}
else
{
app.UseExceptionHandler("/error");
}
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseExceptionHandler("/error-local-development");
}
else
{
app.UseExceptionHandler("/error");
}
}

Yukarıdaki kodda, ara yazılım ile kaydedilir:


Geliştirme ortamında /error-local-development yolu.
Geliştirmeyen ortamlarda /error yolu.
2. Denetleyici eylemlerine öznitelik yönlendirmeyi Uygula:
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}

var context = HttpContext.Features.Get<IExceptionHandlerFeature>();

return Problem(
detail: context.Error.StackTrace,
title: context.Error.Message);
}

[Route("/error")]
public IActionResult Error() => Problem();
}
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IHostingEnvironment webHostEnvironment)
{
if (!webHostEnvironment.IsDevelopment())
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}

var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();


var ex = feature?.Error;

var problemDetails = new ProblemDetails


{
Status = (int)HttpStatusCode.InternalServerError,
Instance = feature?.Path,
Title = ex.GetType().Name,
Detail = ex.StackTrace,
};

return StatusCode(problemDetails.Status.Value, problemDetails);


}

[Route("/error")]
public ActionResult Error(
[FromServices] IHostingEnvironment webHostEnvironment)
{
var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
var ex = feature?.Error;
var isDev = webHostEnvironment.IsDevelopment();
var problemDetails = new ProblemDetails
{
Status = (int)HttpStatusCode.InternalServerError,
Instance = feature?.Path,
Title = isDev ? $"{ex.GetType().Name}: {ex.Message}" : "An error occurred.",
Detail = isDev ? ex.StackTrace : null,
};

return StatusCode(problemDetails.Status.Value, problemDetails);


}
}

Yanıtı değiştirmek için özel durumları kullanın


Yanıtın içeriği, denetleyicinin dışından değiştirilebilir. ASP.NET 4. x Web API 'sinde, bunu yapmanın bir yolu
HttpResponseException türünü kullanmaktır. ASP.NET Core eşdeğer bir tür içermez. HttpResponseException için
destek aşağıdaki adımlarla eklenebilir:
1. HttpResponseException adlı iyi bilinen bir özel durum türü oluşturun:

public class HttpResponseException : Exception


{
public int Status { get; set; } = 500;

public object Value { get; set; }


}

2. HttpResponseExceptionFilter adlı bir eylem filtresi oluşturun:


public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; set; } = int.MaxValue - 10;

public void OnActionExecuting(ActionExecutingContext context) { }

public void OnActionExecuted(ActionExecutedContext context)


{
if (context.Exception is HttpResponseException exception)
{
context.Result = new ObjectResult(exception.Value)
{
StatusCode = exception.Status,
};
context.ExceptionHandled = true;
}
}
}

3. Startup.ConfigureServices , filtre koleksiyonuna eylem filtresini ekleyin:

services.AddControllers(options =>
options.Filters.Add(new HttpResponseExceptionFilter()));

services.AddMvc(options =>
options.Filters.Add(new HttpResponseExceptionFilter()))
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddMvc(options =>
options.Filters.Add(new HttpResponseExceptionFilter()))
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Doğrulama hatası hata yanıtı


Web API denetleyicileri için,, model doğrulama başarısız olduğunda MVC bir ValidationProblemDetails yanıt
türüyle yanıt verir. MVC, bir doğrulama hatasına yönelik hata yanıtını oluşturmak için
InvalidModelStateResponseFactory sonuçlarını kullanır. Aşağıdaki örnek, varsayılan yanıt türünü
Startup.ConfigureServices SerializableError olarak değiştirmek için fabrikası kullanır:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);

// TODO: add `using using System.Net.Mime;` to resolve MediaTypeNames


result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);

return result;
};
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);

// TODO: add `using using System.Net.Mime;` to resolve MediaTypeNames


result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);

return result;
};
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);

// TODO: add `using using System.Net.Mime;` to resolve MediaTypeNames


result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);

return result;
};
});

İstemci hata yanıtı


Bir hata sonucu , 400 veya ÜZERI bir http durum kodu ile sonuç olarak tanımlanır. Web API denetleyicileri için,
MVC bir hata sonucunu ProblemDetailsbir sonuçla dönüştürür.

IMPORTANT
ASP.NET Core 2,1, neredeyse RFC 7807 uyumlu olan bir sorun ayrıntıları yanıtı üretir. Yüzde 100 uyumluluğu önemliyse,
projeyi ASP.NET Core 2,2 veya üzeri bir sürüme yükseltin.

Hata yanıtı aşağıdaki yollarla yapılandırılabilir:


1. Problemayrıntılar Fabrikası Uygulama
2. ApiBehaviorOptions. ClientErrorMapping kullanın
Problemayrıntılar Fabrikası Uygulama
MVC, tüm ProblemDetails ve ValidationProblemDetailsörneklerini üretmek için
Microsoft.AspNetCore.Mvc.ProblemDetailsFactory kullanır. Buna istemci hata yanıtları, doğrulama hatası hata
yanıtları ve Microsoft.AspNetCore.Mvc.ControllerBase.Problem ve ValidationProblem() yardımcı yöntemler dahildir.
Sorun ayrıntıları yanıtını özelleştirmek için Startup.ConfigureServices``ProblemDetailsFactory özel bir
uygulamasını kaydedin:
public void ConfigureServices(IServiceCollection serviceCollection)
{
services.AddControllers();
services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
}

Hata yanıtı, Use ApiBehaviorOptions. ClientErrorMapping bölümünde özetlenen şekilde yapılandırılabilir.


ApiBehaviorOptions. ClientErrorMapping kullanın
ProblemDetails yanıtının içeriğini yapılandırmak için ClientErrorMapping özelliğini kullanın. Örneğin,
Startup.ConfigureServices aşağıdaki kod 404 yanıtları için type özelliğini güncelleştirir:

services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});
HTTP REPL ile Web API 'Lerini test etme
3.12.2019 • 30 minutes to read • Edit Online

Scott Ade tarafından


HTTP okuma-değerlendirme-yazdırma döngüsü (REPL ):
.NET Core 'un her yerde desteklenen basit, platformlar arası bir komut satırı aracı desteklenir.
ASP.NET Core Web API 'Lerini (ve non-ASP.NET çekirdek Web API 'Leri) test etmek ve sonuçlarını
görüntülemek için kullanılır.
Localhost ve Azure App Service dahil olmak üzere herhangi bir ortamda barındırılan Web API 'Lerini test etme
özelliğine sahiptir.
Aşağıdaki http fiilleri desteklenir:
SILMELI
Al
BAŞLı
Seçenekler
DÜZELTMESI
Yayınla
KONUR
Takip etmek için, örnek ASP.NET Core Web API 'sini (indirme) görüntüleyin veya indirin.

Prerequisites
.NET core 2.1 SDK veya üzeri

Yükleme
HTTP REPL 'u yüklemek için aşağıdaki komutu çalıştırın:

dotnet tool install -g Microsoft.dotnet-httprepl

.NET Core küresel aracı , Microsoft. DotNet-httprepl NuGet paketinden yüklenir.

Kullanım
Aracın başarıyla yüklenmesinden sonra, HTTP REPL 'u başlatmak için aşağıdaki komutu çalıştırın:

httprepl

Kullanılabilir HTTP REPL komutlarını görüntülemek için aşağıdaki komutlardan birini çalıştırın:

httprepl -h
httprepl --help

Aşağıdaki çıktı görüntülenir:

Usage:
httprepl [<BASE_ADDRESS>] [options]

Arguments:
<BASE_ADDRESS> - The initial base address for the REPL.

Options:
-h|--help - Show help information.

Once the REPL starts, these commands are valid:

Setup Commands:
Use these commands to configure the tool for your API server

connect Configures the directory structure and base address of the api server
set header Sets or clears a header for all requests. e.g. `set header content-type application/json`

HTTP Commands:
Use these commands to execute requests against your application.

GET get - Issues a GET request


POST post - Issues a POST request
PUT put - Issues a PUT request
DELETE delete - Issues a DELETE request
PATCH patch - Issues a PATCH request
HEAD head - Issues a HEAD request
OPTIONS options - Issues a OPTIONS request

Navigation Commands:
The REPL allows you to navigate your URL space and focus on specific APIs that you are working on.

set base Set the base URI. e.g. `set base http://locahost:5000`
ls Show all endpoints for the current path
cd Append the given directory to the currently selected path, or move up a path when using `cd ..`

Shell Commands:
Use these commands to interact with the REPL shell.

clear Removes all text from the shell


echo [on/off] Turns request echoing on or off, show the request that was made when using request commands
exit Exit the shell

REPL Customization Commands:


Use these commands to customize the REPL behavior.

pref [get/set] Allows viewing or changing preferences, e.g. 'pref set editor.command.default 'C:\\Program
Files\\Microsoft VS Code\\Code.exe'`
run Runs the script at the given path. A script is a set of commands that can be typed with one
command per line
ui Displays the Swagger UI page, if available, in the default browser

Use `help <COMMAND>` for more detail on an individual command. e.g. `help get`.
For detailed tool info, see https://aka.ms/http-repl-doc.

HTTP REPL komut tamamlama sağlar. Sekme tuşuna basıldığında, yazdığınız KARAKTERLERI veya API uç
noktasını tamamlayacak komutların listesi üzerinden yinelenir. Aşağıdaki bölümlerde kullanılabilir CLı komutları
ana hatlarıyla verilmiştir.

Web API 'sine bağlanma


Aşağıdaki komutu çalıştırarak bir Web API 'sine bağlanın:

httprepl <ROOT URI>

<ROOT URI> , Web API 'sinin temel URI 'sidir.Örneğin:

httprepl https://localhost:5001

Alternatif olarak, HTTP REPL çalışırken istediğiniz zaman aşağıdaki komutu çalıştırın:

connect <ROOT URI>

Örneğin:

(Disconnected)~ connect https://localhost:5001

Web API 'SI için Swagger belgesine el ile işaret edin


Yukarıdaki Connect komutu Swagger belgesini otomatik olarak bulmaya çalışacaktır. Bir nedenden dolayı
yapamaması durumunda, --swagger seçeneğini kullanarak Web API 'SI için Swagger belgesinin URI 'sini
belirtebilirsiniz:

connect <ROOT URI> --swagger <SWAGGER URI>

Örneğin:

(Disconnected)~ connect https://localhost:5001 --swagger /swagger/v1/swagger.json

Web API 'sinde gezin


Kullanılabilir uç noktaları görüntüle
Web API adresinin geçerli yolundaki farklı uç noktaları (denetleyiciler) listelemek için ls veya dir komutunu
çalıştırın:

https://localhot:5001/~ ls

Aşağıdaki çıkış biçimi görüntülenir:

. []
Fruits [get|post]
People [get|post]

https://localhost:5001/~

Yukarıdaki çıkış iki denetleyicinin bulunduğunu gösterir: Fruits ve People . Her iki denetleyici de parametresiz
HTTP GET ve POST işlemlerini destekler.
Belirli bir denetleyicide gezinmek daha ayrıntılı bilgi gösterir. Örneğin, aşağıdaki komut çıktısı, Fruits
denetleyicisinin HTTP GET, PUT ve DELETE işlemlerini de desteklediğini gösterir. Bu işlemlerin her biri, rotada bir
id parametresi bekler:

https://localhost:5001/fruits~ ls
. [get|post]
.. []
{id} [get|put|delete]

https://localhost:5001/fruits~

Alternatif olarak, Web API 'sinin Swagger Kullanıcı Arabirimi sayfasını bir tarayıcıda açmak için ui komutunu
çalıştırın. Örneğin:

https://localhost:5001/~ ui

Bir uç noktaya gitme


Web API 'sindeki farklı bir uç noktaya gitmek için cd komutunu çalıştırın:

https://localhost:5001/~ cd people

cd komutundan sonraki yol büyük/küçük harfe duyarlıdır. Aşağıdaki çıkış biçimi görüntülenir:

/people [get|post]

https://localhost:5001/people~

HTTP REPL 'ı özelleştirme


HTTP REPL 'un varsayılan renkleri özelleştirilebilir. Ayrıca, varsayılan bir metin Düzenleyicisi tanımlanabilir. HTTP
REPL tercihleri geçerli oturum genelinde kalıcı hale getirilir ve gelecekteki oturumlarda kabul edilir. Değiştirildikten
sonra, Tercihler aşağıdaki dosyada depolanır:
'Un
macOS
Windows
% GIRIŞ%/. httpreplprefs
. Httpreplprefs dosyası başlangıçta yüklendi ve çalışma zamanında değişiklikler için izlenmiyor. Dosyada el ile
yapılan değişiklikler yalnızca araç yeniden başlatıldıktan sonra devreye girer.
Ayarları görüntüleyin
Kullanılabilir ayarları görüntülemek için pref get komutunu çalıştırın. Örneğin:

https://localhost:5001/~ pref get

Yukarıdaki komut, kullanılabilir anahtar-değer çiftlerini görüntüler:


colors.json=Green
colors.json.arrayBrace=BoldCyan
colors.json.comma=BoldYellow
colors.json.name=BoldMagenta
colors.json.nameSeparator=BoldWhite
colors.json.objectBrace=Cyan
colors.protocol=BoldGreen
colors.status=BoldYellow

Renk tercihlerini ayarla


Yanıt renklendirme Şu anda yalnızca JSON için destekleniyor. Varsayılan HTTP REPL aracı renklendirmesini
özelleştirmek için, değiştirilecek renge karşılık gelen anahtarı bulun. Anahtarları bulma hakkında yönergeler için
bkz. ayarları görüntüleme bölümü. Örneğin, Green colors.json anahtar değerini aşağıdaki gibi White olarak
değiştirin:

https://localhost:5001/people~ pref set colors.json White

Yalnızca izin verilen renkler kullanılabilir. Sonraki HTTP istekleri, yeni renklendirmesi ile çıktıyı görüntüler.
Belirli renk anahtarları ayarlanmamışsa, daha genel anahtarlar kabul edilir. Bu geri dönüş davranışını göstermek
için aşağıdaki örneği göz önünde bulundurun:
colors.json.name bir değere sahip değilse, colors.json.string kullanılır.
colors.json.string bir değere sahip değilse, colors.json.literal kullanılır.
colors.json.literal bir değere sahip değilse, colors.json kullanılır.
colors.json bir değere sahip değilse, komut kabuğun varsayılan metin rengi ( AllowedColors.None ) kullanılır.

Girinti boyutunu ayarla


Yanıt girintileme boyut özelleştirmesi Şu anda yalnızca JSON için destekleniyor. Varsayılan boyut iki boşluklardan
oluşamaz. Örneğin:

[
{
"id": 1,
"name": "Apple"
},
{
"id": 2,
"name": "Orange"
},
{
"id": 3,
"name": "Strawberry"
}
]

Varsayılan boyutu değiştirmek için formatting.json.indentSize anahtarını ayarlayın. Örneğin, her zaman dört
boşluk kullanmak için:

pref set formatting.json.indentSize 4

Sonraki yanıtlar dört boşluk ayarına uyar:


[
{
"id": 1,
"name": "Apple"
},
{
"id": 2,
"name": "Orange"
},
{
"id": 3,
"name": "Strawberry"
}
]

Varsayılan metin düzenleyiciyi ayarlama


Varsayılan olarak, HTTP REPL 'un kullanılmak üzere yapılandırılmış metin Düzenleyicisi yok. HTTP istek gövdesi
gerektiren Web API yöntemlerini test etmek için varsayılan metin Düzenleyicisi ayarlanmalıdır. HTTP REPL Aracı,
istek gövdesini oluşturma amacıyla yapılandırılmış metin düzenleyicisini başlatır. Tercih ettiğiniz metin düzenleyiciyi
varsayılan olarak ayarlamak için aşağıdaki komutu çalıştırın:

pref set editor.command.default "<EXECUTABLE>"

Yukarıdaki komutta, <EXECUTABLE> metin düzenleyicisinin yürütülebilir dosyasının tam yoludur. Örneğin, Visual
Studio Code varsayılan metin düzenleyicisi olarak ayarlamak için aşağıdaki komutu çalıştırın:
'Un
macOS
Windows

pref set editor.command.default "/usr/bin/code"

Varsayılan metin düzenleyiciyi belirli CLı bağımsız değişkenleriyle başlatmak için editor.command.default.arguments
anahtarını ayarlayın. Örneğin, Visual Studio Code varsayılan metin Düzenleyicisi olduğunu ve her zaman HTTP
REPL 'un uzantıları devre dışı bırakılmış yeni bir oturumda Visual Studio Code açmasını istediğinizi varsayalım. Şu
komutu çalıştırın:

pref set editor.command.default.arguments "--disable-extensions --new-window"

Swagger arama yollarını ayarla


Varsayılan olarak, HTTP REPL, --swagger seçeneği olmadan connect komutunu yürütürken Swagger belgesini
bulmak için kullandığı bir göreli yollar kümesine sahiptir. Bu göreli yollar, connect komutunda belirtilen kök ve
taban yollarla birleştirilir. Varsayılan göreli yollar şunlardır:
Swagger. JSON
Swagger/v1/Swagger. JSON
/swagger.json
/swagger/v1/swagger.json
Ortamınızda farklı bir arama yolları kümesi kullanmak için swagger.searchPaths tercihini ayarlayın. Değer, göreli
yolların kanal ile ayrılmış bir listesi olmalıdır. Örneğin:
pref set swagger.searchPaths "swagger/v2/swagger.json|swagger/v3/swagger.json"

HTTP GET isteklerini test etme


Özeti

get <PARAMETER> [-F|--no-formatting] [-h|--header] [--response] [--response:body] [--response:headers] [-s|--


streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
get komutu için aşağıdaki seçenekler kullanılabilir:

-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.


Örnek
HTTP GET isteği vermek için:
1. get komutunu bunu destekleyen bir uç noktada çalıştırın:

https://localhost:5001/people~ get

Yukarıdaki komut aşağıdaki çıkış biçimini görüntüler:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Fri, 21 Jun 2019 03:38:45 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 1,
"name": "Scott Hunter"
},
{
"id": 2,
"name": "Scott Hanselman"
},
{
"id": 3,
"name": "Scott Guthrie"
}
]

https://localhost:5001/people~

2. get komutuna bir parametre geçirerek belirli bir kaydı alın:

https://localhost:5001/people~ get 2

Yukarıdaki komut aşağıdaki çıkış biçimini görüntüler:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Fri, 21 Jun 2019 06:17:57 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 2,
"name": "Scott Hanselman"
}
]

https://localhost:5001/people~

HTTP POST isteklerini test et


Özeti

post <PARAMETER> [-c|--content] [-f|--file] [-h|--header] [--no-body] [-F|--no-formatting] [--response] [--


response:body] [--response:headers] [-s|--streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.


-c|--content

Bir satır içi HTTP isteği gövdesinin sağlar. Örneğin: -c "{ 'id': 2, 'name': 'Cherry' }" .
-f|--file

HTTP isteği gövdesinin içeren bir dosya için bir yol sağlar. Örneğin: -f "C:\request.json" .
--no-body

Hiç HTTP istek gövdesi gerekli olduğunu gösterir.


Örnek
HTTP POST isteği vermek için:
1. post komutunu bunu destekleyen bir uç noktada çalıştırın:

https://localhost:5001/people~ post -h Content-Type=application/json

Önceki komutta, Content-Type HTTP istek üst bilgisi bir istek gövdesi medya türü olan JSON belirten
şekilde ayarlanır. Varsayılan metin Düzenleyicisi, HTTP istek gövdesini temsil eden bir JSON şablonuyla bir .
tmp dosyası açar. Örneğin:

{
"id": 0,
"name": ""
}
TIP
Varsayılan metin düzenleyicisini ayarlamak için varsayılan metin düzenleyiciyi ayarlama bölümüne bakın.

2. JSON şablonunu model doğrulama gereksinimlerini karşılayacak şekilde değiştirin:

{
"id": 0,
"name": "Scott Addie"
}

3. . Tmp dosyasını kaydedin ve metin düzenleyicisini kapatın. Aşağıdaki çıktı komut kabuğu 'nda görünür:

HTTP/1.1 201 Created


Content-Type: application/json; charset=utf-8
Date: Thu, 27 Jun 2019 21:24:18 GMT
Location: https://localhost:5001/people/4
Server: Kestrel
Transfer-Encoding: chunked

{
"id": 4,
"name": "Scott Addie"
}

https://localhost:5001/people~

HTTP PUT isteklerini test etme


Özeti

put <PARAMETER> [-c|--content] [-f|--file] [-h|--header] [--no-body] [-F|--no-formatting] [--response] [--


response:body] [--response:headers] [-s|--streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.
--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.


-c|--content

Bir satır içi HTTP isteği gövdesinin sağlar. Örneğin: -c "{ 'id': 2, 'name': 'Cherry' }" .
-f|--file

HTTP isteği gövdesinin içeren bir dosya için bir yol sağlar. Örneğin: -f "C:\request.json" .
--no-body

Hiç HTTP istek gövdesi gerekli olduğunu gösterir.


Örnek
HTTP PUT isteği vermek için:
1. Isteğe bağlı: verileri değiştirmeden önce görüntülemek için get komutunu çalıştırın:

https://localhost:5001/fruits~ get
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 22 Jun 2019 00:07:32 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 1,
"data": "Apple"
},
{
"id": 2,
"data": "Orange"
},
{
"id": 3,
"data": "Strawberry"
}
]

2. Run the put command on an endpoint that supports it:

https://localhost:5001/fruits~ put 2 -h Content-Type=application/json

Önceki komutta, Content-Type HTTP istek üst bilgisi bir istek gövdesi medya türü olan JSON belirten
şekilde ayarlanır. Varsayılan metin Düzenleyicisi, HTTP istek gövdesini temsil eden bir JSON şablonuyla bir .
tmp dosyası açar. Örneğin:
{
"id": 0,
"name": ""
}

TIP
Varsayılan metin düzenleyicisini ayarlamak için varsayılan metin düzenleyiciyi ayarlama bölümüne bakın.

3. JSON şablonunu model doğrulama gereksinimlerini karşılayacak şekilde değiştirin:

{
"id": 2,
"name": "Cherry"
}

4. . Tmp dosyasını kaydedin ve metin düzenleyicisini kapatın. Aşağıdaki çıktı komut kabuğu 'nda görünür:

[main 2019-06-28T17:27:01.805Z] update#setState idle


HTTP/1.1 204 No Content
Date: Fri, 28 Jun 2019 17:28:21 GMT
Server: Kestrel

5. Isteğe bağlı: değişiklikleri görmek için bir get komutu verin. Örneğin, metin düzenleyicisinde "Chraz"
yazdıysanız, get aşağıdakileri döndürür:

https://localhost:5001/fruits~ get
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 22 Jun 2019 00:08:20 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 1,
"data": "Apple"
},
{
"id": 2,
"data": "Cherry"
},
{
"id": 3,
"data": "Strawberry"
}
]

https://localhost:5001/fruits~

HTTP SILME isteklerini test etme


Özeti
delete <PARAMETER> [-F|--no-formatting] [-h|--header] [--response] [--response:body] [--response:headers] [-s|-
-streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.


Örnek
HTTP SILME isteği vermek için:
1. Isteğe bağlı: verileri değiştirmeden önce görüntülemek için get komutunu çalıştırın:
https://localhost:5001/fruits~ get
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 22 Jun 2019 00:07:32 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 1,
"data": "Apple"
},
{
"id": 2,
"data": "Orange"
},
{
"id": 3,
"data": "Strawberry"
}
]

2. Run the delete command on an endpoint that supports it:

https://localhost:5001/fruits~ delete 2

Yukarıdaki komut aşağıdaki çıkış biçimini görüntüler:

HTTP/1.1 204 No Content


Date: Fri, 28 Jun 2019 17:36:42 GMT
Server: Kestrel

3. Isteğe bağlı: değişiklikleri görmek için bir get komutu verin. Bu örnekte, bir get aşağıdakini döndürür:

https://localhost:5001/fruits~ get
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sat, 22 Jun 2019 00:16:30 GMT
Server: Kestrel
Transfer-Encoding: chunked

[
{
"id": 1,
"data": "Apple"
},
{
"id": 3,
"data": "Strawberry"
}
]

https://localhost:5001/fruits~

HTTP PATCH isteklerini test etme


Özeti
patch <PARAMETER> [-c|--content] [-f|--file] [-h|--header] [--no-body] [-F|--no-formatting] [--response] [--
response:body] [--response:headers] [-s|--streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.


-c|--content

Bir satır içi HTTP isteği gövdesinin sağlar. Örneğin: -c "{ 'id': 2, 'name': 'Cherry' }" .
-f|--file

HTTP isteği gövdesinin içeren bir dosya için bir yol sağlar. Örneğin: -f "C:\request.json" .
--no-body

Hiç HTTP istek gövdesi gerekli olduğunu gösterir.

HTTP HEAD isteklerini test etme


Özeti

head <PARAMETER> [-F|--no-formatting] [-h|--header] [--response] [--response:body] [--response:headers] [-s|--


streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response

Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.

Sınama HTTP SEÇENEKLERI istekleri


Özeti

options <PARAMETER> [-F|--no-formatting] [-h|--header] [--response] [--response:body] [--response:headers] [-


s|--streaming]

Arguments
PARAMETER

Varsa, ilişkili denetleyici eylem yöntemi tarafından beklenen rota parametresi.


Seçenekler
-F|--no-formatting

HTTP yanıt biçimlendirme, varlığı bastırır bir bayrak.


-h|--header

Bir HTTP isteği üstbilgisini ayarlar. Aşağıdaki iki değer biçimleri desteklenir:
{header}={value}
{header}:{value}
--response
Bir dosya (üstbilgi ve gövde dahil) tüm HTTP yanıtı yazılması gerektiğini belirtir. Örneğin:
--response "C:\response.txt" . Dosya yoksa oluşturulur.

--response:body

Bir dosya HTTP yanıt gövdesinde yazılması gerektiğini belirtir. Örneğin: --response:body "C:\response.json"
. Dosya yoksa oluşturulur.
--response:headers

Bir dosya HTTP yanıt üstbilgilerinin yazılması gerektiğini belirtir. Örneğin:


--response:headers "C:\response.txt" . Dosya yoksa oluşturulur.

-s|--streaming

HTTP yanıtı akış, durum sağlayan bir bayrak.

HTTP istek üst bilgilerini ayarla


Bir HTTP istek üst bilgisi ayarlamak için aşağıdaki yaklaşımlardan birini kullanın:
HTTP isteğiyle satır içi ayarlayın. Örneğin:

https://localhost:5001/people~ post -h Content-Type=application/json

Önceki yaklaşımla, her ayrı HTTP istek üst bilgisi kendi -h seçeneğini gerektirir.
HTTP isteğini göndermeden önce ayarlayın. Örneğin:

https://localhost:5001/people~ set header Content-Type application/json

Bir isteği göndermeden önce üst bilgi ayarlanırken üst bilgi, komut kabuğu oturumunun süresi boyunca
ayarlanmış olarak kalır. Üstbilgiyi temizlemek için boş bir değer sağlayın. Örneğin:

https://localhost:5001/people~ set header Content-Type

Güvenli uç noktaları test et


HTTP REPL, HTTP istek üst bilgilerinin kullanımı aracılığıyla güvenli uç noktaların sınamasını destekler.
Desteklenen kimlik doğrulama ve yetkilendirme düzenlerine örnek olarak temel kimlik doğrulaması, JWT taşıyıcı
belirteçleri ve Özet kimlik doğrulaması verilebilir. Örneğin, aşağıdaki komutla bir uç noktaya bir taşıyıcı belirteci
gönderebilirsiniz:

set header Authorization "bearer <TOKEN VALUE>"

Azure 'da barındırılan bir uç noktaya erişmek veya azure REST APIkullanmak için bir taşıyıcı belirtecine ihtiyacınız
vardır. Azure CLIaracılığıyla Azure Aboneliğinize yönelik bir taşıyıcı belirteci almak için aşağıdaki adımları kullanın.
HTTP REPL, bir HTTP istek üstbilgisindeki taşıyıcı belirtecini ayarlar ve Azure App Service Web Apps listesini alır.
1. Azure 'da oturum açın:

az login
2. Aşağıdaki komutla abonelik KIMLIĞINIZI alın:

az account show --query id

3. Abonelik KIMLIĞINIZI kopyalayın ve şu komutu çalıştırın:

az account set --subscription "<SUBSCRIPTION ID>"

4. Aşağıdaki komutla taşıyıcı belirtecinizi alın:

az account get-access-token --query accessToken

5. HTTP REPL aracılığıyla Azure REST API bağlanma:

httprepl https://management.azure.com

6. Authorization HTTP istek üst bilgisini ayarlayın:

https://management.azure.com/> set header Authorization "bearer <ACCESS TOKEN>"

7. Aboneliğe gidin:

https://management.azure.com/> cd subscriptions/<SUBSCRIPTION ID>

8. Aboneliğinizin Azure App Service Web Apps bir listesini alın:

https://management.azure.com/subscriptions/{SUBSCRIPTION ID}> get providers/Microsoft.Web/sites?api-


version=2016-08-01

Aşağıdaki yanıt görüntülenir:

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 35948
Content-Type: application/json; charset=utf-8
Date: Thu, 19 Sep 2019 23:04:03 GMT
Expires: -1
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
x-ms-correlation-request-id: <em>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</em>
x-ms-original-request-ids: <em>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;xxxxxxxx-xxxx-xxxx-xxxx-
xxxxxxxxxxxx</em>
x-ms-ratelimit-remaining-subscription-reads: 11999
x-ms-request-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
x-ms-routing-request-id: WESTUS:xxxxxxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
{
"value": [
<AZURE RESOURCES LIST>
]
}
HTTP istek görüntüsünü değiştirme
Varsayılan olarak, gönderilmekte olan HTTP isteğinin görüntüsü bastırılır. Komut kabuğu oturumunun süresi
boyunca ilgili ayarı değiştirmek mümkündür.
İstek görüntülemesini etkinleştir
echo on komutunu çalıştırarak gönderilmekte olan HTTP isteğini görüntüleyin. Örneğin:

https://localhost:5001/people~ echo on
Request echoing is on

Geçerli oturumdaki sonraki HTTP istekleri, istek üst bilgilerini görüntüler. Örneğin:

https://localhost:5001/people~ post

[main 2019-06-28T18:50:11.930Z] update#setState idle


Request to https://localhost:5001...

POST /people HTTP/1.1


Content-Length: 41
Content-Type: application/json
User-Agent: HTTP-REPL

{
"id": 0,
"name": "Scott Addie"
}

Response from https://localhost:5001...

HTTP/1.1 201 Created


Content-Type: application/json; charset=utf-8
Date: Fri, 28 Jun 2019 18:50:21 GMT
Location: https://localhost:5001/people/4
Server: Kestrel
Transfer-Encoding: chunked

{
"id": 4,
"name": "Scott Addie"
}

https://localhost:5001/people~

İstek görüntüsünü devre dışı bırak


echo off komutu çalıştırılarak gönderilmekte olan HTTP isteğinin görüntülenmesini gizleyin. Örneğin:

https://localhost:5001/people~ echo off


Request echoing is off

Betik çalıştır
Aynı HTTP REPL komutları kümesini sıklıkla yürütüyorsanız bunları bir metin dosyasında depolamayı göz önünde
bulundurun. Dosyadaki komutlar, komut satırında el ile çalıştıranlarla aynı formu alır.Komutlar, run komutu
kullanılarak toplanmış bir biçimde yürütülebilir. Örneğin:
1. Yeni satır için ayrılmış komutlar kümesini içeren bir metin dosyası oluşturun. Göstermek için aşağıdaki
komutları içeren bir People-Script. txt dosyası düşünün:
set base https://localhost:5001
ls
cd People
ls
get 1

2. Metin dosyasının yolunu geçirerek run komutunu yürütün. Örneğin:

https://localhost:5001/~ run C:\http-repl-scripts\people-script.txt

Aşağıdaki çıktı görüntülenir:

https://localhost:5001/~ set base https://localhost:5001


Using swagger metadata from https://localhost:5001/swagger/v1/swagger.json

https://localhost:5001/~ ls
. []
Fruits [get|post]
People [get|post]

https://localhost:5001/~ cd People
/People [get|post]

https://localhost:5001/People~ ls
. [get|post]
.. []
{id} [get|put|delete]

https://localhost:5001/People~ get 1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Fri, 12 Jul 2019 19:20:10 GMT
Server: Kestrel
Transfer-Encoding: chunked

{
"id": 1,
"name": "Scott Hunter"
}

https://localhost:5001/People~

Çıktıyı temizle
HTTP REPL aracı tarafından komut kabuğu 'na yazılan tüm çıktıyı kaldırmak için clear veya cls komutunu
çalıştırın. Göstermek için komut kabuğu 'nun aşağıdaki çıktıyı içerdiğini düşünün:

httprepl https://localhost:5001
(Disconnected)~ set base "https://localhost:5001"
Using swagger metadata from https://localhost:5001/swagger/v1/swagger.json

https://localhost:5001/~ ls
. []
Fruits [get|post]
People [get|post]

https://localhost:5001/~
Çıktıyı temizlemek için aşağıdaki komutu çalıştırın:

https://localhost:5001/~ clear

Yukarıdaki komutu çalıştırdıktan sonra, komut kabuğu yalnızca şu çıktıyı içerir:

https://localhost:5001/~

Ek kaynaklar
REST API istekleri
HTTP REPL GitHub deposu
ASP.NET Core SignalR giriş
3.12.2019 • 3 minutes to read • Edit Online

SignalRnedir?
ASP.NET Core SignalR, uygulamalara gerçek zamanlı Web işlevselliği eklemeyi kolaylaştıran açık kaynaklı
bir kitaplıktır. Gerçek zamanlı Web işlevselliği, sunucu tarafı kodun anında istemcilere içerik
gönderebilmesine olanak sağlar.
SignalRiçin iyi adaylar:
Sunucudan yüksek frekanslı güncelleştirmeler gerektiren uygulamalar. Oyun, sosyal ağlar, oylama, açık
eksiltme, haritalar ve GPS uygulamaları örnekleri verilmiştir.
Panolar ve izleme uygulamaları. Şirket panoları, anlık satış güncelleştirmeleri veya seyahat uyarıları
örnekleri bulunur.
İşbirliğine dayalı uygulamalar. Beyaz tahta uygulamaları ve takım toplantısı yazılımı, işbirliğine dayalı
uygulamalara örnek olarak verilebilir.
Bildirimleri gerektiren uygulamalar. Sosyal ağlar, e-posta, sohbet, Oyunlar, seyahat uyarıları ve diğer
birçok uygulama kullanım bildirimleri.
SignalR, sunucudan istemciye uzak yordam çağrıları (RPC )oluşturmak IÇIN bir API sağlar. RPC 'ler, sunucu
tarafı .NET Core kodundan gelen istemcilerdeki JavaScript işlevlerini çağırır.
ASP.NET Core için SignalR bazı özellikler şunlardır:
Bağlantı yönetimini otomatik olarak işler.
Tüm bağlı istemcilere aynı anda iletiler gönderir. Örneğin, bir sohbet odası.
Belirli istemcilere veya istemci gruplarına iletiler gönderir.
Artan trafiği işleyecek şekilde ölçeklendirilir.
Kaynak, GitHub 'daki birSignalR deposundabarındırılır.

Taşımalar
SignalR gerçek zamanlı iletişimi (düzgün geri dönüş sırasıyla) işlemek için aşağıdaki teknikleri destekler:
WebSockets
Sunucu tarafından gönderilen olaylar
Uzun yoklama
SignalR, sunucu ve istemci özellikleri içinde en iyi taşıma yöntemini otomatik olarak seçer.

Merkezler
SignalR, istemciler ve sunucular arasında iletişim kurmak için hub 'lar kullanır.
Hub, bir istemcinin ve sunucunun birbirlerine Yöntemler çağırmasını sağlayan üst düzey bir işlem hattdır.
SignalR, makinenin sunucu sınırları genelinde dağıtımını otomatik olarak işler ve istemcilerin sunucuda
Yöntemler çağırmasını sağlar ve tam tersi de geçerlidir. Model bağlamayı sağlayan yöntemlere kesin olarak
yazılmış parametreler geçirebilirsiniz. SignalR iki yerleşik hub Protokolü sağlar: JSON tabanlı bir metin
Protokolü ve MessagePacktemelli bir ikili protokol. MessagePack genellikle JSON ile karşılaştırıldığında daha
küçük iletiler oluşturur. Daha eski tarayıcıların, MessagePack protokolü desteği sağlamak için XHR düzey 2 ' i
desteklemesi gerekir.
Hub 'lar, istemci tarafı yönteminin adını ve parametrelerini içeren iletiler göndererek istemci tarafı kodu
çağırır. Yöntem parametreleri olarak gönderilen nesneler, yapılandırılan protokol kullanılarak seri durumdan
çıkarılacak. İstemci, adı istemci tarafı koddaki bir yöntemle eşleştirmeye çalışır. İstemci bir eşleşme
bulduğunda, yöntemini çağırır ve seri durumdan çıkarılan parametre verilerine geçirir.

Ek kaynaklar
ASP.NET Core için SignalR kullanmaya başlama
Desteklenen Platformlar
Merkezler
JavaScript istemcisi
Desteklenen SignalR platformları ASP.NET Core
25.11.2019 • 2 minutes to read • Edit Online

Sunucu sistem gereksinimleri


ASP.NET Core için SignalR, ASP.NET Core desteklediği tüm sunucu platformunu destekler.

JavaScript istemcisi
JavaScript Istemcisi NodeJS 8 ve sonraki sürümlerde ve aşağıdaki tarayıcılarda çalışır:

BROWSER SÜRÜM

Microsoft Edge Geçerli†

Mozilla Firefox Geçerli†

Google Chrome; Android içerir Geçerli†

Uygulamasını iOS içerir Geçerli†

Microsoft Internet Explorer 11

†geçerli , tarayıcının en son sürümünü ifade eder.

.NET istemcisi
.Net Client , ASP.NET Core tarafından desteklenen herhangi bir platformda çalışır. Örneğin, Xamarin geliştiricileri,
Xamarin. iOS 8.4.0.1 ve üstünü kullanarak Android uygulamaları oluşturmak için SignalRkullanabilir ve Xamarin.
iOS 11.14.0.4 ve üstünü kullanarak iOS uygulamaları oluşturabilir.
Sunucu IIS çalıştırıyorsa, WebSockets aktarımı Windows Server 2012 veya üzeri sürümlerde IIS 8,0 veya sonraki
bir sürümü gerektirir. Diğer aktarımlar tüm platformlarda desteklenir.

Java istemcisi
Java istemcisi , Java 8 ve sonraki sürümlerini destekler.

Desteklenmeyen istemciler
Aşağıdaki istemciler mevcuttur, ancak deneysel veya resmi olmayan bir.Şu anda desteklenmemektedir ve hiçbir
şekilde bulunmayabilir.
C++istemcilerinin
Swift istemcisi
Öğretici: ASP.NET Core SignalR ile çalışmaya
başlama
26.11.2019 • 21 minutes to read • Edit Online

Bu öğreticide SignalRkullanarak gerçek zamanlı bir uygulama oluşturmanın temelleri öğretilir. Aşağıdakileri nasıl
yapacağınızı öğrenirsiniz:
Web projesi oluşturun.
SignalR istemci kitaplığı ekleyin.
SignalR hub 'ı oluşturun.
Projeyi SignalRkullanacak şekilde yapılandırın.
Herhangi bir istemciden tüm bağlı istemcilere ileti gönderen kodu ekleyin.
Sonunda, çalışan bir sohbet uygulamanız olacaktır:

Önkoşullar
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Web uygulaması projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Menüden dosya > yeni proje' yi seçin.
Yeni proje oluştur iletişim kutusunda ASP.NET Core Web uygulaması' nı seçin ve ardından İleri' yi
seçin.
Yeni projenizi yapılandırın iletişim kutusunda, proje signalrchatadını adlandırın ve ardından Oluştur' u
seçin.
Yeni bir ASP.NET Core Web uygulaması oluştur iletişim kutusunda .net Core ve ASP.NET Core 3,0' i
seçin.
Razor Pages kullanan bir proje oluşturmak için Web uygulaması ' nı seçin ve ardından Oluştur' u seçin.

SignalR istemci kitaplığı ekleme


SignalR sunucusu kitaplığı, ASP.NET Core 3,0 paylaşılan çerçevesine dahildir. JavaScript istemci kitaplığı projeye
otomatik olarak dahil değildir. Bu öğreticide, istemci kitaplığını unpkg'den almak Için kitaplık Yöneticisi 'Ni
(Libman) kullanacaksınız. unpkg, Node. js Paket Yöneticisi NPM 'de bulunan her şeyi teslim edebilen bir içerik
teslim ağı (CDN )).
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, projeye sağ tıklayın ve > Istemci tarafı kitaplığı Ekle ' yi seçin.
Istemci tarafı kitaplığı Ekle Iletişim kutusunda sağlayıcı için unpkgseçeneğini belirleyin.
Kitaplıkiçin @microsoft/signalr@latest girin.
Belirli dosyaları seç' i seçin, dağ/Browser klasörünü genişletin ve SignalR. js ve SignalR. min. js' yi seçin.
Hedef konumu Wwwroot/js/SignalR/ olarak ayarlayın ve yüklemeyiseçin.
LibMan, bir Wwwroot/js/SignalR klasörü oluşturur ve seçilen dosyaları buna kopyalar.

SignalR hub 'ı oluşturma


Hub , istemci-sunucu iletişimini işleyen yüksek düzeyli bir işlem hattı görevi gören bir sınıftır.
SignalRChat proje klasöründe bir hub klasörü oluşturun.
Hub 'lar klasöründe, aşağıdaki kodla bir ChatHub.cs dosyası oluşturun:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}

ChatHub sınıfı SignalR Hub sınıfından devralır. Hub sınıfı bağlantıları, grupları ve mesajlaşmayı yönetir.
SendMessage yöntemi, tüm istemcilere ileti göndermek için bağlı bir istemci tarafından çağrılabilir. Yöntemi
çağıran JavaScript istemci kodu Öğreticinin ilerleyen kısımlarında gösterilmektedir. SignalR kod, en fazla
ölçeklenebilirlik sağlamak için zaman uyumsuzdur.

SignalR Yapılandır
SignalR sunucusu, SignalRSignalR istekleri geçirilecek şekilde yapılandırılmalıdır.
Aşağıdaki Vurgulanan kodu Startup.cs dosyasına ekleyin.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;

namespace SignalRChat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSignalR();
}

// This method gets called by the runtime. Use this method to configure the HTTP request
pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production
scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chatHub");
});
}
}
}

Bu değişiklikler, ASP.NET Core bağımlılığı ekleme ve yönlendirme sistemlerine SignalR ekler.

SignalR istemci kodu ekle


Pages\ındex.cshtml içindeki içeriği şu kodla değiştirin:

@page
<div class="container">
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-2">User</div>
<div class="col-4"><input type="text" id="userInput" /></div>
</div>
<div class="row">
<div class="col-2">Message</div>
<div class="col-4"><input type="text" id="messageInput" /></div>
</div>
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-6">
<input type="button" id="sendButton" value="Send Message" />
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-6">
<ul id="messagesList"></ul>
</div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

Yukarıdaki kod:
Ad ve ileti metni ve Gönder düğmesi için metin kutuları oluşturur.
SignalR hub 'ından alınan iletileri görüntülemek için id="messagesList" içeren bir liste oluşturur.
Bir sonraki adımda oluşturduğunuz SignalR ve sohbet. js uygulama koduna yönelik betik başvurularını
içerir.
Wwwroot/js klasöründe, aşağıdaki kodla bir chat. js dosyası oluşturun:
"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established


document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {


var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});

connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {


var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});

Yukarıdaki kod:
Bir bağlantı oluşturur ve başlatır.
, Hub 'a ileti gönderen bir işleyiciye Gönder düğmesine ekler.
, Hub 'dan iletileri alan ve bunları listeye ekleyen bir işleyici olan bağlantı nesnesine ekler.

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamadan çalıştırmak için CTRL + F5 tuşlarına basın.
Adres çubuğundan URL 'yi kopyalayın, başka bir tarayıcı örneği veya sekme açın ve adres çubuğuna URL
'YI yapıştırın.
Tarayıcı ' yı seçin, bir ad ve ileti girin ve Ileti gönder düğmesini seçin.
Ad ve ileti anında her iki sayfada da görüntülenir.
TIP
Uygulama işe yaramazsa, tarayıcı geliştirici araçlarınızı (F12) açın ve konsola gidin. HTML ve JavaScript kodunuzla
ilgili hatalarla karşılaşabilirsiniz. Örneğin, SignalR. js ' yi yönlendirenden farklı bir klasöre yerleştirdiğinizi varsayalım.
Bu durumda, bu dosyaya başvuru çalışmaz ve konsolunda 404 hatası görürsünüz.

Chrome 'da hata ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY alırsanız, geliştirme sertifikanızı güncelleştirmek


için şu komutları çalıştırın:

dotnet dev-certs https --clean


dotnet dev-certs https --trust

Bu öğreticide SignalRkullanarak gerçek zamanlı bir uygulama oluşturmanın temelleri öğretilir. Aşağıdakileri nasıl
yapacağınızı öğrenirsiniz:
Web projesi oluşturun.
SignalR istemci kitaplığı ekleyin.
SignalR hub 'ı oluşturun.
Projeyi SignalRkullanacak şekilde yapılandırın.
Herhangi bir istemciden tüm bağlı istemcilere ileti gönderen kodu ekleyin.
Sonunda, çalışan bir sohbet uygulamasına sahipsiniz:
Önkoşullar
Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 2017 sürüm 15,9 veya üzeri ile ASP.NET ve web geliştirme iş yükü. Kullanabileceğiniz Visual
Studio 2019, ancak bazı proje oluşturma adımlarını öğreticide gösterilen öğesinden farklı.
.NET core SDK 2.2 veya üzeri

WARNING
Visual Studio 2017 kullanıyorsanız bkz dotnet/SDK'sı sorun #3124 Visual Studio ile çalışmayan .NET Core SDK sürümleri
hakkında bilgi için.

Bir web projesi oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Menüden dosya > yeni proje' yi seçin.
Yeni proje iletişim kutusunda, yüklü > Visual C# > Web > ASP.NET Core Web uygulaması' nı seçin.
Projeyi Signalrchatolarak adlandırın.
Razor Pages kullanan bir proje oluşturmak için Web uygulaması ' nı seçin.
.NET Core'un hedef çerçevesini seçin, ASP.NET Core 2,2' i seçin ve Tamam' ı tıklatın.

SignalR istemci kitaplığı ekleme


SignalR sunucusu kitaplığı, Microsoft.AspNetCore.App metapackage 'e dahildir. JavaScript istemci kitaplığı
projeye otomatik olarak dahil değildir. Bu öğreticide, istemci kitaplığını unpkg'den almak Için kitaplık Yöneticisi
'Ni (Libman) kullanacaksınız. unpkg, Node. js Paket Yöneticisi NPM 'de bulunan her şeyi teslim edebilen bir içerik
teslim ağı (CDN )).
Visual Studio
Visual Studio Code
Mac için Visual Studio
Çözüm Gezgini, projeye sağ tıklayın ve > Istemci tarafı kitaplığı Ekle ' yi seçin.
Istemci tarafı kitaplığı Ekle Iletişim kutusunda sağlayıcı için unpkgseçeneğini belirleyin.
Kitaplıkiçin @microsoft/signalr@3 girin ve Önizleme olmayan en son sürümü seçin.

Belirli dosyaları seç' i seçin, dağ/Browser klasörünü genişletin ve SignalR. js ve SignalR. min. js' yi seçin.
Hedef konumu Wwwroot/lib/SignalR/ olarak ayarlayın ve yüklemeyiseçin.

LibMan, bir Wwwroot/LIB/SignalR klasörü oluşturur ve seçilen dosyaları buna kopyalar.

SignalR hub 'ı oluşturma


Hub , istemci-sunucu iletişimini işleyen yüksek düzeyli bir işlem hattı görevi gören bir sınıftır.
SignalRChat proje klasöründe bir hub klasörü oluşturun.
Hub 'lar klasöründe, aşağıdaki kodla bir ChatHub.cs dosyası oluşturun:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}

ChatHub sınıfı SignalR Hub sınıfından devralır. Hub sınıfı bağlantıları, grupları ve mesajlaşmayı yönetir.
SendMessage yöntemi, tüm istemcilere ileti göndermek için bağlı bir istemci tarafından çağrılabilir. Yöntemi
çağıran JavaScript istemci kodu Öğreticinin ilerleyen kısımlarında gösterilmektedir. SignalR kod, en fazla
ölçeklenebilirlik sağlamak için zaman uyumsuzdur.

SignalR Yapılandır
SignalR sunucusu, SignalRSignalR istekleri geçirilecek şekilde yapılandırılmalıdır.
Aşağıdaki Vurgulanan kodu Startup.cs dosyasına ekleyin.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SignalRChat.Hubs;

namespace SignalRChat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for
a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddSignalR();
}

// This method gets called by the runtime. Use this method to configure the HTTP request
pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
app.UseMvc();
}
}
}

Bu değişiklikler, ASP.NET Core bağımlılık ekleme sistemine ve ara yazılım ardışık düzenine SignalR ekler.

SignalR istemci kodu ekle


Pages\ındex.cshtml içindeki içeriği şu kodla değiştirin:

@page
<div class="container">
<div class="row">&nbsp;</div>
<div class="row">
<div class="col-6">&nbsp;</div>
<div class="col-6">
User..........<input type="text" id="userInput" />
<br />
Message...<input type="text" id="messageInput" />
<input type="button" id="sendButton" value="Send Message" />
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-6">&nbsp;</div>
<div class="col-6">
<ul id="messagesList"></ul>
</div>
</div>
</div>
<script src="~/lib/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

Yukarıdaki kod:
Ad ve ileti metni ve Gönder düğmesi için metin kutuları oluşturur.
SignalR hub 'ından alınan iletileri görüntülemek için id="messagesList" içeren bir liste oluşturur.
Bir sonraki adımda oluşturduğunuz SignalR ve sohbet. js uygulama koduna yönelik betik başvurularını
içerir.
Wwwroot/js klasöründe, aşağıdaki kodla bir chat. js dosyası oluşturun:
"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established


document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {


var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});

connection.start().then(function(){
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {


var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});

Yukarıdaki kod:
Bir bağlantı oluşturur ve başlatır.
, Hub 'a ileti gönderen bir işleyiciye Gönder düğmesine ekler.
, Hub 'dan iletileri alan ve bunları listeye ekleyen bir işleyici olan bağlantı nesnesine ekler.

Uygulamayı çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Uygulamayı hata ayıklamadan çalıştırmak için CTRL + F5 tuşlarına basın.
Adres çubuğundan URL 'yi kopyalayın, başka bir tarayıcı örneği veya sekme açın ve adres çubuğuna URL
'YI yapıştırın.
Tarayıcı ' yı seçin, bir ad ve ileti girin ve Ileti gönder düğmesini seçin.
Ad ve ileti anında her iki sayfada da görüntülenir.
TIP
Uygulama işe yaramazsa, tarayıcı geliştirici araçlarınızı (F12) açın ve konsola gidin. HTML ve JavaScript kodunuzla ilgili
hatalarla karşılaşabilirsiniz. Örneğin, SignalR. js ' yi yönlendirenden farklı bir klasöre yerleştirdiğinizi varsayalım. Bu durumda,
bu dosyaya başvuru çalışmaz ve konsolunda 404 hatası görürsünüz.

Ek kaynaklar
Bu öğreticinin YouTube sürümü
TypeScript ve WebPack ile ASP.NET Core SignalR
kullanma
26.11.2019 • 34 minutes to read • Edit Online

, Sébastien Sougnez ve Scott Ade tarafından


WebPack , geliştiricilerin bir Web uygulamasının istemci tarafı kaynaklarını paketleyip oluşturmalarına olanak
sağlar. Bu öğretici, istemcisinin TypeScript'te yazıldığı bir ASP.NET Core SignalR Web uygulamasında WebPack 'in
kullanımını gösterir.
Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:
Bir başlatıcı ASP.NET Core SignalR uygulama için yapı iskelesi
SignalR TypeScript istemcisini yapılandırma
WebPack kullanarak derleme işlem hattı yapılandırma
SignalR sunucusunu yapılandırma
İstemci ve sunucu arasındaki iletişimi etkinleştir
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Önkoşullar
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core SDK 3,0 veya üzeri
NPM ile Node. js

ASP.NET Core Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio 'Yu, Path ortam değişkeninde NPM için arama yapmak üzere yapılandırın. Varsayılan olarak, Visual
Studio yükleme dizininde bulunan NPM sürümünü kullanır. Visual Studio 'da şu yönergeleri izleyin:
1. Web Paket Yönetimi > dış web araçları> > > Araçlar ve Seçenekler ' e gidin.
2. Listeden $ (yol) girişini seçin. Girdiyi listedeki ikinci konuma taşımak için yukarı oka tıklayın.
Visual Studio yapılandırması tamamlandı. Projeyi oluşturma zamanı.
1. Dosya > Yeni > projesi menü seçeneğini kullanın ve ASP.NET Core Web uygulaması şablonunu seçin.
2. Projeyi Signalrwebpackolarak adlandırın ve Oluştur' u seçin.
3. Hedef çerçeve açılır listesinden .NET Core ' u seçin ve çerçeve Seçicisi açılır listesinden ASP.NET Core 3,0 ' ı
seçin. Boş şablonu seçin ve Oluştur' u seçin.

WebPack ve TypeScript yapılandırma


Aşağıdaki adımlar, TypeScript 'in JavaScript 'e dönüştürülmesini ve istemci tarafı kaynaklarını paketlemeyi
yapılandırır.
1. Bir Package. JSON dosyası oluşturmak için proje kökünde aşağıdaki komutu yürütün:

npm init -y

2. Vurgulanan özelliği Package. JSON dosyasına ekleyin:

{
"name": "SignalRWebPack",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

private özelliğinin true olarak ayarlanması, sonraki adımda paket yükleme uyarılarını önler.
3. Gerekli NPM paketlerini yükler. Proje kökünden aşağıdaki komutu yürütün:
npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-
extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3

Aklınızda bazı komut ayrıntıları:


Sürüm numarası, her paket adı için @ işaretini izler. NPM bu özel paket sürümlerini yüklüyor.
-E seçeneği, NPM 'nin semantik sürüm aralığı işleçlerini Package. JSONöğesine yazmanın varsayılan
davranışını devre dışı bırakır. Örneğin, "webpack": "^4.29.3" yerine "webpack": "4.29.3" kullanılır. Bu
seçenek, daha yeni paket sürümlerine istenmeden yükseltme yapılmasını engeller.
Daha ayrıntılı bilgi için resmi NPM -Install docs bölümüne bakın.
4. Package. JSON dosyasının scripts özelliğini aşağıdaki kod parçacığıyla değiştirin:

"scripts": {
"build": "webpack --mode=development --watch",
"release": "webpack --mode=production",
"publish": "npm run release && dotnet publish -c Release"
},

Betiklerin bazı açıklamaları:


build : istemci tarafı kaynaklarınızı geliştirme modunda paketler ve dosya değişikliklerini izler. Dosya
izleyici, bir proje dosyası her değiştiğinde paketin yeniden oluşturulmasına neden olur. mode seçeneği,
Tree gerçekleşmesi ve minbirleşme gibi üretim iyileştirmeleri devre dışı bırakır. Yalnızca geliştirmede
build kullanın.
release : istemci tarafı kaynaklarınızı üretim modunda Paketlayın.
publish : release betiği, istemci tarafı kaynaklarını üretim modunda paketleyip çalıştırır. Uygulamayı
yayımlamak için .NET Core CLI Publish komutunu çağırır.
5. Aşağıdaki içeriğe sahip proje kökünde WebPack. config. jsadlı bir dosya oluşturun:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "wwwroot"),
filename: "[name].[chunkhash].js",
publicPath: "/"
},
resolve: {
extensions: [".js", ".ts"]
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new CleanWebpackPlugin(["wwwroot/*"]),
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css"
})
]
};

Yukarıdaki dosya Web paketi derlemesini yapılandırır. Aklınızda bazı yapılandırma ayrıntıları:
output özelliği, dağ'ın varsayılan değerini geçersiz kılar. Paket, Wwwroot dizininde yayınlanır.
resolve.extensions dizisi, SignalR istemci JavaScript 'ı içeri aktarmak için . js içerir.
6. Proje kökünde yeni bir src dizini oluşturun. Amaç, projenin istemci tarafı varlıklarını depolardır.
7. Aşağıdaki içerikle src/index.html oluşturun.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core SignalR</title>
</head>
<body>
<div id="divMessages" class="messages">
</div>
<div class="input-zone">
<label id="lblMessage" for="tbMessage">Message:</label>
<input id="tbMessage" class="input-zone-input" type="text" />
<button id="btnSend">Send</button>
</div>
</body>
</html>
Önceki HTML, giriş sayfasının ortak işaretlemesini tanımlar.
8. Yeni bir src/CSS dizini oluşturun. Amacı, projenin . css dosyalarını depolamadır.
9. Aşağıdaki içerikle src/CSS/Main. css oluşturun:

*, *::before, *::after {
box-sizing: border-box;
}

html, body {
margin: 0;
padding: 0;
}

.input-zone {
align-items: center;
display: flex;
flex-direction: row;
margin: 10px;
}

.input-zone-input {
flex: 1;
margin-right: 10px;
}

.message-author {
font-weight: bold;
}

.messages {
border: 1px solid #000;
margin: 10px;
max-height: 300px;
min-height: 300px;
overflow-y: auto;
padding: 5px;
}

Önceki Main. css dosyası uygulamayı stiller.


10. Şu içerikle src/tsconfig. JSON oluşturun:

{
"compilerOptions": {
"target": "es5"
}
}

Yukarıdaki kod, TypeScript derleyicisini ECMAScript 5 uyumlu JavaScript üretecek şekilde yapılandırır.
11. Aşağıdaki içeriğe sahip src/index. TS oluşturun:
import "./css/main.css";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Önceki TypeScript, DOM öğelerine başvuruları alır ve iki olay işleyicisini ekler:
keyup : Bu olay Kullanıcı metin kutusuna tbMessage olarak tanımlanan bir şeyi yazdığında ateşlenir.
send işlevi, Kullanıcı ENTER tuşuna bastığında çağrılır.
click : Kullanıcı Gönder düğmesine tıkladığında bu olay ateşlenir. send işlevi çağırılır.

ASP.NET Core uygulamasını yapılandırma


1. Startup.Configure yönteminde, Usedefaultfiles ve usestaticfilesöğesine çağrılar ekleyin.

app.UseRouting();
app.UseDefaultFiles();
app.UseStaticFiles();

Yukarıdaki kod, kullanıcının tam URL 'sini veya Web uygulamasının kök URL 'sini girmeksizin Dizin. html
dosyasını bulmasını ve sunmasını sağlar.
2. Startup.Configure yönteminin sonunda, bir /hub yolunu ChatHub hub 'ına eşleyin. Merhaba Dünya
görüntülenen kodu değiştirin ! Aşağıdaki satırla:

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/hub");
});

3. Startup.ConfigureServices yönteminde Addsignalröğesini çağırın. SignalR hizmetlerini projenize ekler.

services.AddSignalR();

4. Proje kökünde hubolarak adlandırılan yeni bir dizin oluşturun. Amacı, bir sonraki adımda oluşturulan
SignalR hub 'ını deposağlamaktır.
5. Aşağıdaki kodla hub hub 'ları/ChatHub. cs oluşturun:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
}
}

6. ChatHub başvurusunu çözümlemek için, Startup.cs dosyasının en üstüne aşağıdaki kodu ekleyin:

using SignalRWebPack.Hubs;

İstemci ve sunucu iletişimini etkinleştir


Uygulama Şu anda ileti göndermek için basit bir form görüntülüyor. Bunu yapmayı denediğinizde hiçbir şey olmaz.
Sunucu belirli bir yolu dinliyor, ancak gönderilen iletilerle hiçbir şey yapmıyor.
1. Proje kökünde aşağıdaki komutu yürütün:

npm install @microsoft/signalr

Yukarıdaki komut, istemcinin sunucuya ileti göndermesini sağlayan SignalR TypeScript istemcisiniyüklüyor.
2. Vurgulanan kodu src/index. TS dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@microsoft/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let m = document.createElement("div");

m.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Yukarıdaki kod, sunucudan ileti almayı destekler. HubConnectionBuilder sınıfı, sunucu bağlantısını
yapılandırmak için yeni bir Oluşturucu oluşturur. withUrl işlevi hub URL 'sini yapılandırır.
SignalR, istemci ile sunucu arasında ileti alışverişi yapılmasını mümkün. Her ileti belirli bir ada sahiptir.
Örneğin, ileti bölgesindeki yeni iletiyi görüntülemekten sorumlu mantığı çalıştıran messageReceived adına
sahip iletilere sahip olabilirsiniz. Belirli bir iletiyi dinlemek on işlevi aracılığıyla yapılabilir. Herhangi bir
sayıda ileti adını dinleyebilmeniz gerekir. Ayrıca, yazarın adı ve alınan iletinin içeriği gibi parametreleri iletiye
geçirmek da mümkündür. İstemci bir ileti aldıktan sonra yazarın adı ve innerHTML özniteliğinde ileti
içeriğiyle yeni bir div öğesi oluşturulur. Bu, iletileri görüntüleyen ana div öğesine eklenir.
3. Artık istemci bir ileti aldığına göre, ileti gönderecek şekilde yapılandırın. Vurgulanan kodu src/index. TS
dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let messageContainer = document.createElement("div");

messageContainer.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(messageContainer);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => tbMessage.value = "");
}

WebSockets bağlantısı aracılığıyla bir ileti gönderildiğinde send yönteminin çağrılması gerekir. Yöntemin ilk
parametresi ileti adıdır. İleti verileri diğer parametreleri geçersiz kılar. Bu örnekte, newMessage sunucusuna
gönderildiği gibi bir ileti gönderilir. İleti, bir metin kutusundan Kullanıcı adından ve Kullanıcı girişinden
oluşur. Gönderme işlemi çalışırsa metin kutusu değeri temizlenir.
4. Vurgulanan yöntemi ChatHub sınıfına ekleyin:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
public async Task NewMessage(long username, string message)
{
await Clients.All.SendAsync("messageReceived", username, message);
}
}
}

Yukarıdaki kod, sunucu onları aldıktan sonra tüm bağlı kullanıcılara ileti almış iletileri yayınlar. Tüm iletileri
almak için genel bir on yöntemi olması gereksizdir. İleti adından sonra adlandırılmış bir yöntem.
Bu örnekte, TypeScript istemcisi newMessage olarak tanımlanan bir ileti gönderir. C# NewMessage yöntemi,
istemci tarafından gönderilen verileri bekler. Istemcilerdeki sendadsync yöntemine bir çağrı yapılır. Alınan
iletiler, hub 'a bağlı tüm istemcilere gönderilir.

Uygulamayı test etme


Uygulamanın aşağıdaki adımlarla çalıştığından emin olun.
Visual Studio
Visual Studio Code
1. Web paketini yayın modunda çalıştırın. Paket Yöneticisi konsol penceresini kullanarak, proje kökünde
aşağıdaki komutu yürütün. Proje kökünde değilseniz, komutu girmeden önce cd SignalRWebPack girin.

npm run release

Bu komut, uygulamayı çalıştırırken alınacağı istemci-tarafı varlıkları verir. Varlıkları yerleştirilir wwwroot
klasör.
Web, aşağıdaki görevleri tamamlandı:
İçeriğini temizleneceği wwwroot dizin.
JavaScript için TypeScript dönüştürülen—olarak da bilinen bir işlem transpilation.
Dosya boyutunu küçültmek için oluşturulan JavaScript karıştırılmış—olarak da bilinen bir işlem
küçültme.
İşlenen JavaScript, CSS ve HTML dosyalarından kopyalanan src için wwwroot dizin.
Aşağıdaki öğeleri içine eklenen wwwroot/index.html dosyası:
A <link> başvuran etiketi wwwroot/main.< karma>.css dosya. Bu etiket kapatılmadan hemen
önce yerleştirilir </head> etiketi.
A <script> küçültülmüş başvuran etiketi wwwroot/main.< karma>.js dosya. Bu etiket
kapatılmadan hemen önce yerleştirilir </body> etiketi.
2. Hata ayıklayıcıyı eklemeden uygulamayı bir tarayıcıda başlatmak **için hata ayıklama > ** Başlat ' ı seçin.
Wwwroot/index.html dosyası http://localhost:<port_number> olarak sunulur.
Derleme hataları alırsanız, çözümü kapatıp yeniden açmayı deneyin.
3. Başka bir tarayıcı örneği (herhangi bir tarayıcı) açın. URL 'YI adres çubuğuna yapıştırın.
4. Tarayıcı seçin, ileti metin kutusuna bir şey yazın ve Gönder düğmesine tıklayın. Benzersiz Kullanıcı adı ve
ileti anında her iki sayfada da görüntülenir.
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core SDK 2,2 veya üzeri
NPM ile Node. js

ASP.NET Core Web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio 'Yu, Path ortam değişkeninde NPM için arama yapmak üzere yapılandırın. Varsayılan olarak, Visual
Studio yükleme dizininde bulunan NPM sürümünü kullanır. Visual Studio 'da şu yönergeleri izleyin:
1. Web Paket Yönetimi > dış web araçları> > > Araçlar ve Seçenekler ' e gidin.
2. Listeden $ (yol) girişini seçin. Girdiyi listedeki ikinci konuma taşımak için yukarı oka tıklayın.
Visual Studio yapılandırması tamamlandı. Projeyi oluşturma zamanı.
1. Dosya > Yeni > projesi menü seçeneğini kullanın ve ASP.NET Core Web uygulaması şablonunu seçin.
2. Projeyi Signalrwebpackolarak adlandırın ve Oluştur' u seçin.
3. Hedef çerçeve açılır listesinden .NET Core ' u seçin ve çerçeve Seçicisi açılır listesinden ASP.NET Core 2,2 ' ı
seçin. Boş şablonu seçin ve Oluştur' u seçin.

WebPack ve TypeScript yapılandırma


Aşağıdaki adımlar, TypeScript 'in JavaScript 'e dönüştürülmesini ve istemci tarafı kaynaklarını paketlemeyi
yapılandırır.
1. Bir Package. JSON dosyası oluşturmak için proje kökünde aşağıdaki komutu yürütün:

npm init -y

2. Vurgulanan özelliği Package. JSON dosyasına ekleyin:

{
"name": "SignalRWebPack",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

private özelliğinin true olarak ayarlanması, sonraki adımda paket yükleme uyarılarını önler.
3. Gerekli NPM paketlerini yükler. Proje kökünden aşağıdaki komutu yürütün:
npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-
extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3

Aklınızda bazı komut ayrıntıları:


Sürüm numarası, her paket adı için @ işaretini izler. NPM bu özel paket sürümlerini yüklüyor.
-E seçeneği, NPM 'nin semantik sürüm aralığı işleçlerini Package. JSONöğesine yazmanın varsayılan
davranışını devre dışı bırakır. Örneğin, "webpack": "^4.29.3" yerine "webpack": "4.29.3" kullanılır. Bu
seçenek, daha yeni paket sürümlerine istenmeden yükseltme yapılmasını engeller.
Daha ayrıntılı bilgi için resmi NPM -Install docs bölümüne bakın.
4. Package. JSON dosyasının scripts özelliğini aşağıdaki kod parçacığıyla değiştirin:

"scripts": {
"build": "webpack --mode=development --watch",
"release": "webpack --mode=production",
"publish": "npm run release && dotnet publish -c Release"
},

Betiklerin bazı açıklamaları:


build : istemci tarafı kaynaklarınızı geliştirme modunda paketler ve dosya değişikliklerini izler. Dosya
izleyici, bir proje dosyası her değiştiğinde paketin yeniden oluşturulmasına neden olur. mode seçeneği,
Tree gerçekleşmesi ve minbirleşme gibi üretim iyileştirmeleri devre dışı bırakır. Yalnızca geliştirmede
build kullanın.
release : istemci tarafı kaynaklarınızı üretim modunda Paketlayın.
publish : release betiği, istemci tarafı kaynaklarını üretim modunda paketleyip çalıştırır. Uygulamayı
yayımlamak için .NET Core CLI Publish komutunu çağırır.
5. Aşağıdaki içeriğe sahip proje kökünde WebPack. config. jsadlı bir dosya oluşturun:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "wwwroot"),
filename: "[name].[chunkhash].js",
publicPath: "/"
},
resolve: {
extensions: [".js", ".ts"]
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader"
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new CleanWebpackPlugin(["wwwroot/*"]),
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css"
})
]
};

Yukarıdaki dosya Web paketi derlemesini yapılandırır. Aklınızda bazı yapılandırma ayrıntıları:
output özelliği, dağ'ın varsayılan değerini geçersiz kılar. Paket, Wwwroot dizininde yayınlanır.
resolve.extensions dizisi, SignalR istemci JavaScript 'ı içeri aktarmak için . js içerir.
6. Proje kökünde yeni bir src dizini oluşturun. Amaç, projenin istemci tarafı varlıklarını depolardır.
7. Aşağıdaki içerikle src/index.html oluşturun.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core SignalR</title>
</head>
<body>
<div id="divMessages" class="messages">
</div>
<div class="input-zone">
<label id="lblMessage" for="tbMessage">Message:</label>
<input id="tbMessage" class="input-zone-input" type="text" />
<button id="btnSend">Send</button>
</div>
</body>
</html>
Önceki HTML, giriş sayfasının ortak işaretlemesini tanımlar.
8. Yeni bir src/CSS dizini oluşturun. Amacı, projenin . css dosyalarını depolamadır.
9. Aşağıdaki içerikle src/CSS/Main. css oluşturun:

*, *::before, *::after {
box-sizing: border-box;
}

html, body {
margin: 0;
padding: 0;
}

.input-zone {
align-items: center;
display: flex;
flex-direction: row;
margin: 10px;
}

.input-zone-input {
flex: 1;
margin-right: 10px;
}

.message-author {
font-weight: bold;
}

.messages {
border: 1px solid #000;
margin: 10px;
max-height: 300px;
min-height: 300px;
overflow-y: auto;
padding: 5px;
}

Önceki Main. css dosyası uygulamayı stiller.


10. Şu içerikle src/tsconfig. JSON oluşturun:

{
"compilerOptions": {
"target": "es5"
}
}

Yukarıdaki kod, TypeScript derleyicisini ECMAScript 5 uyumlu JavaScript üretecek şekilde yapılandırır.
11. Aşağıdaki içeriğe sahip src/index. TS oluşturun:
import "./css/main.css";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Önceki TypeScript, DOM öğelerine başvuruları alır ve iki olay işleyicisini ekler:
keyup : Bu olay Kullanıcı metin kutusuna tbMessage olarak tanımlanan bir şeyi yazdığında ateşlenir.
send işlevi, Kullanıcı ENTER tuşuna bastığında çağrılır.
click : Kullanıcı Gönder düğmesine tıkladığında bu olay ateşlenir. send işlevi çağırılır.

ASP.NET Core uygulamasını yapılandırma


1. Startup.Configure yönteminde belirtilen kod Merhaba Dünya! görüntülüyor. app.Run yöntemi çağrısını,
Usedefaultfiles ve usestaticfilesçağrılarıyla değiştirin.

app.UseDefaultFiles();
app.UseStaticFiles();

Yukarıdaki kod, kullanıcının tam URL 'sini veya Web uygulamasının kök URL 'sini girmeksizin Dizin. html
dosyasını bulmasını ve sunmasını sağlar.
2. Startup.ConfigureServices yönteminde Addsignalr öğesini çağırın. SignalR hizmetlerini projenize ekler.

services.AddSignalR();

3. Bir /hub yolunu ChatHub hub 'ına eşleyin. Startup.Configure yönteminin sonuna aşağıdaki satırları ekleyin:

app.UseSignalR(options =>
{
options.MapHub<ChatHub>("/hub");
});

4. Proje kökünde hubolarak adlandırılan yeni bir dizin oluşturun. Amacı, bir sonraki adımda oluşturulan
SignalR hub 'ını deposağlamaktır.
5. Aşağıdaki kodla hub hub 'ları/ChatHub. cs oluşturun:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
}
}

6. ChatHub başvurusunu çözümlemek için, Startup.cs dosyasının en üstüne aşağıdaki kodu ekleyin:

using SignalRWebPack.Hubs;

İstemci ve sunucu iletişimini etkinleştir


Uygulama Şu anda ileti göndermek için basit bir form görüntülüyor. Bunu yapmayı denediğinizde hiçbir şey olmaz.
Sunucu belirli bir yolu dinliyor, ancak gönderilen iletilerle hiçbir şey yapmıyor.
1. Proje kökünde aşağıdaki komutu yürütün:

npm install @microsoft/signalr

Yukarıdaki komut, istemcinin sunucuya ileti göndermesini sağlayan SignalR TypeScript istemcisiniyüklüyor.
2. Vurgulanan kodu src/index. TS dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let m = document.createElement("div");

m.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
}

Yukarıdaki kod, sunucudan ileti almayı destekler. HubConnectionBuilder sınıfı, sunucu bağlantısını
yapılandırmak için yeni bir Oluşturucu oluşturur. withUrl işlevi hub URL 'sini yapılandırır.
SignalR, istemci ile sunucu arasında ileti alışverişi yapılmasını mümkün. Her ileti belirli bir ada sahiptir.
Örneğin, ileti bölgesindeki yeni iletiyi görüntülemekten sorumlu mantığı çalıştıran messageReceived adına
sahip iletilere sahip olabilirsiniz. Belirli bir iletiyi dinlemek on işlevi aracılığıyla yapılabilir. Herhangi bir
sayıda ileti adını dinleyebilmeniz gerekir. Ayrıca, yazarın adı ve alınan iletinin içeriği gibi parametreleri iletiye
geçirmek da mümkündür. İstemci bir ileti aldıktan sonra yazarın adı ve innerHTML özniteliğinde ileti
içeriğiyle yeni bir div öğesi oluşturulur. Bu, iletileri görüntüleyen ana div öğesine eklenir.
3. Artık istemci bir ileti aldığına göre, ileti gönderecek şekilde yapılandırın. Vurgulanan kodu src/index. TS
dosyasına ekleyin:
import "./css/main.css";
import * as signalR from "@aspnet/signalr";

const divMessages: HTMLDivElement = document.querySelector("#divMessages");


const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

connection.on("messageReceived", (username: string, message: string) => {


let messageContainer = document.createElement("div");

messageContainer.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;

divMessages.appendChild(messageContainer);
divMessages.scrollTop = divMessages.scrollHeight;
});

connection.start().catch(err => document.write(err));

tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {


if (e.keyCode === 13) {
send();
}
});

btnSend.addEventListener("click", send);

function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => tbMessage.value = "");
}

WebSockets bağlantısı aracılığıyla bir ileti gönderildiğinde send yönteminin çağrılması gerekir. Yöntemin ilk
parametresi ileti adıdır. İleti verileri diğer parametreleri geçersiz kılar. Bu örnekte, newMessage sunucusuna
gönderildiği gibi bir ileti gönderilir. İleti, bir metin kutusundan Kullanıcı adından ve Kullanıcı girişinden
oluşur. Gönderme işlemi çalışırsa metin kutusu değeri temizlenir.
4. Vurgulanan yöntemi ChatHub sınıfına ekleyin:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
public async Task NewMessage(long username, string message)
{
await Clients.All.SendAsync("messageReceived", username, message);
}
}
}

Yukarıdaki kod, sunucu onları aldıktan sonra tüm bağlı kullanıcılara ileti almış iletileri yayınlar. Tüm iletileri
almak için genel bir on yöntemi olması gereksizdir. İleti adından sonra adlandırılmış bir yöntem.
Bu örnekte, TypeScript istemcisi newMessage olarak tanımlanan bir ileti gönderir. C# NewMessage yöntemi,
istemci tarafından gönderilen verileri bekler. Istemcilerdeki sendadsync yöntemine bir çağrı yapılır. Alınan
iletiler, hub 'a bağlı tüm istemcilere gönderilir.

Uygulamayı test etme


Uygulamanın aşağıdaki adımlarla çalıştığından emin olun.
Visual Studio
Visual Studio Code
1. Web paketini yayın modunda çalıştırın. Paket Yöneticisi konsol penceresini kullanarak, proje kökünde
aşağıdaki komutu yürütün. Proje kökünde değilseniz, komutu girmeden önce cd SignalRWebPack girin.

npm run release

Bu komut, uygulamayı çalıştırırken alınacağı istemci-tarafı varlıkları verir. Varlıkları yerleştirilir wwwroot
klasör.
Web, aşağıdaki görevleri tamamlandı:
İçeriğini temizleneceği wwwroot dizin.
JavaScript için TypeScript dönüştürülen—olarak da bilinen bir işlem transpilation.
Dosya boyutunu küçültmek için oluşturulan JavaScript karıştırılmış—olarak da bilinen bir işlem
küçültme.
İşlenen JavaScript, CSS ve HTML dosyalarından kopyalanan src için wwwroot dizin.
Aşağıdaki öğeleri içine eklenen wwwroot/index.html dosyası:
A <link> başvuran etiketi wwwroot/main.< karma>.css dosya. Bu etiket kapatılmadan hemen
önce yerleştirilir </head> etiketi.
A <script> küçültülmüş başvuran etiketi wwwroot/main.< karma>.js dosya. Bu etiket
kapatılmadan hemen önce yerleştirilir </body> etiketi.
2. Hata ayıklayıcıyı eklemeden uygulamayı bir tarayıcıda başlatmak **için hata ayıklama > ** Başlat ' ı seçin.
Wwwroot/index.html dosyası http://localhost:<port_number> olarak sunulur.
3. Başka bir tarayıcı örneği (herhangi bir tarayıcı) açın. URL 'YI adres çubuğuna yapıştırın.
4. Tarayıcı seçin, ileti metin kutusuna bir şey yazın ve Gönder düğmesine tıklayın. Benzersiz Kullanıcı adı ve
ileti anında her iki sayfada da görüntülenir.
Ek kaynaklar
ASP.NET Core SignalR JavaScript istemcisi
ASP.NET Core SignalR hub 'ları kullanma
ASP.NET Core için SignalR hub 'ları kullanma
13.11.2019 • 11 minutes to read • Edit Online

, Rachel Appel ve Kevin Griffin tarafından


Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SignalR hub nedir?


SignalR hub 'Ları API 'SI, bağlı istemcilerdeki yöntemleri sunucudan çağırmanızı sağlar. Sunucu kodunda,
istemci tarafından çağrılan yöntemleri tanımlarsınız. İstemci kodunda, sunucudan çağrılan yöntemleri
tanımlarsınız. SignalR, gerçek zamanlı istemciden sunucuya ve sunucudan istemciye iletişimleri olanaklı kılan
arka planda her şeyi ele alır.

SignalR hub 'ları yapılandırma


SignalR ara yazılımı, services.AddSignalR çağırarak yapılandırılmış bazı hizmetler gerektirir.

services.AddSignalR();

Bir ASP.NET Core uygulamasına SignalR işlevselliği eklerken, Startup.Configure yönteminin app.UseEndpoints
geri aramasında endpoint.MapHub çağırarak SignalR yollar ayarlayın.

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});

Bir ASP.NET Core uygulamasına SignalR işlevselliği eklerken, Startup.Configure yöntemindeki app.UseSignalR
çağırarak SignalR yollar ayarlayın.

app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});

Hub 'lar oluşturma ve kullanma


Hub devralan bir sınıf bildirerek bir hub oluşturun ve buna ortak yöntemler ekleyin. İstemciler, public olarak
tanımlanan yöntemleri çağırabilir.

public class ChatHub : Hub


{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Herhangi C# bir yöntemde yaptığınız gibi, karmaşık türler ve diziler dahil olmak üzere bir dönüş türü ve
parametreleri belirtebilirsiniz. SignalR parametrelerinizin ve dönüş değerlerindeki karmaşık nesne ve dizilerin
serileştirilmesi ve serisini kaldırma işlemi gerçekleştirir.

NOTE
Hub 'lar geçicidir:
Durumu hub sınıfının bir özelliğinde depolamayın. Her hub yöntemi çağrısı yeni bir hub örneğinde yürütülür.
Hub 'a bağlı olan zaman uyumsuz yöntemleri çağırırken await kullanın. Örneğin, Clients.All.SendAsync(...) gibi
bir yöntem, await olmadan çağrılırsa ve hub yöntemi SendAsync bitmeden önce tamamlandığında başarısız olabilir.

Bağlam nesnesi
Hub sınıfı, bağlantıyla ilgili bilgilerle aşağıdaki özellikleri içeren bir Context özelliğine sahiptir:

ÖZELLIK AÇIKLAMA

ConnectionId SignalRtarafından atanan bağlantının benzersiz KIMLIĞINI


alır. Her bağlantı için bir bağlantı KIMLIĞI vardır.

UserIdentifier Kullanıcı tanımlayıcısınıalır. Varsayılan olarak, SignalR, Kullanıcı


tanımlayıcısı olarak bağlantıyla ilişkili ClaimsPrincipal
ClaimTypes.NameIdentifier kullanır.

User Geçerli kullanıcıyla ilişkili ClaimsPrincipal alır.

Items Bu bağlantının kapsamındaki verileri paylaşmak için


kullanılabilecek bir anahtar/değer koleksiyonu alır. Veriler bu
koleksiyonda depolanabilir ve farklı hub yöntemi
etkinleştirmeleri arasında bağlantı için kalıcı hale gelir.

Features Bağlantıda kullanılabilen özelliklerin koleksiyonunu alır.


Şimdilik bu koleksiyon Çoğu senaryoda gerekli değildir, bu
nedenle henüz ayrıntılı olarak açıklanmamıştır.

ConnectionAborted Bağlantı iptal edildiğinde bildirim veren bir


CancellationToken alır.

Hub.Context aşağıdaki yöntemleri de içerir:

YÖNTEM AÇIKLAMA

GetHttpContext Bağlantı için HttpContext döndürür veya bağlantı bir HTTP


isteğiyle ilişkilendirilmediği durumlarda null . HTTP
bağlantılarında, HTTP üstbilgileri ve sorgu dizeleri gibi bilgileri
almak için bu yöntemi kullanabilirsiniz.

Abort Bağlantıyı iptal eder.

Istemciler nesnesi
Hub sınıfı, sunucu ve istemci arasındaki iletişim için aşağıdaki özellikleri içeren bir Clients özelliğine sahiptir:
ÖZELLIK AÇIKLAMA

All Tüm bağlı istemcilerde bir yöntemi çağırır

Caller İstemciye, hub yöntemini çağıran bir yöntemi çağırır

Others Yöntemi çağıran istemci hariç tüm bağlı istemcilerde bir


yöntemi çağırır

Hub.Clients aşağıdaki yöntemleri de içerir:

YÖNTEM AÇIKLAMA

AllExcept Belirtilen bağlantılar hariç tüm bağlı istemcilerde bir yöntemi


çağırır

Client Belirli bir bağlı istemcide bir yöntemi çağırır

Clients Belirli bağlı istemcilerde bir yöntemi çağırır

Group Belirtilen gruptaki tüm bağlantılarda bir yöntemi çağırır

GroupExcept Belirtilen bağlantılar dışında, belirtilen gruptaki tüm


bağlantılarda bir yöntemi çağırır

Groups Birden çok bağlantı grubunda bir yöntemi çağırır

OthersInGroup Hub yöntemini çağıran istemci hariç bir bağlantı grubu


üzerinde bir yöntemi çağırır

User Belirli bir kullanıcıyla ilişkili tüm bağlantılarda bir yöntemi


çağırır

Users Belirtilen kullanıcılarla ilişkili tüm bağlantılarda bir yöntemi


çağırır

Yukarıdaki tablolardaki her bir özellik veya yöntem SendAsync yöntemi olan bir nesne döndürür. SendAsync
yöntemi, çağrılacak istemci yönteminin adını ve parametrelerini girmenize olanak sağlar.

İstemcilere ileti gönderme


Belirli istemcilere çağrı yapmak için Clients nesnesinin özelliklerini kullanın. Aşağıdaki örnekte, üç hub yöntemi
vardır:
SendMessage , kullanarak tüm bağlı istemcilere bir ileti gönderir.
Clients.All
SendMessageToCaller , Clients.Caller kullanarak çağırana geri ileti gönderir.
SendMessageToGroups , SignalR Users grubundaki tüm istemcilere bir ileti gönderir.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string message)


{
return Clients.Caller.SendAsync("ReceiveMessage", message);
}

public Task SendMessageToGroup(string message)


{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", message);
}

Türü kesin belirlenmiş hub 'lar


SendAsync kullanmanın bir dezavantajı, çağrılacak istemci yöntemini belirtmek üzere bir sihirli dize kullanır. Bu,
yöntem adı yanlış yazıldığında veya istemcide eksikse kodu, çalışma zamanı hatalarına açık bırakır.
SendAsync kullanmanın bir alternatifi Hub<T>ile Hub kesin olarak yazmadır. Aşağıdaki örnekte, ChatHub
istemci yöntemleri IChatClient adlı bir arabirimde ayıklanır.

public interface IChatClient


{
Task ReceiveMessage(string user, string message);
Task ReceiveMessage(string message);
}

Bu arabirim, önceki ChatHub örneğini yeniden düzenleme için kullanılabilir.

public class StronglyTypedChatHub : Hub<IChatClient>


{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}

public Task SendMessageToCaller(string message)


{
return Clients.Caller.ReceiveMessage(message);
}
}

Hub<IChatClient> kullanmak, istemci yöntemlerinin derleme zamanı denetimini mümkün yapar. Bu, Hub<T>
yalnızca arabirimde tanımlanan yöntemlere erişim sağlayabileceğinizden, sihirli dizeler kullanılarak oluşan
sorunları önler.
Türü kesin belirlenmiş Hub<T> kullanmak SendAsync kullanma özelliğini devre dışı bırakır. Arabirim üzerinde
tanımlanan Yöntemler hala zaman uyumsuz olarak tanımlanabilir. Aslında, bu yöntemlerin her biri bir Task
döndürmelidir. Bir arabirim olduğundan, async anahtar sözcüğünü kullanmayın. Örneğin:

public interface IClient


{
Task ClientMethod();
}
NOTE
Async soneki yöntem adından çıkarılır. İstemci yönteminiz .on('MyMethodAsync') ile tanımlanmamışsa, ad olarak
MyMethodAsync kullanmamalısınız.

Bir hub yönteminin adını değiştirme


Varsayılan olarak, bir sunucu hub 'ı Yöntem adı .NET yönteminin adıdır. Ancak, bu Varsayılanı değiştirmek ve
yöntemi için el ile bir ad belirtmek için Hubmethodname özniteliğini kullanabilirsiniz. İstemci, yöntemi çağırırken
.NET Yöntem adı yerine bu adı kullanmalıdır.

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", message);
}

Bir bağlantı için olayları işleyin


SignalR hub 'Ları API 'SI, bağlantıları yönetmek ve izlemek için OnConnectedAsync ve OnDisconnectedAsync sanal
yöntemleri sağlar. Bir istemci hub 'a bağlanırken bir gruba ekleme gibi işlemleri gerçekleştirmek için
OnConnectedAsync sanal yöntemini geçersiz kılın.

public override async Task OnConnectedAsync()


{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}

Bir istemcinin bağlantısı kesildiğinde eylemler gerçekleştirmek için OnDisconnectedAsync sanal yöntemini
geçersiz kılın. İstemci kasıtlı olarak bağlantı kesildiğinde (örneğin connection.stop() çağırarak), exception
parametresi null olur. Ancak, istemcinin bağlantısı bir hata nedeniyle kesildiyse (örneğin, bir ağ hatası),
exception parametresi hatayı açıklayan bir özel durum içerir.

public override async Task OnDisconnectedAsync(Exception exception)


{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}

Hataları işleme
Hub yöntemleriniz içinde oluşturulan özel durumlar, yöntemi çağıran istemciye gönderilir.JavaScript
istemcisinde invoke yöntemi bir JavaScript Promisedöndürür. İstemci, catch kullanarak Promise 'e eklenmiş
bir işleyiciyle bir hata aldığında, çağrılır ve bir JavaScript Error nesnesi olarak geçirilir.

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Hub 'ınız bir özel durum oluşturursa, bağlantılar kapanmamıştır. Varsayılan olarak, SignalR istemciye genel bir
hata iletisi döndürür. Örneğin:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Beklenmeyen özel durumlar genellikle veritabanı bağlantısı başarısız olduğunda tetiklenen bir özel durumda
veritabanı sunucusunun adı gibi hassas bilgiler içerir. SignalR, bu ayrıntılı hata iletilerini varsayılan olarak bir
güvenlik ölçüsü olarak kullanıma sunmaz. Özel durum ayrıntılarının neden bastırıldığına ilişkin daha fazla bilgi
için güvenlik konuları makalesine bakın.
İstemciye yaymak istediğiniz olağanüstü bir koşulunuz varsa HubException sınıfını kullanabilirsiniz. Hub
yönteinizden bir HubException oluşturursanız , SignalR iletinin tamamını, değiştirilmemiş olarak istemciye
gönderir.

public Task ThrowException()


{
throw new HubException("This error will be sent to the client!");
}

NOTE
SignalR yalnızca özel durumun Message özelliğini istemciye gönderir. Özel durumun yığın izlemesi ve diğer özellikleri
istemci tarafından kullanılamaz.

İlgili kaynaklar
ASP.NET Core SignalR giriş
JavaScript istemcisi
Azure'a Yayımlama
Bir hub dışında ileti gönderme
10.05.2019 • 2 minutes to read • Edit Online

Tarafından Mikael Mengistu


SignalR hub'ı, SignalR sunucuya bağlı istemcilere ileti göndermek için çekirdek soyutlamadır. Diğer yerlerden
uygulama kullanarak ileti göndermek mümkündür IHubContext hizmeti. Bu makalede, bir SignalR erişmeye
açıklanmaktadır IHubContext hub dışında istemcilere bildirimleri göndermek için.
Görüntüleme veya indirme örnek kodu (karşıdan yükleme)

IHubContext örneğini al
ASP.NET Core SignalR öğesinde bir örneğini erişebileceğiniz IHubContext aracılığıyla bağımlılık ekleme. Örneği
ekleyebilir IHubContext bir denetleyici, ara yazılım veya diğer DI hizmeti. İstemcilere göndermek için örneği
kullanın.

NOTE
Bu, ASP.NET tarafından farklıdır 4.x GlobalHost erişim sağlamak için kullanılan SignalR IHubContext . ASP.NET Core, bu genel
tekil gereksinimini ortadan kaldırır, bir bağımlılık ekleme çerçeve vardır.

Bir denetleyici IHubContext örneğinde ekleme


Örneği ekleyebilir IHubContext , oluşturucuya ekleyerek bir denetleyici içinde:

public class HomeController : Controller


{
private readonly IHubContext<NotificationHub> _hubContext;

public HomeController(IHubContext<NotificationHub> hubContext)


{
_hubContext = hubContext;
}
}

Şimdi, örneğine erişimi olan IHubContext , hub içinde değilmiş gibi hub yöntemlerini çağırabilirsiniz.

public async Task<IActionResult> Index()


{
await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
return View();
}

Ara yazılım IHubContext örneğinde Al


Erişim IHubContext ara yazılım ardışık düzenini içinde şu şekilde:
app.Use(async (context, next) =>
{
var hubContext = context.RequestServices
.GetRequiredService<IHubContext<MyHub>>();
//...
});

NOTE
Ne zaman hub yöntemleri çağrıldığında gelen dışında Hub çağırmayla ilgili hiçbir arayan olduğunda, sınıf. Bu nedenle, erişim
yoktur ConnectionId , Caller , ve Others özellikleri.

Kesin türü belirtilmiş bir HubContext ekleme


Hub'ınıza devraldığı kesin türü belirtilmiş bir HubContext eklemesine olun Hub<T> . Kullanarak ekleme
IHubContext<THub, T> arabirimi yerine IHubContext<THub> .

public class ChatController : Controller


{
public IHubContext<ChatHub, IChatClient> _strongChatHubContext { get; }

public ChatController(IHubContext<ChatHub, IChatClient> chatHubContext)


{
_strongChatHubContext = chatHubContext;
}

public async Task SendMessage(string message)


{
await _strongChatHubContext.Clients.All.ReceiveMessage(message);
}
}

İlgili kaynaklar
Kullanmaya başlama
Merkezler
Azure'a Yayımlama
SignalR içinde kullanıcıları ve grupları yönetme
13.11.2019 • 3 minutes to read • Edit Online

Brennan Conroy tarafından


SignalR, iletilerin belirli bir kullanıcıyla ilişkili tüm bağlantılara ve ayrıca adlandırılmış bağlantı gruplarına
gönderilmesini sağlar.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SignalR kullanıcılar
SignalR, belirli bir kullanıcıyla ilişkili tüm bağlantılara ileti göndermenizi sağlar. Varsayılan olarak, SignalR,
Kullanıcı tanımlayıcısı olarak bağlantıyla ilişkili ClaimsPrincipal ClaimTypes.NameIdentifier kullanır. Tek bir
kullanıcının SignalR uygulamasına birden fazla bağlantısı olabilir. Örneğin, bir Kullanıcı masaüstüne ve
telefonlarına bağlanabilir. Her cihazın ayrı bir SignalR bağlantısı vardır, ancak hepsi aynı kullanıcıyla ilişkilendirilir.
Kullanıcıya bir ileti gönderildiğinde, bu kullanıcıyla ilişkili tüm bağlantılar iletiyi alır. Bir bağlantı için Kullanıcı
tanımlayıcısına, hub 'ınızdaki Context.UserIdentifier özelliği tarafından erişilebilir.
Aşağıdaki örnekte gösterildiği gibi, kullanıcı tanımlayıcısını hub yönteminizin User işleve geçirerek belirli bir
kullanıcıya bir ileti gönderin:

NOTE
Kullanıcı tanımlayıcısı büyük/küçük harfe duyarlıdır.

public Task SendPrivateMessage(string user, string message)


{
return Clients.User(user).SendAsync("ReceiveMessage", message);
}

SignalR gruplar
Grup, bir adla ilişkili bir bağlantı koleksiyonudur. İletiler, bir gruptaki tüm bağlantılara gönderilebilir. Gruplar
uygulama tarafından yönetildiğinden, gruplar bir bağlantıya veya birden çok bağlantıya göndermek için önerilen
yoldur. Bir bağlantı, birden fazla grubun üyesi olabilir. Bu, grupları her odanın bir grup olarak gösterilebileceği bir
sohbet uygulaması gibi bir şey için ideal hale getirir. AddToGroupAsync ve RemoveFromGroupAsync yöntemleri
aracılığıyla gruplardan bağlantılar eklenebilir veya gruplardan kaldırılabilir.
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);

await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group


{groupName}.");
}

public async Task RemoveFromGroup(string groupName)


{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);

await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has left the group


{groupName}.");
}

Bağlantı yeniden bağlandığında grup üyeliği korunmaz. Bağlantı, yeniden oluşturulduğunda gruba yeniden
katılması gerekir. Uygulama birden çok sunucuya ölçeklendirildiyse bu bilgiler kullanılamadığından, bir grubun
üyelerini saymak mümkün değildir.
Grupları kullanırken kaynaklara erişimi korumak için ASP.NET Core kimlik doğrulaması ve yetkilendirme işlevini
kullanın. Yalnızca bu grup için kimlik bilgileri geçerliyse bir gruba Kullanıcı eklerseniz, bu gruba gönderilen iletiler
yalnızca yetkili kullanıcılara gider. Ancak, gruplar bir güvenlik özelliği değildir. Kimlik doğrulama talepleri, süre
sonu ve iptal gibi grupların olmadığı özelliklere sahiptir. Bir kullanıcının gruba erişim izni iptal edildiğinde, bunu el
ile tespit etmeniz ve gruptan kaldırmanız gerekir.

NOTE
Grup adları büyük/küçük harfe duyarlıdır.

İlgili kaynaklar
Kullanmaya başlama
Merkezler
Azure'a Yayımlama
SignalR API tasarım konuları
10.05.2019 • 4 minutes to read • Edit Online

Tarafından Andrew Stanton-Nurse


Bu makalede, SignalR tabanlı API'leri oluşturmaya yönelik rehberlik sağlar.

Geriye dönük uyumluluk sağlamak için özel nesne parametreleri


kullanma
Bir SignalR hub'yöntemini (istemci veya sunucu) parametreleri ekleyerek olan bir değişiklik. Başka bir deyişle, eski
istemciler/sunucuları parametreleri uygun sayıda olmayan bir yöntem çağırmak çalıştığınızda bir hata almazsınız.
Ancak, bir özel nesne parametresi için Özellikler ekleme olan değil bir değişiklik. Bu, istemci veya Sunucu'da
değişikliklere dayanıklı uyumlu API'leri tasarlamak için kullanılabilir.
Örneğin, aşağıdaki gibi bir sunucu tarafı API göz önünde bulundurun:

public async Task<string> GetTotalLength(string param1)


{
return param1.Length;
}

JavaScript istemcisi kullanarak bu yöntemi çağıran invoke gibi:

connection.invoke("GetTotalLength", "value1");

Eski istemciler, sunucu yöntemi daha sonra ikinci bir parametre ekleyin, bu parametre değeri sağlamaz. Örneğin:

public async Task<string> GetTotalLength(string param1, string param2)


{
return param1.Length + param2.Length;
}

Eski istemci, bu yöntem çağırmak çalıştığında, şunun gibi bir hata alırsınız:

Microsoft.AspNetCore.SignalR.HubException: Failed to invoke 'GetTotalLength' due to an error on the server.

Sunucuda böyle bir günlük iletisi görürsünüz:

System.IO.InvalidDataException: Invocation provides 1 argument(s) but target expects 2.

Eski istemci yalnızca bir parametreye gönderilen, ancak yeni sunucu API iki parametre gerekli. Parametre olarak
özel nesneler kullanarak daha fazla esneklik sağlar. Şimdi yeniden tasarlamanız özgün API'yi özel bir nesne
kullanın:
public class TotalLengthRequest
{
public string Param1 { get; set; }
}

public async Task GetTotalLength(TotalLengthRequest req)


{
return req.Param1.Length;
}

Şimdi, istemci yöntemini çağırmak için bir nesne kullanır:

connection.invoke("GetTotalLength", { param1: "value1" });

Bir parametre eklemek yerine, özellik eklemek TotalLengthRequest nesnesi:

public class TotalLengthRequest


{
public string Param1 { get; set; }
public string Param2 { get; set; }
}

public async Task GetTotalLength(TotalLengthRequest req)


{
var length = req.Param1.Length;
if (req.Param2 != null)
{
length += req.Param2.Length;
}
return length;
}

Eski istemci, tek bir parametre, ek gönderdiğinde Param2 özellik sol null . Kontrol ederek daha eski bir istemci
tarafından gönderilen bir iletinin algılayabilir Param2 için null ve varsayılan değer geçerlidir. Yeni bir istemci, her
iki parametre gönderebilirsiniz.

connection.invoke("GetTotalLength", { param1: "value1", param2: "value2" });

İstemci üzerinde tanımlanan yöntemleri için aynı tekniği çalışır. Sunucu tarafındaki özel bir nesne gönderebilirsiniz:

public async Task Broadcast(string message)


{
await Clients.All.SendAsync("ReceiveMessage", new
{
Message = message
});
}

İstemci tarafında size erişim Message bir parametre kullanmak yerine özelliği:

connection.on("ReceiveMessage", (req) => {


appendMessageToChatWindow(req.message);
});

İletiyi gönderen yüküne eklemek üzere daha sonra karar verirseniz, nesnenin bir özellik ekleyin:
public async Task Broadcast(string message)
{
await Clients.All.SendAsync("ReceiveMessage", new
{
Sender = Context.User.Identity.Name,
Message = message
});
}

Eski istemciler bekleniyor olmaz Sender bunu yoksaymak şekilde değeri. Yeni bir istemci yeni özelliği okunamıyor
güncelleştirerek kabul edebilirsiniz:

connection.on("ReceiveMessage", (req) => {


let message = req.message;
if (req.sender) {
message = req.sender + ": " + message;
}
appendMessageToChatWindow(message);
});

Bu durumda, yeni istemci de sağlamaz eski bir sunucunun dayanıklıdır Sender değeri. Eski sunucu sağlamayacak
beri Sender değeri, istemci erişmeden önce olup olmadığını görmek için denetler.
ASP.NET Core SignalR istemci özellikleri
4.10.2019 • 2 minutes to read • Edit Online

Özellik dağıtımı
Aşağıdaki tabloda, gerçek zamanlı destek sunan istemciler için özellikler ve destek gösterilmektedir. Her özellik için,
bu özelliği destekleyen En düşük sürüm listelenir. Listelenen bir sürüm yoksa özellik desteklenmez.

ÖZELLIK .NET JAVASCRIPT JAVA

Azure SignalR hizmeti 1.0.0 1.0.0 1.0.0


desteği

Sunucudan istemciye akış 1.0.0 1.0.0 1.0.0

İstemciden sunucuya akış 3.0.0 3.0.0 3.0.0

Otomatik yeniden bağlanma 3.0.0 3.0.0


(.net, JavaScript)

WebSockets taşıma 1.0.0 1.0.0 1.0.0

Sunucu tarafından 1.0.0 1.0.0


gönderilen olay aktarımı

Uzun yoklama taşıması 1.0.0 1.0.0 3.0.0

JSON hub 'ı Protokolü 1.0.0 1.0.0 1.0.0

MessagePack Hub Protokolü 1.0.0 1.0.0

Java istemcisinde otomatik yeniden bağlanma desteği, sorun izleyici'de izlenir.

Ek kaynaklar
ASP.NET Core için SignalR ile çalışmaya başlama
Desteklenen platformlar
Merkezler
JavaScript istemcisi
.NET Client ASP.NET Core SignalR
14.11.2019 • 11 minutes to read • Edit Online

ASP.NET Core SignalR .NET istemci kitaplığı, .NET uygulamalarından SignalR hub 'larla iletişim kurmanızı
sağlar.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Bu makaledeki kod örneği, SignalR .NET Client ASP.NET Core kullanan bir WPF uygulamasıdır.

SignalR .NET istemci paketini yükler


Microsoft. AspNetCore.SignalR. .Net istemcilerinin SignalR hub 'lara bağlanması için istemci paketi gerekir.
Visual Studio
.NET Core CLI
İstemci kitaplığını yüklemek için, Paket Yöneticisi konsolu penceresinde aşağıdaki komutu çalıştırın:

Install-Package Microsoft.AspNetCore.SignalR.Client

Bir hub 'a bağlanma


Bir bağlantı kurmak için bir HubConnectionBuilder oluşturun ve Build çağırın. Hub URL 'SI, protokol, aktarım
türü, günlük düzeyi, üst bilgiler ve diğer seçenekler bir bağlantı oluşturulurken yapılandırılabilir.
HubConnectionBuilder yöntemlerinden herhangi birini Build ekleyerek gerekli seçenekleri yapılandırın.
Bağlantıyı StartAsync başlatın.
using System;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.AspNetCore.SignalR.Client;

namespace SignalRChatClient
{
public partial class MainWindow : Window
{
HubConnection connection;
public MainWindow()
{
InitializeComponent();

connection = new HubConnectionBuilder()


.WithUrl("http://localhost:53353/ChatHub")
.Build();

connection.Closed += async (error) =>


{
await Task.Delay(new Random().Next(0,5) * 1000);
await connection.StartAsync();
};
}

private async void connectButton_Click(object sender, RoutedEventArgs e)


{
connection.On<string, string>("ReceiveMessage", (user, message) =>
{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{user}: {message}";
messagesList.Items.Add(newMessage);
});
});

try
{
await connection.StartAsync();
messagesList.Items.Add("Connection started");
connectButton.IsEnabled = false;
sendButton.IsEnabled = true;
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}
}

private async void sendButton_Click(object sender, RoutedEventArgs e)


{
try
{
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}
}
}
}

Kayıp bağlantıyı işle


Otomatik olarak yeniden bağlan
HubConnection, HubConnectionBuilder WithAutomaticReconnect yöntemi kullanılarak otomatik olarak yeniden
bağlanacak şekilde yapılandırılabilir. Varsayılan olarak otomatik olarak yeniden bağlanmaz.

HubConnection connection= new HubConnectionBuilder()


.WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
.WithAutomaticReconnect()
.Build();

Hiçbir parametre olmadan, WithAutomaticReconnect() her bir yeniden bağlanma denemesini denemeden önce,
dört başarısız denemeden sonra durdurmadan, istemciyi 0, 2, 10 ve 30 saniye bekleyecek şekilde yapılandırır.
Yeniden bağlanma girişimlerini başlatmadan önce, HubConnection HubConnectionState.Reconnecting durumuna
geçer ve Reconnecting olayını harekete geçirebilir. Bu, kullanıcıların bağlantının kaybedildiği ve Kullanıcı arabirimi
öğelerini devre dışı bırakan kullanıcıları uyarma fırsatı sağlar. Etkileşimli olmayan uygulamalar, iletileri sıraya
alabilir veya bırakarak başlatabilir.

connection.Reconnecting += error =>


{
Debug.Assert(connection.State == HubConnectionState.Reconnecting);

// Notify users the connection was lost and the client is reconnecting.
// Start queuing or dropping messages.

return Task.CompletedTask;
};

İstemci ilk dört deneme süresi içinde başarıyla yeniden bağlanırsa, HubConnection Connected duruma geçer ve
Reconnected olayını harekete geçirebilir. Bu, kullanıcılara bağlantı yeniden kurulduğunda ve sıraya alınan tüm
iletileri sıradan bildiren bir fırsat sağlar.
Bağlantı sunucuya tamamen yeni göründüğünden, Reconnected olay işleyicilerine yeni bir ConnectionId
sunulacaktır.

WARNING
Reconnected olay işleyicisinin connectionId parametresi, HubConnection anlaşmayı atlayacakşekilde yapılandırıldıysa
null olacaktır.

connection.Reconnected += connectionId =>


{
Debug.Assert(connection.State == HubConnectionState.Connected);

// Notify users the connection was reestablished.


// Start dequeuing messages queued while reconnecting if any.

return Task.CompletedTask;
};

WithAutomaticReconnect() , ilk başlatma başarısızlıklarını yeniden denemek için HubConnection yapılandırmaz, bu


nedenle başlatma hatalarının el ile işlenmesi gerekir:
public static async Task<bool> ConnectWithRetryAsync(HubConnection connection, CancellationToken token)
{
// Keep trying to until we can start or the token is canceled.
while (true)
{
try
{
await connection.StartAsync(token);
Debug.Assert(connection.State == HubConnectionState.Connected);
return true;
}
catch when (token.IsCancellationRequested)
{
return false;
}
catch
{
// Failed to connect, trying again in 5000 ms.
Debug.Assert(connection.State == HubConnectionState.Disconnected);
await Task.Delay(5000);
}
}
}

İstemci ilk dört denemeden sonra başarıyla yeniden bağlanmazsa, HubConnection Disconnected durumuna geçer
ve Closed olayını harekete geçirebilir. Bu, bağlantıyı el ile yeniden başlatmayı denemek veya bağlantıyı kalıcı
olarak kaybettiğini bildirmek için bir fırsat sağlar.

connection.Closed += error =>


{
Debug.Assert(connection.State == HubConnectionState.Disconnected);

// Notify users the connection has been closed or manually try to restart the connection.

return Task.CompletedTask;
};

Bağlantıyı kesmeden veya yeniden bağlanma zamanlamasını değiştirmeden önce özel sayıda yeniden bağlantı
girişimi yapılandırmak için WithAutomaticReconnect , her bir yeniden bağlanma girişimine başlamadan önce
beklenecek gecikme süresi temsil eden bir sayı dizisini kabul eder.

HubConnection connection= new HubConnectionBuilder()


.WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
.WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(10) })
.Build();

// .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10),


TimeSpan.FromSeconds(30) }) yields the default behavior.

Yukarıdaki örnek, bağlantı kaybolduktan hemen sonra yeniden bağlanmaya başlamak için HubConnection
yapılandırır. Bu, varsayılan yapılandırma için de geçerlidir.
İlk yeniden bağlantı girişimi başarısız olursa, ikinci yeniden bağlanma denemesi de varsayılan yapılandırmada
olduğu gibi 2 saniye beklemek yerine hemen başlatılır.
İkinci yeniden bağlantı girişimi başarısız olursa, üçüncü yeniden bağlanma denemesi varsayılan yapılandırma gibi
10 saniye içinde başlar.
Özel davranış daha sonra, üçüncü yeniden bağlantı girişimi başarısızlığından sonra durarak varsayılan
davranıştan daha sonra yeniden ayrılmış. Varsayılan yapılandırmada, 30 saniye içinde bir veya daha fazla yeniden
bağlantı denemesi olur.
Otomatik yeniden bağlanma denemelerinin zamanlaması ve sayısı üzerinde daha fazla denetime sahip olmak
istiyorsanız WithAutomaticReconnect , NextRetryDelay adlı tek bir yönteme sahip IRetryPolicy arabirimini
uygulayan bir nesneyi kabul eder.
NextRetryDelay türünde tek bir bağımsız değişken alır. RetryContext üç özelliğe sahiptir:
RetryContext
PreviousRetryCount , ElapsedTime ve RetryReason long , TimeSpan ve Exception . İlk yeniden bağlanma
denemesinden önce, hem PreviousRetryCount hem de ElapsedTime sıfır olur ve RetryReason bağlantının
kaybolmasına neden olan özel durum olacaktır. Her başarısız yeniden deneme denemesinden sonra
PreviousRetryCount , bu ana kadar geçen süreyi yansıtacak şekilde ElapsedTime güncelleştirilir ve RetryReason
son yeniden bağlanma denemesinin başarısız olmasına neden olan özel durum olacaktır.
NextRetryDelay, sonraki yeniden bağlanma girişiminden önce beklenecek süreyi temsil eden bir TimeSpan
değeri döndürmelidir veya HubConnection yeniden bağlamayı durdurması gerekiyorsa null .

public class RandomRetryPolicy : IRetryPolicy


{
private readonly Random _random = new Random();

public TimeSpan? NextRetryDelay(RetryContext retryContext)


{
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
if (retryContext.ElapsedTime < TimeSpan.FromSeconds(60))
{
return TimeSpan.FromSeconds(_random.Next() * 10);
}
else
{
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
}
}

HubConnection connection = new HubConnectionBuilder()


.WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
.WithAutomaticReconnect(new RandomRetryPolicy())
.Build();

Alternatif olarak, el ile yeniden bağlanmabölümünde gösterildiği gibi istemcinizi el ile yeniden bağlayacaksınız.
El ile yeniden bağlan

WARNING
3,0 ' den önce, SignalR .NET istemcisi otomatik olarak yeniden bağlanmaz. İstemcinizi el ile yeniden bağlayacaksınız kodu
yazmanız gerekir.

Kayıp bir bağlantıya yanıt vermek için Closed olayını kullanın. Örneğin, yeniden bağlanmayı otomatik hale
getirmek isteyebilirsiniz.
Closed olayı, zaman uyumsuz kodun async void kullanılmadan çalışmasına izin veren bir Task döndüren bir
temsilci gerektirir. Zaman uyumlu olarak çalışan bir Closed olay işleyicisindeki temsilci imzasını karşılamak için
Task.CompletedTask döndürün:
connection.Closed += (error) => {
// Do your close logic.
return Task.CompletedTask;
};

Zaman uyumsuz desteğin ana nedeni, bağlantıyı yeniden başlatabilmeniz için kullanılır. Bir bağlantının
başlatılması zaman uyumsuz bir işlemdir.
Bağlantıyı yeniden başlatan bir Closed işleyicisinde, aşağıdaki örnekte gösterildiği gibi, sunucunun aşırı
yüklenmesini engellemek için bazı rastgele gecikme yapmayı düşünün:

connection.Closed += async (error) =>


{
await Task.Delay(new Random().Next(0,5) * 1000);
await connection.StartAsync();
};

İstemciden çağrı merkezi yöntemleri


InvokeAsync hub 'daki yöntemleri çağırır. Hub yöntemi adını ve hub yönteminde tanımlanan tüm bağımsız
değişkenleri InvokeAsync geçirin. SignalR zaman uyumsuzdur, bu nedenle çağrıları yaparken async ve await
kullanın.

await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);

InvokeAsync yöntemi, sunucu yöntemi döndürüldüğünde tamamlayan bir Task döndürür. Varsa, dönüş değeri
Task sonucu olarak sağlanır. Sunucu üzerindeki yöntemi tarafından oluşturulan özel durumlar hatalı bir Task
üretir. Sunucu yönteminin tamamlanmasını beklemek için await sözdizimini kullanın ve hataları işlemek için söz
dizimini try...catch .
SendAsync yöntemi, ileti sunucuya gönderildiğinde tamamlayan bir Task döndürür. Bu Task sunucu yöntemi
tamamlanana kadar beklemediğinden, dönüş değeri sağlanmaz. İletiyi gönderirken istemcide oluşturulan özel
durumlar hatalı bir Task üretir. Gönderme hatalarını işlemek için await ve try...catch söz dizimini kullanın.

NOTE
Azure SignalR hizmetini sunucusuz moddakullanıyorsanız, bir istemciden hub yöntemlerini çağıramezsiniz. Daha fazla bilgi
için SignalR hizmeti belgelerinebakın.

Hub 'dan istemci yöntemlerini çağır


Bağlantıyı başlatmadan önce, derleme sonrasında connection.On kullanarak hub çağıran yöntemleri tanımlayın.

connection.On<string, string>("ReceiveMessage", (user, message) =>


{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{user}: {message}";
messagesList.Items.Add(newMessage);
});
});
connection.On önceki kod, sunucu tarafı kodu SendAsync yöntemini kullanarak çağırdığında çalışır.

public async Task SendMessage(string user, string message)


{
await Clients.All.SendAsync("ReceiveMessage", user,message);
}

Hata işleme ve günlüğe kaydetme


Try-catch ifadesiyle hataları işleyin. Bir hata oluştuktan sonra gerçekleştirilecek uygun eylemi öğrenmek için
Exception nesnesini inceleyin.

try
{
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}

Ek kaynaklar
Merkezler
JavaScript istemcisi
Azure'a Yayımlama
Azure SignalR hizmeti sunucusuz belgeler
ASP.NET Core SignalR Java istemcisi
13.11.2019 • 4 minutes to read • Edit Online

X MIKAEL Mengistu tarafından


Java istemcisi, Android uygulamaları dahil olmak üzere Java kodundan bir ASP.NET Core SignalR sunucusuna
bağlanmasını sağlar. JavaScript istemcisi ve .NET istemcisigibi Java istemcisi, bir hub 'a gerçek zamanlı iletiler alıp
göndermenizi sağlar. Java istemcisi ASP.NET Core 2,2 ve üzeri sürümlerde kullanılabilir.
Bu makalede başvurulan örnek Java konsol uygulaması SignalR Java istemcisini kullanır.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SignalR Java istemci paketini yükler


SignalR -1.0.0 jar dosyası istemcilerin SignalR hub 'lara bağlanmasına izin verir. En son JAR dosyası sürüm
numarasını bulmak için bkz. Maven arama sonuçları.
Gradle kullanıyorsanız, Build. Gradle dosyanızın dependencies bölümüne aşağıdaki satırı ekleyin:

implementation 'com.microsoft.signalr:signalr:1.0.0'

Maven kullanıyorsanız, Pok. xml dosyanızın <dependencies> öğesinin içine aşağıdaki satırları ekleyin:

<dependency>
<groupId>com.microsoft.signalr</groupId>
<artifactId>signalr</artifactId>
<version>1.0.0</version>
</dependency>

Bir hub 'a bağlanma


HubConnection oluşturmak için HubConnectionBuilder kullanılmalıdır. Hub URL 'SI ve günlük düzeyi bir bağlantı
derlenirken yapılandırılabilir. build önce HubConnectionBuilder yöntemlerinden herhangi birini çağırarak gerekli
seçenekleri yapılandırın. Bağlantıyı start başlatın.

HubConnection hubConnection = HubConnectionBuilder.create(input)


.build();

İstemciden çağrı merkezi yöntemleri


Bir send çağrısı, hub yöntemini çağırır. Hub yöntemi adını ve hub yönteminde tanımlanan tüm bağımsız
değişkenleri send geçirin.

hubConnection.send("Send", input);
NOTE
Azure SignalR hizmetini sunucusuz moddakullanıyorsanız, bir istemciden hub yöntemlerini çağıramezsiniz. Daha fazla bilgi için
SignalR hizmeti belgelerinebakın.

Hub 'dan istemci yöntemlerini çağır


İstemcide hub 'ın çağırakullanabileceği yöntemleri tanımlamak için hubConnection.on kullanın. Bağlantıyı
başlatmadan önce, oluşturma işleminden sonra yöntemleri tanımlayın.

hubConnection.on("Send", (message) -> {


System.out.println("New Message: " + message);
}, String.class);

Günlüğe kaydetme ekleme


SignalR Java istemcisi, günlük kaydı için dolayısıyla slf4j kitaplığını kullanır. Bu, kitaplık kullanıcılarının belirli bir
günlüğe kaydetme bağımlılığı vererek kendi belirli günlük uygulamasını seçmesine olanak sağlayan, üst düzey bir
günlüğe kaydetme API 'sidir. Aşağıdaki kod parçacığı, SignalR Java istemcisiyle java.util.logging nasıl
kullanacağınızı gösterir.

implementation 'org.slf4j:slf4j-jdk14:1.7.25'

Bağımlılıklarınız için günlük kaydını yapılandırmazsanız, DOLAYıSıYLA SLF4J aşağıdaki uyarı iletisiyle varsayılan
işlem olmayan bir günlükçü yükler:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".


SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Bu, güvenle yoksayılabilir.

Android geliştirme notları


SignalR istemci özelliklerine Android SDK uyumlulukla ilgili olarak, hedef Android SDK sürümünüzü belirtirken
aşağıdaki öğeleri göz önünde bulundurun:
SignalR Java Istemcisi, Android API düzeyi 16 ve sonrasında çalışır.
Azure SignalR HIZMETI TLS 1,2 GEREKTIRDIĞINDEN ve SHA-1 tabanlı şifre paketlerini desteklemediğinden
Azure SignalR hizmeti üzerinden bağlanmak IÇIN Android API düzeyi 20 ve üzeri bir sürüm gerekir. Android,
API düzeyi 20 ' de SHA-256 (ve üzeri) şifre paketleri için destek ekledi .

Taşıyıcı belirteç kimlik doğrulamasını yapılandırma


Java istemcisinde SignalR, Httphubconnectionbuilder'a "erişim belirteci fabrikası" sağlayarak kimlik doğrulaması
için kullanılacak bir taşıyıcı belirteç yapılandırabilirsiniz. Rxjava tek bir<dize >sağlamak Için
withaccesstokenfactory kullanın. Tek. erteleçağrısıyla, istemciniz için erişim belirteçleri oluşturmak üzere mantık
yazabilirsiniz.
HubConnection hubConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withAccessTokenProvider(Single.defer(() -> {
// Your logic here.
return Single.just("An Access Token");
})).build();

Bilinen sınırlamalar
Yalnızca JSON Protokolü destekleniyor.
Taşıma geri dönüşü ve sunucu gönderme olayları aktarımı desteklenmez.
Yalnızca JSON Protokolü destekleniyor.
Yalnızca WebSockets taşıması desteklenir.
Akış henüz desteklenmiyor.

Ek kaynaklar
Java API'si başvurusu
ASP.NET Core SignalR hub 'ları kullanma
ASP.NET Core SignalR JavaScript istemcisi
Azure App Service için ASP.NET Core SignalR uygulaması yayımlama
Azure SignalR hizmeti sunucusuz belgeler
ASP.NET Core SignalR JavaScript istemcisi
13.11.2019 • 14 minutes to read • Edit Online

, Oychel Appel tarafından


ASP.NET Core SignalR JavaScript istemci kitaplığı, geliştiricilerin sunucu tarafı hub kodunu çağırmasını sağlar.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SignalR istemci paketini yükler


SignalR JavaScript istemci kitaplığı NPM paketi olarak dağıtılır. Visual Studio kullanıyorsanız, kök klasörde,
Paket Yöneticisi konsolundan npm install çalıştırın. Visual Studio Code için, Tümleşik
terminaldenkomutunu çalıştırın.

npm init -y
npm install @microsoft/signalr

NPM node_modules\@microsoft\signalr\dist\browser klasöre paket içeriğini yüklüyor. Wwwroot\lib klasörü


altında SignalR adlı yeni bir klasör oluşturun. SignalR. js dosyasını wwwroot\lib\signalr klasörüne kopyalayın.

npm init -y
npm install @aspnet/signalr

NPM node_modules\@aspnet\signalr\dist\browser klasöre paket içeriğini yüklüyor. Wwwroot\lib klasörü


altında SignalR adlı yeni bir klasör oluşturun. SignalR. js dosyasını wwwroot\lib\signalr klasörüne kopyalayın.

SignalR JavaScript istemcisini kullanma


<script> öğesinde JavaScript istemcisine SignalR başvurun.

<script src="~/lib/signalr/signalr.js"></script>

Bir hub 'a bağlanma


Aşağıdaki kod bir bağlantı oluşturur ve başlatır. Hub 'ın adı büyük/küçük harfe duyarlıdır.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.configureLogging(signalR.LogLevel.Information)
.build();

connection.start().then(function () {
console.log("connected");
});

Çapraz kaynak bağlantıları


Genellikle, tarayıcılar istenen sayfayla aynı etki alanındaki bağlantıları yükler. Ancak, başka bir etki alanına
bağlantı gerektiğinde bu durumlar vardır.
Kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını engellemek için, Çıkış noktaları varsayılan
olarak devre dışı bırakılır. Bir çapraz kaynak isteğine izin vermek için Startup sınıfında etkinleştirin.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SignalRChat.Hubs;

namespace SignalRChat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc();

services.AddCors(options => options.AddPolicy("CorsPolicy",


builder =>
{
builder.AllowAnyMethod().AllowAnyHeader()
.WithOrigins("http://localhost:55830")
.AllowCredentials();
}));

services.AddSignalR();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chathub");
});
app.UseMvc();
}
}
}
İstemciden çağrı merkezi yöntemleri
JavaScript istemcileri, Hubconnection'un Invoke yöntemi aracılığıyla hub 'larda ortak yöntemleri çağırır.
invoke yöntemi iki bağımsız değişkeni kabul eder:

Hub yönteminin adı. Aşağıdaki örnekte, hub 'daki Yöntem adı SendMessage .
Hub yönteminde tanımlanan bağımsız değişkenler. Aşağıdaki örnekte, bağımsız değişken adı message .
Örnek kod, Internet Explorer hariç tüm büyük tarayıcıların güncel sürümlerinde desteklenen ok işlev
sözdizimini kullanır.

connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));

NOTE
Azure SignalR hizmetini sunucusuz moddakullanıyorsanız, bir istemciden hub yöntemlerini çağıramezsiniz. Daha fazla bilgi
için SignalR hizmeti belgelerinebakın.

invoke yöntemi bir JavaScript Promisedöndürür. Promise , sunucudaki yöntemi döndürdüğünde döndürülen
değer (varsa) ile çözümlenir. Sunucu üzerindeki yöntem bir hata oluşturursa Promise hata iletisiyle reddedilir.
Bu durumları (veya await sözdizimini) işlemek için Promise üzerinde then ve catch yöntemlerini kullanın.
send yöntemi bir JavaScript Promise döndürür. İleti sunucuya gönderildiğinde Promise çözümlenir. İleti
gönderilirken bir hata oluşursa Promise hata iletisiyle reddedilir. Bu durumları (veya await sözdizimini)
işlemek için Promise üzerinde then ve catch yöntemlerini kullanın.

NOTE
send kullanmak sunucu iletiyi almadan önce beklemez. Sonuç olarak, sunucudan veri veya hata döndürülmesi mümkün
değildir.

Hub 'dan istemci yöntemlerini çağır


Hub 'dan ileti almak için HubConnection on metodunu kullanarak bir yöntemi tanımlayın.
JavaScript istemci yönteminin adı. Aşağıdaki örnekte, yöntem adı ReceiveMessage .
Hub 'ın yönteme geçirdiği bağımsız değişkenler. Aşağıdaki örnekte, bağımsız değişken değeri message .

connection.on("ReceiveMessage", (user, message) => {


const encodedMsg = user + " says " + message;
const li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});

connection.on önceki kod, sunucu tarafı kodu Sendadsync yöntemi kullanılarak çağırdığında çalışır.

public async Task SendMessage(string user, string message)


{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}

SignalR, SendAsync ve connection.on tanımlanan yöntem adı ve bağımsız değişkenlerle eşleştirerek hangi
istemci yönteminin çağrılacağını belirler.

NOTE
En iyi uygulama olarak, on sonra HubConnection Başlangıç yöntemini çağırın. Bunun yapılması, işleyicilerinin herhangi
bir ileti alınmadan önce kaydolmasını sağlar.

Hata işleme ve günlüğe kaydetme


İstemci tarafı hatalarını işlemek için start yönteminin sonuna bir catch yöntemi zincirleyin. Hataları tarayıcı
konsoluna çıkarmak için console.error kullanın.

connection.start().catch(function (err) {
return console.error(err.toString());
});

Bağlantı yapıldığında günlüğe bir günlükçü ve olay türü geçirerek istemci tarafı günlük izlemeyi ayarlayın.
İletiler, belirtilen günlük düzeyi ve daha yükseği ile günlüğe kaydedilir. Kullanılabilir günlük düzeyleri aşağıdaki
gibidir:
– hata iletileri signalR.LogLevel.Error . Yalnızca Error iletileri günlüğe kaydeder.
olası hatalar hakkında – uyarı iletileri signalR.LogLevel.Warning . Warning ve Error iletileri günlüğe
kaydeder.
hata olmadan – durum iletileri signalR.LogLevel.Information . Information , Warning ve Error iletileri
günlüğe kaydeder.
Izleme iletilerini – signalR.LogLevel.Trace . Hub ve istemci arasında taşınan veriler de dahil olmak üzere her
şeyi günlüğe kaydeder.
Günlük düzeyini yapılandırmak için Hubconnectionbuilder üzerinde configurelogging yöntemini kullanın.
İletiler tarayıcı konsoluna kaydedilir.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.configureLogging(signalR.LogLevel.Information)
.build();

İstemcileri yeniden bağla


Otomatik olarak yeniden bağlan
SignalR için JavaScript istemcisi, Hubconnectionbuilder'daki withAutomaticReconnect yöntemi kullanılarak
otomatik olarak yeniden bağlanacak şekilde yapılandırılabilir. Varsayılan olarak otomatik olarak yeniden
bağlanmaz.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.withAutomaticReconnect()
.build();

Hiçbir parametre olmadan, withAutomaticReconnect() her bir yeniden bağlanma denemesini denemeden önce,
dört başarısız denemeden sonra durdurmadan, istemciyi 0, 2, 10 ve 30 saniye bekleyecek şekilde yapılandırır.
Yeniden bağlanma girişimlerini başlatmadan önce, HubConnection HubConnectionState.Reconnecting durumuna
geçer ve onclosegeri çağırmaları Disconnected , otomatik yeniden bağlanma yapılandırması olmadan
HubConnection gibi tetikleyerek onreconnecting geri çağırmaları tetikler. Bu, kullanıcıların bağlantının
kaybedildiği ve Kullanıcı arabirimi öğelerini devre dışı bırakan kullanıcıları uyarma fırsatı sağlar.

connection.onreconnecting((error) => {
console.assert(connection.state === signalR.HubConnectionState.Reconnecting);

document.getElementById("messageInput").disabled = true;

const li = document.createElement("li");
li.textContent = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messagesList").appendChild(li);
});

İstemci ilk dört denemeden sonra başarıyla yeniden bağlanırsa, HubConnection Connected duruma geri
dönerek onreconnected geri çağırmaları harekete geçer. Bu, kullanıcılara bağlantı yeniden kurulmadığını
bildirmek için bir fırsat sağlar.
Bağlantı sunucuya tamamen yeni göründüğünden, onreconnected geri çağırması için yeni bir connectionId
sunulacaktır.

WARNING
HubConnection anlaşmayı atlayacakşekilde yapılandırıldıysa, onreconnected geri aramanın connectionId
parametresi tanımsız olacaktır.

connection.onreconnected((connectionId) => {
console.assert(connection.state === signalR.HubConnectionState.Connected);

document.getElementById("messageInput").disabled = false;

const li = document.createElement("li");
li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`;
document.getElementById("messagesList").appendChild(li);
});

withAutomaticReconnect() , ilk başlatma başarısızlıklarını yeniden denemek için HubConnection yapılandırmaz,


bu nedenle başlatma hatalarının el ile işlenmesi gerekir:

async function start() {


try {
await connection.start();
console.assert(connection.state === signalR.HubConnectionState.Connected);
console.log("connected");
} catch (err) {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
console.log(err);
setTimeout(() => start(), 5000);
}
};

İstemci ilk dört denemeden sonra başarıyla yeniden bağlanmazsa, HubConnection Disconnected durumuna
geçer ve OnClose geri aramalarını harekete geçirebilir. Bu, kullanıcılara bağlantının kalıcı olarak
kaybedilmediğini bildirme ve sayfayı yenilemeyi önerme olanağı sağlar:
connection.onclose((error) => {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);

document.getElementById("messageInput").disabled = true;

const li = document.createElement("li");
li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the
connection.`;
document.getElementById("messagesList").appendChild(li);
});

Bağlantıyı kesmeden veya yeniden bağlanma zamanlamasını değiştirmeden önce özel sayıda yeniden bağlantı
girişimi yapılandırmak için withAutomaticReconnect , her bir yeniden bağlanma girişimine başlamadan önce
beklenecek gecikme süresi temsil eden bir sayı dizisini kabul eder.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.withAutomaticReconnect([0, 0, 10000])
.build();

// .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

Yukarıdaki örnek, bağlantı kaybolduktan hemen sonra yeniden bağlanmaya başlamak için HubConnection
yapılandırır. Bu, varsayılan yapılandırma için de geçerlidir.
İlk yeniden bağlantı girişimi başarısız olursa, ikinci yeniden bağlanma denemesi de varsayılan yapılandırmada
olduğu gibi 2 saniye beklemek yerine hemen başlatılır.
İkinci yeniden bağlantı girişimi başarısız olursa, üçüncü yeniden bağlanma denemesi varsayılan yapılandırma
gibi 10 saniye içinde başlar.
Özel davranış daha sonra varsayılan şekilde yeniden bağlantı kurmayı denemek yerine, üçüncü yeniden
bağlantı girişimi başarısızlığından sonra varsayılan davranıştan sonra yeniden bir kez daha fazla yeniden
bağlantı kurmaya çalışır.
Otomatik yeniden bağlanma denemelerinin zamanlaması ve sayısı üzerinde daha fazla denetime sahip olmak
istiyorsanız withAutomaticReconnect , nextRetryDelayInMilliseconds adlı tek bir yönteme sahip IRetryPolicy
arabirimini uygulayan bir nesneyi kabul eder.
nextRetryDelayInMilliseconds RetryContext türünde tek bir bağımsız değişken alır. RetryContext üç özelliğe
sahiptir: previousRetryCount , elapsedMilliseconds ve retryReason number , number ve Error . İlk yeniden
bağlanma denemesinden önce, hem previousRetryCount hem de elapsedMilliseconds sıfır olur ve
retryReason bağlantının kaybolmasına neden olan hata olacaktır. Her başarısız yeniden deneme denemesinden
previousRetryCount , elapsedMilliseconds bir kez artırılır, bu, şimdiye kadar geçen süre (milisaniye olarak) ve
retryReason son yeniden bağlanma denemesinin başarısız olmasına neden olacak hata miktarını yansıtacak
şekilde güncelleştirilir.
nextRetryDelayInMilliseconds , sonraki yeniden bağlanma girişiminden önce beklenecek milisaniye sayısını
temsil eden bir sayı döndürmelidir veya HubConnection yeniden bağlamayı durdurması gerekiyorsa null .
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.elapsedMilliseconds < 60000) {
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
return Math.random() * 10000;
} else {
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
})
.build();

Alternatif olarak, el ile yeniden bağlanmabölümünde gösterildiği gibi istemcinizi el ile yeniden bağlayacaksınız.
El ile yeniden bağlan

WARNING
3,0 ' den önce SignalR JavaScript istemcisi otomatik olarak yeniden bağlanmaz. İstemcinizi el ile yeniden bağlayacaksınız
kodu yazmanız gerekir.

Aşağıdaki kod, genel bir el ile yeniden bağlantı yaklaşımını göstermektedir:


1. Bir işlev (Bu durumda start işlevi) bağlantıyı başlatmak için oluşturulur.
2. Bağlantının onclose olay işleyicisinde start işlevini çağırın.

async function start() {


try {
await connection.start();
console.log("connected");
} catch (err) {
console.log(err);
setTimeout(() => start(), 5000);
}
};

connection.onclose(async () => {
await start();
});

Gerçek dünyada bir uygulama, bir üstel geri kapatmayı kullanır veya vermeden önce belirtilen sayıda kez
yeniden dener.

Ek kaynaklar
JavaScript API'si başvurusu
JavaScript öğreticisi
WebPack ve TypeScript öğreticisi
Merkezler
.NET istemcisi
Azure'a Yayımlama
Çıkış noktaları arası Istekler (CORS )
Azure SignalR hizmeti sunucusuz belgeler
ASP.NET Core SignalR barındırma ve ölçeklendirme
13.11.2019 • 8 minutes to read • Edit Online

, Andrew Stanton-nuri, Brady Gasterve Tom Dykstra,


Bu makalede, ASP.NET Core SignalRkullanan yüksek trafik uygulamalarına yönelik barındırma ve ölçeklendirme
konuları açıklanmaktadır.

Yapışkan oturumlar
SignalR, belirli bir bağlantı için tüm HTTP isteklerinin aynı sunucu işlemi tarafından işlenmesini gerektirir. Sunucu
grubunda (birden çok sunucu) SignalR çalıştığında, "yapışkan oturumlar" kullanılmalıdır. "Yapışkan oturumlar", bazı
yük dengeleyiciler tarafından oturum benzeşimi olarak da adlandırılır. Azure App Service istekleri yönlendirmek
için uygulama Isteği yönlendirme (ARR ) kullanır. Azure App Service "ARR benzeşimi" ayarının etkinleştirilmesi
"yapışkan oturumlar" sağlayacaktır. Yapışkan oturumların gerekmediği tek koşullar şunlardır:
1. Tek bir sunucuda barındırırken, tek bir işlemde.
2. Azure SignalR hizmetini kullanırken.
3. Tüm istemciler yalnızca WebSockets kullanacak şekilde yapılandırıldığında ve istemci yapılandırmasında
skipanlaşma ayarı etkinse.
Tüm diğer koşullarda (Redsıs geri düzlemi kullanıldığında dahil), sunucu ortamının yapışkan oturumlar için
yapılandırılması gerekir.
SignalRiçin Azure App Service yapılandırma hakkında yönergeler için bkz. Azure App Service için ASP.NET Core
SignalR uygulaması yayımlama.

TCP bağlantı kaynakları


Bir Web sunucusunun destekleyebileceği eşzamanlı TCP bağlantısı sayısı sınırlıdır. Standart HTTP istemcileri, kısa
ömürlü bağlantıları kullanır. Bu bağlantılar, istemci boşta kaldığında ve daha sonra yeniden açıldığı zaman
kapatılabilir. Öte yandan, SignalR bir bağlantı kalıcıdır. SignalR bağlantılar, istemci boşta kaldığında bile açık kalır.
Çok sayıda istemciye hizmet veren yüksek trafikli bir uygulamada, bu kalıcı bağlantılar sunucuların en fazla
bağlantı sayısına ulaşmasına neden olabilir.
Kalıcı bağlantılar, her bağlantıyı izlemek için ek bellek de tüketir.
SignalR göre bağlantıyla ilgili kaynakların ağır kullanımı, aynı sunucuda barındırılan diğer Web uygulamalarını
etkileyebilir. SignalR açılıp en son kullanılabilir TCP bağlantılarını tutuyorsa, aynı sunucudaki diğer Web
uygulamalarına da daha fazla bağlantı bulunmaz.
Sunucuda bağlantı biterse rastgele yuva hataları ve bağlantı sıfırlama hataları görürsünüz. Örneğin:

An attempt was made to access a socket in a way forbidden by its access permissions...

SignalR kaynak kullanımını diğer Web uygulamalarındaki hatalara neden olacak şekilde korumak için, diğer Web
uygulamalarınızdan farklı sunucularda SignalR çalıştırın.
SignalR kaynak kullanımını SignalR uygulamasında hatalara neden olacak şekilde korumak için, bir sunucunun
işleyeceği bağlantı sayısını sınırlamak üzere ölçeği ölçeklendirin.
Ölçeklendirme
SignalR kullanan bir uygulamanın, bir sunucu grubu için sorunlar oluşturan tüm bağlantılarını izlemesi gerekir. Bir
sunucu ekleyin ve diğer sunucuların hakkında bilgi sahibi olmadığı yeni bağlantıları alır. Örneğin, aşağıdaki
diyagramdaki her bir sunucuda SignalR diğer sunuculardaki bağlantılardan haberdar değildir. Sunuculardan
birindeki SignalR tüm istemcilere ileti göndermek istediğinde, ileti yalnızca bu sunucuya bağlı olan istemcilere
gider.

Bu sorunu çözmeye yönelik seçenekler Azure SignalR hizmetidir ve redsıs arkadüzledir.

Azure SignalR hizmeti


Azure SignalR hizmeti, arka düzlemi yerine bir ara sunucu. İstemci sunucuya bir bağlantı başlattığında, istemci
hizmete bağlanmak için yeniden yönlendirilir. Bu işlem aşağıdaki diyagramda gösterilmiştir:

Sonuç olarak, hizmetin tüm istemci bağlantılarını yönetmesi, her sunucunun aşağıdaki diyagramda gösterildiği gibi
yalnızca küçük bir sabit bağlantı sayısına ihtiyacı vardır:

Bu genişleme yaklaşımına yönelik bu yaklaşım, Redsıs geri düzlemi 'nin diğer avantajlarından biridir:
İstemci benzeşimiolarak da bilinen yapışkan oturumlar gerekli değildir, çünkü istemciler, bağlandıklarında Azure
SignalR hizmetine anında yönlendirilir.
SignalR bir uygulama, gönderilen ileti sayısına göre ölçeklenebilir, ancak Azure SignalR hizmeti herhangi bir
sayıda bağlantıyı işleyecek şekilde otomatik olarak ölçeklendirilir. Örneğin, binlerce istemci olabilir, ancak saniye
başına yalnızca birkaç ileti gönderiliyorsa, SignalR uygulamanın yalnızca bağlantıları işlemek için birden çok
sunucuya ölçeklendirilmesi gerekmez.
SignalR bir uygulama, SignalRolmayan bir Web uygulamasından daha fazla bağlantı kaynağı kullanmaz.
Bu nedenlerden dolayı, App Service, VM 'Ler ve kapsayıcılar dahil olmak üzere Azure üzerinde barındırılan tüm
ASP.NET Core SignalR uygulamaları için Azure SignalR hizmetini öneririz.
Daha fazla bilgi için bkz. Azure SignalR hizmeti belgeleri.

Redis kartı
Redsıs , bir yayımlama/abonelik modeliyle bir mesajlaşma sistemini destekleyen bellek içi anahtar-değer
deposudur. SignalR redin backdüzlemi, iletileri diğer sunuculara iletmek için pub/Sub özelliğini kullanır. İstemci bir
bağlantı yaptığında, bağlantı bilgileri geri düzleme geçirilir. Bir sunucu tüm istemcilere ileti göndermek istediğinde,
bu geri düzlemi gönderir. Biriktirme listesi, tüm bağlı istemcileri ve bunların hangi sunuculara olduğunu bilir. İletiyi
ilgili sunucuları aracılığıyla tüm istemcilere gönderir. Bu işlem aşağıdaki diyagramda gösterilmiştir:

Redsıs geri düzlemi, kendi altyapınızda barındırılan uygulamalar için önerilen genişleme yaklaşımıdır. Azure
SignalR hizmeti, veri merkezinizdeki bir Azure veri merkezi arasındaki bağlantı gecikmesi nedeniyle Şirket içi
uygulamalarla üretim kullanımı için pratik bir seçenek değildir.
Daha önce bahsedilen Azure SignalR hizmet avantajları Redsıs geri düzlemi için dezavantajlardır:
İstemci benzeşimiolarak da bilinen yapışkan oturumlar gereklidir. Sunucuda bir bağlantı başlatıldıktan sonra
bağlantı o sunucuda kalmaya devam etmek zorunda kalır.
Birkaç ileti gönderilse bile SignalR bir uygulama, istemci sayısına göre ölçeklendirmelidir.
SignalR uygulaması, SignalRolmayan bir Web uygulamasından çok daha fazla bağlantı kaynağı kullanır.

Sonraki adımlar
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
Azure SignalR hizmeti belgeleri
Redsıs geri düzlemi ayarlama
Azure App Service için ASP.NET Core SignalR
uygulaması yayımlama
13.11.2019 • 4 minutes to read • Edit Online

, Brady Gaster tarafından


Azure App Service , Web uygulamalarını barındırmak için ASP.NET Core dahil olmak üzere bir Microsoft bulut
bilgi işlem platformu hizmetidir.

NOTE
Bu makale, Visual Studio 'dan bir ASP.NET Core SignalR uygulaması yayımlamaya başvurur. Daha fazla bilgi için bkz. Azure
içinSignalR hizmeti.

Uygulamayı yayımlama
Bu makalede, Visual Studio 'daki araçları kullanarak yayımlama ele alınmaktadır. Visual Studio Code
kullanıcılar, Azure 'da uygulama yayımlamak için Azure CLI komutlarını kullanabilir. Daha fazla bilgi için bkz.
komut satırı araçlarıyla Azure 'da ASP.NET Core uygulama yayımlama.
1. Çözüm Gezgini projede projeye sağ tıklayın ve Yayımla' yı seçin.
2. Bir yayımlama hedefi seç iletişim kutusunda App Service ve Yeni oluştur ' un seçili olduğunu
doğrulayın.
3. Yayımla düğmesi açılan listesinden Profil oluştur ' u seçin.
App Service oluştur iletişim kutusunda aşağıdaki tabloda açıklanan bilgileri girin ve Oluştur' u seçin.

ÖĞE AÇIKLAMA

Ad Uygulamanın benzersiz adı.

Aboneliğiniz Uygulamanın kullandığı Azure aboneliği.

Kaynak grubu Uygulamanın ait olduğu ilgili kaynaklar grubu.

Barındırma planı Web uygulaması için fiyatlandırma planı.

4. Bağımlılıklar > Ekle açılan listesinden Azure SignalR hizmetini seçin:

5. Azure SignalR hizmeti iletişim kutusunda yeni bir Azure SignalR hizmet örneği oluştur' u seçin.
6. Bir ad, kaynak grubuve konumbelirtin. Azure SignalR hizmeti iletişim kutusuna dönün ve Ekle' yi
seçin.
Visual Studio aşağıdaki görevleri tamamlar:
Yayımlama ayarlarını içeren bir yayımlama profili oluşturur.
Belirtilen ayrıntılarla bir Azure Web uygulaması oluşturur.
Uygulamayı yayımlar.
Web uygulamasını yükleyen bir tarayıcı başlatır.
Uygulama URL 'sinin biçimi {APP SERVICE NAME}.azurewebsites.net . Örneğin, SignalRChatApp adlı bir
uygulamanın https://signalrchatapp.azurewebsites.net URL 'SI vardır.
Bir Preview .NET Core sürümünü hedefleyen bir uygulama dağıtırken HTTP 502,2 -Hatalı ağ geçidi hatası
oluşursa, bu sorunu çözmek için Azure App Service ASP.NET Core önizleme sürümünü dağıtma bölümüne
bakın.

Uygulamayı Azure App Service yapılandırma


NOTE
Bu bölüm yalnızca Azure SignalR hizmetini kullanmayan uygulamalar için geçerlidir.
Uygulama Azure SignalR hizmetini kullanıyorsa, App Service uygulama Isteği yönlendirme (ARR) benzeşimi ve bu
bölümde açıklanan Web Yuvaları yapılandırmasını gerektirmez. İstemciler Web yuvalarını doğrudan uygulamaya değil
Azure SignalR hizmetine birbirine bağlayamıyor.

Azure SignalR hizmeti olmadan barındırılan uygulamalar için şunları etkinleştirin:


İstekleri bir kullanıcıdan tekrar aynı App Service örneğine yönlendirmek için ARR benzeşimi . Varsayılan
ayar Açık ' dır.
Web Sockets taşımanın çalışmasına izin veren Web Yuvaları . Varsayılan ayar kapalıdır.
1. Azure portal, uygulama hizmetleri' nde Web uygulamasına gidin.
2. Yapılandırma > genel ayarları' nı açın.
3. Web yuvalarını Açıkolarak ayarlayın.
4. ARR benzeşiminin Açıkolarak ayarlandığını doğrulayın.

App Service planı limitleri


Web Yuvaları ve diğer aktarımlar, seçilen App Service planına göre sınırlandırılır.Daha fazla bilgi için Azure
abonelik ve hizmet sınırları, Kotalar ve kısıtlamalar makalesinin Azure Cloud Services sınırları ve App Service
sınırları bölümlerine bakın.

Ek kaynaklar
Azure SignalR hizmeti nedir?
ASP.NET Core SignalR giriş
ASP.NET Core barındırma ve dağıtma
Visual Studio ile Azure'a bir ASP.NET Core uygulaması yayımlama
Komut satırı araçlarıyla Azure 'da ASP.NET Core uygulaması yayımlama
Azure 'da ASP.NET Core Preview uygulamaları barındırma ve dağıtma
ASP.NET Core SignalR genişleme için Redsıs arka
düzlemi ayarlama
26.11.2019 • 6 minutes to read • Edit Online

, Andrew Stanton-nuri, Brady Gasterve Tom Dykstra,


Bu makalede, bir ASP.NET Core SignalR uygulamasını ölçeklendirmek için kullanılacak bir redo sunucusu
ayarlamanın SignalRözgü yönleri açıklanmaktadır.

Redsıs geri düzlemi ayarlama


Redsıs sunucusunu dağıtın.

IMPORTANT
Üretim kullanımı için, yalnızca SignalR uygulamasıyla aynı veri merkezinde çalıştığında Redsıs geri düzlemi önerilir. Aksi
takdirde, ağ gecikmesi performansı düşürür. SignalR uygulamanız Azure bulutu 'nda çalışıyorsa, redin geri düzlemi
yerine Azure SignalR hizmeti önerilir. Geliştirme ve test ortamları için Azure Redis Cache hizmetini kullanabilirsiniz.

Daha fazla bilgi için aşağıdaki kaynaklara bakın:


ASP.NET Core SignalR üretim barındırma ve ölçeklendirme
Redsıs belgeleri
Azure Redis Cache belgeleri
SignalR uygulamasında Microsoft.AspNetCore.SignalR.Redis NuGet paketini () yüklemelisiniz.
Startup.ConfigureServices yönteminde, AddSignalR sonra AddRedis çağırın:

services.AddSignalR().AddRedis("<your_Redis_connection_string>");

Seçenekleri gerektiği şekilde yapılandırın:


Çoğu seçenek bağlantı dizesinde veya ConfigurationOptions nesnesinde ayarlanabilir.
ConfigurationOptions belirtilen seçenekler bağlantı dizesinde ayarlanmış olanları geçersiz kılar.

Aşağıdaki örnek, ConfigurationOptions nesnesindeki seçeneklerin nasıl ayarlanacağını gösterir. Bu örnek,


aşağıdaki adımda anlatıldığı gibi birden çok uygulamanın aynı redo örneğini paylaşabilmesi için bir kanal
öneki ekler.

services.AddSignalR()
.AddRedis(connectionString, options => {
options.Configuration.ChannelPrefix = "MyApp";
});

Yukarıdaki kodda options.Configuration , bağlantı dizesinde belirtilen şeyle başlatılır.


SignalR uygulamasında, aşağıdaki NuGet paketlerinden birini yüklemelisiniz:
Microsoft.AspNetCore.SignalR.StackExchangeRedis -StackExchange 'e bağlıdır. Redsıs 2. X.X. Bu, ASP.NET
Core 2,2 ve üzeri için önerilen pakettir.
Microsoft.AspNetCore.SignalR.Redis -StackExchange. Redsıs 1. X.X. 'e bağımlıdır Bu paket ASP.NET Core
3,0 ve üzeri bir sürüme dahil değildir.
Startup.ConfigureServices yönteminde, AddStackExchangeRedisçağırın:

services.AddSignalR().AddStackExchangeRedis("<your_Redis_connection_string>");

Microsoft.AspNetCore.SignalR.Redis kullanırken AddRedisçağırın.


Seçenekleri gerektiği şekilde yapılandırın:
Çoğu seçenek bağlantı dizesinde veya ConfigurationOptions nesnesinde ayarlanabilir.
ConfigurationOptions belirtilen seçenekler bağlantı dizesinde ayarlanmış olanları geçersiz kılar.

Aşağıdaki örnek, ConfigurationOptions nesnesindeki seçeneklerin nasıl ayarlanacağını gösterir. Bu örnek,


aşağıdaki adımda anlatıldığı gibi birden çok uygulamanın aynı redo örneğini paylaşabilmesi için bir kanal
öneki ekler.

services.AddSignalR()
.AddStackExchangeRedis(connectionString, options => {
options.Configuration.ChannelPrefix = "MyApp";
});

Microsoft.AspNetCore.SignalR.Redis kullanırken AddRedisçağırın.


Yukarıdaki kodda options.Configuration , bağlantı dizesinde belirtilen şeyle başlatılır.
Redu seçenekleri hakkında daha fazla bilgi için bkz. StackExchange redin belgeleri.
SignalR uygulamasında, aşağıdaki NuGet paketini yüklerken:
Microsoft.AspNetCore.SignalR.StackExchangeRedis
Startup.ConfigureServices yönteminde, AddStackExchangeRedisçağırın:

services.AddSignalR().AddStackExchangeRedis("<your_Redis_connection_string>");

Seçenekleri gerektiği şekilde yapılandırın:


Çoğu seçenek bağlantı dizesinde veya ConfigurationOptions nesnesinde ayarlanabilir.
ConfigurationOptions belirtilen seçenekler bağlantı dizesinde ayarlanmış olanları geçersiz kılar.

Aşağıdaki örnek, ConfigurationOptions nesnesindeki seçeneklerin nasıl ayarlanacağını gösterir. Bu örnek,


aşağıdaki adımda anlatıldığı gibi birden çok uygulamanın aynı redo örneğini paylaşabilmesi için bir kanal
öneki ekler.

services.AddSignalR()
.AddStackExchangeRedis(connectionString, options => {
options.Configuration.ChannelPrefix = "MyApp";
});

Yukarıdaki kodda options.Configuration , bağlantı dizesinde belirtilen şeyle başlatılır.


Redu seçenekleri hakkında daha fazla bilgi için bkz. StackExchange redin belgeleri.
Birden çok SignalR uygulama için bir Redsıs sunucusu kullanıyorsanız, her bir SignalR uygulaması için farklı
bir kanal öneki kullanın.
Kanal öneki ayarlamak, farklı kanal öneklerini kullanan diğerlerinden bir SignalR uygulamasını yalıtır. Farklı
ön ekler atamadıysanız, bir uygulamadan tüm istemcilerine gönderilen bir ileti, Redo sunucusunu bir geri
düzlemi olarak kullanan tüm uygulamaların tüm istemcilerine gider.
Sunucu grubu yük dengeleme yazılımınızı yapışkan oturumlar için yapılandırın. Bunun nasıl yapılacağını
gösteren bazı örnekler aşağıda verilmiştir:
ISS
HAProxy
NGINX
pfSense

Redsıs sunucu hataları


Bir redin sunucusu aşağı gittiğinde SignalR, iletilerin teslim edilmediğini belirten özel durumlar oluşturur. Bazı tipik
özel durum iletileri:
İleti yazılamadı
' MethodName ' hub yöntemi çağrılamadı
Redsıs bağlantısı başarısız oldu
SignalR, sunucu geri geldiğinde iletileri göndermek için arabelleğe almaz. Redsıs sunucusu kapatıldığında
gönderilen iletiler kaybedilir.
Redi sunucusu yeniden kullanılabilir olduğunda SignalR otomatik olarak yeniden bağlanır.
Bağlantı hatalarıyla ilgili özel davranış
Redsıs bağlantı hatası olaylarının nasıl işleneceğini gösteren bir örnek aşağıda verilmiştir.

services.AddSignalR()
.AddRedis(o =>
{
o.ConnectionFactory = async writer =>
{
var config = new ConfigurationOptions
{
AbortOnConnectFail = false
};
config.EndPoints.Add(IPAddress.Loopback, 0);
config.SetDefaultPorts();
var connection = await ConnectionMultiplexer.ConnectAsync(config, writer);
connection.ConnectionFailed += (_, e) =>
{
Console.WriteLine("Connection to Redis failed.");
};

if (!connection.IsConnected)
{
Console.WriteLine("Did not connect to Redis.");
}

return connection;
};
});
services.AddSignalR()
.AddMessagePackProtocol()
.AddStackExchangeRedis(o =>
{
o.ConnectionFactory = async writer =>
{
var config = new ConfigurationOptions
{
AbortOnConnectFail = false
};
config.EndPoints.Add(IPAddress.Loopback, 0);
config.SetDefaultPorts();
var connection = await ConnectionMultiplexer.ConnectAsync(config, writer);
connection.ConnectionFailed += (_, e) =>
{
Console.WriteLine("Connection to Redis failed.");
};

if (!connection.IsConnected)
{
Console.WriteLine("Did not connect to Redis.");
}

return connection;
};
});

Redsıs Kümelemesi
Redsıs Kümelemesi , birden çok redo sunucusu kullanarak yüksek kullanılabilirlik elde etmek için kullanılan bir
yöntemdir. Kümeleme resmi olarak desteklenmez, ancak çalışmayabilir.

Sonraki adımlar
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
ASP.NET Core SignalR üretim barındırma ve ölçeklendirme
Redsıs belgeleri
StackExchange redin belgeleri
Azure Redis Cache belgeleri
Arka plan hizmetlerinde ana bilgisayar ASP.NET Core
SignalR
13.11.2019 • 5 minutes to read • Edit Online

, Brady Gaster tarafından


Bu makalede şu yönergelere kılavuzluk sunulmaktadır:
ASP.NET Core ile barındırılan arka plan çalışan işlemini kullanarak SignalR hub 'Ları barındırma.
.NET Core Backgroundserviceiçinden bağlı istemcilere ileti gönderme.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Başlangıç sırasında SignalR


Arka plan çalışan işleminin bağlamında ASP.NET Core SignalR hub 'Ları barındırmak, bir ASP.NET Core Web
uygulamasındaki hub barındırmakla aynıdır. Startup.ConfigureServices yönteminde, services.AddSignalR
çağırmak gereken hizmetleri SignalRdesteklemek için ASP.NET Core bağımlılık ekleme (dı) katmanına ekler.
Startup.Configure , MapHub yöntemi, ASP.NET Core isteği ardışık düzeninde Merkez uç noktaları arasında bağlantı
kurmak için UseEndpoints geri çağırmada çağrılır.

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddHostedService<Worker>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ClockHub>("/hubs/clock");
});
}
}

Arka plan çalışan işleminin bağlamında ASP.NET Core SignalR hub 'Ları barındırmak, bir ASP.NET Core Web
uygulamasındaki hub barındırmakla aynıdır. Startup.ConfigureServices yönteminde, services.AddSignalR
çağırmak gereken hizmetleri SignalRdesteklemek için ASP.NET Core bağımlılık ekleme (dı) katmanına ekler.
Startup.Configure , UseSignalR yöntemi ASP.NET Core isteği ardışık düzeninde hub uç noktaları için çağrılır.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddHostedService<Worker>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseSignalR((routes) =>
{
routes.MapHub<ClockHub>("/hubs/clock");
});
}
}

Yukarıdaki örnekte ClockHub sınıfı, türü kesin belirlenmiş bir hub oluşturmak için Hub<T> sınıfını uygular.
ClockHub , uç nokta /hubs/clock isteklere yanıt vermek için Startup sınıfında yapılandırıldı.

Türü kesin belirlenmiş hub 'Lar hakkında daha fazla bilgi için bkz. SignalR hub 'ları ASP.NET Core Için kullanma.

NOTE
Bu işlevsellik, Hub<t > sınıfıyla sınırlı değildir. Dynamichubgibi hub'dan devralan tüm sınıflar da çalışır.

public class ClockHub : Hub<IClock>


{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}

Türü kesin belirlenmiş ClockHub tarafından kullanılan arabirim IClock arabirimidir.

public interface IClock


{
Task ShowTime(DateTime currentTime);
}

Arka plan hizmetinden bir SignalR hub 'ı çağırma


Başlangıç sırasında, BackgroundService``Worker sınıfı AddHostedService kullanılarak bağlanır.

services.AddHostedService<Worker>();

SignalR, her hub 'ın, ASP.NET Core HTTP isteği ardışık düzeninde tek bir uç noktaya eklendiği Startup
aşamasında da kablolu olduğundan, her hub sunucu üzerinde bir IHubContext<T> temsil edilir. ASP.NET Core dı
özelliklerini kullanarak, barındırma katmanı tarafından oluşturulan BackgroundService sınıflar, MVC denetleyici
sınıfları veya Razor sayfa modelleri gibi diğer sınıflar, oluşturma sırasında IHubContext<ClockHub, IClock>
örneklerini kabul ederek sunucu tarafı hub 'Larına başvurular alabilir.

public class Worker : BackgroundService


{
private readonly ILogger<Worker> _logger;
private readonly IHubContext<ClockHub, IClock> _clockHub;

public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)


{
_logger = logger;
_clockHub = clockHub;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)


{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {Time}", DateTime.Now);
await _clockHub.Clients.All.ShowTime(DateTime.Now);
await Task.Delay(1000);
}
}
}

ExecuteAsync yöntemi arka plan hizmetinde yinelemeli olarak çağrıldığı için, sunucunun geçerli tarih ve saati
ClockHub kullanılarak bağlı istemcilere gönderilir.

Arka plan hizmetleriyle SignalR olaylara tepki verme


SignalR veya bir .NET masaüstü uygulamasının JavaScript istemcisini kullanan tek sayfalı bir uygulama gibi .NET
Client ASP.NET Core SignalRkullanarak kullanarak BackgroundService veya IHostedService bir uygulama da
SignalR hub 'Larına bağlanıp olaylara yanıt vermek için kullanılabilir.
ClockHubClient sınıfı hem IClock arabirimini hem de IHostedService arabirimini uygular. Bu şekilde, Startup
sırasında, sürekli olarak çalışmak ve sunucudan hub olaylarına yanıt vermek için bu şekilde kablolu bir şekilde
erişilebilir.

public partial class ClockHubClient : IClock, IHostedService


{
}

Başlatma sırasında ClockHubClient , bir HubConnection örneğini oluşturur ve hub 'ın ShowTime olayı için işleyici
olarak IClock.ShowTime metodunu kablodan bir şekilde kablolar.
private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)


{
_logger = logger;

_connection = new HubConnectionBuilder()


.WithUrl(Strings.HubUrl)
.Build();

_connection.On<DateTime>(Strings.Events.TimeSent,
dateTime => _ = ShowTime(dateTime));
}

public Task ShowTime(DateTime currentTime)


{
_logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

return Task.CompletedTask;
}

IHostedService.StartAsync uygulamasında HubConnection zaman uyumsuz olarak başlatılır.

public async Task StartAsync(CancellationToken cancellationToken)


{
// Loop is here to wait until the server is running
while (true)
{
try
{
await _connection.StartAsync(cancellationToken);

break;
}
catch
{
await Task.Delay(1000);
}
}
}

IHostedService.StopAsync yöntemi sırasında, HubConnection zaman uyumsuz olarak bırakıldı.

public Task StopAsync(CancellationToken cancellationToken)


{
return _connection.DisposeAsync();
}
}

Ek kaynaklar
Kullanmaya başlama
Merkezler
Azure'a Yayımlama
Türü kesin belirlenmiş hub 'Lar
ASP.NET Core SignalR yapılandırması
13.11.2019 • 33 minutes to read • Edit Online

JSON/MessagePack serileştirme seçenekleri


ASP.NET Core SignalR iletileri kodlamak için iki protokolü destekler: JSON ve MessagePack. Her protokol
serileştirme yapılandırma seçenekleri vardır.
JSON serileştirme, Addjsonprotocol genişletme yöntemi kullanılarak sunucuda yapılandırılabilir. AddJsonProtocol ,
Startup.ConfigureServices Addsignalr öğesinden sonra eklenebilir. AddJsonProtocol yöntemi, options nesnesini
alan bir temsilciyi alır. Bu nesnedeki Payloadserializeroptions özelliği, bağımsız değişkenlerin serileştirmesini ve
dönüş değerlerini yapılandırmak için kullanılabilen bir System.Text.Json JsonSerializerOptions nesnesidir. Daha
fazla bilgi için bkz. System. Text. JSON belgeleri.
Örnek olarak, serileştiriciyi varsayılan "camelCase" adları yerine özellik adlarının büyük küçük harflerini
değiştirmemelidir şekilde yapılandırmak için, Startup.ConfigureServices içinde aşağıdaki kodu kullanın:

services.AddSignalR()
.AddJsonProtocol(options => {
options.PayloadSerializerOptions.PropertyNamingPolicy = null
});

.NET istemcisinde aynı AddJsonProtocol uzantısı yöntemi Hubconnectionbuilderüzerinde bulunur. Uzantı


metodunu çözümlemek için Microsoft.Extensions.DependencyInjection ad alanı içeri aktarılmalıdır:

// At the top of the file:


using Microsoft.Extensions.DependencyInjection;

// When constructing your connection:


var connection = new HubConnectionBuilder()
.AddJsonProtocol(options => {
options.PayloadSerializerOptions.PropertyNamingPolicy = null;
})
.Build();

NOTE
JavaScript istemcisinde Şu anda JSON serileştirme yapılandırmak mümkün değildir.

Newtonsoft. JSON öğesine geç


System.Text.Json desteklenmeyen Newtonsoft.Json özelliklerine ihtiyacınız varsa, bkz. Newtonsoft. JSON öğesine
geçme.
JSON serileştirme, Startup.ConfigureServices yönteminizin Addsignalr öğesinden sonra eklenebilecek
addjsonprotocol genişletme yöntemi kullanılarak sunucuda yapılandırılabilir. AddJsonProtocol yöntemi, options
nesnesini alan bir temsilciyi alır. Bu nesnedeki Payloadserializersettings özelliği, bağımsız değişkenlerin
serileştirmesini ve dönüş değerlerini yapılandırmak için kullanılabilen bir JSON.net JsonSerializerSettings
nesnesidir. Daha fazla bilgi için JSON.net belgelerinebakın.
Örnek olarak, serileştiriciyi varsayılan "camelCase" adları yerine "PascalCase" özellik adlarını kullanacak şekilde
yapılandırmak için, Startup.ConfigureServices ' de aşağıdaki kodu kullanın:
services.AddSignalR()
.AddJsonProtocol(options => {
options.PayloadSerializerSettings.ContractResolver =
new DefaultContractResolver();
});

.NET istemcisinde aynı AddJsonProtocol uzantısı yöntemi Hubconnectionbuilderüzerinde bulunur. Uzantı


metodunu çözümlemek için Microsoft.Extensions.DependencyInjection ad alanı içeri aktarılmalıdır:

// At the top of the file:


using Microsoft.Extensions.DependencyInjection;

// When constructing your connection:


var connection = new HubConnectionBuilder()
.AddJsonProtocol(options => {
options.PayloadSerializerSettings.ContractResolver =
new DefaultContractResolver();
})
.Build();

NOTE
JavaScript istemcisinde Şu anda JSON serileştirme yapılandırmak mümkün değildir.

MessagePack serileştirme seçenekleri


MessagePack serileştirme, Addmessagepackprotocol çağrısına bir temsilci sağlanarak yapılandırılabilir. Daha fazla
bilgi için bkz. SignalRMessagePack .

NOTE
Şu anda JavaScript istemcisinde MessagePack serileştirme yapılandırmak mümkün değildir.

Sunucu seçeneklerini yapılandırma


Aşağıdaki tabloda SignalR hub 'ları yapılandırmaya yönelik seçenekler açıklanmaktadır:

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ClientTimeoutInterval 30 saniye Sunucu, bu aralıkta (canlı tut dahil) bir


ileti almamışsa istemcinin bağlantısının
kesileceğini kabul eder. Bu işlem,
uygulanması nedeniyle istemcinin
bağlantısının gerçekten kesilmesinin
ardından bu zaman aşımı aralığından
daha uzun sürebilir. Önerilen değer
KeepAliveInterval değeri iki katına
kaydedilir.
SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

HandshakeTimeout 15 saniye İstemci bu zaman aralığı içinde bir ilk el


sıkışma iletisi göndermezse bağlantı
kapatılır. Bu, yalnızca önemli ağ
gecikmesi nedeniyle el sıkışma zaman
aşımı hataları gerçekleşirken
değiştirilmesi gereken gelişmiş bir
ayardır. El sıkışma işlemi hakkında daha
fazla ayrıntı için SignalR hub protokol
belirtiminebakın.

KeepAliveInterval 15 saniye Sunucu bu Aralık dahilinde bir ileti


göndermediyse bağlantının açık
tutulması için bir ping iletisi otomatik
olarak gönderilir. KeepAliveInterval
değiştirilirken, istemcide
ServerTimeout /
serverTimeoutInMilliseconds ayarını
değiştirin. Önerilen ServerTimeout /
serverTimeoutInMilliseconds değeri
KeepAliveInterval değeri iki katına
kaydedilir.

SupportedProtocols Tüm yüklü protokoller Bu hub tarafından desteklenen


protokoller. Varsayılan olarak, sunucuda
kayıtlı tüm protokollere izin verilir, ancak
tek tek hub 'lara yönelik belirli
protokolleri devre dışı bırakmak için
protokollerin bu listeden kaldırılması
gerekir.

EnableDetailedErrors false true , bir hub yönteminde özel durum


oluştuğunda istemcilere ayrıntılı özel
durum iletileri döndürülür. Varsayılan
değer false , bu özel durum
iletilerinde gizli bilgiler bulunabilir.

StreamBufferCapacity 10 İstemci yükleme akışları için ara belleğe


oluşturulabilecek en fazla öğe sayısı. Bu
sınıra ulaşıldığında, sunucu akış öğelerini
işlemeden, etkinleştirmeleri işleme
engellenir.

MaximumReceiveMessageSize 32 KB Tek bir gelen hub iletisinin en büyük


boyutu.

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ClientTimeoutInterval 30 saniye Sunucu, bu aralıkta (canlı tut dahil) bir


ileti almamışsa istemcinin bağlantısının
kesileceğini kabul eder. Bu işlem,
uygulanması nedeniyle istemcinin
bağlantısının gerçekten kesilmesinin
ardından bu zaman aşımı aralığından
daha uzun sürebilir. Önerilen değer
KeepAliveInterval değeri iki katına
kaydedilir.
SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

HandshakeTimeout 15 saniye İstemci bu zaman aralığı içinde bir ilk el


sıkışma iletisi göndermezse bağlantı
kapatılır. Bu, yalnızca önemli ağ
gecikmesi nedeniyle el sıkışma zaman
aşımı hataları gerçekleşirken
değiştirilmesi gereken gelişmiş bir
ayardır. El sıkışma işlemi hakkında daha
fazla ayrıntı için SignalR hub protokol
belirtiminebakın.

KeepAliveInterval 15 saniye Sunucu bu Aralık dahilinde bir ileti


göndermediyse bağlantının açık
tutulması için bir ping iletisi otomatik
olarak gönderilir. KeepAliveInterval
değiştirilirken, istemcide
ServerTimeout /
serverTimeoutInMilliseconds ayarını
değiştirin. Önerilen ServerTimeout /
serverTimeoutInMilliseconds değeri
KeepAliveInterval değeri iki katına
kaydedilir.

SupportedProtocols Tüm yüklü protokoller Bu hub tarafından desteklenen


protokoller. Varsayılan olarak, sunucuda
kayıtlı tüm protokollere izin verilir, ancak
tek tek hub 'lara yönelik belirli
protokolleri devre dışı bırakmak için
protokollerin bu listeden kaldırılması
gerekir.

EnableDetailedErrors false true , bir hub yönteminde özel durum


oluştuğunda istemcilere ayrıntılı özel
durum iletileri döndürülür. Varsayılan
değer false , bu özel durum
iletilerinde gizli bilgiler bulunabilir.

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

HandshakeTimeout 15 saniye İstemci bu zaman aralığı içinde bir ilk el


sıkışma iletisi göndermezse bağlantı
kapatılır. Bu, yalnızca önemli ağ
gecikmesi nedeniyle el sıkışma zaman
aşımı hataları gerçekleşirken
değiştirilmesi gereken gelişmiş bir
ayardır. El sıkışma işlemi hakkında daha
fazla ayrıntı için SignalR hub protokol
belirtiminebakın.
SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

KeepAliveInterval 15 saniye Sunucu bu Aralık dahilinde bir ileti


göndermediyse bağlantının açık
tutulması için bir ping iletisi otomatik
olarak gönderilir. KeepAliveInterval
değiştirilirken, istemcide
ServerTimeout /
serverTimeoutInMilliseconds ayarını
değiştirin. Önerilen ServerTimeout /
serverTimeoutInMilliseconds değeri
KeepAliveInterval değeri iki katına
kaydedilir.

SupportedProtocols Tüm yüklü protokoller Bu hub tarafından desteklenen


protokoller. Varsayılan olarak, sunucuda
kayıtlı tüm protokollere izin verilir, ancak
tek tek hub 'lara yönelik belirli
protokolleri devre dışı bırakmak için
protokollerin bu listeden kaldırılması
gerekir.

EnableDetailedErrors false true , bir hub yönteminde özel durum


oluştuğunda istemcilere ayrıntılı özel
durum iletileri döndürülür. Varsayılan
değer false , bu özel durum
iletilerinde gizli bilgiler bulunabilir.

Seçenekler, Startup.ConfigureServices``AddSignalR çağrısına bir seçenek temsilcisi sağlayarak tüm Hub 'lar için
yapılandırılabilir.

public void ConfigureServices(IServiceCollection services)


{
services.AddSignalR(hubOptions =>
{
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1);
});
}

Tek bir hub için seçenekler, AddSignalR belirtilen genel seçenekleri geçersiz kılar ve AddHubOptionskullanılarak
yapılandırılabilir:

services.AddSignalR().AddHubOptions<MyHub>(options =>
{
options.EnableDetailedErrors = true;
});

Gelişmiş HTTP yapılandırma seçenekleri


Aktarımlara ve bellek arabelleği yönetimine ilişkin gelişmiş ayarları yapılandırmak için
HttpConnectionDispatcherOptions kullanın. Bu seçenekler, Startup.Configure > Maphub<t 'ye bir temsilci
geçirilerek yapılandırılır.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("/myhub", options =>
{
options.Transports =
HttpTransportType.WebSockets |
HttpTransportType.LongPolling;
});
});
}

Aktarımlara ve bellek arabelleği yönetimine ilişkin gelişmiş ayarları yapılandırmak için


HttpConnectionDispatcherOptions kullanın. Bu seçenekler, Startup.Configure > Maphub<t 'ye bir temsilci
geçirilerek yapılandırılır.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
app.UseSignalR((configure) =>
{
var desiredTransports =
HttpTransportType.WebSockets |
HttpTransportType.LongPolling;

configure.MapHub<MyHub>("/myhub", (options) =>


{
options.Transports = desiredTransports;
});
});
}

Aşağıdaki tabloda ASP.NET Core SignalRgelişmiş HTTP seçeneklerini yapılandırma seçenekleri açıklanmaktadır:

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ApplicationMaxBufferSize 32 KB İstemci tarafından, geri basıncı


uygulamadan önce sunucunun
arabelleğe aldığı en fazla bayt sayısı. Bu
değeri artırmak, sunucunun geri basınç
uygulamadan daha büyük iletileri daha
hızlı almasına izin verir, ancak bellek
tüketimini artırabilir.

AuthorizationData Veriler, hub sınıfına uygulanan Bir istemcinin hub 'a bağlanmasına
Authorize özniteliklerinden otomatik yetkili olup olmadığını belirlemede
olarak toplanır. kullanılan ıauthorizedata nesnelerinin
listesi.

TransportMaxBufferSize 32 KB Uygulama tarafından, geri basıncını


gözlemlenmadan önce sunucunun
arabelleklerinin gönderdiği en fazla bayt
sayısı. Bu değeri artırmak, sunucunun
geri basınç beklemeden daha büyük
iletileri daha hızlı arabelleğe almasına
izin verir, ancak bellek tüketimini
artırabilir.
SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

Transports Tüm aktarımlar etkin. Bir istemcinin bağlanmak için


kullanabileceği taşımaları kısıtlayabilecek
HttpTransportType değerlerinin bir
bit bayrakları numaralandırması.

LongPolling Aşağıya bakın. Uzun yoklama taşımasına özgü ek


seçenekler.

WebSockets Aşağıya bakın. WebSockets taşımasına özgü ek


seçenekler.

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ApplicationMaxBufferSize 32 KB İstemciden sunucunun arabelleğe aldığı


en fazla bayt sayısı. Bu değeri artırmak,
sunucunun daha büyük iletiler almasına
izin verir, ancak bellek tüketimini
olumsuz etkileyebilir.

AuthorizationData Veriler, hub sınıfına uygulanan Bir istemcinin hub 'a bağlanmasına
Authorize özniteliklerinden otomatik yetkili olup olmadığını belirlemede
olarak toplanır. kullanılan ıauthorizedata nesnelerinin
listesi.

TransportMaxBufferSize 32 KB Uygulama tarafından sunucunun


arabelleklerinin gönderdiği en fazla bayt
sayısı. Bu değeri artırmak, sunucunun
daha büyük iletiler göndermesini sağlar,
ancak bellek tüketimini olumsuz
etkileyebilir.

Transports Tüm aktarımlar etkin. Bir istemcinin bağlanmak için


kullanabileceği taşımaları kısıtlayabilecek
HttpTransportType değerlerinin bir
bit bayrakları numaralandırması.

LongPolling Aşağıya bakın. Uzun yoklama taşımasına özgü ek


seçenekler.

WebSockets Aşağıya bakın. WebSockets taşımasına özgü ek


seçenekler.

Uzun yoklama taşıması LongPolling özelliği kullanılarak yapılandırılabilecek ek seçeneklere sahiptir:

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

PollTimeout 90 saniye Tek bir yoklama isteğini sonlandırmadan


önce sunucunun istemciye göndermek
için bekleyeceği en uzun süre. Bu değeri
azaltmak istemcinin yeni yoklama
istekleri daha sık vermesine neden olur.

WebSocket taşıması WebSockets özelliği kullanılarak yapılandırılabilen ek seçeneklere sahiptir:


SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

CloseTimeout 5 saniye Sunucu kapandıktan sonra, istemci bu


zaman aralığında kapanamazsa bağlantı
sonlandırılır.

SubProtocolSelector null Sec-WebSocket-Protocol üst bilgisini


özel bir değere ayarlamak için
kullanılabilen bir temsilci. Temsilci,
istemci tarafından istenen değerleri girdi
olarak alır ve istenen değeri döndürmesi
beklenir.

İstemci seçeneklerini yapılandırma


İstemci seçenekleri HubConnectionBuilder türünde yapılandırılabilir (.NET ve JavaScript istemcilerinde
kullanılabilir). Java istemcisinde de bulunur, ancak HttpHubConnectionBuilder alt sınıfı, Oluşturucu yapılandırma
seçeneklerinin yanı sıra HubConnection kendisidir.
Günlüğe kaydetmeyi yapılandırma
Günlüğe kaydetme, .NET Istemcisinde ConfigureLogging yöntemi kullanılarak yapılandırılır. Günlüğe kaydetme
sağlayıcıları ve filtreler, sunucuda oldukları gibi aynı şekilde kaydedilebilir. Daha fazla bilgi için oturum açma
ASP.NET Core belgelerine bakın.

NOTE
Günlüğe kaydetme sağlayıcılarını kaydetmek için gerekli paketleri yüklemelisiniz. Tam liste için docs 'ın yerleşik günlük
sağlayıcıları bölümüne bakın.

Örneğin, konsol günlüğünü etkinleştirmek için Microsoft.Extensions.Logging.Console NuGet paketini


yüklemelisiniz. AddConsole uzantısı yöntemini çağırın:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/myhub")
.ConfigureLogging(logging => {
logging.SetMinimumLevel(LogLevel.Information);
logging.AddConsole();
})
.Build();

JavaScript istemcisinde benzer bir configureLogging yöntemi vardır. Üretilecek günlük iletilerinin en düşük
düzeyini belirten bir LogLevel değeri girin. Günlükler tarayıcı konsolu penceresine yazılır.

let connection = new signalR.HubConnectionBuilder()


.withUrl("/myhub")
.configureLogging(signalR.LogLevel.Information)
.build();

LogLevel bir değer yerine, bir günlük düzeyi adını temsil eden bir string değeri de sağlayabilirsiniz. Bu, LogLevel
sabitlerine erişiminizin olmadığı ortamlarda SignalR günlüğe kaydetme yapılandırılırken yararlı olur.
let connection = new signalR.HubConnectionBuilder()
.withUrl("/myhub")
.configureLogging("warn")
.build();

Aşağıdaki tabloda kullanılabilir günlük düzeyleri listelenmektedir. configureLogging için sağladığınız değer, günlüğe
kaydedilecek Minimum günlük düzeyini ayarlar. Bu düzeyde günlüğe kaydedilen iletiler veya tabloda bundan
sonra listelenen düzeylergünlüğe kaydedilir.

DIZE LOGLEVEL

trace LogLevel.Trace

debug LogLevel.Debug

info veya information LogLevel.Information

warn veya warning LogLevel.Warning

error LogLevel.Error

critical LogLevel.Critical

none LogLevel.None

NOTE
Günlüğe kaydetmeyi tamamen devre dışı bırakmak için configureLogging yönteminde signalR.LogLevel.None belirtin.

Günlüğe kaydetme hakkında daha fazla bilgi için SignalR tanılama belgelerinebakın.
SignalR Java istemcisi, günlük kaydı için dolayısıyla slf4j kitaplığını kullanır. Bu, kitaplık kullanıcılarının belirli bir
günlüğe kaydetme bağımlılığı vererek kendi belirli günlük uygulamasını seçmesine olanak sağlayan, üst düzey bir
günlüğe kaydetme API 'sidir. Aşağıdaki kod parçacığı, SignalR Java istemcisiyle java.util.logging nasıl
kullanacağınızı gösterir.

implementation 'org.slf4j:slf4j-jdk14:1.7.25'

Bağımlılıklarınız için günlük kaydını yapılandırmazsanız, DOLAYıSıYLA SLF4J aşağıdaki uyarı iletisiyle varsayılan
işlem olmayan bir günlükçü yükler:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".


SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Bu, güvenle yoksayılabilir.


İzin verilen taşımaları yapılandırma
SignalR tarafından kullanılan aktarımlar WithUrl çağrısında ( withUrl JavaScript 'te) yapılandırılabilir.
HttpTransportType değerlerinin bit düzeyinde veya değerleri yalnızca belirtilen aktarımları kullanacak şekilde
sınırlamak için kullanılabilir. Tüm aktarımlar varsayılan olarak etkindir.
Örneğin, sunucu tarafından gönderilen olay taşımasını devre dışı bırakmak, ancak WebSockets ve uzun yoklama
bağlantılarına izin vermek için:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/myhub", HttpTransportType.WebSockets | HttpTransportType.LongPolling)
.Build();

JavaScript istemcisinde aktarımlar, withUrl için sunulan Options nesnesindeki transport alanı ayarlanarak
yapılandırılır:

let connection = new signalR.HubConnectionBuilder()


.withUrl("/myhub", { transport: signalR.HttpTransportType.WebSockets |
signalR.HttpTransportType.LongPolling })
.build();

Java Client WebSockets 'in bu sürümünde, kullanılabilir tek aktarım bir sürümdür.
Java istemcisinde, taşıma, HttpHubConnectionBuilder``withTransport yöntemiyle seçilir. Java istemcisi WebSockets
taşımasını varsayılan olarak kullanmaktır.

HubConnection hubConnection = HubConnectionBuilder.create("https://example.com/myhub")


.withTransport(TransportEnum.WEBSOCKETS)
.build();

NOTE
SignalR Java istemcisi henüz taşıma geri dönüşü desteklemez.

Taşıyıcı kimlik doğrulamasını yapılandırma


SignalR isteklerle birlikte kimlik doğrulama verileri sağlamak için, istenen erişim belirtecini döndüren bir işlevi
belirtmek üzere AccessTokenProvider seçeneğini (JavaScript 'te accessTokenFactory ) kullanın. .NET Istemcisinde, bu
erişim belirteci bir HTTP "taşıyıcı kimlik doğrulaması" belirteci olarak geçirilir ( Bearer türü ile Authorization üst
bilgisi kullanılarak). JavaScript istemcisinde, tarayıcı API 'Lerinin üstbilgileri uygulama özelliğini (özellikle de
sunucu tarafından gönderilen olaylar ve WebSockets istekleri) kısıtlayacağı birkaç durum dışında , erişim belirteci
bir taşıyıcı belirteci olarak kullanılır. Bu durumlarda, erişim belirteci access_token bir sorgu dizesi değeri olarak
sağlanır.
.NET istemcisinde AccessTokenProvider seçeneği, WithUrl içindeki seçenekler temsilcisi kullanılarak belirtilebilir:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/myhub", options => {
options.AccessTokenProvider = async () => {
// Get and return the access token.
};
})
.Build();

JavaScript istemcisinde, erişim belirteci withUrl içindeki seçenekler nesnesindeki accessTokenFactory alanı
ayarlanarak yapılandırılır:
let connection = new signalR.HubConnectionBuilder()
.withUrl("/myhub", {
accessTokenFactory: () => {
// Get and return the access token.
// This function can return a JavaScript Promise if asynchronous
// logic is required to retrieve the access token.
}
})
.build();

Java istemcisinde SignalR, Httphubconnectionbuilder'a bir erişim belirteci fabrikası sağlayarak kimlik doğrulaması
için kullanılacak bir taşıyıcı belirteç yapılandırabilirsiniz. Rxjava tek bir<dize >sağlamak Için withaccesstokenfactory
kullanın. Tek. erteleçağrısıyla, istemciniz için erişim belirteçleri oluşturmak üzere mantık yazabilirsiniz.

HubConnection hubConnection = HubConnectionBuilder.create("https://example.com/myhub")


.withAccessTokenProvider(Single.defer(() -> {
// Your logic here.
return Single.just("An Access Token");
})).build();

Zaman aşımını yapılandırın ve canlı tut seçeneklerini yapılandırın


Zaman aşımını ve canlı tutma davranışını yapılandırmaya yönelik ek seçenekler HubConnection nesnenin
kendisinde bulunabilir:
.NET
JavaScript
Java

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ServerTimeout 30 saniye (30.000 milisaniye) Sunucu etkinliği için zaman aşımı.


Sunucu bu aralıkta bir ileti
göndermediyse istemci, sunucunun
bağlantısının kesileceğini kabul eder ve
Closed olayını (JavaScript 'te onclose
) tetikler. Bu değer, ping iletisinin
sunucudan gönderilmesi ve istemci
tarafından zaman aşımı aralığı içinde
alınması için yeterince büyük olmalıdır.
Önerilen değer, ping için en az iki
sunucunun KeepAliveInterval değeri
olan bir sayıdır.

HandshakeTimeout 15 saniye İlk sunucu el sıkışması için zaman aşımı.


Sunucu bu aralıkta bir el sıkışma yanıtı
göndermezse, istemci el sıkışmasını iptal
eder ve Closed olayını (JavaScript 'te
onclose ) tetikler. Bu, yalnızca önemli
ağ gecikmesi nedeniyle el sıkışma zaman
aşımı hataları gerçekleşirken
değiştirilmesi gereken gelişmiş bir
ayardır. El sıkışma işlemi hakkında daha
fazla ayrıntı için SignalR hub protokol
belirtiminebakın.
SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

KeepAliveInterval 15 saniye İstemcinin ping iletileri gönderdiği aralığı


belirler. İstemciden herhangi bir ileti
gönderildiğinde, süreölçeri aralığın
başına sıfırlanır. İstemci sunucuda
ClientTimeoutInterval ayarlanmış
bir ileti göndermediyse sunucu,
istemcinin bağlantısının kesileceğini
kabul eder.

.NET Istemcisinde zaman aşımı değerleri TimeSpan değerler olarak belirtilir.


.NET
JavaScript
Java

SEÇENEK VARSAYILAN DEĞER AÇIKLAMA

ServerTimeout 30 saniye (30.000 milisaniye) Sunucu etkinliği için zaman aşımı.


Sunucu bu aralıkta bir ileti
göndermediyse istemci, sunucunun
bağlantısının kesileceğini kabul eder ve
Closed olayını (JavaScript 'te onclose
) tetikler. Bu değer, ping iletisinin
sunucudan gönderilmesi ve istemci
tarafından zaman aşımı aralığı içinde
alınması için yeterince büyük olmalıdır.
Önerilen değer, ping için en az iki
sunucunun KeepAliveInterval değeri
olan bir sayıdır.

HandshakeTimeout 15 saniye İlk sunucu el sıkışması için zaman aşımı.


Sunucu bu aralıkta bir el sıkışma yanıtı
göndermezse, istemci el sıkışmasını iptal
eder ve Closed olayını (JavaScript 'te
onclose ) tetikler. Bu, yalnızca önemli
ağ gecikmesi nedeniyle el sıkışma zaman
aşımı hataları gerçekleşirken
değiştirilmesi gereken gelişmiş bir
ayardır. El sıkışma işlemi hakkında daha
fazla ayrıntı için SignalR hub protokol
belirtiminebakın.

.NET Istemcisinde zaman aşımı değerleri TimeSpan değerler olarak belirtilir.

Ek seçenekleri yapılandırma
Ek seçenekler, HubConnectionBuilder veya Java istemcisindeki HttpHubConnectionBuilder çeşitli yapılandırma API
'Lerinde WithUrl (JavaScript 'te withUrl ) yönteminde yapılandırılabilir:
.NET
JavaScript
Java

.NET SEÇENEĞI VARSAYILAN DEĞER AÇIKLAMA


.NET SEÇENEĞI VARSAYILAN DEĞER AÇIKLAMA

AccessTokenProvider null HTTP isteklerinde taşıyıcı kimlik


doğrulama belirteci olarak belirtilen bir
dize döndüren bir işlev.

SkipNegotiation false Anlaşma adımını atlamak için bunu


true olarak ayarlayın. Yalnızca
WebSockets taşıması etkin olan tek
taşıma olduğunda desteklenir. Azure
SignalR hizmeti kullanılırken bu ayar
etkinleştirilemez.

ClientCertificates Olmamalıdır Kimlik doğrulaması isteklerine


gönderilmek üzere TLS sertifikaları
koleksiyonu.

Cookies Olmamalıdır Her HTTP isteğiyle gönderilmek üzere


HTTP tanımlama bilgilerinin bir
koleksiyonu.

Credentials Olmamalıdır Her HTTP isteğiyle gönderilen kimlik


bilgileri.

CloseTimeout 5 saniye Yalnızca WebSockets. Sunucunun


kapatma isteğini onaylaması için
kapatıldıktan sonra bekleyeceği en uzun
süre. Sunucu bu süre içinde kapatmayı
kabul etmezse, istemci bağlantısını keser.

Headers Olmamalıdır Her HTTP isteğiyle birlikte gönderilmek


üzere ek HTTP üstbilgileri haritası.

HttpMessageHandlerFactory null HTTP istekleri göndermek için kullanılan


HttpMessageHandler yapılandırmak
veya değiştirmek için kullanılabilen bir
temsilci. WebSocket bağlantıları için
kullanılmıyor. Bu temsilci null olmayan
bir değer döndürmelidir ve varsayılan
değeri bir parametre olarak alır. Bu
varsayılan değerde ayarları değiştirin ve
döndürün ya da yeni bir
HttpMessageHandler örneği
döndürün. İşleyiciyi değiştirirken,
belirtilen işleyiciden tutmak
istediğiniz ayarları
kopyalamadığınızdan emin olun,
aksi takdirde, yapılandırılan
seçenekler (tanımlama bilgileri ve
üstbilgiler gibi) yeni işleyiciye
uygulanmaz.

Proxy null HTTP istekleri gönderilirken kullanılacak


bir HTTP proxy 'si.
.NET SEÇENEĞI VARSAYILAN DEĞER AÇIKLAMA

UseDefaultCredentials false Bu Boole değeri HTTP ve WebSockets


istekleri için varsayılan kimlik bilgilerini
gönderecek şekilde ayarlayın. Bu,
Windows kimlik doğrulamasının
kullanılmasını mümkün.

WebSocketConfiguration null Ek WebSocket seçeneklerini


yapılandırmak için kullanılabilen bir
temsilci. Seçenekleri yapılandırmak için
kullanılabilecek ClientWebSocketOptions
örneğini alır.

.NET Istemcisinde, bu seçenekler WithUrl için belirtilen seçenekler temsilcisi tarafından değiştirilebilir:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/myhub", options => {
options.Headers["Foo"] = "Bar";
options.Cookies.Add(new Cookie(/* ... */);
options.ClientCertificates.Add(/* ... */);
})
.Build();

JavaScript Istemcisinde, bu seçenekler withUrl için sunulan bir JavaScript nesnesi içinde bulunabilir:

let connection = new signalR.HubConnectionBuilder()


.withUrl("/myhub", {
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
.build();

Java istemcisinde, bu seçenekler HubConnectionBuilder.create("HUB URL") döndürülen HttpHubConnectionBuilder


yöntemleriyle yapılandırılabilir

HubConnection hubConnection = HubConnectionBuilder.create("https://example.com/myhub")


.withHeader("Foo", "Bar")
.shouldSkipNegotiate(true)
.withHandshakeResponseTimeout(30*1000)
.build();

Ek kaynaklar
ASP.NET Core SignalR kullanmaya başlama
ASP.NET Core SignalR hub 'ları kullanma
ASP.NET Core SignalR JavaScript istemcisi
.NET Client ASP.NET Core SignalR
ASP.NET Core için SignalR içinde MessagePack hub protokolünü kullanın
Desteklenen SignalR platformları ASP.NET Core
ASP.NET Core SignalR kimlik doğrulaması ve
yetkilendirme
6.12.2019 • 13 minutes to read • Edit Online

, Andrew Stanton-nurte
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

SignalR hub 'ına bağlanan kullanıcıların kimliğini doğrulama


SignalR, bir kullanıcıyı her bağlantıyla ilişkilendirmek için ASP.NET Core kimlik doğrulamasıyla birlikte
kullanılabilir. Bir hub 'da, Hubconnectioncontext. User özelliğinden kimlik doğrulama verilerine erişilebilir. Kimlik
doğrulaması, hub 'ın bir kullanıcıyla ilişkili tüm bağlantılar üzerinde Yöntemler çağırmasını sağlar. Daha fazla bilgi
için bkz. SignalRkullanıcıları ve grupları yönetme . Birden çok bağlantı tek bir kullanıcıyla ilişkilendirilebilir.
Aşağıda, SignalR ve ASP.NET Core kimlik doğrulaması kullanan Startup.Configure bir örneği verilmiştir:

public void Configure(IApplicationBuilder app)


{
...

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chat");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}

public void Configure(IApplicationBuilder app)


{
...

app.UseStaticFiles();

app.UseAuthentication();

app.UseSignalR(hubs =>
{
hubs.MapHub<ChatHub>("/chat");
});

app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
NOTE
SignalR ve ASP.NET Core kimlik doğrulama ara yazılımını kaydetme sırası önemli. SignalR HttpContext bir kullanıcıya sahip
olması için UseSignalR önce her zaman UseAuthentication çağırın.

Tanımlama bilgisi kimlik doğrulaması


Tarayıcı tabanlı bir uygulamada, tanımlama bilgisi kimlik doğrulaması, mevcut kullanıcı kimlik bilgilerinizin
SignalR bağlantılarına otomatik olarak akmasını sağlar. Tarayıcı istemcisi kullanılırken ek yapılandırma gerekmez.
Kullanıcı uygulamanızda oturum açtıysa, SignalR bağlantı bu kimlik doğrulamasını otomatik olarak devralır.
Tanımlama bilgileri, erişim belirteçleri göndermek için tarayıcıya özgü bir yoldur, ancak tarayıcı olmayan istemciler
bunları gönderebilir. .NET istemcisikullanılırken, tanımlama bilgisi sağlamak için .WithUrl çağrısında Cookies
özelliği yapılandırılabilir. Ancak, .NET istemcisinden tanımlama bilgisi kimlik doğrulamasını kullanmak,
uygulamanın bir tanımlama bilgisi için kimlik doğrulama verilerini Exchange için bir API sağlamasını gerektirir.
Taşıyıcı belirteç kimlik doğrulaması
İstemci, tanımlama bilgisi kullanmak yerine bir erişim belirteci sağlayabilir. Sunucu belirteci doğrular ve kullanıcıyı
tanımlamak için kullanır. Bu doğrulama yalnızca bağlantı kurulduunda yapılır. Bağlantının kullanım ömrü boyunca,
sunucu otomatik olarak yeniden doğrulamadan belirteç iptalini kontrol etmez.
Sunucusunda, taşıyıcı belirteç kimlik doğrulaması JWT taşıyıcı ara yazılımıkullanılarak yapılandırılır.
JavaScript istemcisinde, belirteç Accesstokenfactory seçeneği kullanılarak sağlanabilirler.

// Connect, using the token we got.


this.connection = new signalR.HubConnectionBuilder()
.withUrl("/hubs/chat", { accessTokenFactory: () => this.loginToken })
.build();

.NET istemcisinde, belirteci yapılandırmak için kullanılabilecek, benzer bir Accesstokenprovider özelliği vardır:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/myhub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
})
.Build();

NOTE
Sağladığınız erişim belirteci işlevi, SignalRtarafından yapılan her http isteğinin önüne çağırılır. Bağlantıyı etkin tutmak için
belirteci yenilemeniz gerekiyorsa (bağlantı sırasında süresi dolarsa), bunu bu işlevin içinden yapın ve güncelleştirilmiş belirteci
döndürün.

Standart Web API 'Lerinde, taşıyıcı belirteçleri bir HTTP üst bilgisinde gönderilir. Ancak, bazı aktarımlar
kullanılırken SignalR tarayıcılarda bu üst bilgileri ayarlayamadı. WebSockets ve sunucu tarafından gönderilen
olaylar kullanılırken, belirteç bir sorgu dizesi parametresi olarak iletilir. Bunu sunucuda desteklemek için ek
yapılandırma gerekir:

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

services.AddAuthentication(options =>
{
// Identity made Cookie authentication the default.
// However, we want JWT Bearer Auth to be the default.
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// Configure the Authority to the expected value for your authentication provider
// This ensures the token is appropriately validated
options.Authority = /* TODO: Insert Authority URL here */;

// We have to hook the OnMessageReceived event in order to


// allow the JWT authentication handler to read the access
// token from the query string when a WebSocket or
// Server-Sent Events request comes in.

// Sending the access token in the query string is required due to


// a limitation in Browser APIs. We restrict it to only calls to the
// SignalR hub in this code.
// See https://docs.microsoft.com/aspnet/core/signalr/security#access-token-logging
// for more information about security considerations when using
// the query string to transmit the access token.
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];

// If the request is for our hub...


var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/hubs/chat")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddSignalR();

// Change to use Name as the user identifier for SignalR


// WARNING: This requires that the source of your JWT token
// ensures that the Name claim is unique!
// If the Name claim isn't unique, users could receive messages
// intended for a different user!
services.AddSingleton<IUserIdProvider, NameUserIdProvider>();

// Change to use email as the user identifier for SignalR


// services.AddSingleton<IUserIdProvider, EmailBasedUserIdProvider>();

// WARNING: use *either* the NameUserIdProvider *or* the


// EmailBasedUserIdProvider, but do not use both.
}
NOTE
Sorgu dizesi tarayıcı API 'SI sınırlamaları nedeniyle WebSockets ve sunucu tarafından gönderilen olaylarla bağlantı kurulurken
tarayıcılarda kullanılır. HTTPS kullanılırken sorgu dizesi değerleri TLS bağlantısıyla korunmuş hale getirilir. Ancak, birçok
sunucu günlük sorgu dizesi değerlerini günlüğe kaydeder. Daha fazla bilgi için ASP.NET Core SignalRgüvenlik konuları
bölümüne bakın. SignalR, belirteçleri destekleyen ortamlarda (.NET ve Java istemcileri gibi) belirteçleri iletmek için üst bilgileri
kullanır.

Tanımlama bilgileri ve taşıyıcı belirteçleri karşılaştırması


Tanımlama bilgileri tarayıcılara özeldir. Diğer istemci türlerinden gönderilmesi, taşıyıcı belirteçlerinin
gönderilmesine kıyasla karmaşıklık ekler. Sonuç olarak, uygulamanın yalnızca tarayıcı istemcisinden kullanıcıların
kimliğini doğrulaması gerekmediği takdirde tanımlama bilgisi kimlik doğrulaması önerilmez. Taşıyıcı belirteç
kimlik doğrulaması, tarayıcı istemcisi dışındaki istemcileri kullanırken önerilen yaklaşımdır.
Windows kimlik doğrulama
Uygulamanızda Windows kimlik doğrulaması yapılandırılırsa, SignalR hub 'ları güvenli hale getirmek için bu
kimliği kullanabilir. Ancak, bireysel kullanıcılara ileti göndermek için özel bir kullanıcı KIMLIĞI sağlayıcısı
eklemeniz gerekir. Windows kimlik doğrulama sistemi, "ad tanımlayıcı" talebi sağlamaz. SignalR, Kullanıcı adını
belirlemede talebi kullanır.
IUserIdProvider uygulayan yeni bir sınıf ekleyin ve Kullanıcı tarafından tanımlayıcı olarak kullanılacak taleplerden
birini alın. Örneğin, "ad" talebini ( [Domain]\[Username] biçimde Windows Kullanıcı adı) kullanmak için aşağıdaki
sınıfı oluşturun:

public class NameUserIdProvider : IUserIdProvider


{
public string GetUserId(HubConnectionContext connection)
{
return connection.User?.Identity?.Name;
}
}

ClaimTypes.Name yerine, User herhangi bir değeri (Windows SID tanımlayıcısı gibi) kullanabilirsiniz.

NOTE
Seçtiğiniz değer, sisteminizdeki tüm kullanıcılar arasında benzersiz olmalıdır. Aksi takdirde, bir kullanıcı için tasarlanan bir ileti
farklı bir kullanıcıya gidiyor olabilir.

Bu bileşeni Startup.ConfigureServices yöntemine kaydedin.

public void ConfigureServices(IServiceCollection services)


{
// ... other services ...

services.AddSignalR();
services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
}

.NET Istemcisinde, UseDefaultCredentials özelliği ayarlanarak Windows kimlik doğrulamasının etkinleştirilmesi


gerekir:
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/myhub", options =>
{
options.UseDefaultCredentials = true;
})
.Build();

Windows kimlik doğrulaması yalnızca Microsoft Internet Explorer veya Microsoft Edge kullanılırken tarayıcı
istemcisi tarafından desteklenir.
Kimlik işlemeyi özelleştirmek için talepler kullanma
Kullanıcıların kimliğini doğrulayan bir uygulama, Kullanıcı taleplerinden SignalR Kullanıcı kimliği türetilebilir.
SignalR Kullanıcı kimliklerini nasıl oluşturduğunu belirtmek için, IUserIdProvider uygulayın ve uygulamayı
kaydedin.
Örnek kod, tanımlama özelliği olarak kullanıcının e-posta adresini seçmek için talepleri nasıl kullanacağınızı
gösterir.

NOTE
Seçtiğiniz değer, sisteminizdeki tüm kullanıcılar arasında benzersiz olmalıdır. Aksi takdirde, bir kullanıcı için tasarlanan bir ileti
farklı bir kullanıcıya gidiyor olabilir.

public class EmailBasedUserIdProvider : IUserIdProvider


{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}

Hesap kaydı, ASP.NET Identity veritabanına ClaimsTypes.Email türünde bir talep ekler.

// create a new user


var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);

// add the email claim and value for this user


await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, Input.Email));

Bu bileşeni Startup.ConfigureServices kaydedin.

services.AddSingleton<IUserIdProvider, EmailBasedUserIdProvider>();

Kullanıcılara, hub 'lara ve hub yöntemlerine erişim yetkisi verme


Varsayılan olarak, bir hub 'daki tüm yöntemler kimliği doğrulanmamış bir kullanıcı tarafından çağrılabilir. Kimlik
doğrulaması gerektirmek için, Yetkilendir özniteliğini hub 'a uygulayın:

[Authorize]
public class ChatHub: Hub
{
}
Yalnızca belirli Yetkilendirme ilkeleriyleeşleşen kullanıcılara erişimi kısıtlamak için [Authorize] özniteliğinin
Oluşturucu bağımsız değişkenlerini ve özelliklerini kullanabilirsiniz. Örneğin, MyAuthorizationPolicy adlı bir özel
yetkilendirme ilkeniz varsa, aşağıdaki kodu kullanarak yalnızca bu ilkeyle eşleşen kullanıcıların hub 'a erişmesini
sağlayabilirsiniz:

[Authorize("MyAuthorizationPolicy")]
public class ChatHub : Hub
{
}

Tek tek hub yöntemlerinde [Authorize] özniteliği de uygulanabilir. Geçerli Kullanıcı, yönteme uygulanan ilkeyle
eşleşmezse, çağırana bir hata döndürülür:

[Authorize]
public class ChatHub : Hub
{
public async Task Send(string message)
{
// ... send a message to all users ...
}

[Authorize("Administrators")]
public void BanUser(string userName)
{
// ... ban a user from the chat room (something only Administrators can do) ...
}
}

Hub yöntemi yetkilendirmesini özelleştirmek için yetkilendirme işleyicilerini kullanma


SignalR, bir hub yöntemi yetkilendirme gerektirdiğinde, yetkilendirme işleyicilerine özel bir kaynak sağlar. Kaynak
bir HubInvocationContext örneğidir. HubInvocationContext , HubCallerContext , çağrılan hub yönteminin adını ve
hub yönteminin bağımsız değişkenlerini içerir.
Azure Active Directory aracılığıyla birden çok kuruluşun oturum açmasına izin veren bir sohbet odası örneğini göz
önünde bulundurun. Microsoft hesabı olan herkes sohbet için oturum açabilir, ancak yalnızca sahip olunan
kuruluşun üyeleri kullanıcıları yasaklatabilecek veya kullanıcıların sohbet geçmişlerini görüntüleyebilmelidir.
Ayrıca, belirli kullanıcılardan belirli işlevleri kısıtlamak isteyebilirsiniz. ASP.NET Core 3,0 ' deki güncelleştirilmiş
özellikleri kullanarak bu tamamen mümkündür. DomainRestrictedRequirement nasıl özel bir
IAuthorizationRequirement görevi gördüğüne göz önünde edin. Artık HubInvocationContext kaynak parametresi
geçirildiğinden, iç mantık hub 'ın çağrıldığı bağlamı inceleyebilir ve kullanıcının bireysel hub yöntemlerini
yürütmesine izin verirken kararlar verebilir.
[Authorize]
public class ChatHub : Hub
{
public void SendMessage(string message)
{
}

[Authorize("DomainRestricted")]
public void BanUser(string username)
{
}

[Authorize("DomainRestricted")]
public void ViewUserHistory(string username)
{
}
}

public class DomainRestrictedRequirement :


AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
DomainRestrictedRequirement requirement,
HubInvocationContext resource)
{
if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name) &&
context.User.Identity.Name.EndsWith("@microsoft.com"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}

private bool IsUserAllowedToDoThis(string hubMethodName,


string currentUsername)
{
return !(currentUsername.Equals("asdf42@microsoft.com") &&
hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase));
}
}

Startup.ConfigureServices , yeni ilkeyi ekleyerek DomainRestricted ilkesini oluşturmak için parametre olarak özel
DomainRestrictedRequirement gereksinimini sağlar.

public void ConfigureServices(IServiceCollection services)


{
// ... other services ...

services
.AddAuthorization(options =>
{
options.AddPolicy("DomainRestricted", policy =>
{
policy.Requirements.Add(new DomainRestrictedRequirement());
});
});
}

Yukarıdaki örnekte DomainRestrictedRequirement sınıfı, bu gereksinim için hem IAuthorizationRequirement hem


de kendi AuthorizationHandler . Bu iki bileşeni birbirinden ayrı ayrı sınıflara bölmek kabul edilebilir. Örneğin
yaklaşımın bir avantajı, gereksinim ve işleyicinin aynı şey olduğu için başlangıç sırasında AuthorizationHandler
eklemeye gerek yoktur.
Ek kaynaklar
ASP.NET Core 'de taşıyıcı belirteç kimlik doğrulaması
Kaynak tabanlı yetkilendirme
ASP.NET Core SignalR güvenlik konuları
6.12.2019 • 8 minutes to read • Edit Online

, Andrew Stanton-nurte
Bu makalede SignalRgüvenliğini sağlama hakkında bilgi sağlanır.

Çıkış noktaları arası kaynak paylaşma


Çapraz kaynak kaynak paylaşımı (CORS ) , tarayıcıda çapraz kaynak SignalR bağlantılara izin vermek için
kullanılabilir. JavaScript kodu SignalR uygulamasından farklı bir etki alanında barındırılıyorsa, JavaScript 'In
SignalR uygulamasına bağlanmasına izin vermek için CORS ara yazılımı etkinleştirilmelidir. Yalnızca güvendiğiniz
veya denetlediğiniz etki alanlarından çıkış noktaları arası isteklere izin verin. Örneğin:
Siteniz http://www.example.com barındırılıyor
SignalR uygulamanız http://signalr.example.com üzerinde barındırılıyor
CORS, SignalR uygulamasında yalnızca kaynak www.example.com izin verecek şekilde yapılandırılmalıdır.
CORS 'yi yapılandırma hakkında daha fazla bilgi için bkz. çıkış noktaları arası istekleri (CORS ) etkinleştirme.
SignalR aşağıdaki CORS ilkelerini gerektirir :
Beklenen belirli kaynaklardan izin verin. Herhangi bir kaynağa izin verilmesi mümkün olsa da güvenli veya
önerilmez.
HTTP yöntemlerine GET ve POST izin verilmelidir.
Kimlik doğrulaması kullanılmasa bile kimlik bilgilerinin etkinleştirilmesi gerekir.
Örneğin, aşağıdaki CORS ilkesi, https://example.com barındırılan SignalR tarayıcısı istemcisinin
https://signalr.example.com üzerinde barındırılan SignalR uygulamasına erişmesine izin verir:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
// ... other middleware ...

// Make sure the CORS middleware is ahead of SignalR.


app.UseCors(builder =>
{
builder.WithOrigins("https://example.com")
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});

// ... other middleware ...


app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
});

// ... other middleware ...


}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... other middleware ...

// Make sure the CORS middleware is ahead of SignalR.


app.UseCors(builder =>
{
builder.WithOrigins("https://example.com")
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});

// ... other middleware ...

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});

// ... other middleware ...


}

NOTE
SignalR, Azure App Service yerleşik CORS özelliğiyle uyumlu değildir.

WebSocket kaynak kısıtlaması


CORS tarafından sunulan korumalar WebSockets için geçerlidir. WebSockets üzerindeki kaynak kısıtlaması için
WebSockets kaynak kısıtlaması' nı okuyun.
CORS tarafından sunulan korumalar WebSockets için geçerlidir. Tarayıcılar şunları desteklemez:
CORS ön uçuş istekleri gerçekleştirin.
WebSocket istekleri yaparken Access-Control üst bilgilerinde belirtilen kısıtlamalara saygı.

Ancak, tarayıcılar WebSocket istekleri verirken Origin üst bilgisini gönderir. Yalnızca beklenen kaynaklardan
gelen WebSockets izin verildiğinden emin olmak için uygulamalar bu üstbilgileri doğrulamak üzere
yapılandırılmalıdır.
ASP.NET Core 2,1 ve üzeri sürümlerde, üst bilgi doğrulaması, UseSignalR ve Configure kimlik doğrulama ara
yazılımı aracılığıyla bulunan özel bir ara yazılım kullanılarak elde edilebilir:
// In Startup, add a static field listing the allowed Origin values:
private static readonly HashSet<string> _allowedOrigins = new HashSet<string>()
{
// Add allowed origins here. For example:
"https://www.mysite.com",
"https://mysite.com",
};

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
// ... other middleware ...

// Validate Origin header on WebSocket requests to prevent unexpected cross-site


// WebSocket requests.
app.Use((context, next) =>
{
// Check for a WebSocket request.
if (string.Equals(context.Request.Headers["Upgrade"], "websocket"))
{
var origin = context.Request.Headers["Origin"];

// If there is an origin header, and the origin header doesn't match


// an allowed value:
if (!string.IsNullOrEmpty(origin) && !_allowedOrigins.Contains(origin))
{
// The origin is not allowed, reject the request
context.Response.StatusCode = StatusCodes.Status403Forbidden;
return Task.CompletedTask;
}
}

// The request is a valid Origin or not a WebSocket request, so continue.


return next();
});

// ... other middleware ...

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});

// ... other middleware ...


}

NOTE
Origin üstbilgisi istemci tarafından denetlenir ve Referer üst bilgisi gibi erişilebilir. Bu üst bilgiler bir kimlik doğrulama
mekanizması olarak kullanılmamalıdır.

Erişim belirteci günlüğe kaydetme


WebSockets veya sunucu tarafından gönderilen olaylar kullanılırken, tarayıcı istemcisi erişim belirtecini sorgu
dizesinde gönderir. Sorgu dizesi aracılığıyla erişim belirtecinin alınması genellikle standart Authorization üst
bilgisi kullanılarak güvenlidir. İstemci ve sunucu arasında güvenli bir uçtan uca bağlantı sağlamak için her zaman
HTTPS kullanmanız gerekir. Birçok Web sunucusu, sorgu dizesi dahil olmak üzere her bir isteğin URL 'sini
günlüğe kaydeder. URL 'Leri günlüğe kaydetme erişim belirtecini günlüğe alabilir. ASP.NET Core, her isteğin
URL 'sini varsayılan olarak günlüğe kaydeder ve bu sorgu dizesini içerir. Örneğin:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/myhub?access_token=1234

Bu verileri sunucu günlüklerinize kaydetme hakkında endişeleriniz varsa, Microsoft.AspNetCore.Hosting


günlükçüsü Warning düzeyine veya üstüne yapılandırarak (Bu iletiler Info düzeyinde yazılır) bu günlüğü
tamamen devre dışı bırakabilirsiniz. Daha fazla bilgi için günlük filtrelemeye yönelik belgelere bakın. Hala belirli
istek bilgilerini günlüğe kaydetmek istiyorsanız, ihtiyacınız olan verileri günlüğe kaydetmek için bir ara yazılım
yazabilir ve access_token sorgu dizesi değerini (varsa) filtreleyebilirsiniz.

Özel Durumlar
Özel durum iletileri genellikle bir istemciye görüntülenmemelidir gizli veriler olarak değerlendirilir. Varsayılan
olarak, SignalR bir hub yöntemi tarafından oluşturulan bir özel durumun ayrıntılarını istemciye göndermez.
Bunun yerine, istemci bir hata oluştuğunu belirten genel bir ileti alır. İstemciye özel durum iletisi teslimi,
Enabledetailederrorsile geçersiz kılınabilir (örneğin, geliştirme veya test). Özel durum iletileri, üretim
uygulamalarındaki istemciye gösterilmemelidir.

Arabellek Yönetimi
SignalR gelen ve giden iletileri yönetmek için bağlantı başına arabellekleri kullanır. Varsayılan olarak, SignalR bu
arabellekleri 32 KB ile sınırlandırır. Bir istemcinin veya sunucunun gönderecan en büyük ileti 32 KB 'tır. İleti
bağlantısı tarafından tüketilen maksimum bellek 32 KB 'tır. İletileriniz her zaman 32 KB 'den küçükse, sınırı
azaltabilirsiniz ve şunları yapabilirsiniz:
Bir istemcinin daha büyük bir ileti gönderebilmesini engeller.
Sunucu, iletileri kabul etmek için hiçbir şekilde büyük arabellekler ayırmayı gerektirmez.
İletileriniz 32 KB 'tan büyükse, limiti artırabilirsiniz. Bu sınırı artırmak şu anlama gelir:
İstemci, sunucunun büyük bellek arabellekleri ayırmasına neden olabilir.
Büyük arabelleklerin sunucu ayırması, eşzamanlı bağlantı sayısını azaltabilir.
Gelen ve giden iletiler için her ikisi de MapHub ' de yapılandırılan Httpconnectiondispatcheroptions nesnesinde
yapılandırılabilir:
ApplicationMaxBufferSize , istemciden sunucunun arabelleğe aldığı en fazla bayt sayısını temsil eder. İstemci
bu sınırdan daha büyük bir ileti göndermemeyi denerse bağlantı kapatılabilir.
TransportMaxBufferSize , sunucunun gönderemediği en fazla bayt sayısını temsil eder. Sunucu, bu sınırdan
daha büyük bir ileti (hub metotlarından dönüş değerleri dahil) gönderilmeye çalışırsa, bir özel durum
oluşturulur.
Sınırın 0 olarak ayarlanması sınırı devre dışı bırakır. Sınırı kaldırmak, bir istemcinin herhangi bir boyutta ileti
göndermesini sağlar. Büyük iletiler gönderen kötü amaçlı istemciler fazla belleğin ayrılmasına neden olabilir. Aşırı
bellek kullanımı, eşzamanlı bağlantı sayısını önemli ölçüde azaltabilir.
ASP.NET Core için SignalR içinde MessagePack hub
protokolünü kullanın
13.11.2019 • 8 minutes to read • Edit Online

Brennan Conroy tarafından


Bu makalede, okuyucunun Başlarkenbölümünde ele alınan konular hakkında bilgi sahibi olduğu varsayılır.

MessagePack nedir?
MessagePack hızlı ve kompakt bir ikili serileştirme biçimidir. Bu, JSONile karşılaştırıldığında daha küçük iletiler
oluşturduğundan performans ve bant genişliği açısından yararlıdır. İkili bir biçim olduğundan, baytlar bir
MessagePack ayrıştırıcısı üzerinden geçirilmediği takdirde ağ izlemeleri ve günlükleri aranırken iletiler okunamaz.
SignalR MessagePack biçimi için yerleşik desteğe sahiptir ve istemci ve sunucunun kullanması için API 'Ler sağlar.

Sunucuda MessagePack 'i yapılandırma


Sunucuda MessagePack hub protokolünü etkinleştirmek için Microsoft.AspNetCore.SignalR.Protocols.MessagePack
paketini uygulamanıza yüklersiniz. Startup.cs dosyasında, sunucuda MessagePack desteğini etkinleştirmek için
AddSignalR çağrısına AddMessagePackProtocol ekleyin.

NOTE
JSON varsayılan olarak etkindir. MessagePack eklemek, hem JSON hem de MessagePack istemcileri için destek sunar.

services.AddSignalR()
.AddMessagePackProtocol();

MessagePack 'in verilerinizi nasıl biçimlendiğini özelleştirmek için AddMessagePackProtocol seçenekleri


yapılandırmak için bir temsilci alır. Bu temsilcisinde, FormatterResolvers özelliği MessagePack serileştirme
seçeneklerini yapılandırmak için kullanılabilir. Çözümleyiciler nasıl çalıştığı hakkında daha fazla bilgi için,
MessagePack-CSharpkonumundaki MessagePack kitaplığını ziyaret edin. Öznitelikler, serileştirilmeleri nasıl ele
alınacağını tanımlamak için seri hale getirmek istediğiniz nesnelerde kullanılabilir.

services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});

İstemcide MessagePack 'i yapılandırma


NOTE
JSON, desteklenen istemciler için varsayılan olarak etkindir. İstemciler yalnızca tek bir protokolü destekleyebilir. MessagePack
desteği eklemek, önceden yapılandırılmış tüm protokollerin yerini alır.

.NET istemcisi
.NET Istemcisinde MessagePack 'i etkinleştirmek için Microsoft.AspNetCore.SignalR.Protocols.MessagePack paketini
yükleyip HubConnectionBuilder``AddMessagePackProtocol çağırın.

var hubConnection = new HubConnectionBuilder()


.WithUrl("/chatHub")
.AddMessagePackProtocol()
.Build();

NOTE
Bu AddMessagePackProtocol çağrısı, sunucu gibi seçenekleri yapılandırmak için bir temsilci alır.

JavaScript istemcisi
JavaScript istemcisi için MessagePack desteği @microsoft/signalr-protocol-msgpack NPM paketi tarafından
sağlanmaktadır. Aşağıdaki komutu bir komut kabuğu 'nda yürüterek paketi yüklemelisiniz:

npm install @microsoft/signalr-protocol-msgpack

JavaScript istemcisi için MessagePack desteği @aspnet/signalr-protocol-msgpack NPM paketi tarafından


sağlanmaktadır. Aşağıdaki komutu bir komut kabuğu 'nda yürüterek paketi yüklemelisiniz:

npm install @aspnet/signalr-protocol-msgpack

NPM paketini yükledikten sonra modül, doğrudan bir JavaScript Modül Yükleyicisi aracılığıyla veya aşağıdaki
dosyaya başvurarak tarayıcıya içeri aktarılabilecek şekilde kullanılabilir:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
Bir tarayıcıda msgpack5 kitaplığına da başvurulmalıdır. Başvuru oluşturmak için bir <script> etiketi kullanın.
Kitaplık, node_modules \msgpack5\dist\msgpack5,JSkonumunda bulunabilir.

NOTE
<script> öğesi kullanılırken, sıra önemlidir. SignalR-Protocol-msgpack. js ' msgpack5. js' den önce başvuruluyorsa,
MessagePack ile bağlantı kurmaya çalışırken bir hata oluşur. SignalR. js , SignalR-Protocol-msgpack. js' den önce de
gereklidir.

<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>

HubConnectionBuilder .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) eklemek,


istemciyi bir sunucuya bağlanırken MessagePack protokolünü kullanacak şekilde yapılandırır.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();

NOTE
Şu anda JavaScript istemcisinde MessagePack protokolü için yapılandırma seçeneği yoktur.

MessagePack süslemeler
MessagePack hub protokolünü kullanırken dikkat etmeniz birkaç sorun vardır.
MessagePack büyük/küçük harfe duyarlıdır
MessagePack Protokolü büyük/küçük harfe duyarlıdır. Örneğin, aşağıdaki C# sınıfı göz önünde bulundurun:

public class ChatMessage


{
public string Sender { get; }
public string Message { get; }
}

JavaScript istemcisinden gönderirken, büyük/küçük harf C# sınıfıyla tam olarak eşleşmesi gerektiğinden
PascalCased özellik adlarını kullanmanız gerekir. Örneğin:

connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });

camelCased adları kullanmak C# sınıfa düzgün şekilde bağlanmaz. MessagePack özelliği için farklı bir ad belirtmek
üzere Key özniteliğini kullanarak bu soruna geçici bir çözüm bulabilirsiniz. Daha fazla bilgi için bkz. MessagePack-
CSharp belgeleri.
Seri hale getirme/seri durumdan çıkarma sırasında DateTime. Kind korunmaz
MessagePack protokolü, bir DateTime``Kind değerini kodlamak için bir yol sağlamaz. Sonuç olarak, bir tarih serisi
kaldırılırken, MessagePack hub protokolü gelen tarihin UTC biçiminde olduğunu varsayar. Yerel saat içinde
DateTime değerlerle çalışıyorsanız, göndermeden önce UTC 'ye dönüştürmeniz önerilir. Bunları aldığınızda UTC
'den yerel saate dönüştürün.
Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorun ASPNET/SignalR#2632.
DateTime. MinValue, JavaScript 'te MessagePack tarafından desteklenmiyor
SignalR JavaScript istemcisi tarafından kullanılan msgpack5 kitaplığı MessagePack içindeki timestamp96 türünü
desteklemez. Bu tür, çok büyük tarih değerlerini kodlamak için kullanılır (daha önce geçmişte veya daha önce bir
süre içinde çok erken). DateTime.MinValue değeri, bir timestamp96 değerinde kodlanması gereken
January 1, 0001 . Bu nedenle, JavaScript istemcisine DateTime.MinValue gönderilmesi desteklenmez. JavaScript
istemcisi tarafından DateTime.MinValue alındığında, aşağıdaki hata oluşur:

Uncaught Error: unable to find ext type 255 at decoder.js:427

Genellikle, DateTime.MinValue bir "eksik" veya null değeri kodlamak için kullanılır. Bu değeri MessagePack 'te
kodlamak gerekirse, null yapılabilir DateTime değeri ( DateTime? ) kullanın veya tarihin mevcut olup olmadığını
belirten ayrı bir bool değeri kodlayın.
Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorun ASPNET/SignalR#2228.
"Zamanında" derleme ortamında MessagePack desteği
.NET istemcisi ve sunucusu tarafından kullanılan MessagePack-CSharp kitaplığı, serileştirme işlemini iyileştirmek
için kod oluşturmayı kullanır. Sonuç olarak, "güncel olmayan" derleme (Xamarin iOS veya Unity gibi) kullanan
ortamlarda varsayılan olarak desteklenmez. Seri hale getirici/seri hale getirici kodunu "önceden oluşturma"
yoluyla bu ortamlarda MessagePack kullanmak mümkündür. Daha fazla bilgi için bkz. MessagePack-CSharp
belgeleri. Serileştiriciler önceden oluşturulduktan sonra, AddMessagePackProtocol geçirilen yapılandırma temsilcisini
kullanarak kaydedebilirsiniz:

services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});

Tür denetimleri MessagePack 'te daha sıkı


JSON hub 'ı protokolü, seri durumdan çıkarma sırasında tür dönüştürmeleri gerçekleştirecek. Örneğin, gelen
nesnenin bir sayı olan ( { foo: 42 } ) bir özellik değeri varsa, ancak .NET sınıfındaki özelliği string türündedir,
değer dönüştürülür. Ancak, MessagePack bu dönüştürmeyi gerçekleştirmez ve sunucu tarafı günlüklerinde (ve
konsolunda) görünebileceğini bir özel durum oluşturur:

InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types
of the hub method being invoked.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorun ASPNET/SignalR#2937.

İlgili kaynaklar
Başlarken
.NET istemcisi
JavaScript istemcisi
ASP.NET Core SignalR akışı kullanma
13.11.2019 • 13 minutes to read • Edit Online

Brennan Conroy tarafından


ASP.NET Core SignalR istemciden sunucuya ve sunucudan istemciye akışı destekler. Bu, veri parçalarının zaman
içinde nereden ulaştığını senaryolar için yararlıdır. Akış sırasında her parça, tüm verilerin kullanılabilir hale
gelmesini beklemek yerine istemciye veya sunucuya gönderilir.
ASP.NET Core SignalR, sunucu yöntemlerinin akış dönüş değerlerini destekler. Bu, veri parçalarının zaman içinde
nereden ulaştığını senaryolar için yararlıdır. Bir dönüş değeri istemciye akışa eklendiğinde, her parça, tüm verilerin
kullanılabilir hale gelmesini beklemek yerine istemciye gönderilir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Akış için bir hub ayarlama


Hub yöntemi, IAsyncEnumerable<T>, ChannelReader<T>, Task<IAsyncEnumerable<T>> veya
Task<ChannelReader<T>> döndürdüğünde otomatik olarak bir akış hub yöntemi haline gelir.

Bir hub yöntemi, bir ChannelReader<T> veya Task<ChannelReader<T>> döndürdüğünde otomatik olarak akış hub
yöntemi haline gelir.
Sunucudan istemciye akış
Akış hub 'ı yöntemleri, ChannelReader<T> ek olarak IAsyncEnumerable<T> döndürebilir. IAsyncEnumerable<T>
döndürmenin en kolay yolu, aşağıdaki örnekte gösterildiği gibi hub yöntemini zaman uyumsuz bir yineleyici
yöntemi yaparak kullanmaktır. Merkez zaman uyumsuz Yineleyici yöntemleri, istemci akıştan aboneliği
kaldırdığında tetiklenen bir CancellationToken parametresi kabul edebilir. Zaman uyumsuz Yineleyici yöntemleri,
ChannelReader erken olarak döndürülmemek veya ChannelWriter<T>tamamlamadan yöntemden çıkmak gibi
kanallarla ortak olan sorunlardan kaçının.

NOTE
Aşağıdaki örnek gerektirir C# 8.0 veya üzeri.
public class AsyncEnumerableHub : Hub
{
public async IAsyncEnumerable<int> Counter(
int count,
int delay,
CancellationToken cancellationToken)
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();

yield return i;

// Use the cancellationToken in other APIs that accept cancellation


// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
}
}

Aşağıdaki örnekte, kanalları kullanarak istemciye veri akışı hakkında temel bilgiler gösterilmektedir.
ChannelWriter<T>bir nesne her yazıldığında, nesne hemen istemciye gönderilir. Sonunda ChannelWriter ,
istemciye akışın kapatıldığını bildirmek için tamamlanır.

NOTE
Arka plan iş parçacığında ChannelWriter<T> yazın ve ChannelReader mümkün olan en kısa sürede geri döndürün. Diğer
Merkez çağırmaları ChannelReader döndürülünceye kadar engellenir.
try ... catch mantığı çevrele. Hub yöntemi çağrısının düzgün şekilde tamamlandığından emin olmak için catch ve
catch dışında Channel doldurun.
public ChannelReader<int> Counter(
int count,
int delay,
CancellationToken cancellationToken)
{
var channel = Channel.CreateUnbounded<int>();

// We don't want to await WriteItemsAsync, otherwise we'd end up waiting


// for all the items to be written before returning the channel back to
// the client.
_ = WriteItemsAsync(channel.Writer, count, delay, cancellationToken);

return channel.Reader;
}

private async Task WriteItemsAsync(


ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
Exception localException = null;
try
{
for (var i = 0; i < count; i++)
{
await writer.WriteAsync(i, cancellationToken);

// Use the cancellationToken in other APIs that accept cancellation


// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
}
catch (Exception ex)
{
localException = ex;
}

writer.Complete(localException);
}
public class StreamHub : Hub
{
public ChannelReader<int> Counter(
int count,
int delay,
CancellationToken cancellationToken)
{
var channel = Channel.CreateUnbounded<int>();

// We don't want to await WriteItemsAsync, otherwise we'd end up waiting


// for all the items to be written before returning the channel back to
// the client.
_ = WriteItemsAsync(channel.Writer, count, delay, cancellationToken);

return channel.Reader;
}

private async Task WriteItemsAsync(


ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
try
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();
await writer.WriteAsync(i);

// Use the cancellationToken in other APIs that accept cancellation


// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
}
catch (Exception ex)
{
writer.TryComplete(ex);
}

writer.TryComplete();
}
}
public class StreamHub : Hub
{
public ChannelReader<int> Counter(int count, int delay)
{
var channel = Channel.CreateUnbounded<int>();

// We don't want to await WriteItemsAsync, otherwise we'd end up waiting


// for all the items to be written before returning the channel back to
// the client.
_ = WriteItemsAsync(channel.Writer, count, delay);

return channel.Reader;
}

private async Task WriteItemsAsync(


ChannelWriter<int> writer,
int count,
int delay)
{
try
{
for (var i = 0; i < count; i++)
{
await writer.WriteAsync(i);
await Task.Delay(delay);
}
}
catch (Exception ex)
{
writer.TryComplete(ex);
}

writer.TryComplete();
}
}

Sunucudan istemciye akış hub 'ı yöntemleri, istemci akıştan aboneliği kaldırdığında tetiklenen bir
CancellationToken parametresini kabul edebilir. Sunucu işlemini durdurmak ve istemci akışın sonundan önce
bağlantıyı kestiğinde tüm kaynakları serbest bırakmak için bu belirteci kullanın.
İstemciden sunucuya akış
Hub yöntemi, ChannelReader<T> veya IAsyncEnumerable<T>türünde bir veya daha fazla nesne kabul ettiğinde,
otomatik olarak istemciden sunucuya akış hub yöntemi haline gelir. Aşağıdaki örnek, istemciden gönderilen akış
verilerini okumayla ilgili temel bilgileri gösterir. İstemci ChannelWriter<T>her yazdığında, veriler hub yönteminin
okuduğu sunucuda ChannelReader yazılır.

public async Task UploadStream(ChannelReader<string> stream)


{
while (await stream.WaitToReadAsync())
{
while (stream.TryRead(out var item))
{
// do something with the stream item
Console.WriteLine(item);
}
}
}

Yöntemin IAsyncEnumerable<T> bir sürümü aşağıda verilmiştir.


NOTE
Aşağıdaki örnek gerektirir C# 8.0 veya üzeri.

public async Task UploadStream(IAsyncEnumerable<string> stream)


{
await foreach (var item in stream)
{
Console.WriteLine(item);
}
}

.NET istemcisi
Sunucudan istemciye akış
HubConnection StreamAsync ve StreamAsChannelAsync yöntemleri sunucudan istemciye akış yöntemlerini çağırmak
için kullanılır. Hub yöntemi adı ve StreamAsync veya StreamAsChannelAsync , hub metodunda tanımlanan bağımsız
değişkenleri geçirin. StreamAsync<T> ve StreamAsChannelAsync<T> genel parametresi, akış yöntemi tarafından
döndürülen nesne türünü belirtir. IAsyncEnumerable<T> veya ChannelReader<T> türünde bir nesne, akış çağrısından
döndürülür ve istemcideki akışı temsil eder.
IAsyncEnumerable<int> döndüren StreamAsync bir örnek:

// Call "Cancel" on this CancellationTokenSource to send a cancellation message to


// the server, which will trigger the corresponding token in the hub method.
var cancellationTokenSource = new CancellationTokenSource();
var stream = await hubConnection.StreamAsync<int>(
"Counter", 10, 500, cancellationTokenSource.Token);

await foreach (var count in stream)


{
Console.WriteLine($"{count}");
}

Console.WriteLine("Streaming completed");

ChannelReader<int> döndüren karşılık gelen StreamAsChannelAsync örneği:

// Call "Cancel" on this CancellationTokenSource to send a cancellation message to


// the server, which will trigger the corresponding token in the hub method.
var cancellationTokenSource = new CancellationTokenSource();
var channel = await hubConnection.StreamAsChannelAsync<int>(
"Counter", 10, 500, cancellationTokenSource.Token);

// Wait asynchronously for data to become available


while (await channel.WaitToReadAsync())
{
// Read all currently available data synchronously, before waiting for more data
while (channel.TryRead(out var count))
{
Console.WriteLine($"{count}");
}
}

Console.WriteLine("Streaming completed");

HubConnection StreamAsChannelAsync yöntemi, sunucudan istemciye akış yöntemini çağırmak için kullanılır.
StreamAsChannelAsync için hub yöntemi adını ve hub yöntemi içinde tanımlanan bağımsız değişkenleri geçirin.
StreamAsChannelAsync<T> genel parametresi, akış yöntemi tarafından döndürülen nesne türünü belirtir. Akış
çağrısından bir ChannelReader<T> döndürülür ve istemcideki akışı temsil eder.

// Call "Cancel" on this CancellationTokenSource to send a cancellation message to


// the server, which will trigger the corresponding token in the hub method.
var cancellationTokenSource = new CancellationTokenSource();
var channel = await hubConnection.StreamAsChannelAsync<int>(
"Counter", 10, 500, cancellationTokenSource.Token);

// Wait asynchronously for data to become available


while (await channel.WaitToReadAsync())
{
// Read all currently available data synchronously, before waiting for more data
while (channel.TryRead(out var count))
{
Console.WriteLine($"{count}");
}
}

Console.WriteLine("Streaming completed");

HubConnection yöntemi, sunucudan istemciye akış yöntemini çağırmak için kullanılır.


StreamAsChannelAsync
StreamAsChannelAsync için hub yöntemi adını ve hub yöntemi içinde tanımlanan bağımsız değişkenleri geçirin.
StreamAsChannelAsync<T> genel parametresi, akış yöntemi tarafından döndürülen nesne türünü belirtir. Akış
çağrısından bir ChannelReader<T> döndürülür ve istemcideki akışı temsil eder.

var channel = await hubConnection


.StreamAsChannelAsync<int>("Counter", 10, 500, CancellationToken.None);

// Wait asynchronously for data to become available


while (await channel.WaitToReadAsync())
{
// Read all currently available data synchronously, before waiting for more data
while (channel.TryRead(out var count))
{
Console.WriteLine($"{count}");
}
}

Console.WriteLine("Streaming completed");

İstemciden sunucuya akış


.NET istemcisinden istemciden sunucuya akış hub 'ı yöntemini çağırmak için iki yol vardır. Çağrılan hub yöntemine
bağlı olarak, bir IAsyncEnumerable<T> veya ChannelReader bir bağımsız değişken olarak SendAsync , InvokeAsync
veya StreamAsChannelAsync olarak geçirebilirsiniz.
Veriler IAsyncEnumerable veya ChannelWriter nesnesine yazıldığında, sunucudaki hub yöntemi istemciden alınan
verilerle yeni bir öğe alır.
Bir IAsyncEnumerable nesnesi kullanıyorsanız, akış öğeleri döndüren yöntem çıktıktan sonra akış sonlanır.

NOTE
Aşağıdaki örnek gerektirir C# 8.0 veya üzeri.
async IAsyncEnumerable<string> clientStreamData()
{
for (var i = 0; i < 5; i++)
{
var data = await FetchSomeData();
yield return data;
}
//After the for loop has completed and the local function exits the stream completion will be sent.
}

await connection.SendAsync("UploadStream", clientStreamData());

ChannelWriter kullanıyorsanız, kanalı channel.Writer.Complete() ile tamamlıyoruz:

var channel = Channel.CreateBounded<string>(10);


await connection.SendAsync("UploadStream", channel.Reader);
await channel.Writer.WriteAsync("some data");
await channel.Writer.WriteAsync("some more data");
channel.Writer.Complete();

JavaScript istemcisi
Sunucudan istemciye akış
JavaScript istemcileri, connection.stream hub 'larda sunucudan istemciye akış yöntemlerini çağırır. stream
yöntemi iki bağımsız değişkeni kabul eder:
Hub yönteminin adı. Aşağıdaki örnekte, hub yöntemi adı Counter .
Hub yönteminde tanımlanan bağımsız değişkenler. Aşağıdaki örnekte, bağımsız değişkenler alacak akış öğesi
sayısı ve akış öğeleri arasındaki gecikme için bir sayıdır.
connection.stream , subscribe yöntemi içeren bir IStreamResult döndürür. Bir IStreamSubscriber subscribe
geçirin ve complete çağrısından bildirimleri almak için next , error ve stream geri çağırmaları ayarlayın.

connection.stream("Counter", 10, 500)


.subscribe({
next: (item) => {
var li = document.createElement("li");
li.textContent = item;
document.getElementById("messagesList").appendChild(li);
},
complete: () => {
var li = document.createElement("li");
li.textContent = "Stream completed";
document.getElementById("messagesList").appendChild(li);
},
error: (err) => {
var li = document.createElement("li");
li.textContent = err;
document.getElementById("messagesList").appendChild(li);
},
});

Akışı istemciden sonlandırmak için subscribe yönteminden döndürülen ISubscription dispose yöntemi çağırın.
Bu yöntemi çağırmak, bir tane sağladıysanız hub yönteminin CancellationToken parametresinin iptal edilmesine
neden olur.
connection.stream("Counter", 10, 500)
.subscribe({
next: (item) => {
var li = document.createElement("li");
li.textContent = item;
document.getElementById("messagesList").appendChild(li);
},
complete: () => {
var li = document.createElement("li");
li.textContent = "Stream completed";
document.getElementById("messagesList").appendChild(li);
},
error: (err) => {
var li = document.createElement("li");
li.textContent = err;
document.getElementById("messagesList").appendChild(li);
},
});

Akışı istemciden sonlandırmak için subscribe yönteminden döndürülen ISubscription dispose yöntemi çağırın.
İstemciden sunucuya akış
JavaScript istemcileri, çağrılan hub yöntemine bağlı olarak bir Subject send , invoke veya stream bir bağımsız
değişken olarak geçirerek hub 'larda istemciden sunucuya akış yöntemlerini çağırır. Subject , Subject gibi
görünen bir sınıftır. Örneğin, RxJS ' de, bu kitaplıktaki Konu sınıfını kullanabilirsiniz.

const subject = new signalR.Subject();


yield connection.send("UploadStream", subject);
var iteration = 0;
const intervalHandle = setInterval(() => {
iteration++;
subject.next(iteration.toString());
if (iteration === 10) {
clearInterval(intervalHandle);
subject.complete();
}
}, 500);

Bir öğeyle subject.next(item) çağırmak öğeyi akışa yazar ve hub yöntemi sunucudaki öğeyi alır.
Akışı sonlandırmak için subject.complete() çağırın.

Java istemcisi
Sunucudan istemciye akış
SignalR Java istemcisi, akış yöntemlerini çağırmak için stream yöntemini kullanır. stream üç veya daha fazla
bağımsız değişken kabul eder:
Akış öğelerinin beklenen türü.
Hub yönteminin adı.
Hub yönteminde tanımlanan bağımsız değişkenler.

hubConnection.stream(String.class, "ExampleStreamingHubMethod", "Arg1")


.subscribe(
(item) -> {/* Define your onNext handler here. */ },
(error) -> {/* Define your onError handler here. */},
() -> {/* Define your onCompleted handler here. */});
HubConnection streamyöntemi akış öğesi türü için bir observable döndürür. Observable türünün subscribe
yöntemi onNext , onError ve onCompleted işleyicilerinin tanımlanmıştır.

Ek kaynaklar
Merkezler
.NET istemcisi
JavaScript istemcisi
Azure'a Yayımlama
ASP.NET SignalR ve ASP.NET Core arasındaki farklar
SignalR
13.12.2019 • 9 minutes to read • Edit Online

ASP.NET Core SignalR, ASP.NET SignalRiçin istemcilerle veya sunucularla uyumlu değildir. Bu makalede,
ASP.NET Core SignalRkaldırılan veya değiştirilen özellikler ayrıntılı olarak anlatılmaktadır.

SignalR sürümünü belirleme


ASP.NET SIGNALR ASP.NET CORE SIGNALR

Sunucu NuGet paketi Microsoft. AspNet.SignalR Yok. Microsoft. AspNetCore. app Shared
Framework 'e dahildir.

İstemci NuGet paketleri Microsoft. AspNet.SignalR. İstemcilerinin Microsoft. AspNetCore.SignalR.


Microsoft. AspNet.SignalR. JS İstemcilerinin

JavaScript istemcisi NPM paketi SignalR @microsoft/signalr

Java istemcisi GitHub deposu (kullanım dışı) Maven paketi com. Microsoft. SignalR

Sunucu uygulaması türü ASP.NET (System. Web) veya OWıN Self- ASP.NET Core
Host

Desteklenen sunucu platformları .NET Framework 4,5 veya üzeri .NET Core 3,0 veya üzeri

ASP.NET SIGNALR ASP.NET CORE SIGNALR

Sunucu NuGet paketi Microsoft. AspNet.SignalR Microsoft. AspNetCore. app (.NET Core)
Microsoft. AspNetCore.SignalR (.NET
Framework)

İstemci NuGet paketleri Microsoft. AspNet.SignalR. İstemcilerinin Microsoft. AspNetCore.SignalR.


Microsoft. AspNet.SignalR. JS İstemcilerinin

JavaScript istemcisi NPM paketi SignalR @aspnet/signalr

Java istemcisi GitHub deposu (kullanım dışı) Maven paketi com. Microsoft. SignalR

Sunucu uygulaması türü ASP.NET (System. Web) veya OWıN Self- ASP.NET Core
Host

Desteklenen sunucu platformları .NET Framework 4,5 veya üzeri .NET Framework 4.6.1 veya üzeri
.NET Core 2,1 veya üzeri

Özellik farklılıkları
Otomatik yeniden bağlantılar
ASP.NET SignalR:
Varsayılan olarak, bağlantı kesildiğinde SignalR sunucuya yeniden bağlanmaya çalışır.
ASP.NET Core SignalR:
Otomatik yeniden bağlantılar hem .net istemcisiyle hem de JavaScript istemcisiylebirlikte kabul edilir:

HubConnection connection = new HubConnectionBuilder()


.WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
.WithAutomaticReconnect()
.Build();

const connection = new signalR.HubConnectionBuilder()


.withUrl("/chatHub")
.withAutomaticReconnect()
.build();

ASP.NET Core 3,0 ' dan önce SignalR otomatik yeniden bağlanma desteği desteklemez. İstemcinin bağlantısı
kesilirse, kullanıcının yeniden bağlanmak için açık olarak yeni bir bağlantı başlatması gerekir. ASP.NET SignalR' de,
bağlantı kesildiğinde SignalR sunucuya yeniden bağlanmaya çalışır.
Protokol desteği
ASP.NET Core SignalR, JSON 'ı ve MessagePacktabanlı yeni bir ikili protokolü destekler. Ek olarak özel protokoller
de oluşturulabilir.
Taşımalar
ASP.NET Core SignalRiçin süresiz çerçeve taşıması desteklenmez.

Sunucu farkları
ASP.NET Core SignalR sunucu tarafı kitaplıkları, hem Razor hem de MVC projeleri için ASP.NET Core Web
uygulaması şablonunda kullanılan Microsoft. Aspnetcore. app'e dahildir.
ASP.NET Core SignalR bir ASP.NET Core ara yazılımı. Startup.ConfigureServices AddSignalR çağırarak
yapılandırılması gerekir.

services.AddSignalR()

Yönlendirmeyi yapılandırmak için, yolları Startup.Configure yönteminde UseEndpoints yöntemi çağrısının içindeki
hub 'lara eşleyin.

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/hub");
});

Yönlendirmeyi yapılandırmak için, yolları Startup.Configure yönteminde UseSignalR yöntemi çağrısının içindeki
hub 'lara eşleyin.

app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/hub");
});
Yapışkan oturumlar
ASP.NET SignalR için genişleme modeli, istemcilerin gruptaki herhangi bir sunucuya yeniden bağlanmasını ve
iletileri göndermesini sağlar. ASP.NET Core SignalR, istemci bağlantı süresince aynı sunucu ile etkileşime sahip
olmalıdır. Redsıs kullanarak genişleme için, bu, yapışkan oturumların gerekli olduğu anlamına gelir. Azure SignalR
hizmetinikullanarak genişleme için, hizmet istemcilerle bağlantıları işlediği için yapışkan oturumlar gerekli değildir.
Bağlantı başına tek hub
ASP.NET Core SignalR, bağlantı modeli basitleştirilmiştir. Bağlantılar, birden çok hub 'a erişimi paylaşmak için
kullanılan tek bir bağlantı yerine doğrudan tek bir hub 'a yapılır.
Akış
ASP.NET Core SignalR artık hub 'dan istemciye veri akışını desteklemektedir.
State
İstemcilerle Hub (genellikle HubState olarak adlandırılır) arasında rastgele durum geçirme özelliği kaldırılmıştır ve
ilerleme durumu iletileri için destek de sağlar. Şu anda hub proxy 'lerinin karşılığı yok.
PersistentConnection kaldırma
ASP.NET Core SignalR, Persistentconnection sınıfı kaldırılmıştır.
GlobalHost
ASP.NET Core çerçeveye yerleşik bağımlılık ekleme (dı) vardır. Hizmetler, Hubcontext'e erışmek için dı kullanabilir.
HubContext almak için ASP.NET SignalR içinde kullanılan GlobalHost nesnesi ASP.NET Core SignalRyok.

HubPipeline
ASP.NET Core SignalR HubPipeline modül desteğine sahip değildir.

İstemci farkları
TypeScript
ASP.NET Core SignalR istemcisi TypeScript'te yazılmıştır. JavaScript istemcisinikullanırken JavaScript veya
TypeScript ile yazabilirsiniz.
JavaScript istemcisi NPM 'de barındırılıyor
ASP.NET sürümlerinde JavaScript istemcisi, Visual Studio 'da bir NuGet paketi aracılığıyla elde edildi. ASP.NET
Core sürümlerinde, @microsoft/signalr NPM paketi Javascript kitaplıklarını içerir. Bu paket, ASP.NET Core Web
uygulaması şablonuna dahil değildir. @microsoft/signalr NPM paketini edinmek ve yüklemek için NPM kullanın.

npm init -y
npm install @microsoft/signalr

ASP.NET sürümlerinde JavaScript istemcisi, Visual Studio 'da bir NuGet paketi aracılığıyla elde edildi. ASP.NET
Core sürümlerinde, @aspnet/signalr NPM paketi Javascript kitaplıklarını içerir. Bu paket, ASP.NET Core Web
uygulaması şablonuna dahil değildir. @aspnet/signalr NPM paketini edinmek ve yüklemek için NPM kullanın.

npm init -y
npm install @aspnet/signalr

jQuery
JQuery üzerindeki bağımlılık kaldırılmıştır, ancak projeler jQuery kullanmaya devam edebilir.
Internet Explorer desteği
ASP.NET Core SignalR Microsoft Internet Explorer 11 veya üstünü gerektirir (ASP.NET SignalR desteklenen
Microsoft Internet Explorer 8 ve üzeri).
JavaScript istemci yöntemi sözdizimi
JavaScript sözdizimi, SignalRASP.NET sürümünden değiştirilmiştir. $connection nesnesini kullanmak yerine,
Hubconnectionbuilder API 'sini kullanarak bir bağlantı oluşturun.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

Hub 'ın çağırakullanabileceği istemci yöntemlerini belirtmek için on metodunu kullanın.


JavaScript sözdizimi, SignalRASP.NET sürümünden değiştirilmiştir. $connection nesnesini kullanmak yerine,
Hubconnectionbuilder API 'sini kullanarak bir bağlantı oluşturun.

const connection = new signalR.HubConnectionBuilder()


.withUrl("/hub")
.build();

Hub 'ın çağırakullanabileceği istemci yöntemlerini belirtmek için on metodunu kullanın.

connection.on("ReceiveMessage", (user, message) => {


const msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
const encodedMsg = `${user} says ${msg}`;
console.log(encodedMsg);
});

İstemci yöntemini oluşturduktan sonra hub bağlantısını başlatın. Günlüğe kaydetmek veya hataları işlemek için bir
catch metodunu zincirleyin.

connection.start().catch(err => console.error(err));

Hub proxy 'leri


Hub proxy 'leri artık otomatik olarak oluşturulmaz. Bunun yerine, yöntem adı Invoke API 'sine bir dize olarak
geçirilir.
Hub proxy 'leri artık otomatik olarak oluşturulmaz. Bunun yerine, yöntem adı Invoke API 'sine bir dize olarak
geçirilir.
.NET ve diğer istemciler
Microsoft. AspNetCore.SignalR. İstemci NuGet paketi ASP.NET Core SignalR.NET istemci kitaplıklarını içerir.
Hub 'a bağlantı örneği oluşturmak ve derlemek için HubConnectionBuilder kullanın.

connection = new HubConnectionBuilder()


.WithUrl("url")
.Build();

Ölçek Genişletme farklılıkları


ASP.NET SignalR SQL Server ve Redsıs 'yi destekler. ASP.NET Core SignalR Azure SignalR hizmeti 'ni ve Redsıs
'yi destekler.
ASP.NET
Azure Service Bus ile ölçeği SignalR
Redsıs ile SignalR ölçeği
SQL Server ile ölçeği SignalR
ASP.NET Core
Azure SignalR hizmeti
Redsıs geri düzlemi

Ek kaynaklar
Merkezler
JavaScript istemcisi
.NET istemcisi
Desteklenen platformlar
ASP.NET Core desteği WebSockets
13.11.2019 • 13 minutes to read • Edit Online

Tom Dykstra ve Andrew Stanton-nurte


Bu makalede, ASP.NET Core ' de WebSockets ile çalışmaya başlama açıklanmaktadır. WebSocket (RFC 6455),
TCP bağlantıları üzerinden iki yönlü kalıcı iletişim kanalları sağlayan bir protokoldür. Bu, sohbet, pano ve oyun
uygulamaları gibi hızlı, gerçek zamanlı iletişimden faydalanabilir uygulamalarda kullanılır.
Örnek kodu görüntüleyin veya indirin (nasıl indirilir). Nasıl çalıştırılır?

SignalR
ASP.NET Core SignalR , uygulamalara gerçek zamanlı Web işlevselliği eklemeyi kolaylaştıran bir kitaplıktır.
Mümkün olduğunda WebSockets kullanır.
Çoğu uygulama için ham WebSockets üzerinde SignalR önerilir. SignalR, WebSockets 'in kullanılamadığı
ortamlar için taşıma geri dönüşü sağlar. Ayrıca, basit bir uzak yordam çağrısı uygulama modeli sağlar. Çoğu
senaryoda, ham WebSockets kullanmaya kıyasla SignalR önemli bir performans dezavantajı yoktur.

Prerequisites
ASP.NET Core 1,1 veya üzeri
ASP.NET Core destekleyen herhangi bir işletim sistemi:
Windows 7/Windows Server 2008 veya üzeri
Linux
macOS
Uygulama IIS ile Windows üzerinde çalışıyorsa:
Windows 8/Windows Server 2012 veya üzeri
IIS 8/IIS 8 Express
WebSockets etkinleştirilmelidir ( IIS/IIS Express destek bölümüne bakın.).
Uygulama http. sysüzerinde çalışıyorsa:
Windows 8/Windows Server 2012 veya üzeri
Desteklenen tarayıcılar için bkz. https://caniuse.com/#feat=websockets.

NuGet paketi
Microsoft. AspNetCore. WebSockets paketini yükler.

Ara yazılımı yapılandırma


Startup sınıfının Configure metoduna WebSockets ara yazılımını ekleyin:

app.UseWebSockets();

Aşağıdaki ayarlar yapılandırılabilir:


KeepAliveInterval -proxy 'lerin bağlantının açık kalmasını sağlamak için istemciye "ping" çerçeveleri
gönderme sıklığı. Varsayılan değer iki dakikadır.
ReceiveBufferSize -verileri almak için kullanılan arabelleğin boyutu. Gelişmiş kullanıcıların, verilerin boyutuna
bağlı olarak performans ayarlaması için bunu değiştirmesi gerekebilir. Varsayılan değer 4 KB 'tır.
Aşağıdaki ayarlar yapılandırılabilir:
KeepAliveInterval -proxy 'lerin bağlantının açık kalmasını sağlamak için istemciye "ping" çerçeveleri
gönderme sıklığı. Varsayılan değer iki dakikadır.
ReceiveBufferSize-verileri almak için kullanılan arabelleğin boyutu. Gelişmiş kullanıcıların, verilerin boyutuna
bağlı olarak performans ayarlaması için bunu değiştirmesi gerekebilir. Varsayılan değer 4 KB 'tır.
AllowedOrigins -WebSocket istekleri için izin verilen kaynak üst bilgi değerleri listesi. Varsayılan olarak, tüm
kaynaklardan izin verilir. Ayrıntılar için aşağıdaki "WebSocket kaynak kısıtlaması" başlığına bakın.

var webSocketOptions = new WebSocketOptions()


{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
};

app.UseWebSockets(webSocketOptions);

WebSocket isteklerini kabul et


İstek yaşam döngüsünün (daha sonra Configure yönteminde veya bir eylem yönteminde) daha sonra bir yerde,
bir WebSocket isteği olup olmadığını denetleyin ve WebSocket isteğini kabul edin.
Aşağıdaki örnek daha sonra Configure yönteminde verilmiştir:

app.Use(async (context, next) =>


{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(context, webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}

});

Herhangi bir URL 'de bir WebSocket isteği gelebilir, ancak bu örnek kod yalnızca /ws isteklerini kabul eder.
WebSocket kullanırken, bağlantı süresince ara yazılım işlem hattını çalışır durumda tutmanız gerekir . Ara yazılım
ardışık düzeni bittikten sonra bir WebSocket iletisi göndermeye veya almaya çalışırsanız, aşağıdaki gibi bir özel
durum alabilirsiniz:
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection
without completing the close handshake. ---> System.ObjectDisposedException: Cannot write to the response
body, the response has completed.
Object name: 'HttpResponseStream'.

WebSocket 'e veri yazmak için bir arka plan hizmeti kullanıyorsanız, ara yazılım ardışık düzenini çalışır durumda
tutmanız gerekir. Bunu bir TaskCompletionSource<TResult>kullanarak yapın. TaskCompletionSource arka plan
hizmetinize geçirin ve WebSocket ile bitirdiğinizde TrySetResult çağırın. Ardından, aşağıdaki örnekte gösterildiği
gibi, istek sırasında Task özelliğini await :

app.Use(async (context, next) => {


var socket = await context.WebSockets.AcceptWebSocketAsync();
var socketFinishedTcs = new TaskCompletionSource<object>();

BackgroundSocketProcessor.AddSocket(socket, socketFinishedTcs);

await socketFinishedTcs.Task;
});

Bir eylem yönteminden çok yakında döndürüyseniz, WebSocket kapalı özel durumu da oluşabilir. Bir eylem
yönteminde bir yuvayı kabul ediyorsanız, işlem yönteminden dönmeden önce yuva kullanan kodun
tamamlanmasını bekleyin.
Önemli iş parçacığı sorunlarına neden olabileceği için, yuvanın tamamlanmasını beklemek için Task.Wait() ,
Task.Result veya benzer engelleme çağrılarını hiçbir şekilde kullanmayın. await her zaman kullanın.

İleti gönderme ve alma


AcceptWebSocketAsync yöntemi, TCP bağlantısını WebSocket bağlantısıyla yükseltir ve bir WebSocket nesnesi
sağlar. İleti göndermek ve almak için WebSocket nesnesini kullanın.
WebSocket isteğini kabul eden daha önce gösterilen kod WebSocket nesnesini bir Echo yöntemine geçirir. Kod
bir ileti alır ve hemen aynı iletiyi geri gönderir. İletiler, istemci bağlantıyı kapatana kadar bir döngüde gönderilir ve
alınır:

private async Task Echo(HttpContext context, WebSocket webSocket)


{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer),
CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType,
result.EndOfMessage, CancellationToken.None);

result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);


}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription,
CancellationToken.None);
}

Döngüye başlamadan önce WebSocket bağlantısı kabul edildiğinde, ara yazılım ardışık düzeni sona erer. Yuva
kapatıldıktan sonra işlem hattı kaldırımları. Diğer bir deyişle, WebSocket kabul edildiğinde isteğin işlem hattında
ileri doğru hareket ettirilmesi durduruluyor. Döngü bittiğinde ve yuva kapalıyken, istek ardışık düzeni yedekler.

İstemci bağlantısı kesilen işleme


İstemci bağlantı kaybı nedeniyle bağlantısı kesildiğinde sunucu otomatik olarak bilgilendirilmedi. Sunucu, yalnızca
istemci gönderirse, internet bağlantısı kaybedilmişse gerçekleştirilemez bir bağlantı kesme iletisi alır. Bu durumda
bazı işlemleri gerçekleştirmek istiyorsanız, belirli bir zaman penceresinde istemciden hiçbir şey alınmadığında bir
zaman aşımı ayarlayın.
İstemci her zaman ileti göndermiyor ve bağlantı boşta kaldığı için zaman aşımına uğramasını istemiyorsanız,
istemcinin her X saniyede bir ping iletisi göndermesi için bir Zamanlayıcı kullanmasını sağlamak için bir
Zamanlayıcı kullanmasını sağlayabilirsiniz. Sunucusunda, bir ileti öncekinden sonra 2 *X saniye içinde
gelmediyse, bağlantıyı sonlandırın ve istemcinin bağlantısının kesildiğini bildirin. Beklenen zaman aralığının iki
kez, ping iletisini tutabilecek Ağ gecikmeleri için ek süre kalmasını bekleyin.

WebSocket kaynak kısıtlaması


CORS tarafından sunulan korumalar WebSockets için geçerlidir. Tarayıcılar şunları desteklemez:
CORS ön uçuş istekleri gerçekleştirin.
WebSocket istekleri yaparken Access-Control üst bilgilerinde belirtilen kısıtlamalara saygı.

Ancak, tarayıcılar WebSocket istekleri verirken Origin üst bilgisini gönderir. Yalnızca beklenen kaynaklardan
gelen WebSockets izin verildiğinden emin olmak için uygulamalar bu üstbilgileri doğrulamak üzere
yapılandırılmalıdır.
Sunucunuzu "https://server.com" üzerinde barındırıyorsanız ve istemcinizi "https://client.com" üzerinde
barındırıyorsanız, doğrulamak üzere WebSockets için AllowedOrigins listesine "https://client.com" ekleyin.

var webSocketOptions = new WebSocketOptions()


{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

NOTE
Origin üstbilgisi istemci tarafından denetlenir ve Referer üst bilgisi gibi erişilebilir. Bu üst bilgileri kimlik doğrulama
mekanizması olarak kullanmayın.

IIS/IIS Express desteği


IIS/IIS Express 8 veya üzeri ile Windows Server 2012 veya üzeri ve Windows 8 veya üzeri, WebSocket protokolü
için destek içerir.

NOTE
IIS Express kullanılırken WebSockets her zaman etkindir.

IIS üzerinde WebSockets etkinleştirme


Windows Server 2012 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
NOTE
IIS Express kullanılırken bu adımlar gerekli değildir

1. Yönet menüsündeki rol ve özellik ekleme sihirbazı ' nı veya Sunucu Yöneticisibağlantısındaki bağlantıyı
kullanın.
2. Rol tabanlı veya özellik tabanlı yükleme' yi seçin. İleri ' yiseçin.
3. Uygun sunucuyu seçin (yerel sunucu varsayılan olarak seçilidir). İleri ' yiseçin.
4. Roller ağacında Web sunucusu (IIS ) öğesini genişletin, Web sunucusu' nu genişletin ve ardından
uygulama geliştirme' yi genişletin.
5. WebSocket protokolünüseçin. İleri ' yiseçin.
6. Ek özellikler gerekmiyorsa, İleri' yi seçin.
7. Yükle'yi seçin.
8. Yükleme tamamlandığında sihirbazdan çıkmak için Kapat ' ı seçin.
Windows 8 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:

NOTE
IIS Express kullanılırken bu adımlar gerekli değildir

1. > programlar ve Özellikler > Programlar ve Özellikler '\ *e gidin >\ * Windows özelliklerini açın veya
kapatın (ekranın sol tarafında).
2. Şu düğümleri açın: Internet Information Services > World Wide Web > Hizmetleri uygulama
geliştirme özellikleri.
3. WebSocket protokolü özelliğini seçin. Tamam ' ıseçin.
Node. js üzerinde socket.io kullanırken WebSocket 'i devre dışı bırakma
Socket.io içindeki WebSocket desteğini Node. jsüzerinde kullanıyorsanız, Web. config veya ApplicationHost.
configdosyasındaki webSocket öğesini kullanarak varsayılan IIS WebSocket modülünü devre dışı bırakın. Bu
adım gerçekleştirilmemişse, IIS WebSocket modülü Node. js ve uygulama yerine WebSocket iletişimini işlemeye
çalışır.

<system.webServer>
<webSocket enabled="false" />
</system.webServer>

Örnek uygulama
Bu makaleye eşlik eden örnek uygulama bir Echo uygulamasıdır. WebSocket bağlantısı yapan bir Web sayfasına
sahiptir ve sunucu istemciye geri aldığı tüm iletileri daha sonra sonlandırır. Uygulamayı bir komut isteminden
çalıştırın (IIS Express Visual Studio 'dan çalışacak şekilde ayarlanmamış) ve http://localhost:5000 ' a gidin. Web
sayfası, sol üstteki bağlantı durumunu gösterir:
Gösterilen URL 'ye WebSocket isteği göndermek için Bağlan ' ı seçin. Bir sınama iletisi girin ve Gönder' i seçin.
İşiniz bittiğinde yuvayı kapat' ı seçin. Iletişim günlüğü bölümünde her açık, gönder ve Kapat eylemi
gerçekleşir.
ASP.NET Core SignalR günlüğe kaydetme ve tanılama
13.11.2019 • 12 minutes to read • Edit Online

, Andrew Stanton-nurte
Bu makalede, sorunları gidermeye yardımcı olmak için ASP.NET Core SignalR uygulamanızdan tanılama
toplamaya yönelik rehberlik sunulmaktadır.

Sunucu tarafında günlüğe kaydetme


WARNING
Sunucu tarafı günlükleri, uygulamanızdan önemli bilgiler içerebilir. Ham günlükleri hiçbir şekilde üretim uygulamalarından
GitHub gibi genel forumlara nakletmeyin.

SignalR ASP.NET Core bir parçası olduğundan, ASP.NET Core günlük sistemini kullanır. Varsayılan
yapılandırmada SignalR çok az bilgi günlüğe kaydedilir, ancak bu yapılandırılabilir. ASP.NET Core günlüğü
yapılandırma hakkında ayrıntılar için ASP.NET Core günlüğe kaydetme hakkındaki belgelere bakın.
SignalR iki günlükçü kategorisi kullanır:
Merkez protokolleriyle ilgili Günlükler için Microsoft.AspNetCore.SignalR , hub 'Ları etkinleştirme, yöntemleri
çağırma ve hub ile ilgili diğer etkinlikler için –.
WebSockets, uzun yoklama ve sunucu tarafından gönderilen olaylar ve alt düzey SignalR altyapısı gibi
aktarımlarıyla ilgili Günlükler için Microsoft.AspNetCore.Http.Connections –.
SignalRayrıntılı günlükleri etkinleştirmek için, aşağıdaki öğeleri Logging``LogLevel alt bölümüne ekleyerek,
yukarıdaki ön ekleri appSettings. JSON dosyanızdaki Debug düzeyine yapılandırın:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information",
"Microsoft.AspNetCore.SignalR": "Debug",
"Microsoft.AspNetCore.Http.Connections": "Debug"
}
}
}

Ayrıca, CreateWebHostBuilder yöntemdeki kodda de yapılandırabilirsiniz:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
})
.UseStartup<Startup>();

JSON tabanlı yapılandırma kullanmıyorsanız, yapılandırma sisteminizde aşağıdaki yapılandırma değerlerini


ayarlayın:
Logging:LogLevel:Microsoft.AspNetCore.SignalR = Debug
Logging:LogLevel:Microsoft.AspNetCore.Http.Connections = Debug

İç içe yapılandırma değerlerinin nasıl belirleneceğini belirlemek için yapılandırma sisteminizin belgelerini
denetleyin. Örneğin, ortam değişkenlerini kullanırken, : yerine iki _ karakter kullanılır (örneğin,
Logging__LogLevel__Microsoft.AspNetCore.SignalR ).

Uygulamanız için daha ayrıntılı tanılama toplanırken Debug düzeyinin kullanılması önerilir. Trace düzeyi çok
düşük düzey Tanılamalar üretir ve uygulamanızdaki sorunları tanılamak için nadiren gereklidir.

Sunucu tarafı günlüklerine erişin


Sunucu tarafı günlüklerine erişme, çalıştırdığınız ortama bağlıdır.
IIS dışında bir konsol uygulaması olarak
Konsol uygulamasında çalıştırıyorsanız, konsol günlükçüsü varsayılan olarak etkinleştirilmelidir. SignalR Günlükler
konsolunda görünür.
Visual Studio 'dan IIS Express içinde
Visual Studio çıktı penceresinde günlük çıktısını görüntüler. ASP.NET Core Web sunucusu açılır seçeneğini
belirleyin.
Azure App Service
Azure App Service portalının tanılama günlükleri bölümünde uygulama günlüğü (dosya sistemi) seçeneğini
etkinleştirin ve düzeyi Verbose olarak yapılandırın. Günlükler günlük akış hizmetinden ve App Service dosya
sistemindeki günlüklerde kullanılabilir olmalıdır. Daha fazla bilgi için bkz. Azure günlük akışı.
Diğer ortamlar
Uygulama başka bir ortama (örneğin, Docker, Kubernetes veya Windows hizmeti) dağıtılırsa, ortama uygun
günlük sağlayıcılarının nasıl yapılandırılacağı hakkında daha fazla bilgi için bkz. .NET Core ve ASP.NET Core
oturum açma.

JavaScript istemci günlüğü


WARNING
İstemci tarafı günlükleri, uygulamanızdan önemli bilgiler içerebilir. Ham günlükleri hiçbir şekilde üretim uygulamalarından
GitHub gibi genel forumlara nakletmeyin.

JavaScript istemcisini kullanırken, HubConnectionBuilder``configureLogging yöntemi kullanarak günlüğe kaydetme


seçeneklerini yapılandırabilirsiniz:

let connection = new signalR.HubConnectionBuilder()


.withUrl("/my/hub/url")
.configureLogging(signalR.LogLevel.Debug)
.build();

Günlüğe kaydetmeyi tamamen devre dışı bırakmak için configureLogging yönteminde signalR.LogLevel.None
belirtin.
Aşağıdaki tabloda JavaScript istemcisi için kullanılabilir olan günlük düzeyleri gösterilmektedir. Günlük düzeyinin
bu değerlerden birine ayarlanması, bu düzeyde ve tabloda üzerindeki tüm düzeylerde günlüğe kaydetmeyi sağlar.
DÜZEY AÇIKLAMA

None Hiçbir ileti günlüğe kaydedilmez.

Critical Uygulamanın tamamında bir hata olduğunu gösteren mesajlar.

Error Geçerli işlemdeki bir hatayı gösteren mesajlar.

Warning Önemli olmayan bir sorunu belirten mesajlar.

Information Bilgi iletileri.

Debug Tanılama iletileri hata ayıklama için yararlıdır.

Trace Belirli sorunları tanılamak için tasarlanan çok ayrıntılı tanılama


iletileri.

Ayrıntı düzeyini yapılandırdıktan sonra, Günlükler tarayıcı konsoluna yazılır (veya bir NodeJS uygulamasında
standart çıkış).
Günlükleri özel bir günlüğe kaydetme sistemine göndermek istiyorsanız, ILogger arabirimini uygulayan bir
JavaScript nesnesi sağlayabilirsiniz. Uygulanması gereken tek yöntem, olayın düzeyini ve olayla ilişkili iletiyi alan
log . Örneğin:

import { ILogger, LogLevel, HubConnectionBuilder } from "@aspnet/signalr";

export class MyLogger implements ILogger {


log(logLevel: LogLevel, message: string) {
// Use `message` and `logLevel` to record the log message to your own system
}
}

// later on, when configuring your connection...

let connection = new HubConnectionBuilder()


.withUrl("/my/hub/url")
.configureLogging(new MyLogger())
.build();

.NET istemci günlüğü


WARNING
İstemci tarafı günlükleri, uygulamanızdan önemli bilgiler içerebilir. Ham günlükleri hiçbir şekilde üretim uygulamalarından
GitHub gibi genel forumlara nakletmeyin.

.NET istemcisinden günlükleri almak için HubConnectionBuilder``ConfigureLogging yöntemi kullanabilirsiniz. Bu,


WebHostBuilder ve HostBuilder``ConfigureLogging yöntemiyle aynı şekilde çalışmaktadır. ASP.NET Core ' de
kullandığınız günlük sağlayıcılarını yapılandırabilirsiniz. Ancak, bireysel günlük sağlayıcıları için NuGet paketlerini
el ile yükleyip etkinleştirmeniz gerekir.
Konsol günlüğü
Konsol günlüğünü etkinleştirmek için Microsoft. Extensions. Logging. Console paketini ekleyin. Ardından, konsol
günlükçüsü 'yi yapılandırmak için AddConsole yöntemini kullanın:
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/my/hub/url")
.ConfigureLogging(logging =>
{
// Log to the Console
logging.AddConsole();

// This will set ALL logging to Debug level


logging.SetMinimumLevel(LogLevel.Debug);
})
.Build();

Çıkış penceresi günlüğüne hata ayıkla


Günlükleri, Visual Studio 'daki Çıkış penceresine gitmek için de yapılandırabilirsiniz. Microsoft. Extensions.
Logging. Debug paketini yükleyip AddDebug yöntemi kullanın:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/my/hub/url")
.ConfigureLogging(logging =>
{
// Log to the Output Window
logging.AddDebug();

// This will set ALL logging to Debug level


logging.SetMinimumLevel(LogLevel.Debug)
})
.Build();

Diğer günlüğe kaydetme sağlayıcıları


SignalR, Serilog, seq, NLog veya Microsoft.Extensions.Logging ile tümleştirilen herhangi bir günlük sistemi gibi
diğer günlük sağlayıcılarını destekler. Günlüğe kaydetme sisteminiz bir ILoggerProvider sağlıyorsa, bu dosyayı
AddProvider kaydedebilirsiniz:

var connection = new HubConnectionBuilder()


.WithUrl("https://example.com/my/hub/url")
.ConfigureLogging(logging =>
{
// Log to your custom provider
logging.AddProvider(new MyCustomLoggingProvider());

// This will set ALL logging to Debug level


logging.SetMinimumLevel(LogLevel.Debug)
})
.Build();

Denetim ayrıntı düzeyi


Uygulamanızdaki diğer yerlerden oturum açıyorsanız, varsayılan düzeyin Debug olarak değiştirilmesi çok ayrıntılı
olabilir. Kayıt düzeyini SignalR Günlükler için yapılandırmak üzere bir filtre kullanabilirsiniz. Bu, sunucuda olduğu
şekilde kodda yapılabilir:
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/my/hub/url")
.ConfigureLogging(logging =>
{
// Register your providers

// Set the default log level to Information, but to Debug for SignalR-related loggers.
logging.SetMinimumLevel(LogLevel.Information);
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
})
.Build();

Ağ izlemeleri
WARNING
Bir ağ izlemesi, uygulamanız tarafından gönderilen her iletinin tam içeriğini içerir. Ham ağ izlemelerini, üretim
uygulamalarından GitHub gibi genel forumlara hiçbir şekilde yayımlayamazsınız.

Bir sorunla karşılaşırsanız, ağ izleme bazen yararlı olabilecek çok sayıda bilgi sağlayabilir. Sorun izleyicimizde bir
sorun oluşturacaksanız bu özellikle yararlı olur.

Fiddler ile ağ izleme toplama (tercih edilen seçenek)


Bu yöntem tüm uygulamalar için geçerlidir.
Fiddler, HTTP izlemelerinin toplanması için çok güçlü bir araçtır. Telerik.com/Fiddleradresinden yükleyip
uygulamayı çalıştırın ve sorunu yeniden oluşturun. Fiddler Windows için kullanılabilir ve macOS ve Linux için beta
sürümleri mevcuttur.
HTTPS kullanarak bağlanıyorsanız, Fiddler 'ın HTTPS trafiğinin şifresini çözebilmesini sağlamaya yönelik bazı ek
adımlar vardır. Daha ayrıntılı bilgi için bkz. Fiddler belgeleri.
İzlemeyi topladıktan sonra, dosya > seçerek izlemeyi dışarı aktarabilirsiniz. bu işlemi, menü çubuğundan tüm
oturumları > Kaydet ' i seçin.
Tcpdump ile bir ağ izlemesi toplayın (yalnızca macOS ve Linux)
Bu yöntem tüm uygulamalar için geçerlidir.
Komut kabuğundan aşağıdaki komutu çalıştırarak, tcpdump kullanarak ham TCP izlemeleri toplayabilirsiniz. Bir
izin hatası alırsanız, root olması veya komutun sudo öneki olması gerekebilir:

tcpdump -i [interface] -w trace.pcap

[interface] , yakalamak istediğiniz ağ arabirimiyle değiştirin. Genellikle bu, /dev/eth0 (Standart Ethernet
arabiriminiz için) veya /dev/lo0 (localhost trafiği için) gibi bir şeydir. Daha fazla bilgi için, ana bilgisayar
sisteminizdeki tcpdump Man sayfasına bakın.

Tarayıcıda bir ağ izlemesi toplayın


Bu yöntem yalnızca tarayıcı tabanlı uygulamalar için geçerlidir.
Çoğu tarayıcı Geliştirici Araçları, tarayıcı ve sunucu arasında ağ etkinliğini yakalamanızı sağlayan bir "ağ" sekmesi
vardır. Ancak, bu izlemeler WebSocket ve sunucu tarafından gönderilen olay iletilerini içermez. Bu taşımaları
kullanıyorsanız, Fiddler veya TcpDump (aşağıda açıklanmıştır) gibi bir araç kullanmak daha iyi bir yaklaşımdır.
Microsoft Edge ve Internet Explorer
(Yönergeler hem Edge hem de Internet Explorer için aynıdır)
1. Geliştirici araçlarını açmak için F12 tuşuna basın
2. Ağ sekmesine tıklayın
3. Sayfayı (gerekirse) yenileyin ve sorunu yeniden oluşturun
4. İzlemeyi "HAR" dosyası olarak dışarı aktarmak için araç çubuğundaki Kaydet simgesine tıklayın:
Google Chrome
1. Geliştirici araçlarını açmak için F12 tuşuna basın
2. Ağ sekmesine tıklayın
3. Sayfayı (gerekirse) yenileyin ve sorunu yeniden oluşturun
4. İstek listesinde herhangi bir yere sağ tıklayın ve "İçerikle HAR olarak Kaydet" i seçin:

Mozilla Firefox
1. Geliştirici araçlarını açmak için F12 tuşuna basın
2. Ağ sekmesine tıklayın
3. Sayfayı (gerekirse) yenileyin ve sorunu yeniden oluşturun
4. İstek listesinde herhangi bir yere sağ tıklayın ve "tümünü HAR olarak Kaydet" i seçin
GitHub sorunlarına tanılama dosyaları iliştirme
Tanılama dosyalarını, .txt uzantısına sahip olacak şekilde yeniden adlandırarak ve sonra sorunu üzerine
sürükleyip bırakarak GitHub sorunlarına iliştirebilirsiniz.

NOTE
Lütfen günlük dosyalarının veya ağ izlemelerinin içeriğini bir GitHub sorununa yapıştırmayın. Bu Günlükler ve izlemeler
oldukça büyük olabilir ve GitHub genellikle bunları keser.

Ek kaynaklar
ASP.NET Core SignalR yapılandırması
ASP.NET Core SignalR JavaScript istemcisi
.NET Client ASP.NET Core SignalR
.NET Core 'da gRPC 'ye giriş
4.10.2019 • 3 minutes to read • Edit Online

John Luo ve James bAyKiNg


GRPC , dilden bağımsız, yüksek performanslı bir uzak yordam ÇAĞRıSı (RPC ) çerçevesidir.
GRPC 'nin başlıca avantajları şunlardır:
Modern, yüksek performanslı, hafif RPC çerçevesi.
Sözleşme-ilk API geliştirmesi, varsayılan olarak protokol arabellekleri kullanarak, dilden bağımsız
uygulamalar için izin verir.
Birçok dilde araç, kesin türü belirtilmiş sunucu ve istemciler oluşturmak için kullanılabilir.
İstemci, sunucu ve iki yönlü akış çağrılarını destekler.
Protoarabelleğe ikili serileştirme ile azaltılmış ağ kullanımı.
Bu avantajlar, gRPC 'yi ideal hale getirir:
Verimlilik açısından kritik olan hafif mikro hizmetler.
Geliştirme için birden fazla dilin gerekli olduğu çok yönlü sistemleri.
Akış isteklerini veya yanıtlarını işlemek için gereken noktadan noktaya gerçek zamanlı hizmetler.

C#. Proto dosyaları için araç desteği


gRPC, API geliştirmesi için bir sözleşmenin ilk yaklaşımını kullanır. Hizmetler ve mesajlar *. proto
dosyalarında tanımlanmıştır:

syntax = "proto3";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

Hizmetler, istemciler ve iletiler için .net türleri bir projedeki *. proto dosyaları eklenerek otomatik olarak
oluşturulur:
GRPC. Tools paketine bir paket başvurusu ekleyin.
*. Proto dosyalarını <Protobuf> öğe grubuna ekleyin.

<ItemGroup>
<Protobuf Include="Protos\greet.proto" />
</ItemGroup>

GRPC araç desteği hakkında daha fazla bilgi için bkz C# içeren gRPC hizmetleri.
ASP.NET Core gRPC Hizmetleri
gRPC Hizmetleri, ASP.NET Core üzerinde barındırılabilir. Hizmetler, günlüğe kaydetme, bağımlılık ekleme
(dı), kimlik doğrulama ve yetkilendirme gibi popüler ASP.NET Core özelliklerle tam tümleştirmeye sahiptir.
GRPC hizmeti proje şablonu bir başlatıcı hizmeti sağlar:

public class GreeterService : Greeter.GreeterBase


{
private readonly ILogger<GreeterService> _logger;

public GreeterService(ILogger<GreeterService> logger)


{
_logger = logger;
}

public override Task<HelloReply> SayHello(HelloRequest request,


ServerCallContext context)
{
_logger.LogInformation("Saying hello to {Name}", request.Name);
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

GreeterService ,. proto dosyasındaki GreeterBase Greeter hizmetten oluşturulan türden devralır. * Hizmet,
Startup.csiçindeki istemciler için erişilebilir hale getirilir:

app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});

ASP.NET Core 'de gRPC hizmetleri hakkında daha fazla bilgi edinmek için ASP.NET Core içeren gRPC
Hizmetleribkz.

Bir .NET istemcisiyle gRPC hizmetlerini çağırma


GRPC istemcileri *. proto dosyalarından oluşturulansomut istemci türleridir. Somut GRPC istemcisinde *.
proto dosyasındaki GRPC hizmetine çeviren yöntemler vardır.

var channel = GrpcChannel.ForAddress("https://localhost:5001");


var client = new Greeter.GreeterClient(channel);

var response = await client.SayHello(


new HelloRequest { Name = "World" });

Console.WriteLine(response.Message);

GRPC istemcisi, bir gRPC hizmeti ile uzun süreli bağlantıyı temsil eden bir kanal kullanılarak oluşturulur.
Kullanılarak GrpcChannel.ForAddress bir kanal oluşturulabilir.
İstemci oluşturma ve farklı hizmet yöntemlerini çağırma hakkında daha fazla bilgi için bkz .NET istemcisiyle
gRPC hizmetlerini çağırma.

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub
sorunu.

Ek kaynaklar
C# içeren gRPC hizmetleri
ASP.NET Core içeren gRPC Hizmetleri
.NET istemcisiyle gRPC hizmetlerini çağırma
.NET Core 'da gRPC istemci fabrikası tümleştirmesi
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
Öğretici: ASP.NET Core bir gRPC istemcisi ve
sunucusu oluşturma
6.12.2019 • 15 minutes to read • Edit Online

John Luo tarafından


Bu öğreticide, bir .NET Core GRPC istemcisinin ve bir ASP.NET Core GRPC sunucusunun nasıl oluşturulacağı
gösterilmektedir.
Sonda, gRPC Greeter hizmeti ile iletişim kuran bir gRPC istemcisine sahip olacaksınız.
Örnek kodu görüntüleyin veya indirin (nasıl indirilir).
Bu öğreticide şunları yaptınız:
GRPC sunucusu oluşturun.
GRPC istemcisi oluşturun.
GRPC istemci hizmetini gRPC Greeter hizmeti ile test edin.

Prerequisites
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

GRPC hizmeti oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'Yu başlatın ve Yeni proje oluştur' u seçin. Alternatif olarak, Visual Studio Dosya
menüsünden Yeni > projesi' ni seçin.
Yeni proje oluştur Iletişim kutusunda GRPC hizmeti ' ni seçin ve İleri' yi seçin:

Projeyi Grpcgreeterolarak adlandırın. Kodu kopyalayıp yapıştırdığınızda ad alanlarının eşleşmesi için,


proje Grpcgreeter adında bir ad vermek önemlidir.
Seçin oluşturma.
Yeni bir gRPC hizmeti oluştur iletişim kutusunda:
GRPC hizmeti şablonu seçilidir.
Seçin oluşturma.
Hizmeti çalıştırma
Visual Studio
Visual Studio Code
Mac için Visual Studio
Hata ayıklayıcı olmadan çalıştırmak için CTRL + F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:

IIS Express SSL sertifikasına güveniyorsanız Evet ' i seçin.


Aşağıdaki iletişim kutusu görüntülenir:

Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet ' i seçin.


Visual Studio IIS Express başlar ve uygulamayı çalıştırır. Adres çubuğunda localhost:port# ve
example.com gibi bir şey görüntülenir. Bunun nedeni, localhost yerel bilgisayar için Standart ana
bilgisayar adıdır. Localhost yalnızca yerel bilgisayardan Web isteklerine hizmet verir. Visual Studio bir Web
projesi oluşturduğunda, Web sunucusu için rastgele bir bağlantı noktası kullanılır.
Günlükler, https://localhost:5001 üzerinde dinleme hizmetini gösterir.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development

NOTE
GRPC şablonu, Aktarım Katmanı Güvenliği (TLS)kullanmak üzere yapılandırılmıştır. gRPC istemcilerinin, sunucuyu çağırmak
için HTTPS kullanması gerekir.
macOS, TLS ile ASP.NET Core gRPC 'yi desteklemez. MacOS 'ta gRPC hizmetlerini başarıyla çalıştırmak için ek yapılandırma
gerekir. Daha fazla bilgi için bkz. macOS üzerinde gRPC uygulaması ASP.NET Core başlatılamıyor.

Proje dosyalarını inceleyin


Grpcgreeter proje dosyaları:
Greet. proto – prototips/Greet. proto dosyası Greeter GRPC 'Yi tanımlar ve GRPC sunucu varlıklarını
oluşturmak için kullanılır. Daha fazla bilgi için bkz. gRPC 'ye giriş.
Hizmetler klasörü: Greeter hizmetinin uygulamasını içerir.
appSettings. json –, Kestrel tarafından kullanılan protokol gibi yapılandırma verilerini içerir. Daha fazla bilgi için
bkz. ASP.NET Core yapılandırma.
Program.cs –, GRPC hizmetinin giriş noktasını içerir. Daha fazla bilgi için bkz. .NET genel ana bilgisayar.
Startup.cs – uygulama davranışını yapılandıran kodu içerir. Daha fazla bilgi için bkz. uygulama başlatma.

Bir .NET konsol uygulamasında gRPC istemcisini oluşturma


Visual Studio
Visual Studio Code
Mac için Visual Studio
Visual Studio 'nun ikinci bir örneğini açın ve Yeni proje oluştur' u seçin.
Yeni proje oluştur Iletişim kutusunda konsol uygulaması (.NET Core) öğesini seçin ve İleri' yi seçin.
Ad metin kutusuna Grpcgreeterclient girin ve Oluştur' u seçin.
Gerekli paketleri Ekle
GRPC istemci projesi aşağıdaki paketleri gerektirir:
.NET Core istemcisini içeren GRPC .net. Client.
İçin C#prototipsiz Ileti API 'Leri içeren Google. protoarabellek.
Prototipleme dosyaları için araç desteğini C# Içeren GRPC. Tools. Araç, çalışma zamanında gerekli değildir, bu
nedenle bağımlılık PrivateAssets="All" olarak işaretlenir.

Visual Studio
Visual Studio Code
Mac için Visual Studio
Paket Yöneticisi Konsolu (PMC ) veya NuGet Paketlerini Yönet ' i kullanarak paketleri yükler.
Paket yüklemek için PMC seçeneği
Visual Studio 'da araçlar > NuGet Paket Yöneticisi > Paket Yöneticisi konsolu ' nu seçin.
Paket Yöneticisi konsol penceresinde, Grpcgreeterclient. csproj dosyalarını içeren klasöre Dizin
değiştirmek için cd GrpcGreeterClient çalıştırın.
Aşağıdaki komutları çalıştırın:

Install-Package Grpc.Net.Client
Install-Package Google.Protobuf
Install-Package Grpc.Tools

Paket yüklemek için NuGet Paketlerini Yönet seçeneği


NuGet paketlerini yönetmek > Çözüm Gezgini ' de projeye sağ tıklayın
Gözat sekmesini seçin.
Arama kutusuna GRPC .net. Client girin.
Araştır sekmesinden GRPC .net. Client paketini seçin ve ardından Install' ı seçin.
Google.Protobuf ve Grpc.Tools için yineleyin.

Greet. proto Ekle


GRPC istemci projesinde bir Prototips klasörü oluşturun.
Protos\bilgisem. proto dosyasını GRPC Greeter hizmetinden GRPC istemci projesine kopyalayın.
Grpcgreeterclient. csproj proje dosyasını düzenleyin:
Visual Studio
Visual Studio Code
Mac için Visual Studio
Projeye sağ tıklayın ve Proje dosyasını Düzenle' yi seçin.

Greet. proto dosyasına başvuran <Protobuf> öğesi olan bir öğe grubu ekleyin:

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Greeter istemcisini oluşturma


GrpcGreeter ad alanındaki türleri oluşturmak için projeyi derleyin. GrpcGreeter türleri yapı işlemi tarafından
otomatik olarak oluşturulur.
GRPC Client program.cs dosyasını aşağıdaki kodla güncelleştirin:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using GrpcGreeter;
using Grpc.Net.Client;

namespace GrpcGreeterClient
{
class Program
{
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}

Program.cs , GRPC istemcisinin giriş noktasını ve mantığını içerir.


Greeter istemcisi şu şekilde oluşturulur:
GRPC hizmetine bağlantı oluşturma bilgilerini içeren bir GrpcChannel örnekleniyor.
Greeter istemcisini oluşturmak için GrpcChannel kullanma:

static async Task Main(string[] args)


{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}

Greeter istemcisi zaman uyumsuz SayHello yöntemini çağırır. SayHello çağrısının sonucu görüntülenir:

static async Task Main(string[] args)


{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}

GRPC istemcisini gRPC Greeter hizmeti ile test etme


Visual Studio
Visual Studio Code
Mac için Visual Studio
Greeter hizmetinde, hata ayıklayıcı olmadan sunucuyu başlatmak için Ctrl+F5 ' a basın.
GrpcGreeterClient projede, hata ayıklayıcı olmadan istemcisini başlatmak için Ctrl+F5 ' a basın.

İstemci, adı Greeterclientolan bir iletiyle hizmete bir tebrik gönderir. Hizmet, "Hello GreeterClient" iletisini yanıt
olarak gönderir. Komut isteminde "Hello GreeterClient" yanıtı görüntülenir:

Greeting: Hello GreeterClient


Press any key to exit...

GRPC hizmeti, komut istemine yazılan günlüklerde başarılı çağrının ayrıntılarını kaydeder:

info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\GH\aspnet\docs\4\Docs\aspnetcore\tutorials\grpc\grpc-start\sample\GrpcGreeter
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 POST https://localhost:5001/Greet.Greeter/SayHello application/grpc
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 78.32260000000001ms 200 application/grpc

NOTE
Bu makaledeki kod, gRPC hizmetini güvenli hale getirmek için ASP.NET Core HTTPS geliştirme sertifikası gerektirir. İstemci
The remote certificate is invalid according to the validation procedure. ileti ile başarısız olursa, geliştirme
sertifikası güvenilir değildir. Bu sorunu gidermeye yönelik yönergeler için bkz. Windows ve macOS 'ta ASP.NET Core https
geliştirme sertifikasına güvenin.

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub sorunu.

Sonraki adımlar
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
GRPC hizmetlerini C Core 'dan ASP.NET Core geçirme
C# ile gRPC Hizmetleri
23.11.2019 • 5 minutes to read • Edit Online

Bu belgede, ' de C# GRPC uygulamaları yazmak için gereken kavramlar özetlenmektedir. Burada ele alınan
konular hem C Coretabanlı hem de ASP.NET Core tabanlı GRPC uygulamaları için geçerlidir.

Proto dosyası
gRPC, API geliştirmesi için bir sözleşmenin ilk yaklaşımını kullanır. Protokol arabellekleri (protobellek) varsayılan
olarak arabirim tasarım dili (IDL ) olarak kullanılır. *. proto dosyası şunları içerir:
GRPC hizmetinin tanımı.
İstemciler ve sunucular arasında gönderilen iletiler.
Prototipsiz dosyaların sözdizimi hakkında daha fazla bilgi için, resmi belgelere (protoarabellek)bakın.
Örneğin, gRPC hizmetini kullanmaya başlamabölümünde kullanılan Greet. proto dosyasını düşünün:
Greeter bir hizmeti tanımlar.
Greeter hizmeti SayHello çağrısını tanımlar.
SayHello bir HelloRequest iletisi gönderir ve bir HelloReply iletisi alır:

syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.


service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.


message HelloRequest {
string name = 1;
}

// The response message containing the greetings.


message HelloReply {
string message = 1;
}

C# uygulamasına. proto dosyası ekleme


*. proto dosyası bir projeye <Protobuf> öğesi grubuna eklenerek eklenir:

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

C#. Proto dosyaları için araç desteği


Araç Paketi GRPC. Tools , C# *. proto dosyalarından varlıkları oluşturmak için gereklidir. Oluşturulan varlıklar
(dosyalar):
, Projenin oluşturulduğu her seferinde gerekli olarak oluşturulur.
Projeye eklenmez veya kaynak denetimine iade edilmedi.
Obj dizininde bulunan bir yapı yapıtı.
Bu paket hem sunucu hem de istemci projeleri için gereklidir. Grpc.AspNetCore metapackage Grpc.Tools bir
başvuru içerir. Sunucu projeleri, Visual Studio 'da Paket Yöneticisi 'Ni kullanarak veya proje dosyasına bir
<PackageReference> ekleyerek Grpc.AspNetCore ekleyebilir:

<PackageReference Include="Grpc.AspNetCore" Version="2.23.2" />

İstemci projeleri, gRPC istemcisini kullanmak için gereken diğer paketlerle birlikte Grpc.Tools doğrudan
başvurmalıdır. Araç, çalışma zamanında gerekli değildir, bu nedenle bağımlılık PrivateAssets="All" olarak
işaretlenir:

<PackageReference Include="Google.Protobuf" Version="3.9.2" />


<PackageReference Include="Grpc.Net.Client" Version="2.23.2" />
<PackageReference Include="Grpc.Tools" Version="2.23.0" PrivateAssets="All" />

Oluşturulan C# varlıklar
Araç paketi, eklenen C# *. proto dosyalarında tanımlanan iletileri temsil eden türleri oluşturur.
Sunucu tarafı varlıklar için, soyut bir hizmet temel türü oluşturulur. Temel tür, . proto dosyasında bulunan tüm
GRPC çağrılarının tanımlarını içerir. Bu temel türden türetilen somut bir hizmet uygulamasını oluşturun ve gRPC
çağrılarının mantığını uygular. greet.proto için, daha önce açıklanan örnek, bir sanal SayHello yöntemi içeren
soyut bir GreeterBase türü oluşturulur. Somut bir uygulama GreeterService yöntemi geçersiz kılar ve gRPC
çağrısını idare eden mantığı uygular.

public class GreeterService : Greeter.GreeterBase


{
public override Task<HelloReply> SayHello(
HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

İstemci tarafı varlıklar için somut bir istemci türü oluşturulur. . Proto dosyasındaki GRPC çağrıları, çağrılabilecek
somut türdeki yöntemlere çevrilir. Daha önce açıklanan örnek greet.proto için somut bir GreeterClient türü
oluşturulur. Sunucuya bir gRPC çağrısı başlatmak için GreeterClient.SayHelloAsync çağırın.
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}

Varsayılan olarak, sunucu ve istemci varlıkları <Protobuf> öğesi grubuna eklenen her bir *. proto dosyası için
oluşturulur. Sunucu projesinde yalnızca sunucu varlıklarının oluşturulmasını sağlamak için, GrpcServices
özniteliği Server olarak ayarlanır.

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Benzer şekilde, özniteliği istemci projelerinde Client olarak ayarlanır.

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub
sorunu.

Ek kaynaklar
.NET Core 'da gRPC 'ye giriş
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
ASP.NET Core içeren gRPC Hizmetleri
.NET istemcisiyle gRPC hizmetlerini çağırma
ASP.NET Core içeren gRPC Hizmetleri
4.10.2019 • 7 minutes to read • Edit Online

Bu belgede, ASP.NET Core kullanarak gRPC Hizmetleri ile çalışmaya başlama gösterilmektedir.

Önkoşullar
Visual Studio
Visual Studio Code
Mac için Visual Studio
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

ASP.NET Core’da gRPC hizmeti ile çalışmaya başlama


Örnek kodu görüntüle veya indir (indirme).
Visual Studio
Visual Studio Code/Mac için Visual Studio
GRPC projesi oluşturma hakkında ayrıntılı yönergeler için bkz. GRPC hizmetlerini kullanmaya başlama .

ASP.NET Core uygulamasına gRPC Hizmetleri ekleme


gRPC, GRPC. AspNetCore paketini gerektirir.
GRPC 'yi yapılandırma
Startup.csiçinde:
GRPC, AddGrpc yöntemiyle etkinleştirilir.
Her GRPC hizmeti, yönlendirme ardışık düzenine MapGrpcService yöntemi aracılığıyla eklenir.
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?
LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseRouting();

app.UseEndpoints(endpoints =>
{
// Communication with gRPC endpoints must be made through a gRPC client.
// To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909
endpoints.MapGrpcService<GreeterService>();
});
}
}

ASP.NET Core middlewares ve Özellikler yönlendirme işlem hattını paylaşır, bu nedenle uygulama ek istek
işleyicileri sunacak şekilde yapılandırılabilir. MVC denetleyicileri gibi ek istek işleyicileri, yapılandırılmış gRPC
hizmetleriyle paralel olarak çalışır.
Kestrel yapılandırma
Kestrel gRPC uç noktaları:
HTTP/2 gerektir.
Aktarım Katmanı Güvenliği (TLS )ile güvenli hale getirilmesi gerekir.
HTTP/2
gRPC, HTTP/2 gerektirir. ASP.NET Core için gRPC, HttpRequest. Protocol olduğunu HTTP/2 doğrular.
Kestrel çoğu modern işletim sisteminde http/2 destekler . Kestrel uç noktaları, varsayılan olarak HTTP/1.1 ve
HTTP/2 bağlantılarını destekleyecek şekilde yapılandırılmıştır.
TLS
GRPC için kullanılan Kestrel uç noktaları TLS ile güvenli hale gelmelidir. Geliştirme aşamasında, ASP.NET Core
geliştirme sertifikası mevcut https://localhost:5001 olduğunda, TLS ile güvenli bir uç nokta otomatik olarak
oluşturulur. Yapılandırma gerekmiyor. https Ön ek, Kestrel uç noktasının TLS kullandığını doğrular.
Üretimde, TLS açıkça yapılandırılmalıdır. Aşağıdaki appSettings. JSON ÖRNEĞINDE, TLS ile güvenliği
SAĞLANMıŞ bir http/2 uç noktası verilmiştir:
{
"Kestrel": {
"Endpoints": {
"HttpsInlineCertFile": {
"Url": "https://localhost:5001",
"Protocols": "Http2",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
}
}
}

Alternatif olarak, Kestrel uç noktaları program.csiçinde yapılandırılabilir:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
listenOptions.UseHttps("<path to .pfx file>",
"<certificate password>");
});
});
webBuilder.UseStartup<Startup>();
});

Protokol anlaşması
TLS, iletişimin güvenliğinin daha fazlası için kullanılır. TLS uygulama katmanı protokol anlaşması (ALPN ) el
sıkışması, bir uç nokta birden çok protokolü desteklediğinde istemci ile sunucu arasındaki bağlantı protokolünü
anlaşmak için kullanılır. Bu anlaşma, bağlantının HTTP/1.1 veya HTTP/2 kullanıp kullanmadığını belirler.
Bir HTTP/2 uç noktası TLS olmadan yapılandırılırsa, uç noktanın Listenoptions. Protocols olarak
HttpProtocols.Http2 ayarlanmalıdır. Bir anlaşma olmadığından, birden fazla protokolle (
HttpProtocols.Http1AndHttp2 Örneğin,) bir uç nokta TLS olmadan kullanılamaz. Güvenli olmayan uç nokta
varsayılan HTTP/1.1 ve gRPC çağrıları için tüm bağlantılar başarısız olur.
HTTP/2 ve TLS 'yi Kestrel ile etkinleştirme hakkında daha fazla bilgi için bkz. Kestrel Endpoint Configuration.

NOTE
macOS, TLS ile ASP.NET Core gRPC 'yi desteklemez. MacOS 'ta gRPC hizmetlerini başarıyla çalıştırmak için ek yapılandırma
gerekir. Daha fazla bilgi için bkz. macOS üzerinde gRPC uygulaması ASP.NET Core başlatılamıyor.

ASP.NET Core API 'Leri ile tümleştirme


gRPC Hizmetleri, bağımlılık ekleme (dı) ve günlüğe kaydetmegibi ASP.NET Core özelliklerine tam erişime
sahiptir. Örneğin, hizmet uygulama, Oluşturucu aracılığıyla bir günlükçü hizmetini dı kapsayıcısından
çözümleyebilir:
public class GreeterService : Greeter.GreeterBase
{
public GreeterService(ILogger<GreeterService> logger)
{
}
}

Varsayılan olarak, gRPC hizmeti uygulama diğer dı hizmetlerini herhangi bir yaşam süresi (tek, kapsamlı veya
geçici) ile çözümleyebilir.
GRPC yöntemlerinde HttpContext 'i çözümle
GRPC API 'SI, yöntem, ana bilgisayar, üst bilgi ve tanıtımları gibi bazı HTTP/2 ileti verilerine erişim sağlar.Erişim,
her GRPC yöntemine geçirilen bağımsızdeğişkendir: ServerCallContext

public class GreeterService : Greeter.GreeterBase


{
public override Task<HelloReply> SayHello(
HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

ServerCallContext tüm ASP.NET API 'lerinde tam erişim HttpContext sağlamaz. Genişletme yöntemi, ASP.NET
API 'lerinde temel alınan HttpContext http/2 iletisini temsil eden öğesine tam erişim sağlar: GetHttpContext

public class GreeterService : Greeter.GreeterBase


{
public override Task<HelloReply> SayHello(
HelloRequest request, ServerCallContext context)
{
var httpContext = context.GetHttpContext();
var clientCertificate = httpContext.Connection.ClientCertificate;

return Task.FromResult(new HelloReply


{
Message = "Hello " + request.Name + " from " + clientCertificate.Issuer
});
}
}

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub sorunu.

Ek kaynaklar
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
ASP.NET Core Web sunucusu uygulamasını Kestrel
.NET istemcisiyle gRPC hizmetlerini çağırma
16.09.2019 • 6 minutes to read • Edit Online

GRPC .net. Client NuGet paketinde bir .net GRPC istemci kitaplığı mevcuttur. Bu belgede nasıl yapılacağı
açıklanmaktadır:
GRPC istemcisini, gRPC hizmetlerini çağırmak üzere yapılandırın.
GRPC 'yi birli, sunucu akışı, istemci akışı ve iki yönlü akış yöntemlerine göre çağırır.

GRPC istemcisini yapılandırma


GRPC istemcileri *. proto dosyalarından oluşturulansomut istemci türleridir. Somut GRPC istemcisinde *. proto
dosyasındaki GRPC hizmetine çeviren yöntemler vardır.
Bir kanaldan gRPC istemcisi oluşturulur. ' I kullanarak GrpcChannel.ForAddress bir kanal oluşturun ve ardından bir
GRPC istemcisi oluşturmak için kanalı kullanın:

var channel = GrpcChannel.ForAddress("https://localhost:5001");


var client = new Greet.GreeterClient(channel);

Kanal, gRPC hizmetine uzun süreli bir bağlantıyı temsil eder. Bir kanal oluşturulduğunda, hizmet çağırma ile ilgili
seçeneklerle yapılandırılır. Örneğin, HttpClient çağrı yapmak için kullanılan, en fazla ileti ve alma iletisi boyutu,
ve ' de üzerinde GrpcChannelOptions GrpcChannel.ForAddress günlüğe kaydetme belirlenebilir. Seçeneklerin
tamamı listesi için bkz. istemci yapılandırma seçenekleri.
Kanal oluşturma maliyetli bir işlem olabilir ve gRPC çağrıları için bir kanalı yeniden kullanmak performans
avantajları sunar. Farklı türlerde istemciler de dahil olmak üzere bir kanaldan birden fazla somut gRPC istemcisi
oluşturulabilir. Somut gRPC istemci türleri basit nesnelerdir ve gerektiğinde oluşturulabilir.

var channel = GrpcChannel.ForAddress("https://localhost:5001");

var greeterClient = new Greet.GreeterClient(channel);


var counterClient = new Count.CounterClient(channel);

// Use clients to call gRPC services

GrpcChannel.ForAddress gRPC istemcisi oluşturmak için tek seçenek değildir. GRPC hizmetlerini bir ASP.NET
Core uygulamasından arıyorsanız, GRPC istemci fabrikası tümleştirmesinigöz önünde bulundurun. ile GRPC
tümleştirmesi HttpClientFactory , GRPC istemcileri oluşturmaya yönelik merkezi bir alternatif sunar.

NOTE
.Net istemcisiyle güvenli olmayan gRPC hizmetlerini çağırmakiçin ek yapılandırma gerekir.

GRPC çağrıları yapma


Bir gRPC çağrısı, istemcideki bir yöntem çağırarak başlatılır. GRPC istemcisi, ileti serileştirme işlemini işleyecek ve
doğru hizmete gRPC çağrısını ele alacak.
gRPC farklı türde yöntemlere sahiptir. Bir gRPC çağrısını yapmak için istemcisini nasıl kullandığınız, çağırdığınız
yöntemin türüne bağlıdır. GRPC Yöntem türleri şunlardır:
Li
Sunucu akışı
İstemci akışı
İki yönlü akış
Birli çağrı
Birli çağrı, istemci isteği iletisi gönderen ile başlar. Hizmet bittiğinde bir yanıt iletisi döndürülür.

var client = new Greet.GreeterClient(channel);


var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });

Console.WriteLine("Greeting: " + response.Message);


// Greeting: Hello World

. Proto dosyasındaki her birli hizmet yöntemi * , yöntemi çağırmak için somut GRPC istemci türünde iki .NET
yöntemi oluşmasına neden olur: zaman uyumsuz bir yöntem ve engelleyici bir yöntem. Örneğin, GreeterClient
iki çağırma SayHello yöntemi vardır:
GreeterClient.SayHelloAsync-hizmeti Greeter.SayHello zaman uyumsuz olarak çağırır. Beklenmiş olabilir.
GreeterClient.SayHello -tamamlanana Greeter.SayHello kadar hizmeti ve blokları çağırır. Zaman uyumsuz
kodda kullanmayın.
Sunucu akışı çağrısı
Sunucu akış çağrısı, istemci isteği iletisi gönderen ile başlar. ResponseStream.MoveNext() hizmetten akan iletileri
okur. ' İ ResponseStream.MoveNext() döndüğünde false sunucu akış çağrısı tamamlanmıştır.

var client = new Greet.GreeterClient(channel);


using (var call = client.SayHellos(new HelloRequest { Name = "World" }))
{
while (await call.ResponseStream.MoveNext())
{
Console.WriteLine("Greeting: " + call.ResponseStream.Current.Message);
// "Greeting: Hello World" is written multiple times
}
}

C# 8 veya sonraki bir sürümünü kullanıyorsanız, await foreach söz konusu sözdizimi iletileri okumak için
kullanılabilir. IAsyncStreamReader<T>.ReadAllAsync() Uzantı yöntemi, yanıt akışından gelen tüm iletileri okur:

var client = new Greet.GreeterClient(channel);


using (var call = client.SayHellos(new HelloRequest { Name = "World" }))
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Greeting: " + response.Message);
// "Greeting: Hello World" is written multiple times
}
}

İstemci akışı çağrısı


İstemci akış çağrısı, istemci İleti göndermeden başlatılır. İstemci, ile RequestStream.WriteAsync ileti gönderip
göndermemeyi seçebilir. İstemcinin iletiyi göndermesi tamamlandığında, hizmete bildirimde
RequestStream.CompleteAsync bulunan iletiler çağrılmalıdır. Hizmet bir yanıt iletisi döndürdüğünde çağrı
tamamlanır.
var client = new Counter.CounterClient(channel);
using (var call = client.AccumulateCount())
{
for (var i = 0; i < 3; i++)
{
await call.RequestStream.WriteAsync(new CounterRequest { Count = 1 });
}
await call.RequestStream.CompleteAsync();

var response = await call;


Console.WriteLine($"Count: {response.Count}");
// Count: 3
}

İki yönlü akış çağrısı


Çift yönlü bir akış çağrısı, istemci bir ileti göndermeden başlatılır. İstemci, ile RequestStream.WriteAsync ileti
göndermek için seçim yapabilir. Hizmetten akışa alınan iletilere veya ResponseStream.MoveNext()
ResponseStream.ReadAllAsync() ile erişilebilir. İki yönlü akış çağrısı, ResponseStream daha fazla ileti olmadığında
tamamlanır.

using (var call = client.Echo())


{
Console.WriteLine("Starting background task to receive messages");
var readTask = Task.Run(async () =>
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine(response.Message);
// Echo messages sent to the service
}
});

Console.WriteLine("Starting to send messages");


Console.WriteLine("Type a message to echo then press enter.");
while (true)
{
var result = Console.ReadLine();
if (string.IsNullOrEmpty(result))
{
break;
}

await call.RequestStream.WriteAsync(new EchoMessage { Message = result });


}

Console.WriteLine("Disconnecting");
await call.RequestStream.CompleteAsync();
await readTask;
}

Çift yönlü bir akış araması sırasında, istemci ve hizmet herhangi bir zamanda iletileri birbirlerine gönderebilir. Çift
yönlü bir çağrı ile etkileşimde bulunmak için en iyi istemci mantığı, hizmet mantığına bağlı olarak farklılık gösterir.

Ek kaynaklar
.NET Core 'da gRPC istemci fabrikası tümleştirmesi
C# içeren gRPC hizmetleri
.NET Core 'da gRPC istemci fabrikası tümleştirmesi
13.11.2019 • 3 minutes to read • Edit Online

HttpClientFactory ile gRPC tümleştirmesi, gRPC istemcilerinin oluşturulması için merkezi bir yol sunar. Tek
başına gRPC istemci örneklerini yapılandırmayaalternatif olarak kullanılabilir. Fabrika tümleştirmesi, GRPC .net.
ClientFactory NuGet paketinde bulunabilir.
Fabrika aşağıdaki avantajları sunar:
Mantıksal gRPC istemci örneklerini yapılandırmak için merkezi bir konum sağlar
Temel alınan HttpClientMessageHandler ömrünü yönetir
ASP.NET Core gRPC hizmetinde son tarih ve iptali otomatik olarak yayma

GRPC istemcilerini kaydetme


Bir gRPC istemcisini kaydetmek için genel AddGrpcClient uzantısı yöntemi, Startup.ConfigureServices içinde,
gRPC türü belirtilmiş istemci sınıfı ve hizmet adresi belirtilerek kullanılabilir:

services.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});

GRPC istemci türü, bağımlılık ekleme (dı) ile geçici olarak kaydedilir. İstemci artık, DI tarafından oluşturulan
türlere eklenebilir ve doğrudan tüketilebilir. ASP.NET Core MVC denetleyicileri, SignalR hub 'lar ve gRPC
Hizmetleri, gRPC istemcilerinin otomatik olarak eklenmesi için gereken yerdir:

public class AggregatorService : Aggregator.AggregatorBase


{
private readonly Greeter.GreeterClient _client;

public AggregatorService(Greeter.GreeterClient client)


{
_client = client;
}

public override async Task SayHellos(HelloRequest request,


IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
// Forward the call on to the greeter service
using (var call = _client.SayHellos(request))
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
await responseStream.WriteAsync(response);
}
}
}
}

HttpClient 'ı yapılandırma


HttpClientFactory , gRPC istemcisi tarafından kullanılan HttpClient oluşturur. Standart HttpClientFactory
Yöntemler, giden istek ara yazılımı eklemek veya HttpClient temel HttpClientHandler yapılandırmak için
kullanılabilir:

services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(LoadCertificate());
return handler;
});

Daha fazla bilgi için bkz. ıhttpclientfactory kullanarak http Istekleri oluşturma.

Kanalı ve Yakacıları yapılandırma


gRPC 'ye özgü Yöntemler şu şekilde kullanılabilir:
Bir gRPC istemcisinin temel kanalını yapılandırın.
GRPC çağrıları yaparken İstemcinin kullanacağı Interceptor örnekleri ekleyin.

services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddInterceptor(() => new LoggingInterceptor())
.ConfigureChannel(o =>
{
o.Credentials = new CustomCredentials();
});

Son Tarih ve iptal yayma


bir gRPC hizmetinde fabrika tarafından oluşturulan gRPC istemcileri, son tarih ve iptal belirtecini alt çağrılara
otomatik olarak yaymak için EnableCallContextPropagation() ile yapılandırılabilir. EnableCallContextPropagation()
uzantısı yöntemi GRPC. AspNetCore. Server. ClientFactory NuGet paketinde bulunur.
Çağrı bağlamı yayma, geçerli gRPC isteği bağlamından son tarih ve iptal belirtecini okuyarak ve bunları otomatik
olarak gRPC istemcisi tarafından yapılan giden çağrılara yayarak işe yarar. Çağrı bağlamı yayma, karmaşık, iç içe
gRPC senaryolarının her zaman son tarihi ve iptali yaymasını sağlamaya yönelik mükemmel bir yoldur.

services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation();

Son tarihler ve RPC iptali hakkında daha fazla bilgi için bkz. RPC yaşam döngüsü.

Ek kaynaklar
.NET istemcisiyle gRPC hizmetlerini çağırma
ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP istekleri yapın
.NET için gRPC yapılandırması
4.10.2019 • 5 minutes to read • Edit Online

Hizmet seçeneklerini yapılandırma


GRPC Hizmetleri, Startup.csiçinde AddGrpc ile yapılandırılır. Aşağıdaki tabloda, gRPC hizmetlerini yapılandırma
seçenekleri açıklanmaktadır:

SEÇENEK DEFAULT VALUE AÇIKLAMA

MaxSendMessageSize null Sunucudan gönderilebilecek en büyük


ileti boyutu (bayt). Yapılandırılan en
büyük ileti boyutunu aşan bir ileti
gönderilmeye çalışılıyor, bir özel
durumla sonuçlanır.

MaxReceiveMessageSize 4 MB Sunucu tarafından alınabilecek, bayt


olarak en büyük ileti boyutu. Sunucu bu
sınırı aşan bir ileti alırsa bir özel durum
oluşturur. Bu değeri artırmak,
sunucunun daha büyük iletiler almasına
izin verir, ancak bellek tüketimini
olumsuz etkileyebilir.

EnableDetailedErrors false İse true , bir hizmet yönteminde özel


durum oluştuğunda istemcilere ayrıntılı
özel durum iletileri döndürülür.
Varsayılan, false değeridir.
EnableDetailedErrors İçin true
ayarı, hassas bilgileri sızdırabilir.

CompressionProviders Gzip İletileri sıkıştırmak ve açmak için


kullanılan bir sıkıştırma sağlayıcıları
koleksiyonu. Özel sıkıştırma sağlayıcıları
oluşturulup koleksiyona eklenebilir.
Varsayılan yapılandırılmış sağlayıcılar
gzip sıkıştırmasını destekler.

ResponseCompressionAlgorithm null Sunucudan gönderilen iletileri


sıkıştırmak için kullanılan sıkıştırma
algoritması. Algoritmanın içindeki
CompressionProviders bir sıkıştırma
sağlayıcısıyla eşleşmesi gerekir. Bir yanıtı
sıkıştırmaya yönelik algoritma için,
istemci, GRPC-Accept-Encoding
üstbilgisine göndererek algoritmayı
desteklediğini göstermelidir.

ResponseCompressionLevel null Sunucudan gönderilen iletileri


sıkıştırmak için kullanılan sıkıştırma
düzeyi.

Seçenekler, AddGrpc içindeki Startup.ConfigureServices çağrıya bir seçenek temsilcisi sağlayarak tüm hizmetler
için yapılandırılabilir:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.EnableDetailedErrors = true;
options.MaxReceiveMessageSize = 2 * 1024 * 1024; // 2 MB
options.MaxSendMessageSize = 5 * 1024 * 1024; // 5 MB
});
}

Tek bir hizmetin seçenekleri ' de AddGrpc belirtilen genel seçenekleri geçersiz kılar ve kullanılarak
AddServiceOptions<TService> yapılandırılabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddGrpc().AddServiceOptions<MyService>(options =>
{
options.MaxReceiveMessageSize = 2 * 1024 * 1024; // 2 MB
options.MaxSendMessageSize = 5 * 1024 * 1024; // 5 MB
});
}

İstemci seçeneklerini yapılandırma


gRPC istemci yapılandırması üzerinde GrpcChannelOptions ayarlanır. Aşağıdaki tabloda, gRPC kanallarını
yapılandırma seçenekleri açıklanmaktadır:

SEÇENEK DEFAULT VALUE AÇIKLAMA

HttpClient Yeni örnek GRPC çağrısı yapmak için kullanılır.


HttpClient İstemci, özel
HttpClientHandler yapılandırmak
üzere ayarlanabilir veya GRPC
çağrılarına yönelik http işlem hattına ek
işleyiciler ekleyebilir. Hayır HttpClient
belirtilmişse kanal için yeni
HttpClient bir örnek oluşturulur.
Otomatik olarak elden kaldırılacaktır.

DisposeHttpClient false , Ve bir HttpClient belirtilmişse,


HttpClient ,, bırakıldığında
GrpcChannel örnek de silinir. true

LoggerFactory null İstemci tarafından GRPC çağrıları


hakkındaki bilgileri günlüğe kaydetmek
için kullanılır. LoggerFactory Örnek,
kullanılarak LoggerFactory.Create
bağımlılık ekleme veya oluşturma
öğesinden çözülebilir. LoggerFactory
Günlüğe kaydetmeyi yapılandırma
örnekleri için bkz .NET üzerinde gRPC
'de günlüğe kaydetme ve tanılama.
SEÇENEK DEFAULT VALUE AÇIKLAMA

MaxSendMessageSize null İstemciden gönderilebilecek en büyük


ileti boyutu (bayt). Yapılandırılan en
büyük ileti boyutunu aşan bir ileti
gönderilmeye çalışılıyor, bir özel
durumla sonuçlanır.

MaxReceiveMessageSize 4 MB İstemci tarafından alınabilecek, bayt


olarak en büyük ileti boyutu. İstemci bu
sınırı aşan bir ileti alırsa bir özel durum
oluşturur. Bu değeri artırmak, istemcinin
daha büyük iletiler almasına izin verir,
ancak bellek tüketimini olumsuz
etkileyebilir.

Credentials null Bir ChannelCredentials örnek. Kimlik


bilgileri, gRPC çağrılarına kimlik
doğrulama meta verileri eklemek için
kullanılır.

CompressionProviders Gzip İletileri sıkıştırmak ve açmak için


kullanılan bir sıkıştırma sağlayıcıları
koleksiyonu. Özel sıkıştırma sağlayıcıları
oluşturulup koleksiyona eklenebilir.
Varsayılan yapılandırılmış sağlayıcılar
gzip sıkıştırmasını destekler.

Aşağıdaki kod:
Kanalda en büyük gönderme ve alma iletisi boyutunu ayarlar.
İstemci oluşturur.

static async Task Main(string[] args)


{
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
MaxReceiveMessageSize = 5 * 1024 * 1024, // 5 MB
MaxSendMessageSize = 2 * 1024 * 1024 // 2 MB
});
var client = new Greeter.GreeterClient(channel);

var reply = await client.SayHelloAsync(


new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
}

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub sorunu.

Ek kaynaklar
ASP.NET Core içeren gRPC Hizmetleri
.NET istemcisiyle gRPC hizmetlerini çağırma
.NET üzerinde gRPC 'de günlüğe kaydetme ve tanılama
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
ASP.NET Core için gRPC 'de kimlik doğrulaması ve
yetkilendirme
6.12.2019 • 6 minutes to read • Edit Online

, James bAyKiNg
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

GRPC hizmetini çağıran kullanıcıların kimliğini doğrulama


gRPC, bir kullanıcıyı her çağrıyla ilişkilendirmek için ASP.NET Core kimlik doğrulamasıyla birlikte kullanılabilir.
Aşağıda, gRPC ve ASP.NET Core kimlik doğrulaması kullanan Startup.Configure bir örneği verilmiştir:

public void Configure(IApplicationBuilder app)


{
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
routes.MapGrpcService<GreeterService>();
});
}

NOTE
ASP.NET Core kimlik doğrulama ara yazılımını kaydetme sırası önemli. UseRouting ve UseEndpoints önce
UseAuthentication ve UseAuthorization her zaman çağırın.

Bir çağrı sırasında uygulamanızın kullandığı kimlik doğrulama mekanizması yapılandırılmalıdır. Kimlik doğrulama
yapılandırması Startup.ConfigureServices eklenir ve uygulamanızın kullandığı kimlik doğrulama mekanizmasına
bağlı olarak farklı olacaktır. ASP.NET Core uygulamaları güvenli hale getirmeye yönelik örnekler için bkz. kimlik
doğrulama örnekleri.
Kimlik doğrulaması kurulduktan sonra, kullanıcıya ServerCallContext aracılığıyla bir gRPC hizmeti yöntemleriyle
erişilebilir.

public override Task<BuyTicketsResponse> BuyTickets(


BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;

// ... access data from ClaimsPrincipal ...


}

Taşıyıcı belirteç kimlik doğrulaması


İstemci, kimlik doğrulaması için bir erişim belirteci sağlayabilir. Sunucu belirteci doğrular ve kullanıcıyı tanımlamak
için kullanır.
Sunucusunda, taşıyıcı belirteç kimlik doğrulaması JWT taşıyıcı ara yazılımıkullanılarak yapılandırılır.
.NET gRPC istemcisinde, belirteç aramalar ile üst bilgi olarak gönderilebilir:

public bool DoAuthenticatedCall(


Ticketer.TicketerClient client, string token)
{
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");

var request = new BuyTicketsRequest { Count = 1 };


var response = await client.BuyTicketsAsync(request, headers);

return response.Success;
}

Bir kanalda ChannelCredentials yapılandırmak, belirteci gRPC çağrılarıyla hizmete göndermenin alternatif bir
yoludur. Kimlik bilgisi her bir gRPC çağrısının yapılışında çalıştırılır. Bu, belirteci kendi kendinize geçirmek için
birden çok yere kod yazma gereksinimini ortadan kaldırır.
Aşağıdaki örnekteki kimlik bilgileri, kanalı her gRPC çağrısıyla birlikte gönderecek şekilde yapılandırır:

private static GrpcChannel CreateAuthenticatedChannel(string address)


{
var credentials = CallCredentials.FromInterceptor((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});

// SslCredentials is used here because this channel is using TLS.


// CallCredentials can't be used with ChannelCredentials.Insecure on non-TLS channels.
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}

İstemci sertifikası kimlik doğrulaması


İstemci alternatif olarak kimlik doğrulaması için bir istemci sertifikası sağlayabilir. Sertifika kimlik doğrulaması TLS
düzeyinde gerçekleşir ve bu süre ASP.NET Core. İstek ASP.NET Core girdiğinde, istemci sertifikası kimlik
doğrulama paketi , sertifikayı bir ClaimsPrincipal çözmenize olanak tanır.

NOTE
Konağın istemci sertifikalarını kabul edecek şekilde yapılandırılması gerekir. Bkz. Kestrel, IIS ve Azure 'da istemci sertifikalarını
kabul etme hakkında bilgi için bkz. ana bilgisayarınızı yapılandırma .

.NET gRPC istemcisinde istemci sertifikası, daha sonra gRPC istemcisini oluşturmak için kullanılan
HttpClientHandler eklenir:
public Ticketer.TicketerClient CreateClientWithCert(
string baseAddress,
X509Certificate2 certificate)
{
// Add client cert to the handler
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);

// Create the gRPC channel


var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
{
HttpClient = new HttpClient(handler)
});

return new Ticketer.TicketerClient(channel);


}

Diğer kimlik doğrulama mekanizmaları


Desteklenen birçok ASP.NET Core kimlik doğrulama mekanizması gRPC ile çalışır:
Azure Active Directory
İstemci sertifikası
IdentityServer
JWT belirteci
OAuth 2.0
OpenID Connect
WS -Federation
Sunucuda kimlik doğrulamasını yapılandırma hakkında daha fazla bilgi için, ASP.NET Core kimlik doğrulaması' na
bakın.
GRPC istemcisini kimlik doğrulaması kullanacak şekilde yapılandırmak, kullanmakta olduğunuz kimlik doğrulama
mekanizmasına bağlı olarak değişir. Önceki taşıyıcı belirteci ve istemci sertifikası örnekleri, GRPC istemcisinin,
gRPC çağrılarına yönelik kimlik doğrulama meta verilerini gönderecek şekilde yapılandırılabilmesinin birkaç
yolunu gösterir:
Türü kesin belirlenmiş gRPC istemcileri dahili olarak HttpClient kullanır. Kimlik doğrulaması,
HttpClientHandlerüzerinde veya HttpClient özel HttpMessageHandler örnekleri eklenerek yapılandırılabilir.
Her gRPC çağrısının isteğe bağlı bir CallOptions bağımsız değişkeni vardır. Özel üstbilgiler, seçeneğin
üstbilgiler koleksiyonu kullanılarak gönderilebilir.

NOTE
Windows kimlik doğrulaması (NTLM/Kerberos/Negotiate), gRPC ile kullanılamaz. gRPC için HTTP/2 ve HTTP/2 Windows kimlik
doğrulamasını desteklemez.

Kullanıcılara hizmetlere ve hizmet yöntemlerine erişim yetkisi verme


Varsayılan olarak, bir hizmette tüm yöntemler kimliği doğrulanmamış kullanıcılar tarafından çağrılabilir. Kimlik
doğrulaması gerektirmek için [Authorize] özniteliğini hizmete uygulayın:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Yalnızca belirli Yetkilendirme ilkeleriyleeşleşen kullanıcılara erişimi kısıtlamak için [Authorize] özniteliğinin
Oluşturucu bağımsız değişkenlerini ve özelliklerini kullanabilirsiniz. Örneğin, MyAuthorizationPolicy adlı bir özel
yetkilendirme ilkeniz varsa, aşağıdaki kodu kullanarak yalnızca bu ilkeyle eşleşen kullanıcıların hizmete
erişebildiğinden emin olun:

[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}

Tek tek hizmet yöntemlerinde [Authorize] özniteliği de uygulanabilir. Geçerli Kullanıcı hem yönteme hem de sınıfa
uygulanan ilkelerle eşleşmezse, çağırana bir hata döndürülür:

[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
public override Task<AvailableTicketsResponse> GetAvailableTickets(
Empty request, ServerCallContext context)
{
// ... buy tickets for the current user ...
}

[Authorize("Administrators")]
public override Task<BuyTicketsResponse> RefundTickets(
BuyTicketsRequest request, ServerCallContext context)
{
// ... refund tickets (something only Administrators can do) ..
}
}

Ek kaynaklar
ASP.NET Core 'de taşıyıcı belirteç kimlik doğrulaması
ASP.NET Core 'de Istemci sertifikası kimlik doğrulamasını yapılandırma
.NET üzerinde gRPC 'de günlüğe kaydetme ve
tanılama
25.09.2019 • 4 minutes to read • Edit Online

, James bAyKiNg
Bu makalede, sorunları gidermeye yardımcı olmak için gRPC uygulamanızdan tanılamayı toplamaya yönelik
rehberlik sunulmaktadır.

gRPC Hizmetleri günlüğü


WARNING
Sunucu tarafı günlükleri, uygulamanızdan önemli bilgiler içerebilir. Ham günlükleri hiçbir şekilde üretim uygulamalarından
GitHub gibi genel forumlara nakletmeyin.

GRPC Hizmetleri ASP.NET Core üzerinde barındırıldığından, bu, ASP.NET Core günlük sistemini kullanır.
Varsayılan yapılandırmada, gRPC çok az bilgiyi günlüğe kaydeder, ancak bu yapılandırılabilir.ASP.NET Core
günlüğü yapılandırma hakkında ayrıntılar için ASP.NET Core günlüğe kaydetme hakkındaki belgelere bakın.
GRPC, kategori altına Günlükler ekler. GRPC 'den ayrıntılı günlükleri etkinleştirmek için, aşağıdaki öğeleri
Grpc
Grpc LogLevel içindeki Logging alt bölümüne Debug ekleyerek, ön ekleri appSettings. JSON dosyanızdaki
düzeye yapılandırın:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information",
"Grpc": "Debug"
}
}
}

Bunu, Startup.cs ConfigureLogging içinde şu şekilde de yapılandırabilirsiniz:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFilter("Grpc", LogLevel.Debug);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

JSON tabanlı yapılandırma kullanmıyorsanız, yapılandırma sisteminizde aşağıdaki yapılandırma değerini ayarlayın:
Logging:LogLevel:Grpc = Debug
İç içe yapılandırma değerlerinin nasıl belirleneceğini belirlemek için yapılandırma sisteminizin belgelerini
denetleyin. Örneğin, ortam değişkenleri kullanılırken, yerine _ : iki karakter kullanılır (örneğin,
Logging__LogLevel__Grpc ).

Uygulamanız için daha ayrıntılı Debug tanılama toplanırken düzeyin kullanılmasını öneririz. Düzey Trace , çok
düşük düzey Tanılamalar üretir ve uygulamanızdaki sorunları tanılamak için nadiren gereklidir.
Örnek günlüğe kaydetme çıkışı
Aşağıda, bir GRPC hizmeti Debug düzeyinde konsol çıkışının bir örneği verilmiştir:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 POST https://localhost:5001/Greet.Greeter/SayHello application/grpc
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /Greet.Greeter/SayHello'
dbug: Grpc.AspNetCore.Server.ServerCallHandler[1]
Reading message.
info: GrpcService.GreeterService[0]
Hello World
dbug: Grpc.AspNetCore.Server.ServerCallHandler[6]
Sending message.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 1.4113ms 200 application/grpc

Sunucu tarafı günlüklerine erişin


Sunucu tarafı günlüklerine erişme, çalıştırdığınız ortama bağlıdır.
Konsol uygulaması olarak
Konsol uygulamasında çalıştırıyorsanız, konsol günlükçüsü varsayılan olarak etkinleştirilmelidir. gRPC günlükleri
konsolunda görünür.
Diğer ortamlar
Uygulama başka bir ortama (örneğin, Docker, Kubernetes veya Windows hizmeti) dağıtılırsa, ortama uygun
günlük sağlayıcılarının nasıl .NET Core ve ASP.NET Core oturum açma yapılandırılacağı hakkında daha fazla bilgi
için bkz.

gRPC istemci günlüğü


WARNING
İstemci tarafı günlükleri, uygulamanızdan önemli bilgiler içerebilir. Ham günlükleri hiçbir şekilde üretim uygulamalarından
GitHub gibi genel forumlara nakletmeyin.

.Net istemcisinden günlükleri almak için, GrpcChannelOptions.LoggerFactory özelliği istemci kanalının oluşturulduğu
zaman ayarlayabilirsiniz. Bir ASP.NET Core uygulamasından gRPC hizmetini arıyorsanız, günlükçü fabrikası
bağımlılık ekleme (DI) ' dan çözülebilir:
[ApiController]
[Route("[controller]")]
public class GreetingController : ControllerBase
{
private ILoggerFactory _loggerFactory;

public GreetingController(ILoggerFactory loggerFactory)


{
_loggerFactory = loggerFactory;
}

[HttpGet]
public async Task<ActionResult<string>> Get(string name)
{
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { LoggerFactory = _loggerFactory });
var client = new Greeter.GreeterClient(channel);

var reply = await client.SayHelloAsync(new HelloRequest { Name = name });


return Ok(reply.Message);
}
}

İstemci günlüğünü etkinleştirmenin alternatif bir yolu, istemci oluşturmak için GRPC istemci fabrikası kullanmaktır.
İstemci fabrikasına kayıtlı ve dı 'den çözümlenen bir gRPC istemcisi, otomatik olarak uygulamanın yapılandırılmış
günlüğünü kullanacaktır.
Uygulamanız dı kullanıyorsa, ILoggerFactory loggerfactory. Createile yeni bir örnek oluşturabilirsiniz. Bu yönteme
erişmek için Microsoft. Extensions. Logging paketini uygulamanıza ekleyin.

var loggerFactory = LoggerFactory.Create(logging =>


{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Debug);
});

var channel = GrpcChannel.ForAddress("https://localhost:5001",


new GrpcChannelOptions { LoggerFactory = loggerFactory });

var client = Greeter.GreeterClient(channel);

Örnek günlüğe kaydetme çıkışı


Aşağıda, bir GRPC istemcisinin Debug düzeyindeki konsol çıkışının bir örneği verilmiştir:

dbug: Grpc.Net.Client.Internal.GrpcCall[1]
Starting gRPC call. Method type: 'Unary', URI: 'https://localhost:5001/Greet.Greeter/SayHello'.
dbug: Grpc.Net.Client.Internal.GrpcCall[6]
Sending message.
dbug: Grpc.Net.Client.Internal.GrpcCall[1]
Reading message.
dbug: Grpc.Net.Client.Internal.GrpcCall[4]
Finished gRPC call.

Ek kaynaklar
.NET Core ve ASP.NET Core oturum açma
.NET için gRPC yapılandırması
.NET Core 'da gRPC istemci fabrikası tümleştirmesi
ASP.NET Core için gRPC 'de güvenlik konuları
6.09.2019 • 2 minutes to read • Edit Online

, James bAyKiNg
Bu makalede, gRPC 'yi .NET Core ile güvenli hale getirme hakkında bilgi verilmektedir.

Taşıma güvenliği
gRPC iletileri HTTP/2 kullanılarak gönderilir ve alınır. Şunları öneririz:
Aktarım Katmanı Güvenliği (TLS ) , üretim GRPC uygulamalarında iletileri güvenli hale getirmek için kullanılır.
gRPC Hizmetleri yalnızca güvenli bağlantı noktalarını dinler ve bunlara yanıt vermelidir.
TLS, Kestrel içinde yapılandırılır. Kestrel uç noktalarını yapılandırma hakkında daha fazla bilgi için bkz. Kestrel
Endpoint Configuration.

Özel Durumlar
Özel durum iletileri genellikle bir istemciye görüntülenmemelidir gizli veriler olarak değerlendirilir. Varsayılan
olarak, gRPC, bir gRPC hizmeti tarafından oluşturulan özel durumun ayrıntılarını istemciye göndermez. Bunun
yerine, istemci bir hata oluştuğunu belirten genel bir ileti alır. İstemciye özel durum iletisi teslimi,
Enabledetailederrorsile geçersiz kılınabilir (örneğin, geliştirme veya test). Özel durum iletileri, üretim
uygulamalarındaki istemciye gösterilmemelidir.

İleti boyutu sınırları


GRPC istemcilerine ve hizmetlerine gelen iletiler belleğe yüklenir. İleti boyutu sınırları, gRPC 'nin aşırı kaynak
tüketmesini önlemeye yardımcı olmak için bir mekanizmadır.
gRPC gelen ve giden iletileri yönetmek için ileti başına boyut sınırlarını kullanır. Varsayılan olarak, gRPC gelen
iletileri 4 MB ile sınırlandırır. Giden iletilerde sınır yoktur.
Sunucusunda, gRPC ileti limitleri bir uygulamadaki tüm hizmetler için ile AddGrpc yapılandırılabilir:

public void ConfigureServices(IServiceCollection services)


{
services.AddGrpc(options =>
{
options.MaxReceiveMessageSize = 1 * 1024 * 1024; // 1 MB
options.MaxSendMessageSize = 1 * 1024 * 1024; // 1 MB
});
}

Ayrıca, kullanılarak AddServiceOptions<TService> tek bir hizmet için sınırlamalar da yapılandırılabilir. İleti boyutu
sınırlarını yapılandırma hakkında daha fazla bilgi için bkz. GRPC yapılandırması.

İstemci sertifikası doğrulaması


İstemci sertifikaları , bağlantı oluşturulduğunda başlangıçta onaylanır. Varsayılan olarak, Kestrel bir bağlantının
istemci sertifikası için ek doğrulama gerçekleştirmez.
İstemci sertifikaları tarafından güvenliği sağlanan gRPC hizmetlerinin Microsoft. AspNetCore. Authentication.
Certificate paketini kullanması önerilir. ASP.NET Core sertifika kimlik doğrulaması, bir istemci sertifikasında
aşağıdakiler de dahil olmak üzere ek doğrulama gerçekleştirir:
Sertifikada geçerli bir genişletilmiş anahtar kullanımı (EKU ) vardır
Geçerlilik süresi içinde
Sertifika iptalini denetle
dotnet-grpc ile Protobuf başvurularını yönetme
17.10.2019 • 7 minutes to read • Edit Online

John Luo tarafından


dotnet-grpc , bir .NET gRPC projesindeki protodeğer ( . proto) başvurularını yönetmek için .NET Core küresel bir
araçtır. Araç, prototipleme başvurularını eklemek, yenilemek, kaldırmak ve listelemek için kullanılabilir.

Yükleme
@No__t-0 .NET Core küresel aracı'nı yüklemek için şu komutu çalıştırın:

dotnet tool install -g dotnet-grpc

Başvuru Ekle
dotnet-grpc , . csproj dosyasına <Protobuf /> öğe olarak prototip başvuruları eklemek için kullanılabilir:

<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />

Prototip başvuruları, C# istemci ve/veya sunucu varlıklarını oluşturmak için kullanılır. @No__t-0 aracı şunları
yapabilir:
Diskteki yerel dosyalardan Prototipsiz başvuru oluştur.
Bir URL ile belirtilen uzak dosyadan Protobir başvuru oluştur.
Projeye doğru gRPC paket bağımlılıklarının eklendiğinden emin olun.
Örneğin, Grpc.AspNetCore paketi bir Web uygulamasına eklenir. Grpc.AspNetCore gRPC sunucusu ve istemci
kitaplıklarını ve araç desteğini içerir. Alternatif olarak, yalnızca gRPC istemci kitaplıklarını ve araç desteğini içeren
Grpc.Net.Client Grpc.Tools ve Google.Protobuf paketleri konsol uygulamasına eklenir.

Dosya Ekle
@No__t-0 komutu, disk üzerindeki yerel dosyaları prototip başvuruları olarak eklemek için kullanılır. Belirtilen
dosya yolları:
Geçerli dizin veya mutlak yollarla göreli olabilir.
, Globmodel tabanlı dosya için joker karakterler içerebilir.
Herhangi bir dosya proje dizininin dışındaysa, dosyayı Visual Studio 'da Protos klasörü altında göstermek için
Link öğesi eklenir.

Kullanım

dotnet grpc add-file [options] <files>...

Arguments

BAĞIMSIZ DEĞIŞKEN AÇIKLAMA


BAĞIMSIZ DEĞIŞKEN AÇIKLAMA

dosyaları Prototip dosyası başvuruları. Bunlar yerel prototipli dosyalar


için glob 'nin bir yolu olabilir.

Seçenekler

SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-p --Proje Üzerinde çalışılacak proje dosyasının


yolu. Bir dosya belirtilmemişse, komut
geçerli dizinde bir arama yapar.

-s --Hizmetler Oluşturulması gereken gRPC Hizmetleri


türü. @No__t-0 belirtilirse, Web projeleri
için Both kullanılır ve Web dışı projeler
için Client kullanılır. Kabul edilen
değerler Both , Client , Default ,
None , Server ' tir.

-i --ek-içeri aktarma-Dizin Prototip dosyaları için içeri aktarmalar


çözümlenirken kullanılacak ek dizinler.
Bu, yolların noktalı virgülle ayrılmış
listesidir.

--erişim Oluşturulan C# sınıflar için kullanılacak


erişim değiştiricisi. Varsayılan değer
Public şeklindedir. Kabul edilen
değerler Internal ve Public ' dir.

URL Ekle
@No__t-0 komutu, kaynak URL tarafından belirtilen bir uzak dosyayı prototipde başvuru olarak eklemek için
kullanılır. Uzak dosyanın nereye indirileceği belirtmek için bir dosya yolu belirtilmelidir. Dosya yolu, geçerli dizin
veya mutlak bir yol ile ilişkili olabilir. Dosya yolu proje dizininin dışındaysa, Visual Studio 'da Protos sanal klasörü
altında dosyayı göstermek için bir Link öğesi eklenir.
Kullanım

dotnet-grpc add-url [options] <url>

Arguments

BAĞIMSIZ DEĞIŞKEN AÇIKLAMA

'deki Uzak protoarabellek dosyasının URL 'SI.

Seçenekler

SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-o --çıkış Uzak protoarabellek dosyası için indirme


yolunu belirtir. Bu gerekli bir seçenektir.

-p --Proje Üzerinde çalışılacak proje dosyasının


yolu. Bir dosya belirtilmemişse, komut
geçerli dizinde bir arama yapar.
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-s --Hizmetler Oluşturulması gereken gRPC Hizmetleri


türü. @No__t-0 belirtilirse, Web projeleri
için Both kullanılır ve Web dışı projeler
için Client kullanılır. Kabul edilen
değerler Both , Client , Default ,
None , Server ' tir.

-i --ek-içeri aktarma-Dizin Prototip dosyaları için içeri aktarmalar


çözümlenirken kullanılacak ek dizinler.
Bu, yolların noktalı virgülle ayrılmış
listesidir.

--erişim Oluşturulan C# sınıflar için kullanılacak


erişim değiştiricisi. Varsayılan değer
Public ' dır. Kabul edilen değerler
Internal ve Public ' dir.

Kaldır
@No__t-0 komutu, . csproj dosyasından prototipsiz başvuruları kaldırmak için kullanılır. Komut bağımsız değişken
olarak yol bağımsız değişkenlerini ve kaynak URL 'Lerini kabul eder. Araç:
Yalnızca Prototipsiz başvuruyu kaldırır.
, İlk olarak uzak bir URL 'den indirilse bile, . proto dosyasını silmez.
Kullanım

dotnet-grpc remove [options] <references>...

Arguments
BAĞIMSIZ DEĞIŞKEN AÇIKLAMA

başvurular Kaldırılacak prototip başvurularının URL 'Leri veya dosya


yolları.

Seçenekler
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-p --Proje Üzerinde çalışılacak proje dosyasının


yolu. Bir dosya belirtilmemişse, komut
geçerli dizinde bir arama yapar.

Yenile
@No__t-0 komutu, kaynak URL 'den en son içerikle uzak bir başvuruyu güncelleştirmek için kullanılır. Yalnızca
indirme dosyası yolu ve kaynak URL 'SI, güncellenmek üzere olan başvuruyu belirtmek için kullanılabilir. Not:
Dosya içeriğinin karmaları yerel dosyanın güncelleştirilip güncelleştirilmediğini belirleme ile karşılaştırılır.
Zaman damgası bilgisi karşılaştırılmaz.
Bir güncelleştirme gerekiyorsa araç her zaman yerel dosyayı uzak dosya ile değiştirir.
Kullanım

dotnet-grpc refresh [options] [<references>...]

Arguments
BAĞIMSIZ DEĞIŞKEN AÇIKLAMA

başvurular Güncellenmesi gereken uzak prototip başvurularına yönelik


URL veya dosya yolları. Tüm Uzak başvuruları yenilemek için
bu bağımsız değişkeni boş bırakın.

Seçenekler
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-p --Proje Üzerinde çalışılacak proje dosyasının


yolu. Bir dosya belirtilmemişse, komut
geçerli dizinde bir arama yapar.

--Kuru-Çalıştır Herhangi bir yeni içerik indirilmeden


güncelleştirilenecek dosyaların listesini
verir.

List
@No__t-0 komutu, proje dosyasındaki tüm Prototipsiz başvuruları göstermek için kullanılır. Bir sütunun tüm
değerleri varsayılan değerler ise, sütun atlanabilir.
Kullanım

dotnet-grpc list [options]

Seçenekler
SHORT SEÇENEĞI LONG SEÇENEĞI AÇIKLAMA

-p --Proje Üzerinde çalışılacak proje dosyasının


yolu. Bir dosya belirtilmemişse, komut
geçerli dizinde bir arama yapar.

Ek kaynaklar
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
ASP.NET Core içeren gRPC Hizmetleri
GRPC hizmetlerini C Core 'dan ASP.NET Core
geçirme
6.11.2019 • 5 minutes to read • Edit Online

John Luo tarafından


Temel alınan yığının uygulanması nedeniyle, tüm özellikler C Core tabanlı GRPC uygulamaları ve ASP.NET Core
tabanlı uygulamalar arasında aynı şekilde çalışmaz. Bu belgede, iki yığın arasında geçiş yapmak için önemli
farklılıklar vurgulanmıştır.

gRPC hizmeti uygulama ömrü


ASP.NET Core yığınında, varsayılan olarak gRPC Hizmetleri kapsamlı bir ömürile oluşturulur. Buna karşılık, gRPC
C -Core varsayılan olarak tek bir yaşam süresinesahip bir hizmete bağlanır.
Kapsamlı ömür, hizmet uygulamasının kapsamlı ömürlerle diğer hizmetleri çözümlemesine izin verir.Örneğin,
kapsamlı bir yaşam süresi Ayrıca, Oluşturucu ekleme yoluyla DI kapsayıcısından DbContext çözümleyebilir.
Kapsamlı ömür kullanımı:
Her istek için hizmet uygulamasının yeni bir örneği oluşturulur.
Uygulama türündeki örnek üyeleri aracılığıyla istekler arasında durum paylaşmak mümkün değildir.
Beklentisi, paylaşılan durumları dı kapsayıcısında tek bir hizmette depobir biçimde depokadır. Depolanan
paylaşılan durumlar, gRPC hizmet uygulamasının oluşturucusunda çözümlenir.
Hizmet yaşam süreleri hakkında daha fazla bilgi için bkz. ASP.NET Core bağımlılık ekleme.
Tek bir hizmet ekleyin
GRPC C çekirdekli bir uygulamadan ASP.NET Core geçişi kolaylaştırmak için, hizmet uygulamasının hizmet
ömrünü kapsamlı olarak tek başına değiştirmek mümkündür. Bu, bir hizmet uygulamasının bir örneğini dı
kapsayıcısına eklemeyi içerir:

public void ConfigureServices(IServiceCollection services)


{
services.AddGrpc();
services.AddSingleton(new GreeterService());
}

Ancak, tek bir yaşam süresine sahip bir hizmet uygulamasının kapsamı, kapsamlı hizmetleri Oluşturucu ekleme
yoluyla çözemeyebilir.

GRPC Hizmetleri seçeneklerini yapılandırma


C Core tabanlı uygulamalarda, grpc.max_receive_message_length ve grpc.max_send_message_length gibi ayarlar
sunucu örneği oluşturulurken ChannelOption ile yapılandırılır.
ASP.NET Core, gRPC GrpcServiceOptions türü aracılığıyla yapılandırma sağlar. Örneğin, bir gRPC hizmetinin en
büyük gelen ileti boyutu AddGrpc aracılığıyla yapılandırılabilir. Aşağıdaki örnek, varsayılan MaxReceiveMessageSize
4 MB ile 16 MB arasında değişir:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.MaxReceiveMessageSize = 16 * 1024 * 1024; // 16 MB
});
}

Yapılandırma hakkında daha fazla bilgi için bkz. .NET için gRPC yapılandırması.

Günlüğe Kaydetme
C çekirdekli tabanlı uygulamalar, hata ayıklama amacıyla günlükçüsü yapılandırmak için GrpcEnvironment kullanır.
ASP.NET Core Stack, bu işlevselliği günlüğe kaydetme API 'siaracılığıyla sağlar. Örneğin, gRPC hizmetine
Oluşturucu ekleme yoluyla bir günlükçü eklenebilir:

public class GreeterService : Greeter.GreeterBase


{
public GreeterService(ILogger<GreeterService> logger)
{
}
}

HTTPS
C -Core tabanlı uygulamalar, Server. Ports özelliğiaracılığıyla https 'yi yapılandırır. Benzer bir kavram, ASP.NET
Core sunucuları yapılandırmak için kullanılır. Örneğin, Kestrel Bu işlevsellik için uç nokta yapılandırması kullanır.

gRPC yakalayıcılar vs ara yazılımı


ASP.NET Core Ara yazılım , C çekirdekli tabanlı GRPC uygulamalarındaki yakalayıcılar ile karşılaştırıldığında
benzer işlevler sunar. ASP.NET Core ara yazılımı ve yakalayıcılar kavramsal olarak benzerdir. İs
, Bir gRPC isteğini işleyen bir işlem hattı oluşturmak için kullanılır.
İşlem hattındaki bir sonraki bileşenden önce veya sonra iş gerçekleştirilmesine izin verin.
HttpContext erişim sağlayın:
Ara yazılım ' de HttpContext bir parametredir.
Yakalayıcılar ' de HttpContext , ServerCallContext.GetHttpContext uzantısı yöntemiyle ServerCallContext
parametresi kullanılarak erişilebilir. Bu özelliğin ASP.NET Core ' de çalışan yakalayıcılar için özel
olduğunu unutmayın.
gRPC yakalayıcısı ASP.NET Core ara yazılım farklılıkları:
Kesiciler
Servercallcontextkullanarak GRPC soyutlama katmanı üzerinde çalışır.
Erişim sağla:
Seri durumdan çıkarılmış ileti bir çağrıya gönderildi.
Seri hale getirilmeden önce çağrıdan döndürülen ileti.
Yazılımlar
GRPC yakalayıcılar öncesinde çalışır.
Temel alınan HTTP/2 iletileri üzerinde çalışır.
Yalnızca istek ve yanıt akışlarından gelen baytlara erişebilir.
Ek kaynaklar
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
ASP.NET Core içeren gRPC Hizmetleri
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
gRPC hizmetlerini HTTP API’leriyle karşılaştırma
6.12.2019 • 9 minutes to read • Edit Online

, James bAyKiNg
Bu makalede, GRPC HIZMETLERININ HTTP API 'leri (ASP.NET Core Web API 'leridahil) ile nasıl karşılaştırılacağı
açıklanmaktadır. Uygulamanız için bir API sağlamak için kullanılan teknoloji önemli bir seçimdir ve gRPC, HTTP
API 'Lerine kıyasla benzersiz avantajlar sunmaktadır. Bu makalede, gRPC 'nin güçlü ve zayıf yönleri ele
alınmaktadır ve gRPC 'nin diğer teknolojiler üzerinden kullanılması için senaryolar önerilmektedir.

Üst düzey karşılaştırma


Aşağıdaki tabloda, gRPC ve HTTP API 'Leri arasında JSON ile yüksek düzeyde bir karşılaştırma sunulmaktadır.

ÖZELLIK GRPC JSON ILE HTTP API 'LERI

Sözleşme Gerekli ( . proto) İsteğe bağlı (Openapı)

Protokol HTTP/2 HTTP

Te Prototip (küçük, ikili) JSON (büyük, insan tarafından


okunabilir)

Dikkatli olun Katı belirtim Miş. Herhangi bir HTTP geçerlidir.

Akış İstemci, sunucu, iki yönlü İstemci, sunucu

Tarayıcı desteği Hayır (GRPC-Web gerektirir) Evet

Güvenlik Taşıma (TLS) Taşıma (TLS)

İstemci kod oluşturma Evet Openapı + üçüncü taraf araçları

gRPC güçleri
Performans
gRPC iletileri, etkin bir ikili ileti biçimi olan Protoarabelleğekullanılarak serileştirilir. Sunucu ve istemcide prototip
çok hızlı hale getirir. Prototip serileştirme, mobil uygulamalar gibi sınırlı bant genişliği senaryolarında önemli olan
küçük ileti yüklerine neden olur.
gRPC, http 1. x üzerinden önemli performans avantajları sağlayan büyük bir HTTP düzeltmesi olan HTTP/2 için
tasarlanmıştır:
İkili çerçeveleme ve sıkıştırma. HTTP/2 Protokolü, hem gönderme hem de alma sırasında kompakt ve verimlidir.
Tek bir TCP bağlantısı üzerinden birden çok HTTP/2 çağrısının çoğullama. Çoğullama , satır başı
engellemeyiortadan kaldırır.
Kod oluşturma
Tüm gRPC çerçeveleri, kod oluşturma için birinci sınıf destek sağlar. GRPC geliştirmeye yönelik bir çekirdek dosya,
gRPC Hizmetleri ve iletilerinin sözleşmesini tanımlayan . proto dosyasıdır. Bu dosya gRPC çerçevelerinden kod, bir
hizmet temel sınıfı, iletiler ve tüm istemci oluşturur.
Sunucu ile istemci arasında . proto dosyasını paylaşarak iletiler ve istemci kodu uçtan uca oluşturulabilir. İstemcinin
kod üretimi, istemci ve sunucudaki iletilerin çoğaltılmasını ortadan kaldırır ve sizin için kesin olarak belirlenmiş bir
istemci oluşturur. İstemci yazmak gerekmez, birçok hizmet içeren uygulamalarda önemli geliştirme süresini
kaydeder.
Katı belirtim
JSON ile HTTP API 'SI için biçimsel belirtim yok. Geliştiriciler, URL 'Lerin, HTTP fiillerinin ve yanıt kodlarının en iyi
biçimini kaldırır.
GRPC belirtimi , bir GRPC hizmetinin izlenmesi gereken biçim hakkında ayrıntılı bir şekilde yapılır. GRPC,
platformlar ve uygulamalar arasında tutarlı olduğundan, GRPC başarılacağı 'yı ortadan kaldırır ve geliştirici
süresini kaydeder.
Akış
HTTP/2, uzun süreli, gerçek zamanlı iletişim akışları için bir temel sağlar. gRPC, HTTP/2 üzerinden akış için birinci
sınıf destek sağlar.
GRPC hizmeti tüm akış kombinasyonlarını destekler:
Birli (akış yok)
Sunucudan istemciye akışa
İstemciden sunucuya akışa
İki yönlü akış
Son tarih/zaman aşımları ve iptal
gRPC, istemcilerin bir RPC 'nin tamamlanmasını beklemek zorunda kalabilecekleri süreyi belirtmesini sağlar. Son
tarih sunucuya gönderilir ve sunucu son tarihi aşarsa hangi eylemin yapılacağını seçebilir. Örneğin, sunucu devam
eden gRPC/HTTP/veritabanı isteklerini zaman aşımında iptal edebilir.
Son tarihi ve iptali alt gRPC çağrıları aracılığıyla yayın, kaynak kullanım sınırlarının uygulanmasını sağlar.

gRPC önerilen senaryolar


gRPC aşağıdaki senaryolara uygundur:
Mikro hizmetler – GRPC, düşük gecikme süresi ve yüksek işleme iletişimi için tasarlanmıştır. gRPC, verimlilik
açısından kritik olan hafif mikro hizmetler için harika.
Noktadan noktaya gerçek zamanlı iletişim – GRPC, iki yönlü akış için harika desteğe sahiptir. gRPC
Hizmetleri, yoklama yapmadan iletileri gerçek zamanlı olarak gönderebilir.
– GRPC araçları, tüm popüler geliştirme dillerini destekler ve GRPC 'yi çok dilli ortamlar için iyi bir seçenek
yapar.
Ağ kısıtlamalı ortamlar – GRPC iletileri, hafif bir ileti biçimi olan protoarabellek ile serileştirilir. GRPC iletisi
her zaman denk bir JSON iletisinden daha küçüktür.

gRPC zayıflığı
Sınırlı tarayıcı desteği
Doğrudan bir tarayıcıda bir gRPC hizmetini doğrudan çağırmak olanaksızdır. gRPC, HTTP/2 özelliklerini çok fazla
kullanır ve tarayıcı, bir gRPC istemcisini desteklemek için Web istekleri üzerinde gerekli denetim düzeyini sağlar.
Örneğin, tarayıcılar arayan HTTP/2 ' nin kullanılmasına izin vermez veya temel alınan HTTP/2 çerçevelerine erişim
sağlar.
GRPC -Web , GRPC ekibinin tarayıcıda sınırlı GRPC desteği sağlayan ek bir teknolojidir. gRPC -Web iki bölümden
oluşur: tüm modern tarayıcıları ve sunucudaki gRPC -Web proxy 'sini destekleyen bir JavaScript istemcisi. GRPC -
Web istemcisi ara sunucuyu çağırır ve proxy, gRPC isteklerini gRPC sunucusuna iletir.
GRPC 'nin özelliklerinin hepsi gRPC -Web tarafından desteklenmez. İstemci ve iki yönlü akış desteklenmez ve
sunucu akışı için sınırlı destek vardır.
Okunabilir değil
HTTP API istekleri metin olarak gönderilir ve insanların okuyabilmesi ve oluşturulabilmesi olabilir.
gRPC iletileri varsayılan olarak Protodeğer ile kodlanır. Protoarabellek gönderme ve alma açısından verimli olsa da,
ikili biçimi insanlar tarafından okunabilir değildir. Protoarabelleğe doğru bir şekilde seri durumdan çıkarmak için .
proto dosyasında belirtilen iletinin arabirim açıklaması gereklidir. Ek araçlar, hat üzerindeki prototiplerin yüklerini
analiz etmek ve istekleri el ile oluşturmak için gereklidir.
Sunucu yansıtma ve GRPC komut satırı aracı gibi özellikler, ikili prototipsiz iletilerle yardım etmek için mevcuttur.
Ayrıca, prototipli mesajlar JSON öğesine ve öğesinden dönüştürmeyidestekler. Yerleşik JSON dönüştürmesi, hata
ayıklarken prototip iletileri okunabilir ve okunabilir biçime dönüştürmek için etkili bir yol sağlar.

Alternatif Framework senaryoları


Aşağıdaki senaryolarda gRPC üzerinden diğer çerçeveler önerilir:
Tarayıcı erişilebilir API 'ler – GRPC, tarayıcıda tam olarak desteklenmez. gRPC -Web tarayıcı desteği sunabilir,
ancak sınırlamaları vardır ve sunucu proxy 'sini tanıtır.
Gerçek zamanlı iletişim – GRPC, akış aracılığıyla gerçek zamanlı iletişimi destekler, ancak kayıtlı bağlantılara
bir ileti yayınlama kavramı mevcut değildir. Örneğin, sohbet odasındaki tüm istemcilere yeni sohbet iletilerinin
gönderilmesi gereken bir sohbet odası senaryosunda her bir gRPC çağrısı, istemciye yeni sohbet iletilerini tek
tek akışa almak için gereklidir. SignalR , bu senaryo için kullanışlı bir çerçevedir. SignalR, sürekli bağlantılar ve
yayın iletileri için yerleşik destek kavramıdır.
İşlemler arası iletişim – bir işlem, gelen GRPC çağrılarını kabul etmek IÇIN bir http/2 sunucusu barındırmalıdır.
Windows için, işlemler arası iletişim kanalları hızlı ve hafif bir iletişim yöntemidir.

Ek kaynaklar
ASP.NET Core .NET Core gRPC istemcisi ve sunucusu oluşturma
.NET Core 'da gRPC 'ye giriş
C# içeren gRPC hizmetleri
GRPC hizmetlerini C Core 'dan ASP.NET Core geçirme
.NET Core 'da gRPC sorunlarını giderme
23.11.2019 • 8 minutes to read • Edit Online

, James bAyKiNg
Bu belgede, .NET üzerinde gRPC uygulamaları geliştirirken yaygın olarak karşılaşılan sorunlar ele alınmaktadır.

İstemci ve hizmet SSL/TLS yapılandırması arasında uyuşmazlık


GRPC şablonu ve örnekleri, varsayılan olarak gRPC hizmetlerini güvenli hale getirmek için Aktarım Katmanı
Güvenliği 'ni (TLS ) kullanır. gRPC istemcilerinin güvenli gRPC hizmetlerini başarıyla çağırması için güvenli bir
bağlantı kullanması gerekir.
ASP.NET Core gRPC hizmetinin uygulama başlatma bölümünde yazılan günlüklerde TLS kullandığını
doğrulayabilirsiniz. Hizmet bir HTTPS uç noktasını dinleyerek:

info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development

.NET Core istemcisinin, güvenli bir bağlantıyla çağrı yapmak için sunucu adresinde https kullanması gerekir:

static async Task Main(string[] args)


{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}

Tüm gRPC istemci uygulamaları TLS 'yi destekler. diğer dillerden gRPC istemcileri genellikle SslCredentials ile
yapılandırılmış kanalı gerektirir. SslCredentials , istemcinin kullanacağı sertifikayı belirtir ve güvenli olmayan
kimlik bilgileri yerine kullanılması gerekir. Farklı gRPC istemci uygulamalarını TLS kullanmak üzere yapılandırma
örnekleri için bkz. GRPC kimlik doğrulaması.

Güvenilir olmayan/geçersiz sertifikayla gRPC hizmetini çağırma


.NET gRPC istemcisi hizmetin güvenilen sertifikaya sahip olmasını gerektirir. Bir gRPC hizmeti güvenilir bir
sertifika olmadan çağrılırken aşağıdaki hata iletisi döndürülür:

İşlenmeyen özel durum. System .net. http. HttpRequestException: SSL bağlantısı kurulamadı, iç özel duruma
bakın. ---> System. Security. Authentication. AuthenticationException: uzak sertifika, doğrulama yordamına
göre geçersiz.

Uygulamanızı yerel olarak test ediyorsanız ve ASP.NET Core HTTPS geliştirme sertifikası güvenilir değilse bu
hatayı görebilirsiniz. Bu sorunu gidermeye yönelik yönergeler için bkz. Windows ve macOS 'ta ASP.NET Core
https geliştirme sertifikasına güvenin.
Bir gRPC hizmetini başka bir makineye arıyorsanız ve sertifikaya güvenmiyorsanız, gRPC istemcisi geçersiz
sertifikayı yoksayacak şekilde yapılandırılabilir. Aşağıdaki kod, güvenilir bir sertifika olmadan çağrılara izin vermek
için HttpClientHandler. ServerCertificateCustomValidationCallback kullanır:

var httpClientHandler = new HttpClientHandler();


// Return `true` to allow certificates that are untrusted/invalid
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(httpClientHandler);

var channel = GrpcChannel.ForAddress("https://localhost:5001",


new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greet.GreeterClient(channel);

WARNING
Güvenilmeyen sertifikalar yalnızca uygulama geliştirme sırasında kullanılmalıdır. Üretim uygulamaları her zaman geçerli
sertifikaları kullanmalıdır.

.NET Core istemcisiyle güvenli olmayan gRPC hizmetlerini çağırma


.NET Core istemcisiyle güvenli olmayan gRPC hizmetlerini çağırmak için ek yapılandırma gerekir. GRPC
istemcisinin, System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport anahtarını true olarak ayarlaması ve
sunucu adresinde http kullanması gerekir:

// This switch must be set before creating the GrpcChannel/HttpClient.


AppContext.SetSwitch(
"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

// The port number(5000) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("http://localhost:5000");
var client = new Greet.GreeterClient(channel);

MacOS 'ta ASP.NET Core gRPC uygulaması başlatılamıyor


Kestrel, macOS ve Windows 7 gibi eski Windows sürümlerindeki TLS ile HTTP/2 ' yi desteklemez. ASP.NET Core
gRPC şablonu ve örnekleri varsayılan olarak TLS kullanır. GRPC sunucusunu başlatmayı denediğinizde aşağıdaki
hata iletisini görürsünüz:

IPv4 geri döngü arabirimindeki https://localhost:5001 bağlanamıyor: eksik ALPN desteği nedeniyle, macOS 'ta
' HTTP/2 TLS üzerinden desteklenmez. '.

Bu sorunu geçici olarak çözmek için Kestrel ve gRPC istemcisini TLS olmadan http/2 kullanacak şekilde
yapılandırın. Bunu yalnızca geliştirme sırasında yapmanız gerekir. TLS 'nin kullanılması, gRPC iletilerinin
şifrelenmeden gönderilmesine neden olur.
Kestrel, program.csiçinde TLS olmadan bir http/2 uç noktası yapılandırmalıdır:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5000, o => o.Protocols =
HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});

Bir HTTP/2 uç noktası TLS olmadan yapılandırıldığında, uç noktanın Listenoptions. Protocols HttpProtocols.Http2
olarak ayarlanmalıdır. HTTP/2 üzerinde anlaşmak için TLS gerektiğinden HttpProtocols.Http1AndHttp2
kullanılamıyor. TLS olmadan, uç nokta varsayılan HTTP/1.1 ve gRPC çağrıları için tüm bağlantılar başarısız olur.
GRPC istemcisinin, TLS kullanmak için de yapılandırılması gerekir. Daha fazla bilgi için bkz. .NET Core istemcisiyle
güvenli olmayan gRPC hizmetlerini çağırma.

WARNING
HTTP/2, TLS olmadan yalnızca uygulama geliştirme sırasında kullanılmalıdır. Üretim uygulamaları her zaman aktarım güvenliği
kullanmalıdır. Daha fazla bilgi için bkz. gRPC 'Deki güvenlik konuları ASP.NET Core.

gRPC C# varlıkları. proto dosyalarından oluşturulan kod değildir


aynı somut istemci ve hizmet temel sınıflarının gRPC kod üretimi, bir projeden başvurulmak için prototip dosyaları
ve araçları gerektirir. Şunları dahil etmeniz gerekir:
<Protobuf> öğesi grubunda kullanmak istediğiniz . proto dosyaları. Içeri aktarılan . proto dosyalarına proje
tarafından başvurulmalıdır.
GRPC araç paketi GRPC. Tools'a paket başvurusu.
GRPC C# varlıkları oluşturma hakkında daha fazla bilgi için bkz. C# içeren gRPC hizmetleri.
Varsayılan olarak, bir <Protobuf> başvurusu somut istemci ve hizmet temel sınıfı oluşturur. Başvuru öğesinin
GrpcServices özniteliği varlık oluşturmayı sınırlamak C# için kullanılabilir. Geçerli GrpcServices seçenekleri
şunlardır:
Both (mevcut olmadığında varsayılan)
Server
Client
None

GRPC hizmetlerini barındıran bir ASP.NET Core Web uygulaması yalnızca oluşturulan hizmet taban sınıfına ihtiyaç
duyuyor:

<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

GRPC çağrısı yapan bir gRPC istemci uygulaması yalnızca somut istemcinin oluşturulması gerekir:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

WPF projeleri. proto dosyalarından gRPC C# varlıkları oluşturamıyor


WPF projelerinde, gRPC kod oluşturmanın düzgün çalışmasını engelleyen bilinen bir sorun vardır. Grpc.Tools ve .
proto dosyalarına başvurarak bir WPF projesinde oluşturulan tüm GRPC türleri, kullanıldığında derleme hataları
oluşturur:

hata CS0246: ' MyGrpcServices ' türü veya ad alanı adı bulunamadı (bir using yönergeniz veya derleme
başvurunuz mu eksik?)

Bu soruna geçici çözüm olarak şunları yapabilirsiniz:


1. Yeni bir .NET Core sınıf kitaplığı projesi oluşturun.
2. Yeni projede, C# *. proto dosyalarından kod oluşturmayıetkinleştirmek için başvurular ekleyin:
GRPC. Tools paketine bir paket başvurusu ekleyin.
<Protobuf> öğesi grubuna *. proto dosyaları ekleyin.
3. WPF uygulamasında yeni projeye bir başvuru ekleyin.
WPF uygulaması, yeni sınıf kitaplığı projesinden gRPC tarafından oluşturulan türleri kullanabilir.

gRPC Azure App Service desteklenmiyor


WARNING
ASP.NET Core gRPC Azure App SERVICE veya IIS 'de Şu anda desteklenmiyor. Http. sys ' nin HTTP/2 uygulamasına
uygulanması, gRPC 'nin bağımlı olduğu HTTP yanıtı sondaki üst bilgileri desteklemez. Daha fazla bilgi için bu GitHub sorunu.
ASP.NET Core birim testlerini Razor Pages
19.09.2019 • 30 minutes to read • Edit Online

Tarafından Luke Latham


ASP.NET Core, Razor Pages uygulamaların birim testlerini destekler. Veri erişim katmanı (DAL ) ve sayfa
modellerinin testleri şunları sağlamaya yardımcı olur:
Razor Pages uygulamasının parçaları, uygulama oluşturma sırasında bağımsız olarak ve bir birim olarak
birlikte çalışır.
Sınıfların ve yöntemlerin sınırlı sorumluluk kapsamları vardır.
Uygulamanın nasıl davranması ile ilgili ek belgeler vardır.
Kod güncelleştirmeleri tarafından ilgili hatalar olan gerileme, otomatik derleme ve dağıtım sırasında bulunur.
Bu konu, Razor Pages uygulamalar ve birim testleri hakkında temel bir anladığınızı varsayar. Razor Pages
uygulamalar veya test kavramları hakkında bilgi sahibi değilseniz aşağıdaki konulara bakın:
ASP.NET Core Razor Pages giriş
Öğretici: ASP.NET Core Razor Pages ile çalışmaya başlama
DotNet test C# ve xUnit kullanarak .NET Core 'da birim testi
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Örnek proje iki uygulamalardan oluşur:

UYGULAMA PROJE KLASÖRÜ AÇIKLAMA

İleti uygulaması src/RazorPagesTestSample Kullanıcının ileti eklemesine, bir ileti


silmesine, tüm iletileri silmesine ve
iletileri çözümlemesine (ileti başına
ortalama sözcük sayısını bulur) izin
verir.

Test uygulaması testler/RazorPagesTestSample. testler İleti uygulamasının DAL ve Dizin sayfa


modelini test etmek için kullanılır.

Testler, Visual Studio veya Mac IÇIN VISUAL STUDIOgibi bir IDE 'nin yerleşik test özellikleri kullanılarak
çalıştırılabilir. Visual Studio Code veya komut satırı kullanıyorsanız, testler/RazorPagesTestSample. Tests
klasöründeki bir komut isteminde aşağıdaki komutu yürütün:

dotnet test

İleti uygulama organizasyonu


İleti uygulaması, aşağıdaki özelliklere sahip bir Razor Pages ileti sistemidir:
Uygulamanın (Pages/Index. cshtml ve Pages/index. cshtml. cs) dizin sayfası, iletilerin eklenmesi, silinmesini ve
ANALIZINI denetlemek için bir UI ve sayfa modeli yöntemleri sağlar (ileti başına ortalama sözcük sayısını
bulur).
Bir ileti, Message sınıfı (Data/Message. cs) ile iki özelliği Id olan (anahtar) ve Text (ileti) açıklanmaktadır.
Text Özelliği gereklidir ve 200 karakterle sınırlıdır.
İletiler, Entity Framework bellek içi veritabanı†kullanılarak depolanır.
Uygulama, AppDbContext veritabanı bağlamı sınıfında (Data/appdbcontext. cs) bir dal içerir. DAL Yöntemleri
işaretlenir virtual ve bu yöntemler, testlerde kullanım için izin verir.
Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır. Bu sağlanan iletiler , testlerde de
kullanılır.
†InMemory Ile testolan EF konusu, MSTest ile testler için bellek içi bir veritabanının nasıl kullanılacağını açıklar. Bu
konu xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test uygulamaları benzerdir
ancak aynı değildir.
Örnek uygulama depo desenini kullanmaz ve Iş birimi (UoW ) düzenininetkin bir örneği olmasa da Razor Pages
bu geliştirme düzenlerini destekler. Daha fazla bilgi için bkz. altyapı Kalıcılık katmanını tasarlama ve ASP.NET
Core 'de test denetleyicisi mantığı (örnek depo modelini uygular).

Test uygulaması kuruluşu


Test uygulaması, testler/RazorPagesTestSample. Tests klasörünün içindeki bir konsol uygulamasıdır.

TEST UYGULAMASI KLASÖRÜ AÇIKLAMA

UnitTests DataAccessLayerTest.cs , dal için birim testlerini içerir.


IndexPageTests.cs , Dizin sayfası modelinin birim
testlerini içerir.

Programların Her bir dal birim testi için yeni veritabanı bağlamı seçenekleri
oluşturmak için kullanılan
yöntemiiçerir,böyleceveritabanıhertestiçinkenditemelkoşuluna
sıfırlanır. TestDbContextOptions

Test çerçevesi xUnit' dir. Nesne sahte işlem çerçevesi moqolur.

Veri erişim katmanının birim testleri (DAL)


İleti uygulamasında AppDbContext , sınıfında dört yöntem bulunan bir dal vardır
(src/RazorPagesTestSample/Data/appdbcontext. cs). Her yöntemin test uygulamasında bir veya iki birim testi
vardır.

DAL YÖNTEMI İŞLEV

GetMessagesAsync Özelliği tarafından sıralanan veritabanından bir


List<Message> alır. Text

AddMessageAsync Veritabanına bir Message ekler.

DeleteAllMessagesAsync Tüm Message girdileri veritabanından siler.

DeleteMessageAsync Veritabanından tek tek Message siler. Id

DAL birim testleri her bir test DbContextOptions için yeni AppDbContext bir oluşturma için gereklidir. Her test için
öğesini oluşturmaya DbContextOptions yönelik bir yaklaşım, şunu DbContextOptionsBuilderkullanmaktır:
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");

using (var db = new AppDbContext(optionsBuilder.Options))


{
// Use the db here in the unit test.
}

Bu yaklaşımla ilgili sorun, her testin, önceki testin bulunduğu herhangi bir durumda veritabanını aldığından emin
olur. Bu, birbirleriyle karışmaz atomik birim testleri yazmaya çalışırken sorunlu olabilir. Her test için AppDbContext
yeni bir veritabanı bağlamı kullanmaya zorlamak için, yeni bir hizmet sağlayıcısına DbContextOptions dayalı bir
örnek sağlayın. Test uygulaması, Utilities sınıfının sınıf yöntemi TestDbContextOptions kullanılarak nasıl
yapılacağını gösterir (testler/RazorPagesTestSample. testler/Utilities/Utilities. cs):

public static DbContextOptions<AppDbContext> TestDbContextOptions()


{
// Create a new service provider to create a new in-memory database.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();

// Create a new options instance using an in-memory database and


// IServiceProvider that the context should resolve all of its
// services from.
var builder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb")
.UseInternalServiceProvider(serviceProvider);

return builder.Options;
}

DAL birim DbContextOptions testlerinde kullanılması, her testin yeni bir veritabanı örneğiyle otomatik olarak
çalıştırılmasına izin verir:

using (var db = new AppDbContext(Utilities.TestDbContextOptions()))


{
// Use the db here in the unit test.
}

DataAccessLayerTest Sınıftaki her bir test yöntemi (unittests/DataAccessLayerTest. cs) benzer bir düzenleme-işlem
onaylama düzeni izler:
1. ' Veritabanı test için yapılandırıldı ve/veya beklenen sonuç tanımlandı.
2. Çalışanlarının Test yürütülür.
3. Vermediğini Test sonuçlarının başarılı olup olmadığını belirleme onayları yapılır.
Örneğin, DeleteMessageAsync yöntemi Id (src/RazorPagesTestSample/Data/appdbcontext. cs) tarafından
tanımlanan tek bir iletinin kaldırılmasından sorumludur:
public async virtual Task DeleteMessageAsync(int id)
{
var message = await Messages.FindAsync(id);

if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}

Bu yöntem için iki test vardır. Bir test, bir ileti veritabanında olduğunda yöntemin bir iletiyi sildiğini denetler. Diğer
yöntem, silme iletisi Id yoksa veritabanının değişmediğini sınar.
DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound Yöntemi aşağıda gösterilmiştir:

[Fact]
public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();

// Act
await db.DeleteMessageAsync(recId);

// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}

İlk olarak, yöntemi, hareket adımının hazırlanması gereken düzenleme adımını gerçekleştirir. Dengeli dağıtım
iletileri ' de seedMessages alınır ve tutulur. Dengeli dağıtım iletileri veritabanına kaydedilir. Id İçeren 1 ileti
silinmek üzere ayarlanmış. Yöntemi yürütüldüğünde, beklenen iletilerde, Id ' ın 1 dışında bir ileti olmalıdır.
DeleteMessageAsync Değişken expectedMessages , beklenen bu sonucu temsil eder.

// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();

Yöntemi şu şekilde davranır: DeleteMessageAsync Yöntemi , recId ' ın içinde geçirme yürütülür: 1

// Act
await db.DeleteMessageAsync(recId);

Son olarak, yöntemi bağlamını edinir Messages ve iki eşit olan expectedMessages asserile karşılaştırır:
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));

İki ikisinin List<Message> de aynı olduğunu karşılaştırmak için:


İletiler tarafından Id sıralanır.
İleti çiftleri Text özelliği ile karşılaştırılır.

Benzer bir test yöntemi, DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound mevcut olmayan bir iletiyi


silmeye çalışılması sonucunu denetler. Bu durumda, veritabanındaki beklenen iletiler, DeleteMessageAsync Yöntem
yürütüldükten sonra gerçek iletilere eşit olmalıdır. Veritabanının içeriğinde değişiklik olmamalıdır:

[Fact]
public async Task DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var expectedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(expectedMessages);
await db.SaveChangesAsync();
var recId = 4;

// Act
try
{
await db.DeleteMessageAsync(recId);
}
catch
{
// recId doesn't exist
}

// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}

Sayfa modeli yöntemlerinin birim testleri


Başka bir birim testi kümesi, sayfa modeli yöntemlerinin sınamalarından sorumludur. İleti uygulamasında Dizin
sayfası modelleri IndexModel src/RazorPagesTestSample/Pages/Index. cshtml. csiçindeki sınıfta bulunur.

SAYFA MODELI YÖNTEMI İŞLEV

OnGetAsync GetMessagesAsync Yöntemini kullanarak, Kullanıcı arabirimi


için dal öğesinden gelen iletileri alır.

OnPostAddMessageAsync ModelState geçerliyse, veritabanına bir ileti eklemek


AddMessageAsync için çağırır.
SAYFA MODELI YÖNTEMI İŞLEV

OnPostDeleteAllMessagesAsync Veritabanındaki DeleteAllMessagesAsync tüm iletileri


silmek için çağırır.

OnPostDeleteMessageAsync Id Belirtilen DeleteMessageAsync bir iletiyi silmek için


yürütülür.

OnPostAnalyzeMessagesAsync Veritabanında bir veya daha fazla ileti varsa, ileti başına
ortalama sözcük sayısını hesaplar.

Sayfa modeli yöntemleri, IndexPageTests sınıfında yedi test kullanılarak test edilir
(testler/RazorPagesTestSample. testler/unittests/ındexpagetests. cs). Testler tanıdık düzenleme-onaylama-Işlem
düzeni kullanır. Bu sınamalar üzerinde odaklanılmıştır:
ModelState geçersiz olduğunda yöntemlerin doğru davranışı izleyip izlemediğini belirleme.
Yöntemlerin doğru IActionResultbir şekilde ürettiği doğrulanıyor.
Özellik değeri atamalarının doğru şekilde yapıldığından emin olup olmadığı denetleniyor.
Bu test grubu genellikle, bir sayfa modeli yönteminin yürütüldüğü Işlem adımı için beklenen verileri oluşturmak
üzere DAL yöntemlerini oluşturuyor. Örneğin, GetMessagesAsync AppDbContext öğesinin yöntemi çıkış oluşturmak
için kullanılır. Bir sayfa modeli yöntemi bu yöntemi yürüttüğünde, sahte sonuç döndürür. Veriler veritabanından
gelmiyor. Bu, sayfa modeli testlerinde DAL kullanımı için öngörülebilir, güvenilir bir test koşulları oluşturur.
Test, GetMessagesAsync yöntemin sayfa modeli için nasıl kullanılacağını gösterir:
OnGetAsync_PopulatesThePageModel_WithAListOfMessages

var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);


var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(
db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var pageModel = new IndexModel(mockAppDbContext.Object);

Yöntem, işlem adımında yürütüldüğünde, sayfa GetMessagesAsync modelinin yöntemini çağırır. OnGetAsync

Birim testi Işlem adımı (testler/RazorPagesTestSample. testler/UnitTests/ındexpagetests. cs):

// Act
await pageModel.OnGetAsync();

IndexPage sayfa modelinin OnGetAsync yöntemi (src/RazorPagesTestSample/Pages/Index. cshtml. cs):

public async Task OnGetAsync()


{
Messages = await _db.GetMessagesAsync();
}

DAL GetMessagesAsync içindeki yöntemi bu yöntem çağrısının sonucunu döndürmez. Metodun moclenmiş
sürümü sonucu döndürür.
Adımda, gerçek iletiler ( actualMessages Messages ) sayfa modelinin özelliğinden atanır. Assert İletiler
atandığında bir tür denetimi de gerçekleştirilir. Beklenen ve gerçek iletiler Text özellikleriyle karşılaştırılır. Test, iki
List<Message> örneğinin aynı iletileri içerdiğini onaylar.
// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(pageModel.Messages);
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));

Bu gruptaki diğer testler,,, ve ' ı DefaultHttpContextkurmak PageContext ModelStateDictionary ActionContext


PageContext ViewDataDictionary için,, bir içeren sayfa modeli nesneleri oluşturur. Bunlar, testleri yürütmek için
faydalıdır. Örneğin, ModelState ileti uygulaması yürütüldüğünde geçerli AddModelError PageResult bir
döndürülüp döndürüldüğünden emin olmak için bir hata oluşturur: OnPostAddMessageAsync

[Fact]
public async Task OnPostAddMessageAsync_ReturnsAPageResult_WhenModelStateIsInvalid()
{
// Arrange
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var httpContext = new DefaultHttpContext();
var modelState = new ModelStateDictionary();
var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(),
modelState);
var modelMetadataProvider = new EmptyModelMetadataProvider();
var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
var tempData = new TempDataDictionary(httpContext, Mock.Of<ITempDataProvider>());
var pageContext = new PageContext(actionContext)
{
ViewData = viewData
};
var pageModel = new IndexModel(mockAppDbContext.Object)
{
PageContext = pageContext,
TempData = tempData,
Url = new UrlHelper(actionContext)
};
pageModel.ModelState.AddModelError("Message.Text", "The Text field is required.");

// Act
var result = await pageModel.OnPostAddMessageAsync();

// Assert
Assert.IsType<PageResult>(result);
}

Ek kaynaklar
DotNet test C# ve xUnit kullanarak .NET Core 'da birim testi
ASP.NET Core 'de test denetleyicisi mantığı
Kodunuzun birim testi (Visual Studio)
ASP.NET Core tümleştirme testleri
xUnit.net
Mac için Visual Studio kullanarak macOS’ta eksiksiz bir .NET Core çözümü derleme
XUnit.net kullanmaya başlama: .NET SDK komut satırı ile .NET Core kullanma
Moq dili
Moq hızlı başlangıç
ASP.NET Core, Razor Pages uygulamaların birim testlerini destekler. Veri erişim katmanı (DAL ) ve sayfa
modellerinin testleri şunları sağlamaya yardımcı olur:
Razor Pages uygulamasının parçaları, uygulama oluşturma sırasında bağımsız olarak ve bir birim olarak
birlikte çalışır.
Sınıfların ve yöntemlerin sınırlı sorumluluk kapsamları vardır.
Uygulamanın nasıl davranması ile ilgili ek belgeler vardır.
Kod güncelleştirmeleri tarafından ilgili hatalar olan gerileme, otomatik derleme ve dağıtım sırasında bulunur.
Bu konu, Razor Pages uygulamalar ve birim testleri hakkında temel bir anladığınızı varsayar. Razor Pages
uygulamalar veya test kavramları hakkında bilgi sahibi değilseniz aşağıdaki konulara bakın:
ASP.NET Core Razor Pages giriş
Öğretici: ASP.NET Core Razor Pages ile çalışmaya başlama
DotNet test C# ve xUnit kullanarak .NET Core 'da birim testi
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)
Örnek proje iki uygulamalardan oluşur:

UYGULAMA PROJE KLASÖRÜ AÇIKLAMA

İleti uygulaması src/RazorPagesTestSample Kullanıcının ileti eklemesine, bir ileti


silmesine, tüm iletileri silmesine ve
iletileri çözümlemesine (ileti başına
ortalama sözcük sayısını bulur) izin
verir.

Test uygulaması testler/RazorPagesTestSample. testler İleti uygulamasının DAL ve Dizin sayfa


modelini test etmek için kullanılır.

Testler, Visual Studio veya Mac IÇIN VISUAL STUDIOgibi bir IDE 'nin yerleşik test özellikleri kullanılarak
çalıştırılabilir. Visual Studio Code veya komut satırı kullanıyorsanız, testler/RazorPagesTestSample. Tests
klasöründeki bir komut isteminde aşağıdaki komutu yürütün:

dotnet test

İleti uygulama organizasyonu


İleti uygulaması, aşağıdaki özelliklere sahip bir Razor Pages ileti sistemidir:
Uygulamanın (Pages/Index. cshtml ve Pages/index. cshtml. cs) dizin sayfası, iletilerin eklenmesi, silinmesini ve
ANALIZINI denetlemek için bir UI ve sayfa modeli yöntemleri sağlar (ileti başına ortalama sözcük sayısını
bulur).
Bir ileti, Message sınıfı (Data/Message. cs) ile iki özelliği Id olan (anahtar) ve Text (ileti) açıklanmaktadır.
Text Özelliği gereklidir ve 200 karakterle sınırlıdır.
İletiler, Entity Framework bellek içi veritabanı†kullanılarak depolanır.
Uygulama, AppDbContext veritabanı bağlamı sınıfında (Data/appdbcontext. cs) bir dal içerir. DAL Yöntemleri
işaretlenir virtual ve bu yöntemler, testlerde kullanım için izin verir.
Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır. Bu sağlanan iletiler , testlerde de
kullanılır.
†InMemory Ile testolan EF konusu, MSTest ile testler için bellek içi bir veritabanının nasıl kullanılacağını açıklar. Bu
konu xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test uygulamaları benzerdir
ancak aynı değildir.
Örnek uygulama depo desenini kullanmaz ve Iş birimi (UoW ) düzenininetkin bir örneği olmasa da Razor Pages
bu geliştirme düzenlerini destekler. Daha fazla bilgi için bkz. altyapı Kalıcılık katmanını tasarlama ve ASP.NET
Core 'de test denetleyicisi mantığı (örnek depo modelini uygular).

Test uygulaması kuruluşu


Test uygulaması, testler/RazorPagesTestSample. Tests klasörünün içindeki bir konsol uygulamasıdır.

TEST UYGULAMASI KLASÖRÜ AÇIKLAMA

UnitTests DataAccessLayerTest.cs , dal için birim testlerini içerir.


IndexPageTests.cs , Dizin sayfası modelinin birim
testlerini içerir.

Programların Her bir dal birim testi için yeni veritabanı bağlamı seçenekleri
oluşturmak için kullanılan
yöntemiiçerir,böyleceveritabanıhertestiçinkenditemelkoşuluna
sıfırlanır. TestDbContextOptions

Test çerçevesi xUnit' dir. Nesne sahte işlem çerçevesi moqolur.

Veri erişim katmanının birim testleri (DAL)


İleti uygulamasında AppDbContext , sınıfında dört yöntem bulunan bir dal vardır
(src/RazorPagesTestSample/Data/appdbcontext. cs). Her yöntemin test uygulamasında bir veya iki birim testi
vardır.

DAL YÖNTEMI İŞLEV

GetMessagesAsync Özelliği tarafından sıralanan veritabanından bir


List<Message> alır. Text

AddMessageAsync Veritabanına bir Message ekler.

DeleteAllMessagesAsync Tüm Message girdileri veritabanından siler.

DeleteMessageAsync Veritabanından tek tek Message siler. Id

DAL birim testleri her bir test DbContextOptions için yeni AppDbContext bir oluşturma için gereklidir. Her test için
öğesini oluşturmaya DbContextOptions yönelik bir yaklaşım, şunu DbContextOptionsBuilderkullanmaktır:

var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()


.UseInMemoryDatabase("InMemoryDb");

using (var db = new AppDbContext(optionsBuilder.Options))


{
// Use the db here in the unit test.
}

Bu yaklaşımla ilgili sorun, her testin, önceki testin bulunduğu herhangi bir durumda veritabanını aldığından emin
olur. Bu, birbirleriyle karışmaz atomik birim testleri yazmaya çalışırken sorunlu olabilir. Her test için AppDbContext
yeni bir veritabanı bağlamı kullanmaya zorlamak için, yeni bir hizmet sağlayıcısına DbContextOptions dayalı bir
örnek sağlayın. Test uygulaması, Utilities sınıfının sınıf yöntemi TestDbContextOptions kullanılarak nasıl
yapılacağını gösterir (testler/RazorPagesTestSample. testler/Utilities/Utilities. cs):

public static DbContextOptions<AppDbContext> TestDbContextOptions()


{
// Create a new service provider to create a new in-memory database.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();

// Create a new options instance using an in-memory database and


// IServiceProvider that the context should resolve all of its
// services from.
var builder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb")
.UseInternalServiceProvider(serviceProvider);

return builder.Options;
}

DAL birim DbContextOptions testlerinde kullanılması, her testin yeni bir veritabanı örneğiyle otomatik olarak
çalıştırılmasına izin verir:

using (var db = new AppDbContext(Utilities.TestDbContextOptions()))


{
// Use the db here in the unit test.
}

DataAccessLayerTest Sınıftaki her bir test yöntemi (unittests/DataAccessLayerTest. cs) benzer bir düzenleme-işlem
onaylama düzeni izler:
1. ' Veritabanı test için yapılandırıldı ve/veya beklenen sonuç tanımlandı.
2. Çalışanlarının Test yürütülür.
3. Vermediğini Test sonuçlarının başarılı olup olmadığını belirleme onayları yapılır.
Örneğin, DeleteMessageAsync yöntemi Id (src/RazorPagesTestSample/Data/appdbcontext. cs) tarafından
tanımlanan tek bir iletinin kaldırılmasından sorumludur:

public async virtual Task DeleteMessageAsync(int id)


{
var message = await Messages.FindAsync(id);

if (message != null)
{
Messages.Remove(message);
await SaveChangesAsync();
}
}

Bu yöntem için iki test vardır. Bir test, bir ileti veritabanında olduğunda yöntemin bir iletiyi sildiğini denetler. Diğer
yöntem, silme iletisi Id yoksa veritabanının değişmediğini sınar.
DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound Yöntemi aşağıda gösterilmiştir:
[Fact]
public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();

// Act
await db.DeleteMessageAsync(recId);

// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}

İlk olarak, yöntemi, hareket adımının hazırlanması gereken düzenleme adımını gerçekleştirir. Dengeli dağıtım
iletileri ' de seedMessages alınır ve tutulur. Dengeli dağıtım iletileri veritabanına kaydedilir. Id İçeren 1 ileti
silinmek üzere ayarlanmış. Yöntemi yürütüldüğünde, beklenen iletilerde, Id ' ın 1 dışında bir ileti olmalıdır.
DeleteMessageAsync Değişken expectedMessages , beklenen bu sonucu temsil eder.

// Arrange
var seedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();

Yöntemi şu şekilde davranır: DeleteMessageAsync Yöntemi , recId ' ın içinde geçirme yürütülür: 1

// Act
await db.DeleteMessageAsync(recId);

Son olarak, yöntemi bağlamını edinir Messages ve iki eşit olan expectedMessages asserile karşılaştırır:

// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));

İki ikisinin List<Message> de aynı olduğunu karşılaştırmak için:


İletiler tarafından Id sıralanır.
İleti çiftleri Text özelliği ile karşılaştırılır.

Benzer bir test yöntemi, DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound mevcut olmayan bir iletiyi


silmeye çalışılması sonucunu denetler. Bu durumda, veritabanındaki beklenen iletiler, DeleteMessageAsync Yöntem
yürütüldükten sonra gerçek iletilere eşit olmalıdır. Veritabanının içeriğinde değişiklik olmamalıdır:
[Fact]
public async Task DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound()
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var expectedMessages = AppDbContext.GetSeedingMessages();
await db.AddRangeAsync(expectedMessages);
await db.SaveChangesAsync();
var recId = 4;

// Act
await db.DeleteMessageAsync(recId);

// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}

Sayfa modeli yöntemlerinin birim testleri


Başka bir birim testi kümesi, sayfa modeli yöntemlerinin sınamalarından sorumludur. İleti uygulamasında Dizin
sayfası modelleri IndexModel src/RazorPagesTestSample/Pages/Index. cshtml. csiçindeki sınıfta bulunur.

SAYFA MODELI YÖNTEMI İŞLEV

OnGetAsync GetMessagesAsync Yöntemini kullanarak, Kullanıcı arabirimi


için dal öğesinden gelen iletileri alır.

OnPostAddMessageAsync ModelState geçerliyse, veritabanına bir ileti eklemek


AddMessageAsync için çağırır.

OnPostDeleteAllMessagesAsync Veritabanındaki DeleteAllMessagesAsync tüm iletileri


silmek için çağırır.

OnPostDeleteMessageAsync Id Belirtilen DeleteMessageAsync bir iletiyi silmek için


yürütülür.

OnPostAnalyzeMessagesAsync Veritabanında bir veya daha fazla ileti varsa, ileti başına
ortalama sözcük sayısını hesaplar.

Sayfa modeli yöntemleri, IndexPageTests sınıfında yedi test kullanılarak test edilir
(testler/RazorPagesTestSample. testler/unittests/ındexpagetests. cs). Testler tanıdık düzenleme-onaylama-Işlem
düzeni kullanır. Bu sınamalar üzerinde odaklanılmıştır:
ModelState geçersiz olduğunda yöntemlerin doğru davranışı izleyip izlemediğini belirleme.
Yöntemlerin doğru IActionResultbir şekilde ürettiği doğrulanıyor.
Özellik değeri atamalarının doğru şekilde yapıldığından emin olup olmadığı denetleniyor.
Bu test grubu genellikle, bir sayfa modeli yönteminin yürütüldüğü Işlem adımı için beklenen verileri oluşturmak
üzere DAL yöntemlerini oluşturuyor. Örneğin, GetMessagesAsync AppDbContext öğesinin yöntemi çıkış oluşturmak
için kullanılır. Bir sayfa modeli yöntemi bu yöntemi yürüttüğünde, sahte sonuç döndürür. Veriler veritabanından
gelmiyor. Bu, sayfa modeli testlerinde DAL kullanımı için öngörülebilir, güvenilir bir test koşulları oluşturur.
Test, GetMessagesAsync yöntemin sayfa modeli için nasıl kullanılacağını gösterir:
OnGetAsync_PopulatesThePageModel_WithAListOfMessages

var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);


var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(
db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var pageModel = new IndexModel(mockAppDbContext.Object);

Yöntem, işlem adımında yürütüldüğünde, sayfa GetMessagesAsync modelinin yöntemini çağırır. OnGetAsync

Birim testi Işlem adımı (testler/RazorPagesTestSample. testler/UnitTests/ındexpagetests. cs):

// Act
await pageModel.OnGetAsync();

IndexPage sayfa modelinin OnGetAsync yöntemi (src/RazorPagesTestSample/Pages/Index. cshtml. cs):

public async Task OnGetAsync()


{
Messages = await _db.GetMessagesAsync();
}

DAL GetMessagesAsync içindeki yöntemi bu yöntem çağrısının sonucunu döndürmez. Metodun moclenmiş
sürümü sonucu döndürür.
Adımda, gerçek iletiler ( actualMessages Messages ) sayfa modelinin özelliğinden atanır. Assert İletiler
atandığında bir tür denetimi de gerçekleştirilir. Beklenen ve gerçek iletiler Text özellikleriyle karşılaştırılır. Test, iki
List<Message> örneğinin aynı iletileri içerdiğini onaylar.

// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(pageModel.Messages);
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));

Bu gruptaki diğer testler,,, ve ' ı DefaultHttpContextkurmak PageContext ModelStateDictionary ActionContext


PageContext ViewDataDictionary için,, bir içeren sayfa modeli nesneleri oluşturur. Bunlar, testleri yürütmek için
faydalıdır. Örneğin, ModelState ileti uygulaması yürütüldüğünde geçerli AddModelError PageResult bir
döndürülüp döndürüldüğünden emin olmak için bir hata oluşturur: OnPostAddMessageAsync
[Fact]
public async Task OnPostAddMessageAsync_ReturnsAPageResult_WhenModelStateIsInvalid()
{
// Arrange
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("InMemoryDb");
var mockAppDbContext = new Mock<AppDbContext>(optionsBuilder.Options);
var expectedMessages = AppDbContext.GetSeedingMessages();
mockAppDbContext.Setup(db => db.GetMessagesAsync()).Returns(Task.FromResult(expectedMessages));
var httpContext = new DefaultHttpContext();
var modelState = new ModelStateDictionary();
var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(),
modelState);
var modelMetadataProvider = new EmptyModelMetadataProvider();
var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
var tempData = new TempDataDictionary(httpContext, Mock.Of<ITempDataProvider>());
var pageContext = new PageContext(actionContext)
{
ViewData = viewData
};
var pageModel = new IndexModel(mockAppDbContext.Object)
{
PageContext = pageContext,
TempData = tempData,
Url = new UrlHelper(actionContext)
};
pageModel.ModelState.AddModelError("Message.Text", "The Text field is required.");

// Act
var result = await pageModel.OnPostAddMessageAsync();

// Assert
Assert.IsType<PageResult>(result);
}

Ek kaynaklar
DotNet test C# ve xUnit kullanarak .NET Core 'da birim testi
ASP.NET Core 'de test denetleyicisi mantığı
Kodunuzun birim testi (Visual Studio)
ASP.NET Core tümleştirme testleri
xUnit.net
Mac için Visual Studio kullanarak macOS’ta eksiksiz bir .NET Core çözümü derleme
XUnit.net kullanmaya başlama: .NET SDK komut satırı ile .NET Core kullanma
Moq dili
Moq hızlı başlangıç
ASP.NET Core 'de birim test denetleyicisi mantığı
3.12.2019 • 34 minutes to read • Edit Online

Steve Smith tarafından


Birim testleri , bir uygulamanın bir bölümünü altyapısından ve bağımlılıklarından yalıtımıyla test etmeyi içerir.
Birim testi denetleyici mantığı olduğunda, yalnızca tek bir eylemin içerikleri test edilir, onun bağımlılıkları veya
çerçevenin kendisi değildir.

Birim test denetleyicileri


Denetleyicinin davranışına odaklanmak için denetleyici eylemlerinin birim testlerini ayarlayın. Denetleyici birim
testi Filtreler, yönlendirmeve model bağlamagibi senaryoları önler. Bir isteğe topluca yanıt veren bileşenler
arasındaki etkileşimleri kapsayan testler, tümleştirme testleritarafından işlenir. Tümleştirme testleri hakkında
daha fazla bilgi için bkz. ASP.NET Core tümleştirme testleri.
Özel filtreler ve rotalar yazıyorsanız, birim, belirli bir denetleyici eyleminde testlerin bir parçası olarak değil,
yalıtımına göre test eder.
Denetleyici birim testlerini göstermek için örnek uygulamada aşağıdaki denetleyiciyi gözden geçirin.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Ana denetleyici bir beyin fırtınası oturumlarının listesini görüntüler ve yeni beyin fırtınası oturumlarının bir
POST isteğiyle oluşturulmasına izin verir:
public class HomeController : Controller
{
private readonly IBrainstormSessionRepository _sessionRepository;

public HomeController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index()


{
var sessionList = await _sessionRepository.ListAsync();

var model = sessionList.Select(session => new StormSessionViewModel()


{
Id = session.Id,
DateCreated = session.DateCreated,
Name = session.Name,
IdeaCount = session.Ideas.Count
});

return View(model);
}

public class NewSessionModel


{
[Required]
public string SessionName { get; set; }
}

[HttpPost]
public async Task<IActionResult> Index(NewSessionModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
else
{
await _sessionRepository.AddAsync(new BrainstormSession()
{
DateCreated = DateTimeOffset.Now,
Name = model.SessionName
});
}

return RedirectToAction(actionName: nameof(Index));


}
}

Önceki denetleyici:
Açık bağımlılıklar ilkesiniizler.
IBrainstormSessionRepository örneğini sağlamak için bağımlılık ekleme (dı) bekliyor.
, Moqgibi bir sahte nesne çerçevesi kullanılarak bir moclenmiş IBrainstormSessionRepository hizmeti ile test
edilebilir. Bir ilişkili nesne , test için kullanılan önceden tanımlanmış bir özellik ve Yöntem davranışları
kümesine sahip bir fabricobject nesnesidir. Daha fazla bilgi için bkz. tümleştirme testlerine giriş.
HTTP GET Index yöntemi döngü veya dallandırma içermez ve yalnızca bir yöntem çağırır. Bu eylemin birim testi:
GetTestSessions yöntemini kullanarak IBrainstormSessionRepository hizmetini gizler. GetTestSessions ,
tarihler ve oturum adlarıyla iki adet sahte beyin fırtınası oturumu oluşturur.
Index yöntemini yürütür.
Yöntemi tarafından döndürülen sonuç üzerinde onaylama işlemleri yapar:
Bir ViewResult döndürülür.
ViewDataDictionary. model bir StormSessionViewModel .
ViewDataDictionary.Model depolanan iki beyin fırtınası oturumu vardır.

[Fact]
public async Task Index_ReturnsAViewResult_WithAListOfBrainstormSessions()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);

// Act
var result = await controller.Index();

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<StormSessionViewModel>>(
viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}

private List<BrainstormSession> GetTestSessions()


{
var sessions = new List<BrainstormSession>();
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 2),
Id = 1,
Name = "Test One"
});
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 1),
Id = 2,
Name = "Test Two"
});
return sessions;
}

Ana denetleyicinin HTTP POST Index yöntemi testleri şunları doğrular:


ModelState. IsValid false olduğunda, eylem yöntemi uygun verilerle bir 400 hatalı istek ViewResult
döndürür.
ModelState.IsValid :
true
Depodaki Add yöntemi çağrılır.
Doğru bağımsız değişkenlerle bir RedirectToActionResult döndürülür.
Geçersiz bir model durumu, aşağıdaki ilk testte gösterildiği gibi AddModelError kullanılarak hatalar eklenerek
test edilir:
[Fact]
public async Task IndexPost_ReturnsBadRequestResult_WhenModelStateIsInvalid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);
controller.ModelState.AddModelError("SessionName", "Required");
var newSession = new HomeController.NewSessionModel();

// Act
var result = await controller.Index(newSession);

// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
Assert.IsType<SerializableError>(badRequestResult.Value);
}

[Fact]
public async Task IndexPost_ReturnsARedirectAndAddsSession_WhenModelStateIsValid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.AddAsync(It.IsAny<BrainstormSession>()))
.Returns(Task.CompletedTask)
.Verifiable();
var controller = new HomeController(mockRepo.Object);
var newSession = new HomeController.NewSessionModel()
{
SessionName = "Test Name"
};

// Act
var result = await controller.Index(newSession);

// Assert
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(result);
Assert.Null(redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
mockRepo.Verify();
}

ModelState geçerli olmadığında, bir get isteği için aynı ViewResult döndürülür. Test geçersiz bir modeli
geçirmeye çalışmıyor. Model bağlama çalışmadığından (bir tümleştirme testi model bağlamayı kullansa da),
geçersiz bir modelin geçirilmesi geçerli bir yaklaşım değildir. Bu durumda model bağlama sınanmamıştır. Bu
birim testleri yalnızca eylem yöntemindeki kodu test eder.
İkinci test ModelState geçerli olduğunda doğrular:
Yeni bir BrainstormSession eklenir (depo aracılığıyla).
Yöntemi, beklenen özelliklerle bir RedirectToActionResult döndürür.

Çağrılmayan hiçbir çağrı normalde yok sayılır, ancak kurulum çağrısının sonunda Verifiable çağrısı testte sahte
doğrulamaya izin verir. Bu, beklenen yöntemin çağrılmaması durumunda test başarısız olan mockRepo.Verify
çağrısıyla gerçekleştirilir.
NOTE
Bu örnekte kullanılan moq kitaplığı, doğrulanabilir olmayan bir şekilde ("gevşek" bir veya saplamalar olarak da adlandırılır)
doğrulanabilir veya "katı" olarak karışık bir şekilde karışık bir şekilde karıştırılamaz. Moq Ile sahte davranışı
özelleştirmehakkında daha fazla bilgi edinin.

Örnek uygulamadaki Sessioncontroller , belirli bir beyin fırtınası oturumuyla ilgili bilgileri görüntüler.
Denetleyici geçersiz id değerlerle ilgilenme mantığını içerir (bu senaryoları kapsayan aşağıdaki örnekte iki
return senaryo vardır ). Son return ifade görünüme yeni bir StormSessionViewModel döndürür
(Controllers/SessionController. cs):

public class SessionController : Controller


{
private readonly IBrainstormSessionRepository _sessionRepository;

public SessionController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index(int? id)


{
if (!id.HasValue)
{
return RedirectToAction(actionName: nameof(Index),
controllerName: "Home");
}

var session = await _sessionRepository.GetByIdAsync(id.Value);


if (session == null)
{
return Content("Session not found.");
}

var viewModel = new StormSessionViewModel()


{
DateCreated = session.DateCreated,
Name = session.Name,
Id = session.Id
};

return View(viewModel);
}
}

Birim testleri, oturum denetleyicisi Index eyleminde her bir return senaryosu için bir test içerir:
[Fact]
public async Task IndexReturnsARedirectToIndexHomeWhenIdIsNull()
{
// Arrange
var controller = new SessionController(sessionRepository: null);

// Act
var result = await controller.Index(id: null);

// Assert
var redirectToActionResult =
Assert.IsType<RedirectToActionResult>(result);
Assert.Equal("Home", redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
}

[Fact]
public async Task IndexReturnsContentWithSessionNotFoundWhenSessionNotFound()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var contentResult = Assert.IsType<ContentResult>(result);
Assert.Equal("Session not found.", contentResult.Content);
}

[Fact]
public async Task IndexReturnsViewResultWithStormSessionViewModel()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSessions().FirstOrDefault(
s => s.Id == testSessionId));
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsType<StormSessionViewModel>(
viewResult.ViewData.Model);
Assert.Equal("Test One", model.Name);
Assert.Equal(2, model.DateCreated.Day);
Assert.Equal(testSessionId, model.Id);
}

Uygulama, fikirler denetleyicisine geçiş yaparken api/ideas rotasında bir Web API 'SI olarak işlevselliği
kullanıma sunar:
Bir beyin fırtınası oturumuyla ilişkili fikirler ( IdeaDTO ) listesi, ForSession yöntemi tarafından döndürülür.
Create yöntemi bir oturuma yeni fikirler ekler.
[HttpGet("forsession/{sessionId}")]
public async Task<IActionResult> ForSession(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);
if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return Ok(result);
}

[HttpPost("create")]
public async Task<IActionResult> Create([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);


if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return Ok(session);
}

İş etki alanı varlıklarını doğrudan API çağrıları aracılığıyla döndürmekten kaçının. Etki alanı varlıkları:
Genellikle istemcinin gerektirdiğinden daha fazla veri içerir.
Genel olarak sunulan API ile uygulamanın iç etki alanı modelini gereksiz bir şekilde yapın.
Etki alanı varlıkları ve istemciye döndürülen türler arasında eşleme gerçekleştirilebilir:
Örnek uygulamanın kullandığı şekilde bir LINQ Select el ile. Daha fazla bilgi için bkz. LINQ (dil Ile tümleşik
sorgu).
Otomatik olarak bir kitaplıkla (örneğin, Automaber).
Ardından, örnek uygulama, fikirler denetleyicisinin Create ve ForSession API yöntemlerine yönelik birim
testlerini gösterir.
Örnek uygulama iki ForSession test içerir. İlk test, ForSession geçersiz bir oturum için NotFoundObjectResult
(HTTP bulunamadı) döndürüp döndürmeyeceğini belirler:
[Fact]
public async Task ForSession_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var notFoundObjectResult = Assert.IsType<NotFoundObjectResult>(result);
Assert.Equal(testSessionId, notFoundObjectResult.Value);
}

İkinci ForSession testi, ForSession geçerli bir oturum için oturum fikirleri ( <List<IdeaDTO>> ) listesini döndürüp
döndürmeyeceğini belirler. Denetimler Ayrıca, Name özelliğinin doğru olduğunu onaylamak için ilk fikri de
inceler:

[Fact]
public async Task ForSession_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(okResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

ModelState geçersiz olduğunda Create yönteminin davranışını test etmek için, örnek uygulama, testin bir
parçası olarak denetleyiciye bir model hatası ekler. Birim testlerinde model doğrulama veya model bağlamayı
sınamayı denemeyin—geçersiz bir ModelState sahip olduğunda eylem yönteminin davranışını test edin:

[Fact]
public async Task Create_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.Create(model: null);

// Assert
Assert.IsType<BadRequestObjectResult>(result);
}
Create ikinci testi, null döndüren depoya bağlıdır, bu nedenle, sahte depo null döndürecek şekilde
yapılandırılır. Bir test veritabanı (bellekte veya başka türlü) oluşturmanız gerekmez ve bu sonucu döndüren bir
sorgu oluşturun. Örnek kodun gösterildiği gibi, test tek bir bildirimde gerçekleştirilebilir:

[Fact]
public async Task Create_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.Create(new NewIdeaModel());

// Assert
Assert.IsType<NotFoundObjectResult>(result);
}

Create_ReturnsNewlyCreatedIdeaForSession üçüncü Create testi, deponun UpdateAsync yönteminin çağrıldığını


doğrular. Sahte, Verifiable ile çağrılır ve doğrulanabilen yöntemin yürütüldüğünü onaylamak için, moclenmiş
deponun Verify yöntemi çağırılır. UpdateAsync yönteminin bir tümleştirme testiyle gerçekleştirilebilecek
verileri—kaydettiğinizden emin olmak için birim testinin sorumluluğu yoktur.

[Fact]
public async Task Create_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.Create(newIdea);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnSession = Assert.IsType<BrainstormSession>(okResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnSession.Ideas.Count());
Assert.Equal(testName, returnSession.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnSession.Ideas.LastOrDefault().Description);
}
Test ActionResult<T >
ASP.NET Core 2,1 veya sonraki bir sürümde, actionresult<t > (ActionResult<TValue>) ActionResult türetilen
bir tür döndürmenizi veya belirli bir tür döndürmenizi sağlar.
Örnek uygulama, belirli bir oturum id için List<IdeaDTO> döndüren bir yöntemi içerir. Oturum id yoksa,
denetleyici NotFounddöndürür:

[HttpGet("forsessionactionresult/{sessionId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<ActionResult<List<IdeaDTO>>> ForSessionActionResult(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);

if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return result;
}

ForSessionActionResult denetleyicisinin iki testi ApiIdeasControllerTests dahil edilir.


İlk test, denetleyicinin varolmayan bir oturum id için varolmayan bir fikir listesi ActionResult döndürdüğünü
onaylar:
ActionResult türü ActionResult<List<IdeaDTO>> .
Result bir NotFoundObjectResult.

[Fact]
public async Task ForSessionActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
var nonExistentSessionId = 999;

// Act
var result = await controller.ForSessionActionResult(nonExistentSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için ikinci test, yöntemin döndürdüğünü doğrular:


List<IdeaDTO> türüne sahip bir ActionResult .
ActionResult<t >. Değer bir List<IdeaDTO> türüdür.
Listedeki ilk öğe, sahte oturumda saklanan fikrle eşleşen geçerli bir fikrdir ( GetTestSession çağırarak elde
edilir).
[Fact]
public async Task ForSessionActionResult_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSessionActionResult(testSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(actionResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

Örnek uygulama, belirli bir oturum için yeni Idea oluşturmak üzere bir yöntemi de içerir. Denetleyici şunu
döndürür:
geçersiz bir model için BadRequest.
oturum yoksa NotFound.
oturum yeni fikrle güncelleştirildiği zaman CreatedAtAction.

[HttpPost("createactionresult")]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
public async Task<ActionResult<BrainstormSession>> CreateActionResult([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);

if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return CreatedAtAction(nameof(CreateActionResult), new { id = session.Id }, session);


}

CreateActionResult üç test ApiIdeasControllerTests dahil edilir.


İlk metin, geçersiz bir model için BadRequest döndürüldüğünü onaylar.
[Fact]
public async Task CreateActionResult_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.CreateActionResult(model: null);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<BadRequestObjectResult>(actionResult.Result);
}

İkinci test, oturum yoksa NotFound döndürülüp döndürülmediğini denetler.

[Fact]
public async Task CreateActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var nonExistentSessionId = 999;
string testName = "test name";
string testDescription = "test description";
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = nonExistentSessionId
};

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için son test şunları onaylar:


Yöntemi, bir BrainstormSession türü ile ActionResult döndürür.
ActionResult<t >. Sonuç bir CreatedAtActionResult. CreatedAtActionResult , bir Location üst bilgisiyle 201
tarafından oluşturulan bir yanıta benzerdir.
ActionResult<t >. Değer bir BrainstormSession türüdür.
Oturumu güncelleştirmek için kullanılan sahte çağrı, UpdateAsync(testSession) çağrıldı. Verifiable yöntemi
çağrısı onaylamalarda mockRepo.Verify() yürütülerek denetlenir.
Oturum için iki Idea nesnesi döndürülür.
Son öğe (sahte çağrının UpdateAsync tarafından eklenen Idea ) testteki oturuma eklenen newIdea eşleşir.
[Fact]
public async Task CreateActionResult_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
var createdAtActionResult = Assert.IsType<CreatedAtActionResult>(actionResult.Result);
var returnValue = Assert.IsType<BrainstormSession>(createdAtActionResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnValue.Ideas.Count());
Assert.Equal(testName, returnValue.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnValue.Ideas.LastOrDefault().Description);
}

Denetleyiciler herhangi BIR ASP.NET Core MVC uygulamasında merkezi bir rol oynar. Bu nedenle,
denetleyicilerin amaçlanan gibi davrandığına güvenmelisiniz. Otomatik testler, uygulama bir üretim ortamına
dağıtılmadan önce hataları tespit edebilir.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Denetleyici mantığının birim testleri


Birim testleri , bir uygulamanın bir bölümünü altyapısından ve bağımlılıklarından yalıtımıyla test etmeyi içerir.
Birim testi denetleyici mantığı olduğunda, yalnızca tek bir eylemin içerikleri test edilir, onun bağımlılıkları veya
çerçevenin kendisi değildir.
Denetleyicinin davranışına odaklanmak için denetleyici eylemlerinin birim testlerini ayarlayın. Denetleyici birim
testi Filtreler, yönlendirmeve model bağlamagibi senaryoları önler. Bir isteğe topluca yanıt veren bileşenler
arasındaki etkileşimleri kapsayan testler, tümleştirme testleritarafından işlenir. Tümleştirme testleri hakkında
daha fazla bilgi için bkz. ASP.NET Core tümleştirme testleri.
Özel filtreler ve rotalar yazıyorsanız, birim, belirli bir denetleyici eyleminde testlerin bir parçası olarak değil,
yalıtımına göre test eder.
Denetleyici birim testlerini göstermek için örnek uygulamada aşağıdaki denetleyiciyi gözden geçirin. Ana
denetleyici bir beyin fırtınası oturumlarının listesini görüntüler ve yeni beyin fırtınası oturumlarının bir POST
isteğiyle oluşturulmasına izin verir:
public class HomeController : Controller
{
private readonly IBrainstormSessionRepository _sessionRepository;

public HomeController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index()


{
var sessionList = await _sessionRepository.ListAsync();

var model = sessionList.Select(session => new StormSessionViewModel()


{
Id = session.Id,
DateCreated = session.DateCreated,
Name = session.Name,
IdeaCount = session.Ideas.Count
});

return View(model);
}

public class NewSessionModel


{
[Required]
public string SessionName { get; set; }
}

[HttpPost]
public async Task<IActionResult> Index(NewSessionModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
else
{
await _sessionRepository.AddAsync(new BrainstormSession()
{
DateCreated = DateTimeOffset.Now,
Name = model.SessionName
});
}

return RedirectToAction(actionName: nameof(Index));


}
}

Önceki denetleyici:
Açık bağımlılıklar ilkesiniizler.
IBrainstormSessionRepository örneğini sağlamak için bağımlılık ekleme (dı) bekliyor.
, Moqgibi bir sahte nesne çerçevesi kullanılarak bir moclenmiş IBrainstormSessionRepository hizmeti ile test
edilebilir. Bir ilişkili nesne , test için kullanılan önceden tanımlanmış bir özellik ve Yöntem davranışları
kümesine sahip bir fabricobject nesnesidir. Daha fazla bilgi için bkz. tümleştirme testlerine giriş.
HTTP GET Index yöntemi döngü veya dallandırma içermez ve yalnızca bir yöntem çağırır. Bu eylemin birim testi:
GetTestSessions yöntemini kullanarak IBrainstormSessionRepository hizmetini gizler. GetTestSessions ,
tarihler ve oturum adlarıyla iki adet sahte beyin fırtınası oturumu oluşturur.
Index yöntemini yürütür.
Yöntemi tarafından döndürülen sonuç üzerinde onaylama işlemleri yapar:
Bir ViewResult döndürülür.
ViewDataDictionary. model bir StormSessionViewModel .
ViewDataDictionary.Model depolanan iki beyin fırtınası oturumu vardır.

[Fact]
public async Task Index_ReturnsAViewResult_WithAListOfBrainstormSessions()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);

// Act
var result = await controller.Index();

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<StormSessionViewModel>>(
viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}

private List<BrainstormSession> GetTestSessions()


{
var sessions = new List<BrainstormSession>();
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 2),
Id = 1,
Name = "Test One"
});
sessions.Add(new BrainstormSession()
{
DateCreated = new DateTime(2016, 7, 1),
Id = 2,
Name = "Test Two"
});
return sessions;
}

Ana denetleyicinin HTTP POST Index yöntemi testleri şunları doğrular:


ModelState. IsValid false olduğunda, eylem yöntemi uygun verilerle bir 400 hatalı istek ViewResult
döndürür.
ModelState.IsValid :
true
Depodaki Add yöntemi çağrılır.
Doğru bağımsız değişkenlerle bir RedirectToActionResult döndürülür.
Geçersiz bir model durumu, aşağıdaki ilk testte gösterildiği gibi AddModelError kullanılarak hatalar eklenerek
test edilir:
[Fact]
public async Task IndexPost_ReturnsBadRequestResult_WhenModelStateIsInvalid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.ListAsync())
.ReturnsAsync(GetTestSessions());
var controller = new HomeController(mockRepo.Object);
controller.ModelState.AddModelError("SessionName", "Required");
var newSession = new HomeController.NewSessionModel();

// Act
var result = await controller.Index(newSession);

// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
Assert.IsType<SerializableError>(badRequestResult.Value);
}

[Fact]
public async Task IndexPost_ReturnsARedirectAndAddsSession_WhenModelStateIsValid()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.AddAsync(It.IsAny<BrainstormSession>()))
.Returns(Task.CompletedTask)
.Verifiable();
var controller = new HomeController(mockRepo.Object);
var newSession = new HomeController.NewSessionModel()
{
SessionName = "Test Name"
};

// Act
var result = await controller.Index(newSession);

// Assert
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(result);
Assert.Null(redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
mockRepo.Verify();
}

ModelState geçerli olmadığında, bir get isteği için aynı ViewResult döndürülür. Test geçersiz bir modeli
geçirmeye çalışmıyor. Model bağlama çalışmadığından (bir tümleştirme testi model bağlamayı kullansa da),
geçersiz bir modelin geçirilmesi geçerli bir yaklaşım değildir. Bu durumda model bağlama sınanmamıştır. Bu
birim testleri yalnızca eylem yöntemindeki kodu test eder.
İkinci test ModelState geçerli olduğunda doğrular:
Yeni bir BrainstormSession eklenir (depo aracılığıyla).
Yöntemi, beklenen özelliklerle bir RedirectToActionResult döndürür.

Çağrılmayan hiçbir çağrı normalde yok sayılır, ancak kurulum çağrısının sonunda Verifiable çağrısı testte sahte
doğrulamaya izin verir. Bu, beklenen yöntemin çağrılmaması durumunda test başarısız olan mockRepo.Verify
çağrısıyla gerçekleştirilir.
NOTE
Bu örnekte kullanılan moq kitaplığı, doğrulanabilir olmayan bir şekilde ("gevşek" bir veya saplamalar olarak da adlandırılır)
doğrulanabilir veya "katı" olarak karışık bir şekilde karışık bir şekilde karıştırılamaz. Moq Ile sahte davranışı
özelleştirmehakkında daha fazla bilgi edinin.

Örnek uygulamadaki Sessioncontroller , belirli bir beyin fırtınası oturumuyla ilgili bilgileri görüntüler.
Denetleyici geçersiz id değerlerle ilgilenme mantığını içerir (bu senaryoları kapsayan aşağıdaki örnekte iki
return senaryo vardır ). Son return ifade görünüme yeni bir StormSessionViewModel döndürür
(Controllers/SessionController. cs):

public class SessionController : Controller


{
private readonly IBrainstormSessionRepository _sessionRepository;

public SessionController(IBrainstormSessionRepository sessionRepository)


{
_sessionRepository = sessionRepository;
}

public async Task<IActionResult> Index(int? id)


{
if (!id.HasValue)
{
return RedirectToAction(actionName: nameof(Index),
controllerName: "Home");
}

var session = await _sessionRepository.GetByIdAsync(id.Value);


if (session == null)
{
return Content("Session not found.");
}

var viewModel = new StormSessionViewModel()


{
DateCreated = session.DateCreated,
Name = session.Name,
Id = session.Id
};

return View(viewModel);
}
}

Birim testleri, oturum denetleyicisi Index eyleminde her bir return senaryosu için bir test içerir:
[Fact]
public async Task IndexReturnsARedirectToIndexHomeWhenIdIsNull()
{
// Arrange
var controller = new SessionController(sessionRepository: null);

// Act
var result = await controller.Index(id: null);

// Assert
var redirectToActionResult =
Assert.IsType<RedirectToActionResult>(result);
Assert.Equal("Home", redirectToActionResult.ControllerName);
Assert.Equal("Index", redirectToActionResult.ActionName);
}

[Fact]
public async Task IndexReturnsContentWithSessionNotFoundWhenSessionNotFound()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var contentResult = Assert.IsType<ContentResult>(result);
Assert.Equal("Session not found.", contentResult.Content);
}

[Fact]
public async Task IndexReturnsViewResultWithStormSessionViewModel()
{
// Arrange
int testSessionId = 1;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSessions().FirstOrDefault(
s => s.Id == testSessionId));
var controller = new SessionController(mockRepo.Object);

// Act
var result = await controller.Index(testSessionId);

// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsType<StormSessionViewModel>(
viewResult.ViewData.Model);
Assert.Equal("Test One", model.Name);
Assert.Equal(2, model.DateCreated.Day);
Assert.Equal(testSessionId, model.Id);
}

Uygulama, fikirler denetleyicisine geçiş yaparken api/ideas rotasında bir Web API 'SI olarak işlevselliği
kullanıma sunar:
Bir beyin fırtınası oturumuyla ilişkili fikirler ( IdeaDTO ) listesi, ForSession yöntemi tarafından döndürülür.
Create yöntemi bir oturuma yeni fikirler ekler.
[HttpGet("forsession/{sessionId}")]
public async Task<IActionResult> ForSession(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);
if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return Ok(result);
}

[HttpPost("create")]
public async Task<IActionResult> Create([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);


if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return Ok(session);
}

İş etki alanı varlıklarını doğrudan API çağrıları aracılığıyla döndürmekten kaçının. Etki alanı varlıkları:
Genellikle istemcinin gerektirdiğinden daha fazla veri içerir.
Genel olarak sunulan API ile uygulamanın iç etki alanı modelini gereksiz bir şekilde yapın.
Etki alanı varlıkları ve istemciye döndürülen türler arasında eşleme gerçekleştirilebilir:
Örnek uygulamanın kullandığı şekilde bir LINQ Select el ile. Daha fazla bilgi için bkz. LINQ (dil Ile tümleşik
sorgu).
Otomatik olarak bir kitaplıkla (örneğin, Automaber).
Ardından, örnek uygulama, fikirler denetleyicisinin Create ve ForSession API yöntemlerine yönelik birim
testlerini gösterir.
Örnek uygulama iki ForSession test içerir. İlk test, ForSession geçersiz bir oturum için NotFoundObjectResult
(HTTP bulunamadı) döndürüp döndürmeyeceğini belirler:
[Fact]
public async Task ForSession_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var notFoundObjectResult = Assert.IsType<NotFoundObjectResult>(result);
Assert.Equal(testSessionId, notFoundObjectResult.Value);
}

İkinci ForSession testi, ForSession geçerli bir oturum için oturum fikirleri ( <List<IdeaDTO>> ) listesini döndürüp
döndürmeyeceğini belirler. Denetimler Ayrıca, Name özelliğinin doğru olduğunu onaylamak için ilk fikri de
inceler:

[Fact]
public async Task ForSession_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSession(testSessionId);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(okResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

ModelState geçersiz olduğunda Create yönteminin davranışını test etmek için, örnek uygulama, testin bir
parçası olarak denetleyiciye bir model hatası ekler. Birim testlerinde model doğrulama veya model bağlamayı
sınamayı denemeyin—geçersiz bir ModelState sahip olduğunda eylem yönteminin davranışını test edin:

[Fact]
public async Task Create_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.Create(model: null);

// Assert
Assert.IsType<BadRequestObjectResult>(result);
}
Create ikinci testi, null döndüren depoya bağlıdır, bu nedenle, sahte depo null döndürecek şekilde
yapılandırılır. Bir test veritabanı (bellekte veya başka türlü) oluşturmanız gerekmez ve bu sonucu döndüren bir
sorgu oluşturun. Örnek kodun gösterildiği gibi, test tek bir bildirimde gerçekleştirilebilir:

[Fact]
public async Task Create_ReturnsHttpNotFound_ForInvalidSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync((BrainstormSession)null);
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.Create(new NewIdeaModel());

// Assert
Assert.IsType<NotFoundObjectResult>(result);
}

Create_ReturnsNewlyCreatedIdeaForSession üçüncü Create testi, deponun UpdateAsync yönteminin çağrıldığını


doğrular. Sahte, Verifiable ile çağrılır ve doğrulanabilen yöntemin yürütüldüğünü onaylamak için, moclenmiş
deponun Verify yöntemi çağırılır. UpdateAsync yönteminin bir tümleştirme testiyle gerçekleştirilebilecek
verileri—kaydettiğinizden emin olmak için birim testinin sorumluluğu yoktur.

[Fact]
public async Task Create_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.Create(newIdea);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnSession = Assert.IsType<BrainstormSession>(okResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnSession.Ideas.Count());
Assert.Equal(testName, returnSession.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnSession.Ideas.LastOrDefault().Description);
}
Test ActionResult<T >
ASP.NET Core 2,1 veya sonraki bir sürümde, actionresult<t > (ActionResult<TValue>) ActionResult türetilen
bir tür döndürmenizi veya belirli bir tür döndürmenizi sağlar.
Örnek uygulama, belirli bir oturum id için List<IdeaDTO> döndüren bir yöntemi içerir. Oturum id yoksa,
denetleyici NotFounddöndürür:

[HttpGet("forsessionactionresult/{sessionId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<ActionResult<List<IdeaDTO>>> ForSessionActionResult(int sessionId)
{
var session = await _sessionRepository.GetByIdAsync(sessionId);

if (session == null)
{
return NotFound(sessionId);
}

var result = session.Ideas.Select(idea => new IdeaDTO()


{
Id = idea.Id,
Name = idea.Name,
Description = idea.Description,
DateCreated = idea.DateCreated
}).ToList();

return result;
}

ForSessionActionResult denetleyicisinin iki testi ApiIdeasControllerTests dahil edilir.


İlk test, denetleyicinin varolmayan bir oturum id için varolmayan bir fikir listesi ActionResult döndürdüğünü
onaylar:
ActionResult türü ActionResult<List<IdeaDTO>> .
Result bir NotFoundObjectResult.

[Fact]
public async Task ForSessionActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
var nonExistentSessionId = 999;

// Act
var result = await controller.ForSessionActionResult(nonExistentSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için ikinci test, yöntemin döndürdüğünü doğrular:


List<IdeaDTO> türüne sahip bir ActionResult .
ActionResult<t >. Değer bir List<IdeaDTO> türüdür.
Listedeki ilk öğe, sahte oturumda saklanan fikrle eşleşen geçerli bir fikrdir ( GetTestSession çağırarak elde
edilir).
[Fact]
public async Task ForSessionActionResult_ReturnsIdeasForSession()
{
// Arrange
int testSessionId = 123;
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(GetTestSession());
var controller = new IdeasController(mockRepo.Object);

// Act
var result = await controller.ForSessionActionResult(testSessionId);

// Assert
var actionResult = Assert.IsType<ActionResult<List<IdeaDTO>>>(result);
var returnValue = Assert.IsType<List<IdeaDTO>>(actionResult.Value);
var idea = returnValue.FirstOrDefault();
Assert.Equal("One", idea.Name);
}

Örnek uygulama, belirli bir oturum için yeni Idea oluşturmak üzere bir yöntemi de içerir. Denetleyici şunu
döndürür:
geçersiz bir model için BadRequest.
oturum yoksa NotFound.
oturum yeni fikrle güncelleştirildiği zaman CreatedAtAction.

[HttpPost("createactionresult")]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
public async Task<ActionResult<BrainstormSession>> CreateActionResult([FromBody]NewIdeaModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var session = await _sessionRepository.GetByIdAsync(model.SessionId);

if (session == null)
{
return NotFound(model.SessionId);
}

var idea = new Idea()


{
DateCreated = DateTimeOffset.Now,
Description = model.Description,
Name = model.Name
};
session.AddIdea(idea);

await _sessionRepository.UpdateAsync(session);

return CreatedAtAction(nameof(CreateActionResult), new { id = session.Id }, session);


}

CreateActionResult üç test ApiIdeasControllerTests dahil edilir.


İlk metin, geçersiz bir model için BadRequest döndürüldüğünü onaylar.
[Fact]
public async Task CreateActionResult_ReturnsBadRequest_GivenInvalidModel()
{
// Arrange & Act
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");

// Act
var result = await controller.CreateActionResult(model: null);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<BadRequestObjectResult>(actionResult.Result);
}

İkinci test, oturum yoksa NotFound döndürülüp döndürülmediğini denetler.

[Fact]
public async Task CreateActionResult_ReturnsNotFoundObjectResultForNonexistentSession()
{
// Arrange
var nonExistentSessionId = 999;
string testName = "test name";
string testDescription = "test description";
var mockRepo = new Mock<IBrainstormSessionRepository>();
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = nonExistentSessionId
};

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
Assert.IsType<NotFoundObjectResult>(actionResult.Result);
}

Geçerli bir oturum id için son test şunları onaylar:


Yöntemi, bir BrainstormSession türü ile ActionResult döndürür.
ActionResult<t >. Sonuç bir CreatedAtActionResult. CreatedAtActionResult , bir Location üst bilgisiyle 201
tarafından oluşturulan bir yanıta benzerdir.
ActionResult<t >. Değer bir BrainstormSession türüdür.
Oturumu güncelleştirmek için kullanılan sahte çağrı, UpdateAsync(testSession) çağrıldı. Verifiable yöntemi
çağrısı onaylamalarda mockRepo.Verify() yürütülerek denetlenir.
Oturum için iki Idea nesnesi döndürülür.
Son öğe (sahte çağrının UpdateAsync tarafından eklenen Idea ) testteki oturuma eklenen newIdea eşleşir.
[Fact]
public async Task CreateActionResult_ReturnsNewlyCreatedIdeaForSession()
{
// Arrange
int testSessionId = 123;
string testName = "test name";
string testDescription = "test description";
var testSession = GetTestSession();
var mockRepo = new Mock<IBrainstormSessionRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(testSessionId))
.ReturnsAsync(testSession);
var controller = new IdeasController(mockRepo.Object);

var newIdea = new NewIdeaModel()


{
Description = testDescription,
Name = testName,
SessionId = testSessionId
};
mockRepo.Setup(repo => repo.UpdateAsync(testSession))
.Returns(Task.CompletedTask)
.Verifiable();

// Act
var result = await controller.CreateActionResult(newIdea);

// Assert
var actionResult = Assert.IsType<ActionResult<BrainstormSession>>(result);
var createdAtActionResult = Assert.IsType<CreatedAtActionResult>(actionResult.Result);
var returnValue = Assert.IsType<BrainstormSession>(createdAtActionResult.Value);
mockRepo.Verify();
Assert.Equal(2, returnValue.Ideas.Count());
Assert.Equal(testName, returnValue.Ideas.LastOrDefault().Name);
Assert.Equal(testDescription, returnValue.Ideas.LastOrDefault().Description);
}

Ek kaynaklar
ASP.NET Core tümleştirme testleri
Visual Studio ile birim testleri oluşturma ve çalıştırma
ASP.NET Core – MVC Için Mysınanan. AspNetCore. Mvc-Floent test Kitaplığı , MVC ve Web API
uygulamalarını test etmek için akıcı bir arabirim sağlar. (Microsoft tarafından korunmaz veya desteklenmez. )
ASP.NET Core tümleştirme testleri
31.10.2019 • 62 minutes to read • Edit Online

Luke Latham, Javier Calvarro Nelson, Steve Smithve Jos van der .
Tümleştirme sınamaları, uygulamanın bileşenlerinin veritabanı, dosya sistemi ve ağ gibi destekleyici
altyapısını içeren bir düzeyde doğru şekilde çalışmasını güvence altına alır. ASP.NET Core, test Web ana
bilgisayarı ve bellek içi test sunucusu olan bir birim testi çerçevesini kullanarak tümleştirme testlerini
destekler.
Bu konuda, birim testlerinin temel bir şekilde anlaşıldığı varsayılır. Test kavramları hakkında bilgi sahibi
değilseniz, .NET Core 'Da birim testine ve .NET Standard konusuna ve bağlı içeriğine bakın.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Örnek uygulama bir Razor Pages uygulamasıdır ve Razor Pages temel bir anlama sahip olduğunu varsayar.
Razor Pages hakkında bilginiz yoksa, aşağıdaki konulara bakın:
Razor Pages’e giriş
Razor Sayfaları kullanmaya başlama
Razor Sayfaları birim testleri

NOTE
Maça 'Ları test etmek için, bir tarayıcıyı otomatikleştirebilen Seleniumgibi bir araç öneririz.

Tümleştirme testlerine giriş


Tümleştirme testleri, bir uygulamanın bileşenlerini birim testlerindendaha geniş bir düzeyde değerlendirir.
Birim testleri, ayrı sınıf yöntemleri gibi yalıtılmış yazılım bileşenlerini test etmek için kullanılır. Tümleştirme
testleri iki veya daha fazla uygulama bileşeninin beklenen bir sonuç üretmek için birlikte çalıştığını ve
muhtemelen bir isteği tam olarak işlemek için gereken her bileşeni de dahil olduğunu onaylar.
Bu geniş testler, uygulamanın altyapısını ve tüm çatısını test etmek için kullanılır, genellikle aşağıdaki
bileşenler dahil:
Veritabanı
Dosya sistemi
Ağ gereçleri
İstek-yanıt işlem hattı
Birim testleri, altyapı bileşenlerinin yerine, Fakes veya sahte nesnelerolarak bilinen fabriccomponents
bileşenlerini kullanır.
Birim testlerinin aksine, tümleştirme testleri:
Uygulamanın üretimde kullandığı gerçek bileşenleri kullanın.
Daha fazla kod ve veri işleme gerektir.
Çalıştırmak daha uzun sürer.
Bu nedenle, tümleştirme testlerinin kullanımını en önemli altyapı senaryolarıyla sınırlayın. Bir davranış, birim
testi veya tümleştirme testi kullanılarak test edilebilir ise, birim testini seçin.
TIP
Veritabanları ve dosya sistemleriyle ilgili her olası veri ve dosya erişimi için tümleştirme testleri yazma. Bir
uygulamadaki kaç yerde veritabanlarıyla ve dosya sistemleriyle etkileşime girdiğinize bakılmaksızın, bir dizi Read, Write,
Update ve DELETE tümleştirme testi, genellikle veritabanı ve dosya sistemi bileşenlerinin yeterli şekilde test edilmesine
sahip olur. Bu bileşenlerle etkileşime geçen Yöntem mantığının rutin testleri için birim testleri kullanın. Birim testlerinde,
altyapı kullanımı ve moizler 'in kullanılması daha hızlı test yürütmesiyle sonuçlanır.

NOTE
Tümleştirme testlerinin tartışmalarında, test edilen proje genellikle test altındaki sistemveya kısa IÇIN "sut" olarak
adlandırılır.
Bu konu başlığı altında, sınanan ASP.NET Core uygulamasına başvurmak için "SUT" kullanılır.

ASP.NET Core tümleştirme testleri


ASP.NET Core tümleştirme testleri şunları gerektirir:
Testleri içermesi ve yürütmek için bir test projesi kullanılır. Test projesinin SUT 'a bir başvurusu vardır.
Test projesi SUT için bir test Web Konağı oluşturur ve SUT ile istekleri ve yanıtları işlemek için bir test
sunucusu istemcisi kullanır.
Test Çalıştırıcısı, testleri yürütmek ve test sonuçlarını raporlamak için kullanılır.
Tümleştirme testleri, olağan düzenleme, hareketve onaylama testi adımlarını içeren bir olay dizisini izler:
1. SUT 'un web ana bilgisayarı yapılandırıldı.
2. İstekleri uygulamaya göndermek için bir test sunucusu istemcisi oluşturulur.
3. Testi Düzenle adımı yürütülür: test uygulaması bir istek hazırlar.
4. Davran test adımı yürütülür: istemci, isteği gönderir ve yanıtını alır.
5. Onaylama testi adımı yürütülür: Gerçek yanıt, beklenen bir yanıta bağlı olarak başarılı veya başarısız
olarak onaylanır.
6. İşlem, tüm testler yürütülene kadar devam eder.
7. Test sonuçları raporlanır.
Genellikle, test Web ana bilgisayarı, test çalıştırmaları için uygulamanın normal web ana bilgisayarında farklı
şekilde yapılandırılır. Örneğin, testler için farklı bir veritabanı veya farklı uygulama ayarları kullanılıyor
olabilir.
Test Web Konağı ve bellek içi test sunucusu (TestServer) gibi altyapı bileşenleri, Microsoft. Aspnetcore. Mvc.
Testing paketi tarafından sağlanır veya yönetilir. Bu paketin kullanımı, test oluşturma ve yürütmeyi
kolaylaştırır.
Microsoft.AspNetCore.Mvc.Testing paketi aşağıdaki görevleri gerçekleştirir:
Bağımlılıklar dosyasını ( . Deps) sut 'den test projesinin bin dizinine kopyalar.
, Testler yürütüldüğünde statik dosya ve sayfa/görünümlerin bulunması için içerik kökünü sut 'nin proje
köküne ayarlar.
TestServer ile SUT önyükleyiciyi kolaylaştırmak için Webapplicationfactory sınıfını sağlar.

Birim testi belgeleri bir test projesi ve Test Çalıştırıcısı ayarlamayı ve testlerin ve test sınıflarının nasıl
belirleneceğini gösteren testlerin ve önerilerin nasıl çalıştırılacağını gösteren ayrıntılı yönergelerle birlikte
açıklanır.
NOTE
Bir uygulama için test projesi oluştururken, birim testlerini tümleştirme testlerinden farklı projelere ayırın. Bu, altyapı
testi bileşenlerinin birim testlerine yanlışlıkla dahil olmamasını sağlamaya yardımcı olur. Birim ve tümleştirme testlerinin
ayrımı, hangi test kümesinin çalıştırılmasına da izin verir.

Razor Pages Apps ve MVC uygulamalarının testleri için yapılandırma arasında neredeyse fark yoktur. Tek
fark testlerin adlandırılmasınlardır. Razor Pages uygulamasında, sayfa uç noktalarının testleri genellikle sayfa
modeli sınıfından sonra adlandırılır (örneğin, dizin sayfasına yönelik bileşen tümleştirmesini test etmek için
IndexPageTests ). MVC uygulamasında testler genellikle denetleyici sınıfları tarafından düzenlenir ve test
ettikleri denetleyiciler (örneğin, ana denetleyicinin bileşen tümleştirmesini test etmek için
HomeControllerTests ).

Test uygulaması önkoşulları


Test projesi şunları vermelidir:
Microsoft. AspNetCore. Mvc. Testing paketine başvurun.
Proje dosyasında Web SDK 'sını belirtin ( <Project Sdk="Microsoft.NET.Sdk.Web"> ).
Bu Önkoşullar örnek uygulamadagörülebilir. Testler/RazorPagesProject. Tests/RazorPagesProject. Tests.
csproj dosyasını inceleyin. Örnek uygulama, xUnit test çerçevesini ve anglesharp Parser kitaplığını kullanır,
bu nedenle örnek uygulama de şu şekilde başvurur:
xUnit
xUnit. Çalıştırıcısı. VisualStudio
AngleSharp
Entity Framework Core, testlerde de kullanılır. Uygulama başvuru:
Microsoft. AspNetCore. Diagnostics. EntityFrameworkCore
Microsoft. AspNetCore. Identity. EntityFrameworkCore
Microsoft. EntityFrameworkCore
Microsoft. EntityFrameworkCore. InMemory
Microsoft. EntityFrameworkCore. Tools

SUT ortamı
SUT ortamı ayarlanmamışsa, ortam varsayılan olarak geliştirme olur.

Varsayılan WebApplicationFactory ile temel testler


Webapplicationfactory <TEntryPoint > , tümleştirme testleri Için bir TestServer oluşturmak üzere kullanılır.
TEntryPoint , genellikle Startup sınıfının SUT giriş noktası sınıfıdır.

Test sınıfları sınıfı testlerin içerdiğini göstermek ve sınıftaki testler arasında paylaşılan nesne örnekleri
sağlamak için bir sınıf armatürü arabirimi (ıssfixture) uygular.
Aşağıdaki test sınıfı , SUT 'yi önyüklemek ve bir test yöntemine HttpClient sağlamak için
BasicTests
WebApplicationFactory kullanır Get_EndpointsReturnSuccessAndCorrectContentType . Yöntemi, yanıt durum
kodunun başarılı olup olmadığını denetler (200-299 aralığındaki durum kodları) ve Content-Type üstbilgisi
çeşitli uygulama sayfaları için text/html; charset=utf-8 ' dir.
Createclient , yeniden yönlendirmeleri otomatik olarak izleyen ve tanımlama bilgilerini işleyen bir
HttpClient örneği oluşturur.

public class BasicTests


: IClassFixture<WebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly WebApplicationFactory<RazorPagesProject.Startup> _factory;

public BasicTests(WebApplicationFactory<RazorPagesProject.Startup> factory)


{
_factory = factory;
}

[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/About")]
[InlineData("/Privacy")]
[InlineData("/Contact")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
{
// Arrange
var client = _factory.CreateClient();

// Act
var response = await client.GetAsync(url);

// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}

Varsayılan olarak, GDPR onay ilkesi etkinleştirildiğinde, önemli olmayan tanımlama bilgileri istekler arasında
korunmaz. TempData sağlayıcısı tarafından kullanılanlar gibi, önemli olmayan tanımlama bilgilerini korumak
için, bunları testlerinizde gerekli olarak işaretleyin. Tanımlama bilgisini önemli olarak işaretleme hakkında
yönergeler için bkz. temel tanımlama bilgileri.

WebApplicationFactory 'yi özelleştirme


Web ana bilgisayar yapılandırması, bir veya daha fazla özel fabrika oluşturmak için WebApplicationFactory '
dan devralarak test sınıflarından bağımsız olarak oluşturulabilir:
1. WebApplicationFactory'den devralma ve Configurewebhost'i geçersiz kılma. Iwebhostbuilder , hizmet
koleksiyonunun ConfigureServicesile yapılandırılmasına izin verir:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Remove the app's ApplicationDbContext registration.
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<ApplicationDbContext>));

if (descriptor != null)
{
services.Remove(descriptor);
}

// Add ApplicationDbContext using an in-memory database for testing.


services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
});

// Build the service provider.


var sp = services.BuildServiceProvider();

// Create a scope to obtain a reference to the database


// context (ApplicationDbContext).
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApplicationDbContext>();
var logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

// Ensure the database is created.


db.Database.EnsureCreated();

try
{
// Seed the database with test data.
Utilities.InitializeDbForTests(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding the " +
"database with test messages. Error: {Message}", ex.Message);
}
}
});
}
}

Örnek uygulamadaki veritabanı dengeli dağıtımı InitializeDbForTests yöntemi tarafından


gerçekleştirilir. Yöntemi, tümleştirme testleri örneği: test uygulaması kuruluşu bölümünde
açıklanmaktadır.
SUT 'un veritabanı bağlamı yönteminde kayıtlı. Uygulamanın
Startup.ConfigureServices
Startup.ConfigureServices kodu yürütüldükten sonra , test uygulamasının builder.ConfigureServices
geri çağırması yürütülür. Uygulamanın veritabanından farklı testler için farklı bir veritabanı kullanmak
istiyorsanız, uygulamanın veritabanı bağlamı builder.ConfigureServices ' da değiştirilmelidir.
Örnek uygulama, veritabanı bağlamı için hizmet tanımlayıcısını bulur ve hizmet kaydını kaldırmak için
tanımlayıcıyı kullanır. Ardından, fabrika, testler için bellek içi veritabanı kullanan yeni bir
ApplicationDbContext ekler.
Bellek içi veritabanından farklı bir veritabanına bağlanmak için, bağlamı farklı bir veritabanına
bağlamak üzere UseInMemoryDatabase çağrısını değiştirin. SQL Server test veritabanı kullanmak için:
Proje dosyasındaki Microsoft. EntityFrameworkCore. SqlServer NuGet paketine başvurun.
Veritabanına bir bağlantı dizesiyle UseSqlServer çağrısı yapın.

services.AddDbContext<ApplicationDbContext>((options, context) =>


{
context.UseSqlServer(
Configuration.GetConnectionString("TestingDbConnectionString"));
});

2. Test sınıflarında özel CustomWebApplicationFactory kullanın. Aşağıdaki örnek IndexPageTests sınıfında


fabrikası kullanır:

public class IndexPageTests :


IClassFixture<CustomWebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly HttpClient _client;
private readonly CustomWebApplicationFactory<RazorPagesProject.Startup>
_factory;

public IndexPageTests(
CustomWebApplicationFactory<RazorPagesProject.Startup> factory)
{
_factory = factory;
_client = factory.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
}

Örnek uygulamanın istemcisi, aşağıdaki yeniden yönlendirmelere HttpClient ' i engelleyecek şekilde
yapılandırılmıştır. Daha sonra, sahte kimlik doğrulama bölümünde açıklandığı gibi, bu, testlerin
uygulamanın ilk yanıtının sonucunu denetlemesini sağlar. İlk yanıt, Location üst bilgisiyle bu testlerin
çoğunda bir yeniden yönlendirmelidir.
3. Tipik bir test, isteği ve yanıtı işlemek için HttpClient ve yardımcı yöntemlerini kullanır:

[Fact]
public async Task Post_DeleteAllMessagesHandler_ReturnsRedirectToRoot()
{
// Arrange
var defaultPage = await _client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);

//Act
var response = await _client.SendAsync(
(IHtmlFormElement)content.QuerySelector("form[id='messages']"),
(IHtmlButtonElement)content.QuerySelector("button[id='deleteAllBtn']"));

// Assert
Assert.Equal(HttpStatusCode.OK, defaultPage.StatusCode);
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.Equal("/", response.Headers.Location.OriginalString);
}

SUT 'a yönelik herhangi bir POST isteği, uygulamanın veri koruma antiforgery sistemitarafından otomatik
olarak oluşturulan antiforgery denetimini karşılamalıdır. Bir testin POST isteğini düzenlemek için test
uygulaması şunları kullanmalıdır:
1. Sayfa için bir istek oluşturun.
2. Antiforgery tanımlama bilgisini ayrıştırın ve yanıt doğrulama belirtecini istekten isteyin.
3. POST isteğini, antiforgery tanımlama bilgisiyle ve istek doğrulama belirteciyle birlikte yapın.
Örnek uygulamadaki SendAsync yardımcı uzantı yöntemleri (yardımcılar/Httpclienconversionsions. cs) ve
GetDocumentAsync yardımcı yöntemi (yardımcılar/htmlyardımcıları. cs ), Aşağıdaki Yöntemler:

GetDocumentAsync – HttpResponseMessage 'yi alır ve bir IHtmlDocument döndürür. GetDocumentAsync ,


özgün HttpResponseMessage göre sanal bir Yanıt hazırlayan bir fabrika kullanır. Daha fazla bilgi için bkz.
Anglesharp belgeleri.
HttpClient için SendAsync genişletme yöntemleri bir HttpRequestMessage oluşturun ve istekleri sut 'e
göndermek Için sendadsync (HttpRequestMessage) çağrısı yapın. SendAsync için aşırı yüklemeler HTML
formunu ( IHtmlFormElement ) ve aşağıdakileri kabul eder:
Formun Gönder düğmesi ( IHtmlElement )
Form değerleri koleksiyonu ( IEnumerable<KeyValuePair<string, string>> )
Gönder düğmesi ( IHtmlElement ) ve form değerleri ( IEnumerable<KeyValuePair<string, string>> )

NOTE
Anglesharp , bu konuda ve örnek uygulamada Gösterim amacıyla kullanılan bir üçüncü taraf ayrıştırma kitaplığıdır.
ASP.NET Core uygulamalarının tümleştirme testi için AngleSharp desteklenmez veya gerekli değildir. Diğer
çözümleyiciler, HTML çevikliği paketi (HAP)gibi kullanılabilir. Diğer bir yaklaşım ise, antiforgery sisteminin istek
doğrulama belirtecini ve antiforgery tanımlama bilgisini doğrudan işlemek için kod yazmaktır.

WithWebHostBuilder ile istemciyi özelleştirme


Bir test yönteminde ek yapılandırma gerektiğinde, Withwebhostbuilder , yapılandırmaya göre daha fazla
özelleştirilmiş bir ıwebhostbuilder ile yeni bir WebApplicationFactory oluşturur.
Örnek uygulamanın Post_DeleteMessageHandler_ReturnsRedirectToRoot test yöntemi WithWebHostBuilder
kullanımını gösterir. Bu test, SUT 'da form gönderimini tetikleyerek veritabanında silme işlemini
gerçekleştirir.
IndexPageTests sınıftaki başka bir test, veritabanındaki tüm kayıtları silen ve
Post_DeleteMessageHandler_ReturnsRedirectToRoot yönteminden önce çalışabilen bir işlem
gerçekleştirdiğinden, SUT 'in silinmesine yönelik bir kaydın mevcut olduğundan emin olmak için veritabanı
bu test yönteminde yeniden oluşturulur. SUT içindeki messages formunun ilk Sil düğmesini seçmek, SUT
isteğine göre benzetilir:
[Fact]
public async Task Post_DeleteMessageHandler_ReturnsRedirectToRoot()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var serviceProvider = services.BuildServiceProvider();

using (var scope = serviceProvider.CreateScope())


{
var scopedServices = scope.ServiceProvider;
var db = scopedServices
.GetRequiredService<ApplicationDbContext>();
var logger = scopedServices
.GetRequiredService<ILogger<IndexPageTests>>();

try
{
Utilities.ReinitializeDbForTests(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding " +
"the database with test messages. Error: {Message}",
ex.Message);
}
}
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
var defaultPage = await client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);

//Act
var response = await client.SendAsync(
(IHtmlFormElement)content.QuerySelector("form[id='messages']"),
(IHtmlButtonElement)content.QuerySelector("form[id='messages']")
.QuerySelector("div[class='panel-body']")
.QuerySelector("button"));

// Assert
Assert.Equal(HttpStatusCode.OK, defaultPage.StatusCode);
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.Equal("/", response.Headers.Location.OriginalString);
}

İstemci seçenekleri
Aşağıdaki tabloda HttpClient örnekleri oluşturulurken kullanılabilen varsayılan
Webapplicationfactoryclientoptions gösterilmektedir.

SEÇENEK AÇIKLAMA VARSAYILAN

Allowoto yeniden yönlendirme HttpClient örneklerinin yeniden true


yönlendirme yanıtlarını otomatik
olarak izleyip ayarlamamayacağını alır
veya ayarlar.
SEÇENEK AÇIKLAMA VARSAYILAN

BaseAddress HttpClient örneklerinin temel http://localhost


adresini alır veya ayarlar.

HandleCookies HttpClient örneklerinin tanımlama true


bilgilerini işlemesinin gerekip
gerekmediğini alır veya ayarlar.

Maxautomaticyönlendirmeler HttpClient örneklerin izlemesi 7


gereken en fazla yeniden yönlendirme
yanıtı sayısını alır veya ayarlar.

WebApplicationFactoryClientOptions sınıfını oluşturun ve Createclient yöntemine geçirin (varsayılan değerler


kod örneğinde gösterilir):

// Default client option values are shown


var clientOptions = new WebApplicationFactoryClientOptions();
clientOptions.AllowAutoRedirect = true;
clientOptions.BaseAddress = new Uri("http://localhost");
clientOptions.HandleCookies = true;
clientOptions.MaxAutomaticRedirections = 7;

_client = _factory.CreateClient(clientOptions);

Sahte hizmetler ekleme


Hizmetler, ana bilgisayar tasarımcısında Configuretestservices çağrısıyla bir testte geçersiz kılınabilir. Sahte
hizmetleri eklemek için SUT, Startup.ConfigureServices yöntemine sahip Startup sınıfına sahip
olmalıdır.
Örnek SUT, bir teklif döndüren kapsamlı bir hizmet içerir. Dizin sayfası istendiğinde, teklif Dizin sayfasındaki
gizli bir alana katıştırılır.
Hizmetler/ıquoteservice. cs:

public interface IQuoteService


{
Task<string> GenerateQuote();
}

Hizmetler/QuoteService. cs:

// Quote ©1975 BBC: The Doctor (Tom Baker); Dr. Who: Planet of Evil
// https://www.bbc.co.uk/programmes/p00pyrx6
public class QuoteService : IQuoteService
{
public Task<string> GenerateQuote()
{
return Task.FromResult<string>(
"Come on, Sarah. We've an appointment in London, " +
"and we're already 30,000 years late.");
}
}

Startup.cs:
services.AddScoped<IQuoteService, QuoteService>();

Pages/Index. cshtml. cs:

public class IndexModel : PageModel


{
private readonly ApplicationDbContext _db;
private readonly IQuoteService _quoteService;

public IndexModel(ApplicationDbContext db, IQuoteService quoteService)


{
_db = db;
_quoteService = quoteService;
}

[BindProperty]
public Message Message { get; set; }

public IList<Message> Messages { get; private set; }

[TempData]
public string MessageAnalysisResult { get; set; }

public string Quote { get; private set; }

public async Task OnGetAsync()


{
Messages = await _db.GetMessagesAsync();

Quote = await _quoteService.GenerateQuote();


}

Sayfa/dizin. cs:

<input id="quote" type="hidden" value="@Model.Quote">

Aşağıdaki biçimlendirme, SUT uygulaması çalıştırıldığında oluşturulur:

<input id="quote" type="hidden" value="Come on, Sarah. We&#x27;ve an appointment in


London, and we&#x27;re already 30,000 years late.">

Bir tümleştirme testinde hizmet ve teklif ekleme işlemini test etmek için, test tarafından SUT 'ye bir sahte
hizmet eklenir. Sahte hizmet, uygulamanın QuoteService ' ı, TestQuoteService adlı test uygulaması
tarafından verilen bir hizmetle değiştirir:
IntegrationTests.IndexPageTests.cs:

// Quote ©1975 BBC: The Doctor (Tom Baker); Pyramids of Mars


// https://www.bbc.co.uk/programmes/p00pys55
public class TestQuoteService : IQuoteService
{
public Task<string> GenerateQuote()
{
return Task.FromResult<string>(
"Something's interfering with time, Mr. Scarman, " +
"and time is my business.");
}
}
ConfigureTestServices çağrılır ve kapsamlı hizmet kaydedilir:

[Fact]
public async Task Get_QuoteService_ProvidesQuoteInPage()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddScoped<IQuoteService, TestQuoteService>();
});
})
.CreateClient();

//Act
var defaultPage = await client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);
var quoteElement = content.QuerySelector("#quote");

// Assert
Assert.Equal("Something's interfering with time, Mr. Scarman, " +
"and time is my business.", quoteElement.Attributes["value"].Value);
}

Testin yürütülmesi sırasında üretilen biçimlendirme TestQuoteService tarafından sağlanan tırnak metnini
yansıtır, bu nedenle onaylama işlemi geçirilir:

<input id="quote" type="hidden" value="Something&#x27;s interfering with time,


Mr. Scarman, and time is my business.">

Sahte kimlik doğrulaması


AuthTests sınıftaki testler güvenli bir uç noktanın bulunup bulunmadığını denetler:
Kimliği doğrulanmamış bir kullanıcıyı uygulamanın oturum açma sayfasına yönlendirir.
Kimliği doğrulanmış bir kullanıcı için içerik döndürür.
SUT 'de /SecurePage sayfası, sayfaya bir Authorizefilter uygulamak Için bir authorizepage kuralı kullanır.
Daha fazla bilgi için bkz. Razor Pages yetkilendirme kuralları.

services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizePage("/SecurePage");
});

Get_SecurePageRedirectsAnUnauthenticatedUser testinde, bir Webapplicationfactoryclientoptions , false


olarak allowoto Redirect ayarlanarak yeniden yönlendirmeye izin vermez olarak ayarlanır:
[Fact]
public async Task Get_SecurePageRedirectsAnUnauthenticatedUser()
{
// Arrange
var client = _factory.CreateClient(
new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});

// Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.StartsWith("http://localhost/Identity/Account/Login",
response.Headers.Location.OriginalString);
}

İstemcinin yeniden yönlendirmeyi izlemeye izin vererek aşağıdaki denetimler yapılabilir:


SUT tarafından döndürülen durum kodu, oturum açma sayfasına yeniden yönlendirmeden sonra,
HttpStatusCode. Tamamolacak şekilde, son durum koduna değil beklenen HttpStatusCode. Redirect
sonucuyla denetlenebilir.
Yanıt üst bilgilerindeki Location üst bilgi değeri, Location üstbilgisinin mevcut olmadığı son oturum
açma sayfası yanıtıyla değil http://localhost/Identity/Account/Login ile başlayacağını doğrulamak üzere
denetlenir.
Test uygulaması, kimlik doğrulama ve yetkilendirme işlemlerini test etmek için Configuretestservices içindeki
bir AuthenticationHandler<TOptions> sahte olabilir. En az bir senaryo, bir kimlik doğrulayan Poesult.
Successdöndürür:

public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>


{
public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}

protected override Task<AuthenticateResult> HandleAuthenticateAsync()


{
var claims = new[] { new Claim(ClaimTypes.Name, "Test user") };
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Test");

var result = AuthenticateResult.Success(ticket);

return Task.FromResult(result);
}
}

TestAuthHandler , kimlik doğrulama şeması, ConfigureTestServices için AddAuthentication kaydedildiği


Test olarak ayarlandığında bir kullanıcının kimliğini doğrulamak için çağrılır:
[Fact]
public async Task Get_SecurePageIsReturnedForAnAuthenticatedUser()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
"Test", options => {});
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});

client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Test");

//Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

WebApplicationFactoryClientOptions hakkında daha fazla bilgi için istemci seçenekleri bölümüne bakın.

Ortamı ayarlama
Varsayılan olarak, SUT 'nin ana bilgisayar ve uygulama ortamı geliştirme ortamını kullanacak şekilde
yapılandırılmıştır. SUT ortamını geçersiz kılmak için:
ASPNETCORE_ENVIRONMENT ortam değişkenini ayarlayın (örneğin, Staging , Production veya Testing gibi
başka bir özel değer).
ASPNETCORE ön eki eklenmiş ortam değişkenlerini okumak için test uygulamasındaki CreateHostBuilder
geçersiz kılın.

protected override IHostBuilder CreateHostBuilder() =>


base.CreateHostBuilder()
.ConfigureHostConfiguration(
config => config.AddEnvironmentVariables("ASPNETCORE"));

Test altyapısının uygulama içeriği kök yolunu nasıl öğrendiğini


WebApplicationFactory Oluşturucusu, TEntryPoint bütünleştirilmiş System.Reflection.Assembly.FullName
koduna eşit bir anahtarla tümleştirme testlerini içeren derlemede bir
Webapplicationfactorycontentrootattribute arayarak uygulama içeriği kök yolunu alır. Doğru anahtara sahip
bir özniteliğin bulunamaması durumunda, WebApplicationFactory bir çözüm dosyasını ( . sln) aramaya geri
döner ve TEntryPoint derleme adını çözüm dizinine ekler. Uygulama kök dizini (içerik kök yolu) görünümleri
ve içerik dosyalarını saptamak için kullanılır.

Gölge kopyalamayı devre dışı bırak


Gölge kopyalama, testlerin çıkış dizininden farklı bir dizinde yürütülmesine neden olur. Testlerin düzgün
çalışması için gölge kopyalama devre dışı bırakılmalıdır. Örnek uygulama xUnit kullanır ve doğru
yapılandırma ayarıyla bir xUnit. Runner. JSON dosyası ekleyerek xUnit için gölge kopyalamayı devre dışı
bırakır. Daha fazla bilgi için bkz. JSON Ile xUnit yapılandırma.
Aşağıdaki içeriğe sahip test projesinin köküne xUnit. Runner. JSON dosyasını ekleyin:

{
"shadowCopy": false
}

Nesnelerin elden çıkarılması


IClassFixture uygulamasının testleri yürütüldükten sonra, TestServer ve HttpClient ,
webapplicationfactory'nin xUnit 'i çıkardığı zaman yürütülür. Geliştirici tarafından oluşturulan nesneler için
aktiften çıkarma gerekiyorsa, bunları IClassFixture uygulamasında atın. Daha fazla bilgi için bkz. Dispose
yöntemi uygulama.

Tümleştirme Testleri örneği


Örnek uygulama iki uygulamalardan oluşur:

UYGULAMANIZDA PROJE DIZINI AÇIKLAMA

İleti uygulaması (SUT) src/RazorPagesProject Bir kullanıcının, iletileri eklemesini,


silmesini, silmesini ve analiz etmesini
sağlar.

Test uygulaması testler/RazorPagesProject. testler SUT test tümleştirmesi için kullanılır.

Testler, Visual Studiogıbı bir IDE 'nin yerleşik test özellikleri kullanılarak çalıştırılabilir. Visual Studio Code
veya komut satırı kullanıyorsanız, testler/RazorPagesProject. Tests dizinindeki bir komut isteminde aşağıdaki
komutu yürütün:

dotnet test

İleti uygulaması (SUT ) kuruluşu


SUT, aşağıdaki özelliklere sahip bir Razor Pages ileti sistemidir:
Uygulamanın (Pages/Index. cshtml ve Pages/index. cshtml. cs) dizin sayfası, iletilerin eklenmesi,
silinmesini ve ANALIZINI denetlemek için bir UI ve sayfa modeli yöntemleri sağlar (ileti başına ortalama
sözcük).
Bir ileti, iki özellik içeren Message sınıfı (Data/Message. cs) tarafından tanımlanır: Id (anahtar) ve Text
(ileti). Text özelliği gereklidir ve 200 karakterle sınırlıdır.
İletiler, Entity Framework bellek içi veritabanı†kullanılarak depolanır.
Uygulama, AppDbContext (Data/AppDbContext. cs) veritabanı bağlamı sınıfında bir veri erişim KATMANı
(dal) içerir.
Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır.
Uygulama yalnızca kimliği doğrulanmış bir kullanıcı tarafından erişilebilen bir /SecurePage içerir.
†InMemory Ile testolan EF konusu, MSTest ile testler için bellek içi bir veritabanının nasıl kullanılacağını
açıklar. Bu konu xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test
uygulamaları benzerdir ancak aynı değildir.
Uygulama, depo desenini kullanmıyor ve Iş birimi (UoW ) düzenininetkin bir örneği olmamasına karşın,
Razor Pages bu geliştirme düzenlerini destekler. Daha fazla bilgi için bkz. altyapı Kalıcılık katmanını
tasarlama ve Test denetleyicisi mantığı (örnek, depo modelini uygular).
Test uygulaması kuruluşu
Test uygulaması, testler/RazorPagesProject. Tests dizini içindeki bir konsol uygulamasıdır.

UYGULAMA DIZININI TEST ET AÇIKLAMA

AuthTests İçin test yöntemleri içerir:


Güvenli bir sayfaya, kimliği doğrulanmamış bir
kullanıcıyla erişme.
Bir sahte AuthenticationHandler<TOptions>kimliği
doğrulanmış bir kullanıcı tarafından güvenli bir
sayfaya erişme.
GitHub kullanıcı profilini alma ve profilin Kullanıcı
oturum açma bilgilerini denetleme.

BasicTests Yönlendirme ve içerik türü için bir test yöntemi içerir.

Tümleştirme Testleri Özel WebApplicationFactory sınıfı kullanarak dizin


sayfasına yönelik tümleştirme testlerini içerir.

Yardımcılar/yardımcı programlar Utilities.cs , veritabanını test verileriyle tohum için


kullanılan InitializeDbForTests metodunu içerir.
HtmlHelpers.cs , test yöntemleri tarafından
kullanılmak üzere AngleSharp IHtmlDocument
döndüren bir yöntem sağlar.
HttpClientExtensions.cs , istekleri sut 'a göndermek
için SendAsync için aşırı yüklemeler sağlar.

Test çerçevesi xUnit' dir. Tümleştirme testleri, TestServeriçeren Microsoft. Aspnetcore. testhostkullanılarak
yürütülür. Test ana bilgisayarı ve test sunucusunu yapılandırmak için Microsoft. AspNetCore. Mvc. Testing
paketi kullanıldığından, TestHost ve TestServer paketleri test uygulamasının proje dosyasında ya da
testteki geliştirici yapılandırmasında doğrudan paket başvuruları gerektirmez uygulamanızda.
Test için veritabanının temelini sağlama
Tümleştirme testleri genellikle veritabanında test yürütmeden önce küçük bir veri kümesi gerektirir. Örneğin,
veritabanı kaydı silme için bir silme testi çağrılarında, silme isteğinin başarılı olması için veritabanının en az
bir kaydı olmalıdır.
Örnek uygulama, Utilities.cs içinde testlerin, yürütme sırasında kullanabileceği üç iletiyle birlikte veritabanını
kullanır:
public static void InitializeDbForTests(ApplicationDbContext db)
{
db.Messages.AddRange(GetSeedingMessages());
db.SaveChanges();
}

public static void ReinitializeDbForTests(ApplicationDbContext db)


{
db.Messages.RemoveRange(db.Messages);
InitializeDbForTests(db);
}

public static List<Message> GetSeedingMessages()


{
return new List<Message>()
{
new Message(){ Text = "TEST RECORD: You're standing on my scarf." },
new Message(){ Text = "TEST RECORD: Would you like a jelly baby?" },
new Message(){ Text = "TEST RECORD: To the rational mind, " +
"nothing is inexplicable; only unexplained." }
};
}

SUT 'un veritabanı bağlamı Startup.ConfigureServices yönteminde kayıtlı. Uygulamanın


Startup.ConfigureServices kodu yürütüldükten sonra , test uygulamasının builder.ConfigureServices geri
çağırması yürütülür. Testler için farklı bir veritabanı kullanmak istiyorsanız, uygulamanın veritabanı bağlamı
builder.ConfigureServices ' da değiştirilmelidir. Daha fazla bilgi için, WebApplicationFactory 'Yi özelleştirme
bölümüne bakın.
Tümleştirme sınamaları, uygulamanın bileşenlerinin veritabanı, dosya sistemi ve ağ gibi destekleyici
altyapısını içeren bir düzeyde doğru şekilde çalışmasını güvence altına alır. ASP.NET Core, test Web ana
bilgisayarı ve bellek içi test sunucusu olan bir birim testi çerçevesini kullanarak tümleştirme testlerini
destekler.
Bu konuda, birim testlerinin temel bir şekilde anlaşıldığı varsayılır. Test kavramları hakkında bilgi sahibi
değilseniz, .NET Core 'Da birim testine ve .NET Standard konusuna ve bağlı içeriğine bakın.
Örnek kodu görüntüleme veya indirme (nasıl indirileceği)
Örnek uygulama bir Razor Pages uygulamasıdır ve Razor Pages temel bir anlama sahip olduğunu varsayar.
Razor Pages hakkında bilginiz yoksa, aşağıdaki konulara bakın:
Razor Pages’e giriş
Razor Sayfaları kullanmaya başlama
Razor Sayfaları birim testleri

NOTE
Maça 'Ları test etmek için, bir tarayıcıyı otomatikleştirebilen Seleniumgibi bir araç öneririz.

Tümleştirme testlerine giriş


Tümleştirme testleri, bir uygulamanın bileşenlerini birim testlerindendaha geniş bir düzeyde değerlendirir.
Birim testleri, ayrı sınıf yöntemleri gibi yalıtılmış yazılım bileşenlerini test etmek için kullanılır. Tümleştirme
testleri iki veya daha fazla uygulama bileşeninin beklenen bir sonuç üretmek için birlikte çalıştığını ve
muhtemelen bir isteği tam olarak işlemek için gereken her bileşeni de dahil olduğunu onaylar.
Bu geniş testler, uygulamanın altyapısını ve tüm çatısını test etmek için kullanılır, genellikle aşağıdaki
bileşenler dahil:
Veritabanı
Dosya sistemi
Ağ gereçleri
İstek-yanıt işlem hattı
Birim testleri, altyapı bileşenlerinin yerine, Fakes veya sahte nesnelerolarak bilinen fabriccomponents
bileşenlerini kullanır.
Birim testlerinin aksine, tümleştirme testleri:
Uygulamanın üretimde kullandığı gerçek bileşenleri kullanın.
Daha fazla kod ve veri işleme gerektir.
Çalıştırmak daha uzun sürer.
Bu nedenle, tümleştirme testlerinin kullanımını en önemli altyapı senaryolarıyla sınırlayın. Bir davranış, birim
testi veya tümleştirme testi kullanılarak test edilebilir ise, birim testini seçin.

TIP
Veritabanları ve dosya sistemleriyle ilgili her olası veri ve dosya erişimi için tümleştirme testleri yazma. Bir
uygulamadaki kaç yerde veritabanlarıyla ve dosya sistemleriyle etkileşime girdiğinize bakılmaksızın, bir dizi Read, Write,
Update ve DELETE tümleştirme testi, genellikle veritabanı ve dosya sistemi bileşenlerinin yeterli şekilde test edilmesine
sahip olur. Bu bileşenlerle etkileşime geçen Yöntem mantığının rutin testleri için birim testleri kullanın. Birim testlerinde,
altyapı kullanımı ve moizler 'in kullanılması daha hızlı test yürütmesiyle sonuçlanır.

NOTE
Tümleştirme testlerinin tartışmalarında, test edilen proje genellikle test altındaki sistemveya kısa IÇIN "sut" olarak
adlandırılır.
Bu konu başlığı altında, sınanan ASP.NET Core uygulamasına başvurmak için "SUT" kullanılır.

ASP.NET Core tümleştirme testleri


ASP.NET Core tümleştirme testleri şunları gerektirir:
Testleri içermesi ve yürütmek için bir test projesi kullanılır. Test projesinin SUT 'a bir başvurusu vardır.
Test projesi SUT için bir test Web Konağı oluşturur ve SUT ile istekleri ve yanıtları işlemek için bir test
sunucusu istemcisi kullanır.
Test Çalıştırıcısı, testleri yürütmek ve test sonuçlarını raporlamak için kullanılır.
Tümleştirme testleri, olağan düzenleme, hareketve onaylama testi adımlarını içeren bir olay dizisini izler:
1. SUT 'un web ana bilgisayarı yapılandırıldı.
2. İstekleri uygulamaya göndermek için bir test sunucusu istemcisi oluşturulur.
3. Testi Düzenle adımı yürütülür: test uygulaması bir istek hazırlar.
4. Davran test adımı yürütülür: istemci, isteği gönderir ve yanıtını alır.
5. Onaylama testi adımı yürütülür: Gerçek yanıt, beklenen bir yanıta bağlı olarak başarılı veya başarısız
olarak onaylanır.
6. İşlem, tüm testler yürütülene kadar devam eder.
7. Test sonuçları raporlanır.
Genellikle, test Web ana bilgisayarı, test çalıştırmaları için uygulamanın normal web ana bilgisayarında farklı
şekilde yapılandırılır. Örneğin, testler için farklı bir veritabanı veya farklı uygulama ayarları kullanılıyor
olabilir.
Test Web Konağı ve bellek içi test sunucusu (TestServer) gibi altyapı bileşenleri, Microsoft. Aspnetcore. Mvc.
Testing paketi tarafından sağlanır veya yönetilir. Bu paketin kullanımı, test oluşturma ve yürütmeyi
kolaylaştırır.
Microsoft.AspNetCore.Mvc.Testing paketi aşağıdaki görevleri gerçekleştirir:
Bağımlılıklar dosyasını ( . Deps) sut 'den test projesinin bin dizinine kopyalar.
, Testler yürütüldüğünde statik dosya ve sayfa/görünümlerin bulunması için içerik kökünü sut 'nin proje
köküne ayarlar.
TestServer ile SUT önyükleyiciyi kolaylaştırmak için Webapplicationfactory sınıfını sağlar.

Birim testi belgeleri bir test projesi ve Test Çalıştırıcısı ayarlamayı ve testlerin ve test sınıflarının nasıl
belirleneceğini gösteren testlerin ve önerilerin nasıl çalıştırılacağını gösteren ayrıntılı yönergelerle birlikte
açıklanır.

NOTE
Bir uygulama için test projesi oluştururken, birim testlerini tümleştirme testlerinden farklı projelere ayırın. Bu, altyapı
testi bileşenlerinin birim testlerine yanlışlıkla dahil olmamasını sağlamaya yardımcı olur. Birim ve tümleştirme testlerinin
ayrımı, hangi test kümesinin çalıştırılmasına da izin verir.

Razor Pages Apps ve MVC uygulamalarının testleri için yapılandırma arasında neredeyse fark yoktur. Tek
fark testlerin adlandırılmasınlardır. Razor Pages uygulamasında, sayfa uç noktalarının testleri genellikle sayfa
modeli sınıfından sonra adlandırılır (örneğin, dizin sayfasına yönelik bileşen tümleştirmesini test etmek için
IndexPageTests ). MVC uygulamasında testler genellikle denetleyici sınıfları tarafından düzenlenir ve test
ettikleri denetleyiciler (örneğin, ana denetleyicinin bileşen tümleştirmesini test etmek için
HomeControllerTests ).

Test uygulaması önkoşulları


Test projesi şunları vermelidir:
Aşağıdaki paketlere başvurun:
Microsoft. AspNetCore. app
Microsoft. AspNetCore. Mvc. test
Proje dosyasında Web SDK 'sını belirtin ( <Project Sdk="Microsoft.NET.Sdk.Web"> ). Microsoft.
AspNetCore. app metapackage'e başvururken Web SDK 'sı gereklidir.
Bu Önkoşullar örnek uygulamadagörülebilir. Testler/RazorPagesProject. Tests/RazorPagesProject. Tests.
csproj dosyasını inceleyin. Örnek uygulama, xUnit test çerçevesini ve anglesharp Parser kitaplığını kullanır,
bu nedenle örnek uygulama de şu şekilde başvurur:
xUnit
xUnit. Çalıştırıcısı. VisualStudio
AngleSharp

SUT ortamı
SUT ortamı ayarlanmamışsa, ortam varsayılan olarak geliştirme olur.
Varsayılan WebApplicationFactory ile temel testler
Webapplicationfactory <TEntryPoint > , tümleştirme testleri Için bir TestServer oluşturmak üzere kullanılır.
TEntryPoint , genellikle Startup sınıfının SUT giriş noktası sınıfıdır.

Test sınıfları sınıfı testlerin içerdiğini göstermek ve sınıftaki testler arasında paylaşılan nesne örnekleri
sağlamak için bir sınıf armatürü arabirimi (ıssfixture) uygular.
Aşağıdaki test sınıfı , SUT 'yi önyüklemek ve bir test yöntemine HttpClient sağlamak için
BasicTests
WebApplicationFactory kullanır Get_EndpointsReturnSuccessAndCorrectContentType . Yöntemi, yanıt durum
kodunun başarılı olup olmadığını denetler (200-299 aralığındaki durum kodları) ve Content-Type üstbilgisi
çeşitli uygulama sayfaları için text/html; charset=utf-8 ' dir.
Createclient , yeniden yönlendirmeleri otomatik olarak izleyen ve tanımlama bilgilerini işleyen bir
HttpClient örneği oluşturur.

public class BasicTests


: IClassFixture<WebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly WebApplicationFactory<RazorPagesProject.Startup> _factory;

public BasicTests(WebApplicationFactory<RazorPagesProject.Startup> factory)


{
_factory = factory;
}

[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/About")]
[InlineData("/Privacy")]
[InlineData("/Contact")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
{
// Arrange
var client = _factory.CreateClient();

// Act
var response = await client.GetAsync(url);

// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}

Varsayılan olarak, GDPR onay ilkesi etkinleştirildiğinde, önemli olmayan tanımlama bilgileri istekler arasında
korunmaz. TempData sağlayıcısı tarafından kullanılanlar gibi, önemli olmayan tanımlama bilgilerini korumak
için, bunları testlerinizde gerekli olarak işaretleyin. Tanımlama bilgisini önemli olarak işaretleme hakkında
yönergeler için bkz. temel tanımlama bilgileri.

WebApplicationFactory 'yi özelleştirme


Web ana bilgisayar yapılandırması, bir veya daha fazla özel fabrika oluşturmak için WebApplicationFactory '
dan devralarak test sınıflarından bağımsız olarak oluşturulabilir:
1. WebApplicationFactory'den devralma ve Configurewebhost'i geçersiz kılma. Iwebhostbuilder , hizmet
koleksiyonunun ConfigureServicesile yapılandırılmasına izin verir:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Create a new service provider.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();

// Add a database context (ApplicationDbContext) using an in-memory


// database for testing.
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
options.UseInternalServiceProvider(serviceProvider);
});

// Build the service provider.


var sp = services.BuildServiceProvider();

// Create a scope to obtain a reference to the database


// context (ApplicationDbContext).
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApplicationDbContext>();
var logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

// Ensure the database is created.


db.Database.EnsureCreated();

try
{
// Seed the database with test data.
Utilities.InitializeDbForTests(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding the database. Error:
{Message}", ex.Message);
}
}
});
}
}

Örnek uygulamadaki veritabanı dengeli dağıtımı InitializeDbForTests yöntemi tarafından


gerçekleştirilir. Yöntemi, tümleştirme testleri örneği: test uygulaması kuruluşu bölümünde
açıklanmaktadır.
2. Test sınıflarında özel CustomWebApplicationFactory kullanın. Aşağıdaki örnek IndexPageTests sınıfında
fabrikası kullanır:
public class IndexPageTests :
IClassFixture<CustomWebApplicationFactory<RazorPagesProject.Startup>>
{
private readonly HttpClient _client;
private readonly CustomWebApplicationFactory<RazorPagesProject.Startup>
_factory;

public IndexPageTests(
CustomWebApplicationFactory<RazorPagesProject.Startup> factory)
{
_factory = factory;
_client = factory.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
}

Örnek uygulamanın istemcisi, aşağıdaki yeniden yönlendirmelere HttpClient ' i engelleyecek şekilde
yapılandırılmıştır. Daha sonra, sahte kimlik doğrulama bölümünde açıklandığı gibi, bu, testlerin
uygulamanın ilk yanıtının sonucunu denetlemesini sağlar. İlk yanıt, Location üst bilgisiyle bu testlerin
çoğunda bir yeniden yönlendirmelidir.
3. Tipik bir test, isteği ve yanıtı işlemek için HttpClient ve yardımcı yöntemlerini kullanır:

[Fact]
public async Task Post_DeleteAllMessagesHandler_ReturnsRedirectToRoot()
{
// Arrange
var defaultPage = await _client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);

//Act
var response = await _client.SendAsync(
(IHtmlFormElement)content.QuerySelector("form[id='messages']"),
(IHtmlButtonElement)content.QuerySelector("button[id='deleteAllBtn']"));

// Assert
Assert.Equal(HttpStatusCode.OK, defaultPage.StatusCode);
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.Equal("/", response.Headers.Location.OriginalString);
}

SUT 'a yönelik herhangi bir POST isteği, uygulamanın veri koruma antiforgery sistemitarafından otomatik
olarak oluşturulan antiforgery denetimini karşılamalıdır. Bir testin POST isteğini düzenlemek için test
uygulaması şunları kullanmalıdır:
1. Sayfa için bir istek oluşturun.
2. Antiforgery tanımlama bilgisini ayrıştırın ve yanıt doğrulama belirtecini istekten isteyin.
3. POST isteğini, antiforgery tanımlama bilgisiyle ve istek doğrulama belirteciyle birlikte yapın.
Örnek uygulamadaki SendAsync yardımcı uzantı yöntemleri (yardımcılar/Httpclienconversionsions. cs) ve
GetDocumentAsync yardımcı yöntemi (yardımcılar/htmlyardımcıları. cs ), Aşağıdaki Yöntemler:

GetDocumentAsync – HttpResponseMessage 'yi alır ve bir IHtmlDocument döndürür. GetDocumentAsync ,


özgün HttpResponseMessage göre sanal bir Yanıt hazırlayan bir fabrika kullanır. Daha fazla bilgi için bkz.
Anglesharp belgeleri.
HttpClient için SendAsync genişletme yöntemleri bir HttpRequestMessage oluşturun ve istekleri sut 'e
göndermek Için sendadsync (HttpRequestMessage) çağrısı yapın. SendAsync için aşırı yüklemeler HTML
formunu ( IHtmlFormElement ) ve aşağıdakileri kabul eder:
Formun Gönder düğmesi ( IHtmlElement )
Form değerleri koleksiyonu ( IEnumerable<KeyValuePair<string, string>> )
Gönder düğmesi ( IHtmlElement ) ve form değerleri ( IEnumerable<KeyValuePair<string, string>> )

NOTE
Anglesharp , bu konuda ve örnek uygulamada Gösterim amacıyla kullanılan bir üçüncü taraf ayrıştırma kitaplığıdır.
ASP.NET Core uygulamalarının tümleştirme testi için AngleSharp desteklenmez veya gerekli değildir. Diğer
çözümleyiciler, HTML çevikliği paketi (HAP)gibi kullanılabilir. Diğer bir yaklaşım ise, antiforgery sisteminin istek
doğrulama belirtecini ve antiforgery tanımlama bilgisini doğrudan işlemek için kod yazmaktır.

WithWebHostBuilder ile istemciyi özelleştirme


Bir test yönteminde ek yapılandırma gerektiğinde, Withwebhostbuilder , yapılandırmaya göre daha fazla
özelleştirilmiş bir ıwebhostbuilder ile yeni bir WebApplicationFactory oluşturur.
Örnek uygulamanın Post_DeleteMessageHandler_ReturnsRedirectToRoot test yöntemi WithWebHostBuilder
kullanımını gösterir. Bu test, SUT 'da form gönderimini tetikleyerek veritabanında silme işlemini
gerçekleştirir.
IndexPageTests sınıftaki başka bir test, veritabanındaki tüm kayıtları silen ve
Post_DeleteMessageHandler_ReturnsRedirectToRoot yönteminden önce çalışabilen bir işlem
gerçekleştirdiğinden, SUT 'in silinmesine yönelik bir kaydın mevcut olduğundan emin olmak için veritabanı
bu test yönteminde yeniden oluşturulur. SUT içindeki messages formunun ilk Sil düğmesini seçmek, SUT
isteğine göre benzetilir:
[Fact]
public async Task Post_DeleteMessageHandler_ReturnsRedirectToRoot()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var serviceProvider = services.BuildServiceProvider();

using (var scope = serviceProvider.CreateScope())


{
var scopedServices = scope.ServiceProvider;
var db = scopedServices
.GetRequiredService<ApplicationDbContext>();
var logger = scopedServices
.GetRequiredService<ILogger<IndexPageTests>>();

try
{
Utilities.ReinitializeDbForTests(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding " +
"the database with test messages. Error: {Message}" +
ex.Message);
}
}
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
var defaultPage = await client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);

//Act
var response = await client.SendAsync(
(IHtmlFormElement)content.QuerySelector("form[id='messages']"),
(IHtmlButtonElement)content.QuerySelector("form[id='messages']")
.QuerySelector("div[class='panel-body']")
.QuerySelector("button"));

// Assert
Assert.Equal(HttpStatusCode.OK, defaultPage.StatusCode);
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.Equal("/", response.Headers.Location.OriginalString);
}

İstemci seçenekleri
Aşağıdaki tabloda HttpClient örnekleri oluşturulurken kullanılabilen varsayılan
Webapplicationfactoryclientoptions gösterilmektedir.

SEÇENEK AÇIKLAMA VARSAYILAN

Allowoto yeniden yönlendirme HttpClient örneklerinin yeniden true


yönlendirme yanıtlarını otomatik
olarak izleyip ayarlamamayacağını alır
veya ayarlar.
SEÇENEK AÇIKLAMA VARSAYILAN

BaseAddress HttpClient örneklerinin temel http://localhost


adresini alır veya ayarlar.

HandleCookies HttpClient örneklerinin tanımlama true


bilgilerini işlemesinin gerekip
gerekmediğini alır veya ayarlar.

Maxautomaticyönlendirmeler HttpClient örneklerin izlemesi 7


gereken en fazla yeniden yönlendirme
yanıtı sayısını alır veya ayarlar.

WebApplicationFactoryClientOptions sınıfını oluşturun ve Createclient yöntemine geçirin (varsayılan değerler


kod örneğinde gösterilir):

// Default client option values are shown


var clientOptions = new WebApplicationFactoryClientOptions();
clientOptions.AllowAutoRedirect = true;
clientOptions.BaseAddress = new Uri("http://localhost");
clientOptions.HandleCookies = true;
clientOptions.MaxAutomaticRedirections = 7;

_client = _factory.CreateClient(clientOptions);

Sahte hizmetler ekleme


Hizmetler, ana bilgisayar tasarımcısında Configuretestservices çağrısıyla bir testte geçersiz kılınabilir. Sahte
hizmetleri eklemek için SUT, Startup.ConfigureServices yöntemine sahip Startup sınıfına sahip
olmalıdır.
Örnek SUT, bir teklif döndüren kapsamlı bir hizmet içerir. Dizin sayfası istendiğinde, teklif Dizin sayfasındaki
gizli bir alana katıştırılır.
Hizmetler/ıquoteservice. cs:

public interface IQuoteService


{
Task<string> GenerateQuote();
}

Hizmetler/QuoteService. cs:

// Quote ©1975 BBC: The Doctor (Tom Baker); Dr. Who: Planet of Evil
// https://www.bbc.co.uk/programmes/p00pyrx6
public class QuoteService : IQuoteService
{
public Task<string> GenerateQuote()
{
return Task.FromResult<string>(
"Come on, Sarah. We've an appointment in London, " +
"and we're already 30,000 years late.");
}
}

Startup.cs:
services.AddScoped<IQuoteService, QuoteService>();

Pages/Index. cshtml. cs:

public class IndexModel : PageModel


{
private readonly ApplicationDbContext _db;
private readonly IQuoteService _quoteService;

public IndexModel(ApplicationDbContext db, IQuoteService quoteService)


{
_db = db;
_quoteService = quoteService;
}

[BindProperty]
public Message Message { get; set; }

public IList<Message> Messages { get; private set; }

[TempData]
public string MessageAnalysisResult { get; set; }

public string Quote { get; private set; }

public async Task OnGetAsync()


{
Messages = await _db.GetMessagesAsync();

Quote = await _quoteService.GenerateQuote();


}

Sayfa/dizin. cs:

<input id="quote" type="hidden" value="@Model.Quote">

Aşağıdaki biçimlendirme, SUT uygulaması çalıştırıldığında oluşturulur:

<input id="quote" type="hidden" value="Come on, Sarah. We&#x27;ve an appointment in


London, and we&#x27;re already 30,000 years late.">

Bir tümleştirme testinde hizmet ve teklif ekleme işlemini test etmek için, test tarafından SUT 'ye bir sahte
hizmet eklenir. Sahte hizmet, uygulamanın QuoteService ' ı, TestQuoteService adlı test uygulaması
tarafından verilen bir hizmetle değiştirir:
IntegrationTests.IndexPageTests.cs:

// Quote ©1975 BBC: The Doctor (Tom Baker); Pyramids of Mars


// https://www.bbc.co.uk/programmes/p00pys55
public class TestQuoteService : IQuoteService
{
public Task<string> GenerateQuote()
{
return Task.FromResult<string>(
"Something's interfering with time, Mr. Scarman, " +
"and time is my business.");
}
}
ConfigureTestServices çağrılır ve kapsamlı hizmet kaydedilir:

[Fact]
public async Task Get_QuoteService_ProvidesQuoteInPage()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddScoped<IQuoteService, TestQuoteService>();
});
})
.CreateClient();

//Act
var defaultPage = await client.GetAsync("/");
var content = await HtmlHelpers.GetDocumentAsync(defaultPage);
var quoteElement = content.QuerySelector("#quote");

// Assert
Assert.Equal("Something's interfering with time, Mr. Scarman, " +
"and time is my business.", quoteElement.Attributes["value"].Value);
}

Testin yürütülmesi sırasında üretilen biçimlendirme TestQuoteService tarafından sağlanan tırnak metnini
yansıtır, bu nedenle onaylama işlemi geçirilir:

<input id="quote" type="hidden" value="Something&#x27;s interfering with time,


Mr. Scarman, and time is my business.">

Sahte kimlik doğrulaması


AuthTests sınıftaki testler güvenli bir uç noktanın bulunup bulunmadığını denetler:
Kimliği doğrulanmamış bir kullanıcıyı uygulamanın oturum açma sayfasına yönlendirir.
Kimliği doğrulanmış bir kullanıcı için içerik döndürür.
SUT 'de /SecurePage sayfası, sayfaya bir Authorizefilter uygulamak Için bir authorizepage kuralı kullanır.
Daha fazla bilgi için bkz. Razor Pages yetkilendirme kuralları.

services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizePage("/SecurePage");
});

Get_SecurePageRedirectsAnUnauthenticatedUser testinde, bir Webapplicationfactoryclientoptions , false


olarak allowoto Redirect ayarlanarak yeniden yönlendirmeye izin vermez olarak ayarlanır:
[Fact]
public async Task Get_SecurePageRedirectsAnUnauthenticatedUser()
{
// Arrange
var client = _factory.CreateClient(
new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});

// Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Assert.StartsWith("http://localhost/Identity/Account/Login",
response.Headers.Location.OriginalString);
}

İstemcinin yeniden yönlendirmeyi izlemeye izin vererek aşağıdaki denetimler yapılabilir:


SUT tarafından döndürülen durum kodu, oturum açma sayfasına yeniden yönlendirmeden sonra,
HttpStatusCode. Tamamolacak şekilde, son durum koduna değil beklenen HttpStatusCode. Redirect
sonucuyla denetlenebilir.
Yanıt üst bilgilerindeki Location üst bilgi değeri, Location üstbilgisinin mevcut olmadığı son oturum
açma sayfası yanıtıyla değil http://localhost/Identity/Account/Login ile başlayacağını doğrulamak üzere
denetlenir.
Test uygulaması, kimlik doğrulama ve yetkilendirme işlemlerini test etmek için Configuretestservices içindeki
bir AuthenticationHandler<TOptions> sahte olabilir. En az bir senaryo, bir kimlik doğrulayan Poesult.
Successdöndürür:

public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>


{
public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}

protected override Task<AuthenticateResult> HandleAuthenticateAsync()


{
var claims = new[] { new Claim(ClaimTypes.Name, "Test user") };
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Test");

var result = AuthenticateResult.Success(ticket);

return Task.FromResult(result);
}
}

TestAuthHandler , kimlik doğrulama şeması, ConfigureTestServices için AddAuthentication kaydedildiği


Test olarak ayarlandığında bir kullanıcının kimliğini doğrulamak için çağrılır:
[Fact]
public async Task Get_SecurePageIsReturnedForAnAuthenticatedUser()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
"Test", options => {});
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});

client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Test");

//Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

WebApplicationFactoryClientOptions hakkında daha fazla bilgi için istemci seçenekleri bölümüne bakın.

Ortamı ayarlama
Varsayılan olarak, SUT 'nin ana bilgisayar ve uygulama ortamı geliştirme ortamını kullanacak şekilde
yapılandırılmıştır. SUT ortamını geçersiz kılmak için:
ASPNETCORE_ENVIRONMENT ortam değişkenini ayarlayın (örneğin, Staging , Production veya Testing gibi
başka bir özel değer).
ASPNETCORE ön eki eklenmiş ortam değişkenlerini okumak için test uygulamasındaki CreateHostBuilder
geçersiz kılın.

protected override IHostBuilder CreateHostBuilder() =>


base.CreateHostBuilder()
.ConfigureHostConfiguration(
config => config.AddEnvironmentVariables("ASPNETCORE"));

Test altyapısının uygulama içeriği kök yolunu nasıl öğrendiğini


WebApplicationFactory Oluşturucusu, TEntryPoint bütünleştirilmiş System.Reflection.Assembly.FullName
koduna eşit bir anahtarla tümleştirme testlerini içeren derlemede bir
Webapplicationfactorycontentrootattribute arayarak uygulama içeriği kök yolunu alır. Doğru anahtara sahip
bir özniteliğin bulunamaması durumunda, WebApplicationFactory bir çözüm dosyasını ( . sln) aramaya geri
döner ve TEntryPoint derleme adını çözüm dizinine ekler. Uygulama kök dizini (içerik kök yolu) görünümleri
ve içerik dosyalarını saptamak için kullanılır.

Gölge kopyalamayı devre dışı bırak


Gölge kopyalama, testlerin çıkış dizininden farklı bir dizinde yürütülmesine neden olur. Testlerin düzgün
çalışması için gölge kopyalama devre dışı bırakılmalıdır. Örnek uygulama xUnit kullanır ve doğru
yapılandırma ayarıyla bir xUnit. Runner. JSON dosyası ekleyerek xUnit için gölge kopyalamayı devre dışı
bırakır. Daha fazla bilgi için bkz. JSON Ile xUnit yapılandırma.
Aşağıdaki içeriğe sahip test projesinin köküne xUnit. Runner. JSON dosyasını ekleyin:

{
"shadowCopy": false
}

Visual Studio kullanıyorsanız, dosyanın Çıkış Dizinine Kopyala özelliğini her zaman Kopyalaolarak
ayarlayın. Visual Studio kullanmıyorsanız, test uygulamasının proje dosyasına bir Content hedefi ekleyin:

<ItemGroup>
<Content Update="xunit.runner.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

Nesnelerin elden çıkarılması


IClassFixture uygulamasının testleri yürütüldükten sonra, TestServer ve HttpClient ,
webapplicationfactory'nin xUnit 'i çıkardığı zaman yürütülür. Geliştirici tarafından oluşturulan nesneler için
aktiften çıkarma gerekiyorsa, bunları IClassFixture uygulamasında atın. Daha fazla bilgi için bkz. Dispose
yöntemi uygulama.

Tümleştirme Testleri örneği


Örnek uygulama iki uygulamalardan oluşur:

UYGULAMANIZDA PROJE DIZINI AÇIKLAMA

İleti uygulaması (SUT) src/RazorPagesProject Bir kullanıcının, iletileri eklemesini,


silmesini, silmesini ve analiz etmesini
sağlar.

Test uygulaması testler/RazorPagesProject. testler SUT test tümleştirmesi için kullanılır.

Testler, Visual Studiogıbı bir IDE 'nin yerleşik test özellikleri kullanılarak çalıştırılabilir. Visual Studio Code
veya komut satırı kullanıyorsanız, testler/RazorPagesProject. Tests dizinindeki bir komut isteminde aşağıdaki
komutu yürütün:

dotnet test

İleti uygulaması (SUT ) kuruluşu


SUT, aşağıdaki özelliklere sahip bir Razor Pages ileti sistemidir:
Uygulamanın (Pages/Index. cshtml ve Pages/index. cshtml. cs) dizin sayfası, iletilerin eklenmesi,
silinmesini ve ANALIZINI denetlemek için bir UI ve sayfa modeli yöntemleri sağlar (ileti başına ortalama
sözcük).
Bir ileti, iki özellik içeren Message sınıfı (Data/Message. cs) tarafından tanımlanır: Id (anahtar) ve Text
(ileti). Text özelliği gereklidir ve 200 karakterle sınırlıdır.
İletiler, Entity Framework bellek içi veritabanı†kullanılarak depolanır.
Uygulama, AppDbContext (Data/AppDbContext. cs) veritabanı bağlamı sınıfında bir veri erişim KATMANı
(dal) içerir.
Veritabanı uygulama başlangıcında boşsa, ileti deposu üç iletiyle başlatılır.
Uygulama yalnızca kimliği doğrulanmış bir kullanıcı tarafından erişilebilen bir /SecurePage içerir.

†InMemory Ile testolan EF konusu, MSTest ile testler için bellek içi bir veritabanının nasıl kullanılacağını
açıklar. Bu konu xUnit test çerçevesini kullanır. Farklı test çerçeveleri genelinde test kavramları ve test
uygulamaları benzerdir ancak aynı değildir.
Uygulama, depo desenini kullanmıyor ve Iş birimi (UoW ) düzenininetkin bir örneği olmamasına karşın,
Razor Pages bu geliştirme düzenlerini destekler. Daha fazla bilgi için bkz. altyapı Kalıcılık katmanını
tasarlama ve Test denetleyicisi mantığı (örnek, depo modelini uygular).
Test uygulaması kuruluşu
Test uygulaması, testler/RazorPagesProject. Tests dizini içindeki bir konsol uygulamasıdır.

UYGULAMA DIZININI TEST ET AÇIKLAMA

AuthTests İçin test yöntemleri içerir:


Güvenli bir sayfaya, kimliği doğrulanmamış bir
kullanıcıyla erişme.
Bir sahte AuthenticationHandler<TOptions>kimliği
doğrulanmış bir kullanıcı tarafından güvenli bir
sayfaya erişme.
GitHub kullanıcı profilini alma ve profilin Kullanıcı
oturum açma bilgilerini denetleme.

BasicTests Yönlendirme ve içerik türü için bir test yöntemi içerir.

Tümleştirme Testleri Özel WebApplicationFactory sınıfı kullanarak dizin


sayfasına yönelik tümleştirme testlerini içerir.

Yardımcılar/yardımcı programlar Utilities.cs , veritabanını test verileriyle tohum için


kullanılan InitializeDbForTests metodunu içerir.
HtmlHelpers.cs , test yöntemleri tarafından
kullanılmak üzere AngleSharp IHtmlDocument
döndüren bir yöntem sağlar.
HttpClientExtensions.cs , istekleri sut 'a göndermek
için SendAsync için aşırı yüklemeler sağlar.

Test çerçevesi xUnit' dir. Tümleştirme testleri, TestServeriçeren Microsoft. Aspnetcore. testhostkullanılarak
yürütülür. Test ana bilgisayarı ve test sunucusunu yapılandırmak için Microsoft. AspNetCore. Mvc. Testing
paketi kullanıldığından, TestHost ve TestServer paketleri test uygulamasının proje dosyasında ya da
testteki geliştirici yapılandırmasında doğrudan paket başvuruları gerektirmez uygulamanızda.
Test için veritabanının temelini sağlama
Tümleştirme testleri genellikle veritabanında test yürütmeden önce küçük bir veri kümesi gerektirir. Örneğin,
veritabanı kaydı silme için bir silme testi çağrılarında, silme isteğinin başarılı olması için veritabanının en az
bir kaydı olmalıdır.
Örnek uygulama, Utilities.cs içinde testlerin, yürütme sırasında kullanabileceği üç iletiyle birlikte veritabanını
kullanır:
public static void InitializeDbForTests(ApplicationDbContext db)
{
db.Messages.AddRange(GetSeedingMessages());
db.SaveChanges();
}

public static void ReinitializeDbForTests(ApplicationDbContext db)


{
db.Messages.RemoveRange(db.Messages);
InitializeDbForTests(db);
}

public static List<Message> GetSeedingMessages()


{
return new List<Message>()
{
new Message(){ Text = "TEST RECORD: You're standing on my scarf." },
new Message(){ Text = "TEST RECORD: Would you like a jelly baby?" },
new Message(){ Text = "TEST RECORD: To the rational mind, " +
"nothing is inexplicable; only unexplained." }
};
}

Ek kaynaklar
Birim testleri
ASP.NET Core birim testlerini Razor Pages
ASP.NET Core ara yazılımı
ASP.NET Core 'de test denetleyicisi mantığı
Yük/stres testini ASP.NET Core
25.11.2019 • 2 minutes to read • Edit Online

Yük testi ve stres testi, Web uygulamasının performansı ve ölçeklenebilir olmasını sağlamak için önemlidir.
Genellikle benzer testleri paylaşsalar bile hedefleri farklıdır.
Yük testleri , uygulamanın belirli bir kullanıcı yükünü, yanıt hedefini karşılarken, belirli bir senaryo için işleyebilip
Işleyemeyeceğini Test eder –. Uygulama normal koşullarda çalıştırılır.
Stres testleri , genellikle uzun bir süre boyunca yoğun koşullarda çalışırken test uygulaması kararlılığını –. Testler,
uygulamanın yoğun veya aşamalı olarak yükünü artırır ya da uygulamanın bilgi işlem kaynaklarını sınırlar.
Stres testleri, stres kapsamındaki bir uygulamanın hatadan kurtulacağını ve düzgün biçimde beklenen davranışa
geri döneceğini denetler. Stres altında, uygulama normal koşullarda çalıştırılmamaları.
Visual Studio 2019, Visual Studio 'nun yük testi özellikleriyle son sürümüdür. Gelecekte yük testi araçları gerektiren
müşteriler için Apache JMeter, Akamai CloudTest ve BlazeMeter gibi alternatif araçlar önerilir. Daha fazla bilgi için
bkz. Visual Studio 2019 sürüm notları.

Visual Studio Araçları


Visual Studio, kullanıcıların Web performans ve yük testleri oluşturmalarına, geliştirmesine ve hata ayıklamasına
olanak tanır. Bir Web tarayıcısında eylemleri kaydederek testler oluşturmak için bir seçenek mevcuttur.
Visual Studio 2017 kullanarak yük testi projeleri oluşturma, yapılandırma ve çalıştırma hakkında daha fazla bilgi için
bkz. hızlı başlangıç: yük testi projesi oluşturma.
Yük testleri, şirket içinde çalışacak veya Azure DevOps kullanılarak bulutta çalıştırılacak şekilde yapılandırılabilir.

Üçüncü taraf araçları


Aşağıdaki listede, çeşitli özellik kümelerine sahip üçüncü taraf Web performans araçları yer almaktadır:
Apache JMeter
ApacheBench (AB )
Gatling
Locust
Batı rüzgar Web dalgalanma
Netling
Vegeta
ASP.NET Core projeleri sorunlarını giderme
18.07.2019 • 6 minutes to read • Edit Online

Tarafından Rick Anderson


Aşağıdaki bağlantılar sorun giderme kılavuzunu sağlar:
Azure App Service ve IIS 'de ASP.NET Core sorunlarını giderme
ASP.NET Core ile Azure App Service ve IIS için ortak hatalar başvurusu
NDC Konferansı (Londra, 2018): ASP.NET Core uygulamalardaki sorunları tanılama
ASP.NET blogu: ASP.NET Core performans sorunlarını giderme

.NET Core SDK uyarılar


.NET Core SDK hem 32-bit hem de 64-bit sürümleri yüklenir
Yeni proje iletişim kutusunda ASP.NET Core için aşağıdaki uyarıyı görebilirsiniz:

.NET Core SDK hem 32-bit hem de 64-bit sürümleri yüklenir. Yalnızca\' C: Program Files\DotNet\SDK\'
konumunda yüklü olan 64 bitlik sürümlerden alınan şablonlar görüntülenir.

Bu uyarı, .NET Core SDK hem 32-bit (x86) hem de 64-bit (x64) sürümleri yüklendiğinde görüntülenir. Her iki
sürümün de sık yüklenebileceği yaygın nedenler şunlardır:
İlk olarak 32 bitlik bir makine kullanarak .NET Core SDK yükleyicisini indirdiniz, ancak bu dosyayı bir 64 bit
makineye kopyaladınız ve bu makinede yüklediniz.
32 bit .NET Core SDK başka bir uygulama tarafından yüklendi.
Yanlış sürüm indirildi ve yüklendi.
Bu uyarıyı engellemek için 32 bit .NET Core SDK kaldırın. Denetim Masası > Programlar ve Özellikler > 'den
Kaldırbir programı kaldırma veya değiştirme. Uyarının neden oluştuğunu ve etkilerini anladıysanız, uyarıyı
yoksayabilirsiniz.
.NET Core SDK birden çok konuma yüklendi
Yeni proje iletişim kutusunda ASP.NET Core için aşağıdaki uyarıyı görebilirsiniz:

.NET Core SDK birden çok konuma yüklenir. Yalnızca\' C: Program Files\DotNet\SDK\' konumunda yüklü
SDK 'lardan şablonlar görüntülenir.

C:\Program Files\DotNet\SDKdışındabirdizindeenazbir.NETCoreSDKyüklemenizolduğundabuiletiyigörürsünüz.\
Genellikle bu, .NET Core SDK MSI yükleyicisi yerine Kopyala/Yapıştır kullanılarak bir makineye dağıtıldığında
meydana gelir.
Bu uyarıyı engellemek için tüm 32-bit .NET Core SDK 'larını ve çalışma zamanlarını kaldırın. Denetim Masası >
Programlar ve Özellikler > 'den Kaldırbir programı kaldırma veya değiştirme. Uyarının neden oluştuğunu
ve etkilerini anladıysanız, uyarıyı yoksayabilirsiniz.
.NET Core SDK 'Ları algılanmadı
ASP.NET Core için Visual Studio Yeni proje iletişim kutusunda aşağıdaki uyarıyı görebilirsiniz:

.NET Core SDK 'Ları algılanmadı, ortam değişkenine PATH dahil olduklarından emin olun.
Bir dotnet komut yürütürken, uyarı şöyle görünür:

Yüklü olan DotNet SDK 'Ları bulmak mümkün değildi.

Bu uyarılar, ortam değişkeni PATH makinede herhangi bir .NET Core SDK 'sı üzerine işaret etmez görüntülenir.
Bu sorunu çözmek için:
.NET Core SDK 'i yükler. .Net Indirmelerindeen son yükleyiciyi edinin.
Ortam değişkeninin SDK 'nın yüklü olduğu konuma işaret ettiğini doğrulayın ( C:\Program Files\dotnet\ 64
bit/x64 veya C:\Program Files (x86)\dotnet\ 32 bit/x86 için). PATH SDK yükleyicisi normalde ' i ayarlar
PATH . Aynı bit genişliği SDK 'larını ve çalışma zamanlarını aynı makineye her zaman yükler.

.NET Core barındırma paketi yüklendikten sonra SDK eksik


.NET Core barındırma paketinin yüklenmesi, PATH .NET Core 'un 32-bit (x86) sürümünü (
C:\Program Files (x86)\dotnet\ ) işaret etmek üzere .NET Core çalışma zamanını yüklerken değiştirir. Bu, 32 -bit
(x86) .NET Core dotnet komutu kullanıldığında (.NET Core SDK 'ları algılanmadığında) eksik SDK 'lara yol
açabilir. Bu sorunu çözmek için, öncesinde C:\Program Files\dotnet\ C:\Program Files (x86)\dotnet\ PATH bir
konuma geçin.

Bir uygulamadan veri alın


Bir uygulama isteklere yanıt veriyorsa, ara yazılım kullanarak uygulamadan aşağıdaki verileri alabilirsiniz:
İstek – yöntemi, düzen, ana bilgisayar, pathbase, yol, sorgu dizesi, üst bilgiler
Bağlantı – uzak IP adresi, uzak bağlantı noktası, yerel IP adresi, yerel bağlantı noktası, istemci sertifikası
Kimlik – adı, görünen ad
Yapılandırma ayarları
Ortam değişkenleri
Aşağıdaki Ara yazılım kodunu Startup.Configure metodun istek işleme işlem hattının başına yerleştirin. Bu
ortam, kodun yalnızca geliştirme ortamında yürütülmesini sağlamak için, ara yazılım çalıştırılmadan önce
denetlenir.
Ortamı edinmek için aşağıdaki yaklaşımlardan birini kullanın:
Metodunuyöntemine Startup.Configure ekleyin ve yerel değişkenle ortamı kontrol edin.
IHostingEnvironment Aşağıdaki örnek kodda bu yaklaşım gösterilmektedir.

Ortamı Startup sınıfındaki bir özelliğe atayın. Özelliğini kullanarak ortamı denetleyin (örneğin,
if (Environment.IsDevelopment()) ).

public void Configure(IApplicationBuilder app, IHostingEnvironment env,


IConfiguration config)
{
if (env.IsDevelopment())
{
app.Run(async (context) =>
{
var sb = new StringBuilder();
var nl = System.Environment.NewLine;
var rule = string.Concat(nl, new string('-', 40), nl);
var authSchemeProvider = app.ApplicationServices
.GetRequiredService<IAuthenticationSchemeProvider>();

sb.Append($"Request{rule}");
sb.Append($"{DateTimeOffset.Now}{nl}");
sb.Append($"{context.Request.Method} {context.Request.Path}{nl}");
sb.Append($"Scheme: {context.Request.Scheme}{nl}");
sb.Append($"Scheme: {context.Request.Scheme}{nl}");
sb.Append($"Host: {context.Request.Headers["Host"]}{nl}");
sb.Append($"PathBase: {context.Request.PathBase.Value}{nl}");
sb.Append($"Path: {context.Request.Path.Value}{nl}");
sb.Append($"Query: {context.Request.QueryString.Value}{nl}{nl}");

sb.Append($"Connection{rule}");
sb.Append($"RemoteIp: {context.Connection.RemoteIpAddress}{nl}");
sb.Append($"RemotePort: {context.Connection.RemotePort}{nl}");
sb.Append($"LocalIp: {context.Connection.LocalIpAddress}{nl}");
sb.Append($"LocalPort: {context.Connection.LocalPort}{nl}");
sb.Append($"ClientCert: {context.Connection.ClientCertificate}{nl}{nl}");

sb.Append($"Identity{rule}");
sb.Append($"User: {context.User.Identity.Name}{nl}");
var scheme = await authSchemeProvider
.GetSchemeAsync(IISDefaults.AuthenticationScheme);
sb.Append($"DisplayName: {scheme?.DisplayName}{nl}{nl}");

sb.Append($"Headers{rule}");
foreach (var header in context.Request.Headers)
{
sb.Append($"{header.Key}: {header.Value}{nl}");
}
sb.Append(nl);

sb.Append($"Websockets{rule}");
if (context.Features.Get<IHttpUpgradeFeature>() != null)
{
sb.Append($"Status: Enabled{nl}{nl}");
}
else
{
sb.Append($"Status: Disabled{nl}{nl}");
}

sb.Append($"Configuration{rule}");
foreach (var pair in config.AsEnumerable())
{
sb.Append($"{pair.Path}: {pair.Value}{nl}");
}
sb.Append(nl);

sb.Append($"Environment Variables{rule}");
var vars = System.Environment.GetEnvironmentVariables();
foreach (var key in vars.Keys.Cast<string>().OrderBy(key => key,
StringComparer.OrdinalIgnoreCase))
{
var value = vars[key];
sb.Append($"{key}: {value}{nl}");
}

context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(sb.ToString());
});
}
}
.NET Core ve ASP.NET Core oturum açma
5.12.2019 • 52 minutes to read • Edit Online

Tom Dykstra ve Steve Smith tarafından


.NET Core, çeşitli yerleşik ve üçüncü taraf oturum açma sağlayıcılarıyla birlikte çalışarak bir günlüğe
kaydetme API 'sini destekler. Bu makalede, yerleşik sağlayıcılarla günlüğe kaydetme API 'sinin nasıl
kullanılacağı gösterilmektedir.
Bu makalede gösterilen kod örneklerinin çoğu ASP.NET Core uygulamalardan oluşur. Bu kod
parçacıklarının günlüğe kaydetmeye özgü bölümleri, genel ana bilgisayarıkullanan tüm .NET Core
uygulamaları için geçerlidir. Genel konağın Web 'de olmayan uygulamalarda kullanımı hakkında bilgi
için bkz. barındırılan hizmetler.
Genel ana bilgisayarı olmayan uygulamalar için günlük kodu, sağlayıcıların Eklenme ve günlükçülerin
oluşturulmabiçiminde farklılık gösterir. Ana bilgisayar olmayan kod örnekleri, makalenin bu
bölümlerinde gösterilmiştir.
Görüntüleme veya indirme örnek kodu (nasıl indirileceğini)

Sağlayıcı Ekle
Günlük sağlayıcısı günlükleri görüntüler veya depolar. Örneğin, konsol sağlayıcısı günlükleri
konsolunda görüntüler ve Azure Application Insights sağlayıcısı bunları Azure Application Insights
depolar. Birden çok sağlayıcı eklenerek Günlükler birden çok hedefe gönderilebilir.
Genel ana bilgisayar kullanan bir uygulamaya sağlayıcı eklemek için, program.cs'de sağlayıcının
Add{provider name} uzantısı metodunu çağırın:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Konak olmayan bir konsol uygulamasında, bir LoggerFactory oluştururken sağlayıcının


Add{provider name} uzantısı metodunu çağırın:
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

LoggerFactory ve AddConsole , Microsoft.Extensions.Logging için using bir ifade gerektirir.


Varsayılan ASP.NET Core proje şablonları, aşağıdaki günlük sağlayıcılarını ekleyen
CreateDefaultBuilderçağırır:
Console
Hata ayıklama
EventSource
Olay günlüğü (yalnızca Windows üzerinde çalışırken)
Varsayılan sağlayıcıları kendi seçimlerinizle değiştirebilirsiniz. ClearProvidersçağırın ve istediğiniz
sağlayıcıları ekleyin.

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Bir sağlayıcı eklemek için sağlayıcının Add{provider name} uzantısı yöntemini program.csiçinde çağırın:
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
// Requires `using Microsoft.Extensions.Logging;`
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
.UseStartup<Startup>()
.Build();

webHost.Run();
}

Yukarıdaki kod Microsoft.Extensions.Logging ve Microsoft.Extensions.Configuration başvuruları


gerektirir.
Varsayılan proje şablonu, aşağıdaki günlük sağlayıcılarını ekleyen CreateDefaultBuilderçağırır:
Konsolu
Hata ayıklama
EventSource (ASP.NET Core 2,2 ' den başlayarak)

public static void Main(string[] args)


{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();

CreateDefaultBuilder kullanıyorsanız, varsayılan sağlayıcıları kendi seçimlerinizle değiştirebilirsiniz.


ClearProvidersçağırın ve istediğiniz sağlayıcıları ekleyin.
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});

Makalenin ilerleyen kısımlarında yerleşik günlük sağlayıcıları ve üçüncü taraf günlüğü sağlayıcıları
hakkında daha fazla bilgi edinin.

Günlükleri oluştur
Günlükler oluşturmak için bir ILogger<TCategoryName> nesnesi kullanın. Bir Web uygulamasında
veya barındırılan hizmette, bağımlılık ekleme (DI) ILogger alın. Konak dışı konsol uygulamalarında, bir
ILogger oluşturmak için LoggerFactory kullanın.

Aşağıdaki ASP.NET Core örnek kategori olarak TodoApiSample.Pages.AboutModel içeren bir günlükçü
oluşturur. Günlük kategorisi , her günlük ile ilişkili bir dizedir. Dı tarafından belirtilen ILogger<T> örneği,
kategori olarak T tam adı olan Günlükler oluşturur.

public class AboutModel : PageModel


{
private readonly ILogger _logger;

public AboutModel(ILogger<AboutModel> logger)


{
_logger = logger;
}

Aşağıdaki konak olmayan konsol uygulaması örneği, kategori olarak LoggingConsoleApp.Program olan
bir günlükçü oluşturur.

var loggerFactory = LoggerFactory.Create(builder =>


{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
public class AboutModel : PageModel
{
private readonly ILogger _logger;

public AboutModel(ILogger<AboutModel> logger)


{
_logger = logger;
}

Aşağıdaki ASP.NET Core ve konsol uygulaması örneklerinde, günlükçü, düzeyi Information olan
günlükleri oluşturmak için kullanılır. Günlük düzeyi günlüğe kaydedilen etkinliğin önem derecesini
gösterir.

public void OnGet()


{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation("Message displayed: {Message}", Message);
}

var loggerFactory = LoggerFactory.Create(builder =>


{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");

public void OnGet()


{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation("Message displayed: {Message}", Message);
}

Düzeyler ve Kategoriler Bu makalenin ilerleyen kısımlarında daha ayrıntılı olarak açıklanmıştır.


Program sınıfında Günlükler oluşturma
ASP.NET Core uygulamasının Program sınıfında Günlükler yazmak için, konak oluşturulduktan sonra
bir ILogger örneği alın:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

IMyService myService = host.Services.GetRequiredService<IMyService>();


myService.WriteLog("Logged from MyService.");

host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Ana bilgisayar oluşturma sırasında günlüğe kaydetme doğrudan desteklenmez. Ancak, ayrı bir
günlükçü kullanılabilir. Aşağıdaki örnekte, CreateHostBuilder oturum açmak için bir Serilog günlükçü
kullanılır. AddSerilog , Log.Logger belirtilen statik yapılandırmayı kullanır:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Program


{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args)


{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();

Log.Logger = new LoggerConfiguration()


.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();

try
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddRazorPages();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");

throw;
}
finally
{
Log.CloseAndFlush();
}
}
}

Başlangıç sınıfında Günlükler oluşturma


Bir ASP.NET Core uygulamasının Startup.Configure yönteminde Günlükler yazmak için, yöntem
imzasına bir ILogger parametresi ekleyin:
public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
logger.LogInformation("In Development environment");
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}

Startup.ConfigureServices yönteminde DI kapsayıcısı kurulumu tamamlanmadan önce Günlüklerin


yazılması desteklenmez:
Startup oluşturucusuna günlükçü ekleme desteklenmiyor.
Startup.ConfigureServices yöntemi imzasına günlükçü ekleme desteklenmiyor

Bu kısıtlamanın nedeni, günlük kaydının dı ve yapılandırmaya göre değişir ve bu da, ara ' ya bağlıdır. DI
kapsayıcısı ConfigureServices bitene kadar ayarlanamaz.
Web ana bilgisayarı için ayrı bir dı kapsayıcısı oluşturulduğundan, bir günlükçü Startup ' ye
Oluşturucu Ekleme ASP.NET Core önceki sürümlerinde çalışmaktadır. Genel ana bilgisayar için yalnızca
bir kapsayıcı oluşturma hakkında daha fazla bilgi için bkz. Son değişiklik duyurusu.
ILogger<T> bağımlı bir hizmet yapılandırmanız gerekiyorsa, bunu Oluşturucu ekleme veya bir fabrika
yöntemi sağlayarak de yapabilirsiniz. Fabrika yöntemi yaklaşımı yalnızca başka bir seçenek yoksa
önerilir. Örneğin, bir özelliği kaynağından bir hizmete doldurmanız gerektiğini varsayalım:

public void ConfigureServices(IServiceCollection services)


{
services.AddControllers();
services.AddRazorPages();

services.AddSingleton<IMyService>((container) =>
{
var logger = container.GetRequiredService<ILogger<MyService>>();
return new MyService() { Logger = logger };
});

services.AddSingleton<ITodoRepository, TodoRepository>();
}

Önceki vurgulanan kod, DI kapsayıcısının bir MyService örneği oluşturmak için ilk kez çalışan bir Func .
Kayıtlı hizmetlerden herhangi birine bu şekilde erişebilirsiniz.
Başlangıçta günlük oluşturma
Startup sınıfında Günlükler yazmak için, Oluşturucu imzasına bir ILogger parametresi ekleyin:

public class Startup


{
private readonly ILogger _logger;

public Startup(IConfiguration configuration, ILogger<Startup> logger)


{
Configuration = configuration;
_logger = logger;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

// Add our repository type


services.AddSingleton<ITodoRepository, TodoRepository>();
_logger.LogInformation("Added TodoRepository to services");
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
_logger.LogInformation("In Development environment");
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc();
}
}

Program sınıfında Günlükler oluşturma


Program sınıfında Günlükler yazmak için, DI 'den bir ILogger örneği alın:
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});

Ana bilgisayar oluşturma sırasında günlüğe kaydetme doğrudan desteklenmez. Ancak, ayrı bir
günlükçü kullanılabilir. Aşağıdaki örnekte, CreateWebHostBuilder oturum açmak için bir Serilog
günlükçü kullanılır. AddSerilog , Log.Logger belirtilen statik yapılandırmayı kullanır:
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

public class Program


{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)


{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();

Log.Logger = new LoggerConfiguration()


.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();

try
{
return WebHost.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddMvc();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.UseStartup<Startup>();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");

throw;
}
finally
{
Log.CloseAndFlush();
}
}
}

Zaman uyumsuz günlükçü yöntemi yok


Günlüğe kaydetme, zaman uyumsuz kodun performans maliyetine değer olmaması kadar hızlı
olmalıdır. Günlüğe kaydetme veri depoluizin yavaşsa, doğrudan buna yazmayın. Başlangıç olarak
günlük iletilerini hızlı bir mağazaya yazmayı ve sonra yavaş depoya daha sonra taşımayı düşünün.
Örneğin, SQL Server için günlük kaydı yapıyorsanız, Log Yöntemler zaman uyumlu olduğundan bunu
doğrudan bir Log yönteminde yapmak istemezsiniz. Bunun yerine, günlük iletilerini bir bellek içi
kuyruğa eşzamanlı olarak ekleyin ve bir arka plan çalışanı, SQL Server veri gönderme zaman uyumsuz
çalışmasını sağlamak için iletileri kuyruktan çekin. Daha fazla bilgi için Bu GitHub sorununa bakın.
Yapılandırma
Günlüğe kaydetme sağlayıcısı yapılandırması bir veya daha fazla yapılandırma sağlayıcısı tarafından
sağlanır:
Dosya biçimleri (ıNı, JSON ve XML ).
Komut satırı bağımsız değişkenleri.
Ortam değişkenleri.
Bellek içi .NET nesneleri.
Şifrelenmemiş gizli dizi Yöneticisi depolaması.
Azure Key Vaultgibi şifreli bir kullanıcı deposu.
Özel sağlayıcılar (yüklü veya oluşturulmuş).
Örneğin, günlük yapılandırma genellikle uygulama ayarları dosyalarının Logging bölümü tarafından
sağlanır. Aşağıdaki örnek tipik bir appSettings 'in içeriğini gösterir . Development. JSON dosyası:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console":
{
"IncludeScopes": true
}
}
}

Logging özelliği LogLevel ve günlük sağlayıcısı özelliklerine sahip olabilir (konsol gösterilir).
Logging altındaki LogLevel özelliği, Seçili kategoriler için günlüğe kaydedilecek minimum düzeyi
belirtir. Örnekte, System ve Microsoft kategorileri Information düzeyinde günlüğe kaydedilir ve
diğerleri Debug düzeyinde günlüğe kaydedilir.
Logging altındaki diğer özellikler günlük sağlayıcılarını belirtir. Örnek, konsol sağlayıcısına yöneliktir.
Bir sağlayıcı, günlük kapsamlarınıdestekliyorsa IncludeScopes etkinleştirilip etkinleştirilmeyeceğini
gösterir. Bir sağlayıcı özelliği (örneğin Console gibi), bir LogLevel özelliği de belirtebilir. sağlayıcı
altında LogLevel , bu sağlayıcının günlüğe kaydedilecek düzeyleri belirtir.
Logging.{providername}.LogLevel düzeyler belirtilirse, Logging.LogLevel ayarlanan her şeyi geçersiz kılar.
Günlüğe kaydetme API 'SI, bir uygulama çalışırken günlük düzeylerini değiştirme senaryosu içermez.
Ancak, bazı yapılandırma sağlayıcıları yapılandırmayı yeniden yükleme yeteneğine sahiptir ve bu,
günlüğe kaydetme yapılandırması üzerinde etkili bir şekilde gerçekleşir. Örneğin, ayar dosyalarını
okumak için CreateDefaultBuilder tarafından eklenen dosya yapılandırma sağlayıcısı, varsayılan olarak
günlük yapılandırmasını yeniden yükler. Uygulama çalışırken kodda yapılandırma değiştirilirse
uygulama, uygulamanın günlük yapılandırmasını güncelleştirmek için IController. Reload ' i çağırabilir.
Yapılandırma sağlayıcılarını uygulama hakkında daha fazla bilgi için bkz. ASP.NET Core yapılandırma.

Örnek günlüğe kaydetme çıkışı


Yukarıdaki bölümde gösterilen örnek kodla, uygulama komut satırından çalıştırıldığında Günlükler
konsolunda görüntülenir. Konsol çıkışının bir örneği aşağıda verilmiştir:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 84.26180000000001ms 307
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/api/todo/0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller
action with signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
info: TodoApiSample.Controllers.TodoController[1002]
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments
(0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 42.9286ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 148.889ms 404

Yukarıdaki Günlükler, http://localhost:5000/api/todo/0 konumundaki örnek uygulamaya HTTP GET


isteği yapılarak oluşturulmuştur.
Visual Studio 'da örnek uygulamayı çalıştırdığınızda hata ayıklama penceresinde göründükleri
günlüklere yönelik bir örnek aşağıda verilmiştir:

Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 GET


https://localhost:44328/api/todo/0
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint
'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with
{action = "GetById", controller = "Todo", page = ""}. Executing controller action with signature
Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
TodoApiSample.Controllers.TodoController: Information: Getting item 0
TodoApiSample.Controllers.TodoController: Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult: Information: Executing HttpStatusCodeResult, setting
HTTP status code 404
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action
TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in 34.167ms
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint
'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 98.41300000000001ms 404

Yukarıdaki bölümde gösterilen ILogger çağrıları tarafından oluşturulan Günlükler "TodoApiSample"


ile başlar. "Microsoft" kategorileri ile başlayan Günlükler ASP.NET Core Framework kodundan alınır.
ASP.NET Core ve uygulama kodu aynı günlük API 'sini ve sağlayıcılarını kullanıyor.

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET


http://localhost:53104/api/todo/0
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method
TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
TodoApi.Controllers.TodoController:Information: Getting item 0
TodoApi.Controllers.TodoController:Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult:Information: Executing HttpStatusCodeResult, setting HTTP
status code 404
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action
TodoApi.Controllers.TodoController.GetById (TodoApi) in 152.5657ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 316.3195ms 404

Yukarıdaki bölümde gösterilen ILogger çağrıları tarafından oluşturulan Günlükler "TodoApi" ile başlar.
"Microsoft" kategorileri ile başlayan Günlükler ASP.NET Core Framework kodundan alınır. ASP.NET
Core ve uygulama kodu aynı günlük API 'sini ve sağlayıcılarını kullanıyor.
Bu makalenin geri kalanında günlüğe kaydetme için bazı ayrıntılar ve seçenekler açıklanmaktadır.

NuGet paketleri
ILogger ve ILoggerFactory arabirimleri Microsoft. Extensions. Logging. soyutlamalarve bunların
varsayılan uygulamaları Microsoft. Extensions. Logging' dir.

Günlük kategorisi
ILogger bir nesne oluşturulduğunda, için bir Kategori belirtilir. Bu kategori, bu ILogger örneği
tarafından oluşturulan her günlük iletisine dahildir. Kategori herhangi bir dize olabilir, ancak kural,
"TodoApi. Controllers. TodoController" gibi sınıf adını kullanmaktır.
Kategori olarak T tam nitelikli tür adını kullanan bir ILogger örneğini almak için ILogger<T> kullanın:

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}

Kategoriyi açıkça belirtmek için ILoggerFactory.CreateLogger çağırın:


public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
}

public class TodoController : Controller


{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;

public TodoController(ITodoRepository todoRepository,


ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
}

ILogger<T> , T tam nitelikli tür adıyla CreateLogger çağırma ile eşdeğerdir.

Günlük düzeyi
Her günlük bir LogLevel değerini belirtir. Günlük düzeyi önem derecesini veya önemini gösterir.
Örneğin, bir yöntem normal olarak sona erdiğinde bir Information günlüğü ve bir yöntem 404
bulunmayan bir durum kodu döndürdüğünde bir Warning günlüğü yazabilirsiniz.
Aşağıdaki kod Information ve Warning günlüklerini oluşturur:

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

Önceki kodda, ilk parametredir oturum öğesini belirten Olay No. İkinci parametre, kalan Yöntem
parametreleri tarafından belirtilen bağımsız değişken değerleri için yer tutucuları olan bir ileti
şablonudur. Yöntem parametreleri bu makalenin ilerleyen kısımlarında bulunan ileti şablonu
bölümünde açıklanmaktadır.
Yöntem adındaki düzeyi (örneğin, LogInformation ve LogWarning ) içeren günlük yöntemleri, ILogger
için uzantı yöntemleridir. Bu yöntemler bir LogLevel parametresi alan Log yöntemini çağırır. Bu uzantı
yöntemlerinden biri yerine doğrudan Log yöntemi çağırabilirsiniz, ancak söz dizimi görece karmaşıktır.
Daha fazla bilgi için bkz. ILogger ve günlükçü uzantıları kaynak kodu.
ASP.NET Core, en küçükten en yüksek öneme doğru sıralanan aşağıdaki günlük düzeylerini tanımlar.
İzleme = 0
Genellikle yalnızca hata ayıklama için değerli bilgiler için. Bu iletiler hassas uygulama verileri
içerebilir, bu nedenle bir üretim ortamında etkinleştirilmemelidir. Varsayılan olarak devre dışıdır.
Hata Ayıkla = 1
Geliştirme ve hata ayıklama konusunda yararlı olabilecek bilgiler için. Örnek:
Entering method Configure with flag set to true. en yüksek günlük hacimden dolayı yalnızca
sorun giderirken Debug düzeyi günlüklerini etkinleştirin.
Bilgi = 2
Uygulamanın genel akışını izlemek için. Bu günlüklerde genellikle uzun süreli bir değer vardır.
Örnek: Request received for path /api/todo
Uyarı = 3
Uygulama akışında anormal veya beklenmedik olaylar için. Bunlar, uygulamanın durmasına
neden olmayan ancak araştırılması gerekebilecek hataları veya diğer koşulları içerebilir. İşlenmiş
özel durumlar Warning günlük düzeyini kullanmak için yaygın bir yerdir. Örnek:
FileNotFoundException for file quotes.txt.

Hata = 4
İşlenemeyen hatalar ve özel durumlar için. Bu iletiler, uygulama genelinde bir hata değil geçerli
etkinlikte veya işlemde (geçerli HTTP isteği gibi) bir hata olduğunu gösterir. Örnek günlük iletisi:
Cannot insert record due to duplicate key violation.

Kritik = 5
Anında ilgilenilmesi gereken hatalarda. Örnekler: veri kaybı senaryoları, disk alanı yetersiz.
Belirli bir depolama ortamında veya görüntüleme penceresinde ne kadar günlük çıkışının yazıldığını
denetlemek için günlük düzeyini kullanın. Örneğin:
Üretimde:
Trace Information düzeylerinde günlüğe kaydetme, yüksek hacimli ayrıntılı günlük iletileri
oluşturur. Maliyetleri denetlemek ve veri depolama sınırlarını aşmamak için, Information
düzey iletileri kullanarak Trace yüksek hacimli, düşük maliyetli bir veri deposuna günlüğe
kaydedin.
Warning Critical düzeyler aracılığıyla günlüğe kaydetme işlemi genellikle daha az, daha
küçük günlük iletileri üretir. Bu nedenle, maliyetler ve depolama sınırları genellikle bir sorun
değildir ve bu da veri deposu seçiminden daha fazla esneklik elde etmez.
Geliştirme sırasında:
Konsola Critical iletileri aracılığıyla Warning .
Sorun giderirken Information iletileri aracılığıyla Trace ekleyin.
Bu makalede daha sonra bulunan günlük filtreleme bölümünde, bir sağlayıcının hangi günlük
düzeylerinin işlediğini nasıl denetleneceği açıklanmaktadır.
ASP.NET Core çerçeve olayları için günlükleri yazar. Bu makalede daha önce gelen günlük örnekleri
Information düzeyin altında tutulur, dolayısıyla hiçbir Debug veya Trace düzeyi günlüğü
oluşturulmaz. Aşağıda, Debug günlüklerini göstermek için yapılandırılmış örnek uygulama çalıştırılarak
oluşturulan konsol günlüklerinin bir örneği verilmiştir:

info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller
action with signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller
TodoApiSample.Controllers.TodoController (TodoApiSample).
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of authorization filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of resource filters (in the following order):
Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of action filters (in the following order):
Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter (Order: -2147483648),
Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of exception filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of result filters (in the following order):
Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[22]
Attempting to bind parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[44]
Attempting to bind parameter 'id' of type 'System.String' using the name 'id' in request data
...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[45]
Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[23]
Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[26]
Attempting to validate the bound parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[27]
Done attempting to validate the bound parameter 'id' of type 'System.String'.
info: TodoApiSample.Controllers.TodoController[1002]
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in
32.690400000000004ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 176.9103ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:62555/api/todo/0
dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
Request successfully matched the route with name 'GetTodo' and template 'api/Todo/{id}'.
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Update (TodoApi)' with id '089d59b6-92ec-472d-
b552-cc613dfd625d' did not match the constraint
'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Delete (TodoApi)' with id 'f3476abe-4bd9-4ad3-
9261-3ead09607366' did not match the constraint
'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action TodoApi.Controllers.TodoController.GetById (TodoApi)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments
(0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method TodoApi.Controllers.TodoController.GetById (TodoApi), returned result
Microsoft.AspNetCore.Mvc.NotFoundResult.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 0.8788ms
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
Connection id "0HL6L7NEFF2QD" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2.7286ms 404

Günlüğe olay KIMLIĞI


Her günlük belirtebilirsiniz bir öğesini belirten Olay No. Örnek uygulama bunu yerel olarak
tanımlanmış bir LoggingEvents sınıfını kullanarak yapar:

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
public class LoggingEvents
{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;

public const int GetItemNotFound = 4000;


public const int UpdateItemNotFound = 4001;
}

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public class LoggingEvents


{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;

public const int GetItemNotFound = 4000;


public const int UpdateItemNotFound = 4001;
}

Olay KIMLIĞI bir olay kümesini ilişkilendirir. Örneğin, bir sayfadaki öğelerin listesini görüntülemek için
ilgili tüm Günlükler 1001 olabilir.
Günlüğe kaydetme sağlayıcısı, olay KIMLIĞINI günlüğe kaydetme iletisindeki kimlik alanında veya hiç
değil, bir kimlik alanında saklayabilir. Hata ayıklama sağlayıcısı olay kimliklerini göstermiyor. Konsol
sağlayıcısı, etkinlik kimliklerini kategoriden sonra parantez içinde gösterir:

info: TodoApi.Controllers.TodoController[1002]
Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
GetById(invalidid) NOT FOUND

Günlük iletisi şablonu


Her günlük bir ileti şablonunu belirtir. İleti şablonu, bağımsız değişkenlerin sağlandığı yer tutucuları
içerebilir. Sayılar değil, yer tutucular için adları kullanın.
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

public IActionResult GetById(string id)


{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}

Adlarının, değerlerinin sağlanması için hangi parametrelerin kullanılacağını belirleyen yer tutucular
sırası. Aşağıdaki kodda, parametre adlarının ileti şablonunda sıra dışı olduğuna dikkat edin:

string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);

Bu kod, sırasıyla parametre değerleriyle bir günlük iletisi oluşturur:

Parameter values: parm1, parm2

Günlüğe kaydetme altyapısı bu şekilde çalışarak, günlük sağlayıcılarının yapılandırılmış günlüğe yazma
olarak da bilinen anlamsal günlüğüuygulayabilmesini sağlayabilir. Bağımsız değişkenler yalnızca biçimli
ileti şablonuna değil, günlük sistemine geçirilir. Bu bilgiler, günlük sağlayıcılarının parametre değerlerini
alan olarak depolamasına olanak sağlar. Örneğin, günlükçü yönteminin şuna benzer şekilde
göründüğünü varsayın:

_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);

Günlükleri Azure Tablo depolama alanına gönderiyorsanız, her bir Azure Tablo varlığı ID ve
RequestTime özelliklerine sahip olabilir. Bu, günlük verilerinde sorguları basitleştirir.Bir sorgu, belirli bir
RequestTime aralığındaki tüm günlükleri, metin iletisinden zaman aşımına uğratmadan bulabilir.

Günlüğe kaydetme özel durumları


Günlükçü yöntemlerinin, aşağıdaki örnekte olduğu gibi bir özel durum iletmenizi sağlayan aşırı
yüklemeleri vardır:
catch (Exception ex)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);

catch (Exception ex)


{
_logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);

Özel durum bilgileri farklı yollarla farklı sağlayıcılarda işler. Yukarıda gösterilen koddan hata ayıklama
sağlayıcısı çıktısına bir örnek aşağıda verilmiştir.

TodoApiSample.Controllers.TodoController: Warning: GetById(55) NOT FOUND

System.Exception: Item not found exception.


at TodoApiSample.Controllers.TodoController.GetById(String id) in
C:\TodoApiSample\Controllers\TodoController.cs:line 226

Günlük filtreleme
Belirli bir sağlayıcı ve kategori için en az bir günlük düzeyi veya tüm sağlayıcılar ya da tüm kategoriler
için belirtebilirsiniz. Minimum düzeyin altındaki tüm Günlükler bu sağlayıcıya aktarılmaz, bu nedenle
görüntülenmez veya depolanmaz.
Tüm günlükleri gizlemek için en düşük günlük düzeyi olarak LogLevel.None belirtin. LogLevel.None
tamsayı değeri 6 ' dır ve LogLevel.Critical (5) daha yüksektir.
Yapılandırmada filtre kuralları oluşturma
Proje şablonu kodu, konsol, hata ayıklama ve EventSource (ASP.NET Core 2,2 veya üzeri) sağlayıcılar
için günlük kaydı ayarlamak üzere CreateDefaultBuilder çağırır. CreateDefaultBuilder yöntemi, Bu
makalenin önceki kısımlarındaaçıklandığı gibi, Logging bir bölümünde yapılandırma aramak için
günlüğe kaydetmeyi ayarlar.
Yapılandırma verileri aşağıdaki örnekte olduğu gibi sağlayıcıya ve kategoriye göre en düşük günlük
düzeylerini belirtir:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}

{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}

Bu JSON altı filtre kuralı oluşturur: biri hata ayıklama sağlayıcısı, konsol sağlayıcısı için dört ve diğeri
tüm sağlayıcılar için. ILogger bir nesne oluşturulduğunda her sağlayıcı için tek bir kural seçilir.
Koddaki filtre kuralları
Aşağıdaki örnek, koddaki filtre kurallarının nasıl kaydedileceği gösterilmektedir:

.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace))

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));
İkinci AddFilter , tür adını kullanarak hata ayıklama sağlayıcısını belirtir. İlk AddFilter bir sağlayıcı türü
belirtmediğinden, tüm sağlayıcılar için geçerlidir.
Filtreleme kuralları nasıl uygulanır
Yapılandırma verileri ve önceki örneklerde gösterilen AddFilter kodu, aşağıdaki tabloda gösterilen
kuralları oluşturur. İlk altı yapılandırma örneğinde ve son iki ise kod örneğinde gelir.

ŞUNUNLA BAŞLAYAN EN DÜŞÜK GÜNLÜK


SAYI SAĞLAYICI KATEGORILER... DÜZEYI

1. Hata ayıklama Tüm kategoriler Bilgisi

2 Konsolu Microsoft.AspNetCore.M Uyarı


vc.Razor.Internal

3 Konsolu Microsoft.AspNetCore.M Hata ayıklama


vc.Razor.Razor

4 Konsolu Microsoft.AspNetCore.M Hata


vc.Razor

5 Konsolu Tüm kategoriler Bilgisi

6 Tüm sağlayıcılar Tüm kategoriler Hata ayıklama

7 Tüm sağlayıcılar Sistem Hata ayıklama

8 Hata ayıklama Microsoft İzleme

Bir ILogger nesnesi oluşturulduğunda, ILoggerFactory nesnesi, bu günlükçü için uygulanacak her
sağlayıcı için tek bir kural seçer. Bir ILogger örneği tarafından yazılan tüm iletiler, seçilen kurallara göre
filtrelenmiştir. Her sağlayıcı ve kategori çifti için mümkün olan en özel kural kullanılabilir kurallardan
seçilir.
Belirli bir kategori için ILogger oluşturulduğunda, her sağlayıcı için aşağıdaki algoritma kullanılır:
Sağlayıcı veya diğer adıyla eşleşen tüm kuralları seçin. Hiçbir eşleşme bulunmazsa, boş bir
sağlayıcıya sahip tüm kurallar ' ı seçin.
Önceki adımın sonucunda, en uzun eşleşen kategori ön ekine sahip kurallar ' ı seçin. Eşleşme
bulunmazsa, kategori belirtmeyen tüm kuralları seçin.
Birden çok kural seçilirse, son olanı götürün.
Hiçbir kural seçilmezse MinimumLevel kullanın.
Yukarıdaki kurallar listesinde, "Microsoft. AspNetCore. Mvc. Razor. RazorViewEngine" kategorisi için
bir ILogger nesnesi oluşturduğunuzu varsayalım:
Hata ayıklama sağlayıcısı, kurallar 1, 6 ve 8 için geçerlidir. Kural 8 ' i en özeldir, yani seçili olanı
seçilidir.
Konsol sağlayıcısı için, kurallar 3, 4, 5 ve 6 geçerlidir. Kural 3 en özeldir.
Elde edilen ILogger örneği, hata ayıklama sağlayıcısına Trace düzeyi ve üzeri Günlükler gönderir.
Debug düzeyi ve üzeri Günlükler konsol sağlayıcısına gönderilir.

Sağlayıcı diğer adları


Her sağlayıcı, tam nitelikli tür adı yerine yapılandırmada kullanılabilecek bir diğer ad tanımlar. Yerleşik
sağlayıcılar için aşağıdaki diğer adları kullanın:
Konsolu
Hata ayıklama
EventSource
EventLog
TraceSource
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Varsayılan en düşük düzey
Yalnızca belirli bir sağlayıcı ve kategori için yapılandırma veya koddan kural uygulanmaz geçerli olan en
düşük düzey ayar vardır. Aşağıdaki örnekte, en düşük düzeyin nasıl ayarlanacağı gösterilmektedir:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))

WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));

En düşük düzeyi açıkça ayarlamazsanız, varsayılan değer Information , bu da Trace ve Debug


günlüklerinin yoksayıldığı anlamına gelir.
Filtre işlevleri
Configuration veya Code tarafından kendisine atanmış kuralları olmayan tüm sağlayıcılar ve kategoriler
için bir filtre işlevi çağırılır. İşlevindeki kodun sağlayıcı türü, kategorisi ve günlük düzeyine erişimi vardır.
Örneğin:

.ConfigureLogging(logBuilder =>
{
logBuilder.AddFilter((provider, category, logLevel) =>
{
if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
category == "TodoApiSample.Controllers.TodoController")
{
return false;
}
return true;
});
})
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logBuilder =>
{
logBuilder.AddFilter((provider, category, logLevel) =>
{
if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
category == "TodoApiSample.Controllers.TodoController")
{
return false;
}
return true;
});
});

Sistem kategorileri ve Düzeyler


ASP.NET Core ve Entity Framework Core tarafından kullanılan bazı kategoriler şunlardır ve bunlardan
beklenen Günlükler hakkında notlar bulunur:

KATEGORI NOTLAR

Microsoft.AspNetCore Genel ASP.NET Core tanılama.

Microsoft.AspNetCore.DataProtection Hangi anahtarların kabul edildiği, bulunduğu ve


kullanıldığı.

Microsoft.AspNetCore.HostFiltering İzin verilen konaklar.

Microsoft.AspNetCore.Hosting HTTP isteklerinin tamamlanması için geçen süre ve ne


zaman başladıkları. Hangi barındırma başlangıç
derlemeleri yüklendi.

Microsoft.AspNetCore.Mvc MVC ve Razor tanılama. Model bağlama, filtre yürütme,


derlemeyi görüntüleme, eylem seçimi.

Microsoft.AspNetCore.Routing Eşleşen bilgileri yönlendirin.

Microsoft. AspNetCore. Server Bağlantı başlatın, durdurun ve canlı yanıtları koruyun.


HTTPS sertifika bilgileri.

Microsoft.AspNetCore.StaticFiles Sunulan dosyalar.

Microsoft. EntityFrameworkCore Genel Entity Framework Core tanılama. Veritabanı


etkinliği ve yapılandırması, değişiklik algılama, geçişler.

Günlük kapsamları
Kapsam bir mantıksal işlemler kümesini gruplandırabilir. Bu gruplandırma, kümenin bir parçası olarak
oluşturulan her günlüğe aynı verileri eklemek için kullanılabilir. Örneğin, bir işlemin işlenmesi
kapsamında oluşturulan her günlük işlem KIMLIĞI içerebilir.
Kapsam, BeginScope yöntemi tarafından döndürülen ve atılana kadar bir IDisposable türüdür. using
bloğunda günlükçü çağrılarını sarmalayarak kapsam kullanın:
public IActionResult GetById(string id)
{
TodoItem item;
using (_logger.BeginScope("Message attached to logs created in the using block"))
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
}
return new ObjectResult(item);
}

public IActionResult GetById(string id)


{
TodoItem item;
using (_logger.BeginScope("Message attached to logs created in the using block"))
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {Id}", id);
item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({Id}) NOT FOUND", id);
return NotFound();
}
}
return new ObjectResult(item);
}

Aşağıdaki kod konsol sağlayıcısı için kapsamları etkinleştirilir:


Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

.ConfigureLogging((hostingContext, logging) =>


{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
NOTE
IncludeScopes konsolu günlükçüsü seçeneğini yapılandırmak, kapsam tabanlı günlüğe kaydetmeyi
etkinleştirmek için gereklidir.
Yapılandırma hakkında bilgi için yapılandırma bölümüne bakın.

Her günlük iletisi kapsamlı bilgiler içerir:

info: TodoApiSample.Controllers.TodoController[1002]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 =>
TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in
the using block
Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 =>
TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in
the using block
GetById(0) NOT FOUND

Yerleşik günlük oluşturma sağlayıcıları


ASP.NET Core aşağıdaki sağlayıcıları sevk eder:
Console
Hata ayıklama
EventSource
EventLog
TraceSource
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
ASP.NET Core modülüyle stdout ve hata ayıklama günlüğü hakkında daha fazla bilgi için, bkz. Azure
App Service ve IIS 'de ASP.NET Core sorunlarını giderme ve ASP.NET Core Modülü.
Konsol sağlayıcısı
Microsoft. Extensions. Logging. Console sağlayıcı paketi, günlük çıktısını konsola gönderir.

logging.AddConsole();

Konsol günlüğü çıkışını görmek için proje klasöründe bir komut istemi açın ve aşağıdaki komutu
çalıştırın:

dotnet run

Hata ayıklama sağlayıcısı


Microsoft. Extensions. Logging. Debug sağlayıcı paketi, System. Diagnostics. Debug sınıfını (
Debug.WriteLine Yöntem çağrıları) kullanarak günlük çıktısını yazar.

Linux 'ta, bu sağlayıcı günlükleri /var/log/Messagedosyasına yazar.


logging.AddDebug();

Olay kaynak sağlayıcısı


Microsoft. Extensions. Logging. EventSource sağlayıcı paketi, Microsoft-Extensions-Logging adı Ile bir
olay kaynağı platformlar arası yazar. Windows 'da, sağlayıcı ETWkullanır.

logging.AddEventSourceLogger();

Konak oluşturmak için CreateDefaultBuilder çağrıldığında olay kaynak sağlayıcısı otomatik olarak
eklenir.
DotNet izleme araçları
DotNet-Trace Aracı, çalışan bir Işlemin .NET Core izlemelerinin toplanmasını sağlayan platformlar arası
CLI genel aracıdır. Araç, bir LoggingEventSourcekullanarak Microsoft.Extensions.Logging.EventSource
sağlayıcı verileri toplar.
DotNet Trace araçları komutunu aşağıdaki komutla birlikte yüklersiniz:

dotnet tool install --global dotnet-trace

Bir uygulamadan izleme toplamak için DotNet Trace araçları kullanın:


1. Uygulama ana bilgisayarı CreateDefaultBuilder oluşturmaz, olay kaynak sağlayıcısını
uygulamanın günlük yapılandırmasına ekleyin.
2. dotnet run komutuyla uygulamayı çalıştırın.
3. .NET Core uygulamasının işlem tanımlayıcısını (PID ) belirleme:
Windows 'ta aşağıdaki yaklaşımlardan birini kullanın:
Görev Yöneticisi (Ctrl + Alt + Del)
Tasklist komutu
Get-Process PowerShell komutu
Linux 'ta pidof komutunukullanın.
Uygulamanın derlemesi ile aynı ada sahip olan işlem için PID 'i bulun.
4. dotnet trace komutunu yürütün.
Genel komut sözdizimi:

dotnet trace collect -p {PID}


--providers Microsoft-Extensions-Logging:{Keyword}:{Event Level}
:FilterSpecs=\"
{Logger Category 1}:{Event Level 1};
{Logger Category 2}:{Event Level 2};
...
{Logger Category N}:{Event Level N}\"

PowerShell komut kabuğu kullanırken --providers değerini tek tırnak içine alın ( ' ):
dotnet trace collect -p {PID}
--providers 'Microsoft-Extensions-Logging:{Keyword}:{Event Level}
:FilterSpecs=\"
{Logger Category 1}:{Event Level 1};
{Logger Category 2}:{Event Level 2};
...
{Logger Category N}:{Event Level N}\"'

Windows dışı platformlarda, çıkış izleme dosyasının biçimini speedscope olarak değiştirmek için
-f speedscope seçeneğini ekleyin.

ANAHTAR SÖZCÜĞÜ AÇIKLAMA

1. LoggingEventSource ilgili meta olayları günlüğe


kaydedin. Olayları ILogger ) günlüğe kaydetmez.

2 ILogger.Log() çağrıldığında Message olayı açar.


Programlı biçimlendirilmedi) bir şekilde bilgi sağlar.
(

4 ILogger.Log() çağrıldığında FormatMessage


olayı açar. , Bilgilerin biçimlendirilen dize sürümünü
sağlar.

8 ILogger.Log() çağrıldığında MessageJson olayı


açar. Bağımsız değişkenlerin JSON gösterimini sağlar.

OLAY DÜZEYI AÇIKLAMA

0 LogAlways

1. Critical

2 Error

3 Warning

4 Informational

5 Verbose

{Logger Category} ve {Event Level} için FilterSpecs girişleri ek günlük filtreleme koşullarını
temsil eder. FilterSpecs girdileri noktalı virgülle ayırın ( ; ).
Windows komut kabuğu ile örnek ( --providers değeri etrafında tek tırnakyoktur ):

dotnet trace collect -p {PID} --providers Microsoft-Extensions-


Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"

Yukarıdaki komut şunları etkinleştirir:


Hatalar için ( 2 ) biçimlendirilen dizeler ( 4 ) üretmek üzere olay kaynağı günlükçüsü.
günlüğe kaydetme Informational günlük düzeyinde ( 4 ) Microsoft.AspNetCore.Hosting .
5. ENTER tuşuna veya CTRL + C tuşlarına basarak DotNet izleme araçlarını durdurun.
İzleme, dotnet trace komutunun yürütüldüğü klasörde Trace. NetTrace adıyla kaydedilir.
6. Trace 'i PerfViewile açın. Trace. NetTrace dosyasını açın ve izleme olaylarını araştırın.
Daha fazla bilgi için bkz.
Performans Analizi yardımcı programı Için izleme (DotNet-Trace) (.NET Core belgeleri)
Performans Analizi yardımcı programı (DotNet-Trace) Için izleme (DotNet/Diagnostics GitHub
deposu belgeleri)
Loggingeventsource sınıfı (.NET API tarayıcısı)
EventLevel
Loggingeventsource başvuru kaynağı (3,0) – farklı bir sürüm için başvuru kaynağı elde etmek üzere,
dalı release/{Version} olarak değiştirin, burada {Version} istenen ASP.NET Core sürümüdür.
PerfView , olay kaynağı izlemelerini görüntülemek için kullanışlıdır –.
PerfView
Günlükleri toplamak ve görüntülemek için PerfView yardımcı programını kullanın. ETW günlüklerini
görüntülemeye yönelik başka araçlar da mevcuttur, ancak PerfView, ASP.NET Core tarafından
yayınlanan ETW olaylarıyla çalışmak için en iyi deneyimi sağlar.
Bu sağlayıcı tarafından günlüğe kaydedilen olayları toplamak için PerfView 'ı yapılandırmak için,
*Microsoft-Extensions-Logging dizeyi ek sağlayıcılar listesine ekleyin. ( Dizenin başlangıcında yıldız
işaretini kaçırmayın.)

Windows olay günlüğü sağlayıcısı


Microsoft. Extensions. Logging. EventLog sağlayıcı paketi, Windows olay günlüğüne günlük çıktısı
gönderir.

logging.AddEventLog();

AddEventLog aşırı yüklemeler EventLogSettingsiletmenizi sağlar. null veya belirtilmemişse, aşağıdaki


varsayılan ayarlar kullanılır:
"uygulama" LogName –
SourceName – ".NET Runtime"
MachineName – yerel makine
TraceSource sağlayıcısı
Microsoft. Extensions. Logging. TraceSource sağlayıcı paketi TraceSource kitaplıklarını ve sağlayıcıları
kullanır.

logging.AddTraceSource(sourceSwitchName);

Addtracesource aşırı yüklemeleri , bir kaynak anahtarı ve bir izleme dinleyicisi geçirmenize olanak
sağlar.
Bu sağlayıcıyı kullanmak için, bir uygulamanın .NET Framework çalışması gerekir (.NET Core yerine).
Sağlayıcı, iletileri örnek uygulamada kullanılan TextWriterTraceListener gibi çeşitli
dinleyicilerineyönlendirebilir.
Azure App Service sağlayıcı
Microsoft. Extensions. Logging. AzureAppServices sağlayıcı paketi, günlükleri bir Azure App Service
uygulamasının dosya sistemindeki metin dosyalarına ve bir Azure depolama hesabındaki BLOB
depolama alanına yazar.

logging.AddAzureWebAppDiagnostics();

Sağlayıcı paketi, paylaşılan çerçeveye dahil değildir. Sağlayıcıyı kullanmak için sağlayıcı paketini projeye
ekleyin.
Sağlayıcı paketi Microsoft. AspNetCore. app metapackage'e dahil değildir. .NET Framework veya
Microsoft.AspNetCore.App metapackage 'e başvuru yaparken, sağlayıcı paketini projeye ekleyin.

Sağlayıcı ayarlarını yapılandırmak için aşağıdaki örnekte gösterildiği gibi AzureFileLoggerOptions ve


AzureBlobLoggerOptionskullanın:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
})
)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Sağlayıcı ayarlarını yapılandırmak için aşağıdaki örnekte gösterildiği gibi AzureFileLoggerOptions ve


AzureBlobLoggerOptionskullanın:

public static void Main(string[] args)


{
var host = CreateWebHostBuilder(args).Build();

var todoRepository = host.Services.GetRequiredService<ITodoRepository>();


todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });

var logger = host.Services.GetRequiredService<ILogger<Program>>();


logger.LogInformation("Seeded the database.");

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
}))
.UseStartup<Startup>();
AddAzureWebAppDiagnostics aşırı yüklemesi AzureAppServicesDiagnosticsSettingsgeçirmenize
olanak tanır. Ayarlar nesnesi, günlük çıkış şablonu, blob adı ve dosya boyutu sınırı gibi varsayılan
ayarları geçersiz kılabilir. (Çıktı şablonu , bir ILogger yöntemi çağrısıyla sağlandığının yanı sıra tüm
günlüklere uygulanan bir ileti şablonudur.)
App Service uygulamasına dağıtırken, uygulama, Azure portal App Service sayfasının App Service
Günlükler bölümündeki ayarları kabul eder. Aşağıdaki ayarlar güncelleştirilirken, değişiklikler
uygulamanın yeniden başlatılmasını veya yeniden dağıtımı gerekmeden hemen etkili olur.
Uygulama günlüğü (dosya sistemi)
Uygulama günlüğü (blob)
Günlük dosyaları için varsayılan konum D:\home\LogFiles\uygulama klasöründedir ve varsayılan
dosya adı Diagnostics-YYYYMMDD. txt' dir. Varsayılan dosya boyutu sınırı 10 MB 'tır ve tutulan
varsayılan en fazla dosya sayısı 2 ' dir. Varsayılan blob adı {app -name}
{timestamp }/yyyy/mm/dd/ss/{Guid }-ApplicationLog.txt.
Sağlayıcı yalnızca proje Azure ortamında çalıştırıldığında çalışır. Proje yerel olarak çalıştırıldığında, yerel
dosyalara veya Bloblar için yerel geliştirme depolamasına yazmazsa—hiçbir etkisi yoktur.
Azure günlük akışı
Azure günlük akışı, günlük etkinliklerini gerçek zamanlı olarak görüntülemenize izin verir:
Uygulama sunucusu
Web sunucusu
Başarısız istek izleme
Azure günlük akışını yapılandırmak için:
Uygulamanızın Portal sayfasından App Service günlükleri sayfasına gidin.
Uygulama günlüğünü (FileSystem ) Açıkolarak ayarlayın.
Günlük düzeyiniseçin. Bu ayar, uygulamadaki diğer günlük sağlayıcılarını değil, yalnızca Azure
günlük akışı için geçerlidir.
Uygulama iletilerini görüntülemek için günlük akışı sayfasına gidin. Uygulama tarafından ILogger
arabirimi aracılığıyla günlüğe kaydedilir.
Azure Application Insights izleme günlüğü
Microsoft. Extensions. Logging. ApplicationInsights sağlayıcı paketi günlükleri Azure Application
Insights yazar. Application Insights, bir Web uygulamasını izleyen ve telemetri verilerini sorgulamak ve
analiz etmek için araçlar sağlayan bir hizmettir. Bu sağlayıcıyı kullanıyorsanız, Application Insights
araçlarını kullanarak günlüklerinizi sorgulayabilir ve analiz edebilirsiniz.
Günlüğe kaydetme sağlayıcısı, ASP.NET Core için tüm kullanılabilir telemetri sağlayan paket olan
Microsoft. ApplicationInsights. AspNetCore'un bağımlılığı olarak eklenmiştir. Bu paketi kullanırsanız,
sağlayıcı paketini yüklemek zorunda kalmazsınız.
ASP.NET 4. x için olan Microsoft. ApplicationInsights. Web paketini kullanmayın—.
Daha fazla bilgi için aşağıdaki kaynaklara bakın:
Application Insights genel bakış
ASP.NET Core uygulamalar için Application Insights -günlük kaydı ile birlikte Application Insights
telemetrinin tam aralığını uygulamak istiyorsanız buraya başlayın.
.NET Core ILogger günlükleri Için Applicationınsightsloggerprovider -günlük sağlayıcısını
Application Insights telemetri olmadan uygulamak istiyorsanız buraya başlayın.
Günlüğe kaydetme bağdaştırıcılarını Application Insights.
Microsoft Learn sitede Application Insights SDK-etkileşimli öğreticisini yükleyip başlatın .

Üçüncü taraf günlük oluşturma sağlayıcıları


ASP.NET Core ile birlikte çalışan üçüncü taraf günlük çerçeveleri:
ELMAH.io (GitHub deposu)
Gelf (GitHub deposu)
Jsnlog (GitHub deposu)
KissLog.net (GitHub deposu)
Log4Net (GitHub deposu)
Loggr (GitHub deposu)
NLog (GitHub deposu)
Sentry (GitHub deposu)
Serilog (GitHub deposu)
Stackdriver (GitHub deposu)
Bazı üçüncü taraf çerçeveler , yapılandırılmış günlük olarak da bilinen anlam günlüğe kaydetmeişlemini
gerçekleştirebilir.
Bir üçüncü taraf çerçevesinin kullanılması, yerleşik sağlayıcılardan birini kullanmaya benzer:
1. Projenize bir NuGet paketi ekleyin.
2. Günlüğe kaydetme çerçevesi tarafından sağlanmış bir ILoggerFactory Extension yöntemi çağırın.
Daha fazla bilgi için bkz. her sağlayıcının belgeleri. Üçüncü taraf günlüğü sağlayıcıları Microsoft
tarafından desteklenmez.

Ek kaynaklar
ASP.NET Core 'de LoggerMessage ile yüksek performanslı günlüğe kaydetme
Azure App Service ve IIS 'de ASP.NET Core
sorunlarını giderme
26.11.2019 • 42 minutes to read • Edit Online

, Luke Latham ve, kotalik tarafından


Bu makalede, bir uygulama Azure App Service veya IIS 'ye dağıtıldığında hataların nasıl tanılanacağı hakkında
genel uygulama başlatma hataları ve yönergeleri hakkında bilgi verilmektedir:
Uygulama başlatma hataları
Ortak Başlangıç HTTP durum kodu senaryolarını açıklar.
Azure App Service sorunlarını giderme
Azure App Service dağıtılan uygulamalar için sorun giderme önerisi sağlar.
IIS üzerinde sorun giderme
IIS 'ye dağıtılan veya IIS Express yerel olarak çalışan uygulamalar için sorun giderme önerisi sağlar. Bu kılavuz hem
Windows Server hem de Windows masaüstü dağıtımları için geçerlidir.
Paket önbelleklerini temizle
Önemli güncelleştirmeler gerçekleştirirken veya paket sürümlerini değiştirirken ne yapmanız gerektiğini açıklar.
Ek kaynaklar
Ek sorun giderme konularını listeler.

Uygulama başlatma hataları


Visual Studio 'da bir ASP.NET Core projesi, hata ayıklama sırasında IIS Express barındırmak için varsayılan
değerdir. 502,5 -Işlem hatası veya yerel olarak hata ayıklarken oluşan 500,30 -başlatma hatası , bu konudaki öneri
kullanılarak tanılanabilir.
Visual Studio 'da bir ASP.NET Core projesi, hata ayıklama sırasında IIS Express barındırmak için varsayılan
değerdir. Yerel olarak hata ayıklamada oluşan 502,5 Işlem hatası , bu konudaki öneri kullanılarak tanılanabilir.
403,14 yasak
Uygulama başlatılamıyor. Aşağıdaki hata günlüğe kaydedilir:

The Web server is configured to not list the contents of this directory.

Hata genellikle barındırma sisteminde, aşağıdaki senaryolardan birini içeren bozuk bir dağıtım nedeniyle oluşur:
Uygulama, barındırma sisteminde yanlış klasöre dağıtılır.
Dağıtım işlemi, uygulamanın tüm dosyalarını ve klasörlerini barındırma sistemindeki dağıtım klasörüne
taşıyamadı.
Web. config dosyası dağıtımda yok veya Web. config dosyası içerikleri hatalı biçimlendirilmiş.
Aşağıdaki adımları uygulayın:
1. Tüm dosya ve klasörleri barındırma sistemindeki dağıtım klasöründen silin.
2. Visual Studio, PowerShell veya el ile dağıtım gibi normal dağıtım yönteminizi kullanarak, uygulamanın
Yayımlama klasörünün içeriğini barındırma sistemine yeniden dağıtın:
Web. config dosyasının dağıtımda mevcut olduğunu ve içeriğinin doğru olduğunu doğrulayın.
Web. config dosyasının dağıtımda mevcut olduğunu ve içeriğinin doğru olduğunu doğrulayın.
Azure App Service barındırırken, uygulamanın D:\home\site\wwwroot klasörüne dağıtıldığını doğrulayın.
Uygulama IIS tarafından barındırılıyorsa, uygulamanın IIS yöneticisinin temel ayarlarındagösterilen
IIS fiziksel yoluna dağıtıldığını doğrulayın.
3. Barındırma sistemindeki dağıtımı projenin Yayımla klasörünün içeriğiyle karşılaştırarak uygulamanın tüm dosya
ve klasörlerinin dağıtıldığını doğrulayın.
Yayımlanan ASP.NET Core uygulamasının düzeni hakkında daha fazla bilgi için bkz. ASP.NET Core dizin yapısı.
Web. config dosyası hakkında daha fazla bilgi için bkz. ASP.NET Core Modülü.
500 İç sunucu hatası
Uygulamayı başlatır, ancak bir hata sunucu isteği yerine getirmesini önler.
Bu hata, başlatma sırasında veya bir yanıt oluşturulurken uygulamanın kod içinde oluşur. Yanıtta içerik yok olabilir
veya Yanıt, tarayıcıda 500 Iç sunucu hatası olarak görünebilir. Uygulama olay günlüğü, genellikle uygulama normal
şekilde çalışmaya belirtir. Sunucunun açısından bakıldığında, doğru olmasıdır. Uygulama başladı, ancak geçerli bir
yanıt oluşturulamıyor. Uygulamayı sunucuda bir komut isteminde çalıştırın veya sorunu gidermek için ASP.NET
Core modülü stdout günlüğünü etkinleştirin.
500.0 işlem içi işleyici yükleme hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core modülü .NET Core CLR 'yi bulamıyor ve işlem içi istek işleyicisini (aspnetcorev2_inprocess. dll)
bulamıyor. Kontrol edin:
Uygulama Microsoft. AspNetCore. Server. IIS NuGet paketini ya da Microsoft. Aspnetcore. app metapackage'i
hedefler.
ASP.NET Core paylaşılan framework'ün hedefliyorsa hedef makinede yüklü sürümü.
500.0 giden işlem işleyicisi yükleme hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core modülü işlem dışı barındırma isteği işleyicisini bulamıyor. Aspnetcorev2_outofprocess. dll ' nin
aspnetcorev2. dll' nin yanındaki bir alt klasörde bulunduğundan emin olun.
500.0 işlem içi işleyici yükleme hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core Module bileşenleri yüklenirken bilinmeyen bir hata oluştu. Aşağıdaki eylemlerden birini
gerçekleştirin:
Microsoft desteği iletişim kurun ( Geliştirici Araçları ve ASP.NET Core' i seçin).
Stack Overflow soru sorun.
GitHub deponuzdabir sorun yapın.
500.30 işlemdeki başlatma hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core modülü .NET Core CLR 'yi işlem içi başlatmaya çalışır, ancak başlatılamıyor.İşlem başlatma
hatasının nedeni genellikle uygulama olay günlüğündeki girişlerden ve ASP.NET Core modülü stdout günlüğünde
belirlenebilir.
Ortak bir hata durumu, uygulamanın mevcut olmayan ASP.NET Core paylaşılan framework sürümü hedefleme
nedeniyle yanlış yapılandırılmış ' dir. Hangi sürümlerinin bir ASP.NET Core paylaşılan çerçeve hedef makinede
yüklü olduğunu denetleyin.
500,31 ANCM yerel bağımlılıklar bulunamadı
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core modülü , .NET Core çalışma zamanını işlem içinde başlatmaya çalışır, ancak başlatılamıyor.Bu
başlatma hatasının en yaygın nedeni, Microsoft.NETCore.App veya Microsoft.AspNetCore.App çalışma zamanının
yüklenmemesine neden olur. Uygulama, hedef ASP.NET Core 3,0 ' ye dağıtılmışsa ve bu sürüm makinede yoksa, bu
hata oluşur. Örnek bir hata iletisi aşağıda verilmiştir:

The specified framework 'Microsoft.NETCore.App', version '3.0.0' was not found.


- The following frameworks were found:
2.2.1 at [C:\Program Files\dotnet\x64\shared\Microsoft.NETCore.App]
3.0.0-preview5-27626-15 at [C:\Program Files\dotnet\x64\shared\Microsoft.NETCore.App]
3.0.0-preview6-27713-13 at [C:\Program Files\dotnet\x64\shared\Microsoft.NETCore.App]
3.0.0-preview6-27714-15 at [C:\Program Files\dotnet\x64\shared\Microsoft.NETCore.App]
3.0.0-preview6-27723-08 at [C:\Program Files\dotnet\x64\shared\Microsoft.NETCore.App]

Hata iletisi, yüklü tüm .NET Core sürümlerini ve uygulama tarafından istenen sürümü listeler. Bu hatayı onarmak
için aşağıdakilerden birini yapın:
Uygun .NET Core sürümünü makineye yükler.
Uygulamayı, makinede bulunan .NET Core 'un bir sürümünü hedefleyecek şekilde değiştirin.
Uygulamayı kendi kendine kapsanan bir dağıtımolarak yayımlayın.
Geliştirme aşamasında çalışırken ( ASPNETCORE_ENVIRONMENT ortam değişkeni Development olarak ayarlandığında),
HTTP yanıtına belirli bir hata yazılır. İşlem başlatma hatasının nedeni uygulama olay günlüğünde de bulunur.
500,32 ANCM dll yüklenemedi
Çalışan işlemi başarısız olur. Uygulama başlamaz.
Bu hatanın en yaygın nedeni, uygulamanın uyumsuz bir işlemci mimarisi için yayımlanmakta olması olabilir. Çalışan
işlemi 32 bitlik bir uygulama olarak çalışıyorsa ve uygulama 64 bit hedef için yayımlandıysa, bu hata oluşur.
Bu hatayı onarmak için aşağıdakilerden birini yapın:
Çalışan işlemle aynı işlemci mimarisi için uygulamayı yeniden yayımlayın.
Uygulamayı çerçeveye bağlı bir dağıtımolarak yayımlayın.
500,33 ANCM Istek Işleyicisi yükleme hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
Uygulama Microsoft.AspNetCore.App çerçevesine başvurmadı. Yalnızca Microsoft.AspNetCore.App çerçevesini
hedefleyen uygulamalar ASP.NET Core modülütarafından barındırılabilir.
Bu hatayı düzeltemedi, uygulamanın Microsoft.AspNetCore.App çerçevesini hedeflediğinden emin olun.
Uygulamanın hedeflediği çerçeveyi doğrulamak için .runtimeconfig.json denetleyin.
500,34 ANCM karışık barındırma modelleri desteklenmez
Çalışan işlem, aynı işlemde hem işlem içi uygulama hem de işlem dışı bir uygulama çalıştırılamaz.
Bu hatayı onarmak için uygulamaları ayrı IIS uygulama havuzlarında çalıştırın.
500,35 ANCM birden çok işlem Içi uygulama aynı Işlemde
Çalışan işlemi aynı işlemde birden çok işlem içi uygulama çalıştıramıyor.
Bu hatayı onarmak için uygulamaları ayrı IIS uygulama havuzlarında çalıştırın.
500,36 ANCM Işlem dışı Işleyici yükleme hatası
İşlem dışı istek işleyicisi, aspnetcorev2_outofprocess. dll, aspnetcorev2. dll dosyasının yanında değildir. Bu, ASP.NET
Core modülününbozuk bir yüklemesini gösterir.
Bu hatayı gidermek için .NET Core barındırma paketi (IIS için) veya Visual Studio (IIS Express için) yüklemesini
onarın.
500,37 ANCM başlangıç zamanı sınırı Içinde başlatılamadı
ANCM, kısımları başlangıç süresi sınırı içinde başlatılamadı. Varsayılan olarak, zaman aşımı 120 saniyedir.
Aynı makinede çok sayıda uygulama başlatılırken bu hata oluşabilir. Başlangıç sırasında sunucuda CPU/bellek
kullanımı artışlarını denetleyin. Birden çok uygulamanın başlatma işlemini şaşırtmayı yapmanız gerekebilir.
502.5 işlem hatası
Çalışan işlemi başarısız olur. Uygulama başlamaz.
ASP.NET Core modülü çalışan işlemini başlatmaya çalışır, ancak başlatılamıyor. İşlem başlatma hatasının nedeni
genellikle uygulama olay günlüğündeki girişlerden ve ASP.NET Core modülü stdout günlüğünde belirlenebilir.
Ortak bir hata durumu, uygulamanın mevcut olmayan ASP.NET Core paylaşılan framework sürümü hedefleme
nedeniyle yanlış yapılandırılmış ' dir. Hangi sürümlerinin bir ASP.NET Core paylaşılan çerçeve hedef makinede
yüklü olduğunu denetleyin. Paylaşılan çerçeve , makinede yüklü olan ve Microsoft.AspNetCore.App gibi bir
metapackage tarafından başvurulan derleme ( . dll dosyaları) kümesidir. Metapackage başvurusu, gerekli en düşük
sürümü belirtebilir. Daha fazla bilgi için bkz. paylaşılan çerçeve.
Bir barındırma veya uygulamanın yanlış yapılandırılması, çalışan işleminin başarısız olmasına neden olduğunda,
502,5 Işlem hata hatası sayfası döndürülür:
Uygulama (hata kodu: '0x800700c1') başlatılamadı.

EventID: 1010
Source: IIS AspNetCore Module V2
Failed to start application '/LM/W3SVC/6/ROOT/', ErrorCode '0x800700c1'.

Uygulamanın derlemesi ( . dll) yüklenemediğinden uygulama başlatılamadı.


W3wp/ıısexpress işlemi ile yayımlanan uygulama arasındaki bir bit genişliği uyuşmazlığı olduğunda bu hata oluşur.
Uygulama havuzunun 32-bit ayarının doğru olduğundan emin olun:
1. IIS yöneticisinin uygulama havuzlarındauygulama havuzunu seçin.
2. Eylemler panelinde uygulama havuzunu Düzenle altında Gelişmiş ayarlar ' ı seçin.
3. Enable 32 bit uygulamalarınıayarla:
32-bit (x86) bir uygulama dağıtıyorsanız, değeri True olarak ayarlayın.
64 bit (x64) uygulaması dağıtıyorsanız, değeri False olarak ayarlayın.
Proje dosyasındaki <Platform> MSBuild özelliği ile uygulamanın yayınlanan bit durumuyla ilgili bir çakışma
olmadığını doğrulayın.
Bağlantı sıfırlama
Üstbilgiler gönderildikten sonra bir hata oluşursa, bir hata oluştuğunda sunucunun 500 Iç sunucu hatası
gönderebilmesi için çok geç olur. Bu durum, genellikle bir yanıt için karmaşık nesne serileştirme sırasında bir hata
oluştuğunda gerçekleşir. Bu tür bir hata, istemcide bir bağlantı sıfırlama hatası olarak görüntülenir. Uygulama
günlüğü bu tür hataların giderilmesine yardımcı olabilir.
Varsayılan başlangıç sınırları
ASP.NET Core modülü varsayılan bir StartupTimeLimit 120 saniye ile yapılandırılır. Varsayılan değer olarak sol
uygulama modülü bir işlem hatası oturum önce başlatmak için iki dakika sürebilir. Modülü yapılandırma hakkında
daha fazla bilgi için bkz. aspNetCore öğesinin öznitelikleri.
Azure App Service sorunlarını giderme
IMPORTANT
Azure App Service ile Önizleme sürümlerini ASP.NET Core
ASP.NET Core önizleme sürümleri varsayılan olarak Azure App Service dağıtılır. ASP.NET Core Preview sürümü kullanan bir
uygulamayı barındırmak için, bkz. Azure App Service için ASP.NET Core Preview sürümünü dağıtma.

Uygulama olay günlüğü (Azure App Service )


Uygulama olay günlüğüne erişmek için Azure portal sorunları Tanıla ve çöz dikey penceresini kullanın:
1. Azure portal uygulama Hizmetleri' nde uygulamayı açın.
2. Tanıla ve sorunları çöz ' ü seçin.
3. Tanılama araçları başlığını seçin.
4. Destek Araçları' nın altında, uygulama olayları düğmesini seçin.
5. Kaynak sütununda IIS AspNetCoreModule veya IIS Aspnetcoremodule v2 girişi tarafından belirtilen en son
hatayı inceleyin.
Sorunları Tanıla ve çöz dikey penceresini kullanmanın bir alternatifi, uygulama olay günlüğü dosyasını doğrudan
kudukullanarak incelemektir:
1. Gelişmiş araçları geliştirme araçları alanında açın. Git→ düğmesini seçin. Kudu konsolu yeni bir tarayıcı
sekmesi veya penceresinde açılır.
2. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi seçin.
3. LogFiles klasörünü açın.
4. EventLog. xml dosyasının yanındaki kurşun kalem simgesini seçin.
5. Günlüğü inceleyin. En son olayları görmek için günlüğün en altına gidin.
Uygulamayı kudu konsolunda çalıştırma
Başlatma hataları birçok yararlı bilgiler uygulama olay günlüğü'ndeki üretmediği. Bu hatayı saptamak için,
uygulamayı kudu uzaktan yürütme konsolu 'nda çalıştırabilirsiniz:
1. Gelişmiş araçları geliştirme araçları alanında açın. Git→ düğmesini seçin. Kudu konsolu yeni bir tarayıcı
sekmesi veya penceresinde açılır.
2. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi seçin.
32 bit (x86) uygulamayı test etme
Geçerli yayın
1. cd d:\home\site\wwwroot
2. Uygulamayı çalıştırın:
Uygulama, çerçeveye bağımlı bir dağıtımise:

dotnet .\{ASSEMBLY NAME}.dll

Uygulama, kendinden bağımsız bir dağıtımise:

{ASSEMBLY NAME}.exe

Uygulamadan alınan konsol çıktısı, tüm hataları gösteren kudu konsoluna gönderilir.
Önizleme sürümünde çalışan çerçeveye bağımlı dağıtım
ASP.NET Core {VERSION } (x86 ) çalışma zamanı site uzantısının yüklenmesini gerektirir.
1. cd D:\home\SiteExtensions\AspNetCoreRuntime.{X.Y}.x32 ( {X.Y} çalışma zamanı sürümüdür)
2. Uygulamayı çalıştırın: dotnet \home\site\wwwroot\{ASSEMBLY NAME}.dll
Uygulamadan alınan konsol çıktısı, tüm hataları gösteren kudu konsoluna gönderilir.
64 bit (x64) uygulamayı test etme
Geçerli yayın
Uygulama 64 bit (x64) çerçeveye bağımlı bir dağıtımise:
1. cd D:\Program Files\dotnet
2. Uygulamayı çalıştırın: dotnet \home\site\wwwroot\{ASSEMBLY NAME}.dll
Uygulama, kendinden bağımsız bir dağıtımise:
1. cd D:\home\site\wwwroot
2. Uygulamayı çalıştırın: {ASSEMBLY NAME}.exe

Uygulamadan alınan konsol çıktısı, tüm hataları gösteren kudu konsoluna gönderilir.
Önizleme sürümünde çalışan çerçeveye bağımlı dağıtım
ASP.NET Core {VERSION } (x64 ) çalışma zamanı site uzantısını yüklemeyi gerektirir.
1. cd D:\home\SiteExtensions\AspNetCoreRuntime.{X.Y}.x64 ( {X.Y} çalışma zamanı sürümüdür)
2. Uygulamayı çalıştırın: dotnet \home\site\wwwroot\{ASSEMBLY NAME}.dll

Uygulamadan alınan konsol çıktısı, tüm hataları gösteren kudu konsoluna gönderilir.
ASP.NET Core modülü stdout günlüğü (Azure App Service )
ASP.NET Core Module stdout günlüğü genellikle uygulama olay günlüğünde bulunmayan yararlı hata iletilerini
kaydeder. Stdout günlükleri görüntülemek ve etkinleştirmek için:
1. Azure portal sorunları Tanıla ve çöz dikey penceresine gidin.
2. Sorun kategorisini seçinaltında Web uygulaması aşağı düğmesini seçin.
3. Önerilen çözümler ' de stdout günlük yeniden yönlendirmeyi etkinleştirmek > , Web. config dosyasını
düzenlemek için kudu konsolunu açmaküzere düğmeyi seçin.
4. Kudu Tanılama konsolunda, dosyaları Wwwroot > yol sitesine açın. Listenin altındaki Web. config dosyasını
açığa çıkarmak için aşağı kaydırın.
5. Web. config dosyasının yanındaki kurşun kalem simgesine tıklayın.
6. StdoutLogEnabled olarak ayarlayın ve stdoutLogFile yolunu true olarak değiştirin:
\\?\%home%\LogFiles\stdout .
7. Güncelleştirilmiş Web. config dosyasını kaydetmek için Kaydet ' i seçin.
8. Uygulamaya bir istek oluşturun.
9. Azure portal dönün. GELIŞTIRME araçları alanında Gelişmiş Araçlar dikey penceresini seçin. Git→
düğmesini seçin. Kudu konsolu yeni bir tarayıcı sekmesi veya penceresinde açılır.
10. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi seçin.
11. LogFiles klasörünü seçin.
12. Değiştirilen sütunu inceleyin ve son değiştirilme tarihiyle stdout günlüğünü düzenlemek için kalem simgesini
seçin.
13. Günlük dosyası açıldığında hata görüntülenir.
Sorun giderme tamamlandığında stdout günlüğünü devre dışı bırak:
1. Kudu Tanılama konsolunda, Web. config dosyasını açığa çıkarmak için Wwwroot > yolu sitesine dönün.
Kalem simgesini seçerek Web. config dosyasını tekrar açın.
2. false için stdoutLogEnabled ayarlayın.
3. Dosyayı kaydetmek için Kaydet ' i seçin.
Daha fazla bilgi için bkz. ASP.NET Core Modülü.

WARNING
Uygulama veya sunucu başarısızlığı için hata stdout günlüğünü devre dışı bırakmak için yol açabilir. Günlük dosyası boyutunu
sınırlama yok veya oluşturulan günlük dosyası sayısı yoktur. Yalnızca uygulama başlatma sorunlarını gidermek için stdout
günlüğünü kullanın.
Başlangıçtan sonra ASP.NET Core bir uygulamada genel günlüğe kaydetme için, günlük dosyası boyutunu sınırlayan ve
günlükleri döndüren bir günlüğe kaydetme kitaplığı kullanın. Daha fazla bilgi için bkz. üçüncü taraf günlüğü sağlayıcıları.

ASP.NET Core modülü hata ayıklama günlüğü (Azure App Service )


ASP.NET Core Module hata ayıklama günlüğü, ASP.NET Core modülünden daha ayrıntılı günlük kaydı sağlar.
Stdout günlükleri görüntülemek ve etkinleştirmek için:
1. Gelişmiş tanılama günlüğünü etkinleştirmek için aşağıdakilerden birini yapın:
Uygulamayı gelişmiş tanılama günlüğü için yapılandırmak üzere Gelişmiş tanılama günlükleri
bölümündeki yönergeleri izleyin. Uygulamayı yeniden dağıtın.
Gelişmiş tanılama günlüklerinde gösterilen <handlerSettings> kudu konsolunu kullanarak canlı
uygulamanın Web. config dosyasına ekleyin:
a. Gelişmiş araçları geliştirme araçları alanında açın. Git→ düğmesini seçin. Kudu konsolu yeni bir
tarayıcı sekmesi veya penceresinde açılır.
b. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi
seçin.
c. Dosyaları wwwroot > yol sitesine açın. Web. config dosyasını, kurşun kalem düğmesini seçerek
düzenleyin. <handlerSettings> bölümünü, Gelişmiş tanılama günlüklerindegösterildiği gibi
ekleyin. Kaydet düğmesini seçin.
2. Gelişmiş araçları geliştirme araçları alanında açın. Git→ düğmesini seçin. Kudu konsolu yeni bir tarayıcı
sekmesi veya penceresinde açılır.
3. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi seçin.
4. Dosyaları wwwroot > yol sitesine açın. Aspnetcore-Debug. log dosyası için bir yol sağlamadıysanız dosya
listede görüntülenir. Bir yol sağladıysanız, günlük dosyasının konumuna gidin.
5. Dosya adının yanındaki kurşun kalem düğmesiyle günlük dosyasını açın.
Sorun giderme tamamlandığında hata ayıklama günlüğünü devre dışı bırak:
Gelişmiş hata ayıklama günlüğünü devre dışı bırakmak için aşağıdakilerden birini yapın:
Web. config dosyasından <handlerSettings> yerel olarak kaldırın ve uygulamayı yeniden dağıtın.
Web. config dosyasını düzenlemek ve <handlerSettings> bölümünü kaldırmak Için kudu konsolunu kullanın.
Dosyayı kaydedin.
Daha fazla bilgi için bkz. ASP.NET Core Modülü.
WARNING
Hata ayıklama günlüğünü devre dışı bırakma hatası, uygulama veya sunucu hatasına yol açabilir. Günlük dosyası boyutunda
sınır yoktur. Yalnızca uygulama başlatma sorunlarını gidermek için hata ayıklama günlüğünü kullanın.
Başlangıçtan sonra ASP.NET Core bir uygulamada genel günlüğe kaydetme için, günlük dosyası boyutunu sınırlayan ve
günlükleri döndüren bir günlüğe kaydetme kitaplığı kullanın. Daha fazla bilgi için bkz. üçüncü taraf günlüğü sağlayıcıları.

Yavaş veya askıda olan uygulama (Azure App Service )


Bir uygulama bir istek üzerinde yavaş bir şekilde yanıt verdiğinde veya Kilitlenmelerinde, aşağıdaki makalelere
bakın:
Azure App Service 'de yavaş Web uygulaması performans sorunlarını giderme
Azure Web uygulamasında aralıklı özel durum sorunları veya performans sorunları için döküm yakalamak üzere
kilitlenme tanılayıcı site uzantısı 'nı kullanın
İzleme kanatları
İzleme dikey pencereleri, konusunda daha önce açıklanan yöntemlere alternatif bir sorun giderme deneyimi sağlar.
Bu kanatlar 500 serisi hataları tanılamak için kullanılabilir.
ASP.NET Core uzantılarının yüklü olduğunu doğrulayın. Uzantılar yüklü değilse, bunları el ile yükleyebilirsiniz:
1. GELIŞTIRME araçları dikey penceresinde Uzantılar dikey penceresini seçin.
2. ASP.NET Core uzantıları listede görünmelidir.
3. Uzantılar yüklü değilse, Ekle düğmesini seçin.
4. Listeden ASP.NET Core uzantılarını seçin.
5. Yasal koşulları kabul etmek için Tamam ' ı seçin.
6. Uzantı Ekle dikey penceresinde Tamam ' ı seçin.
7. Bilgilendirici bir açılan ileti, uzantıların başarıyla yüklenip yüklenmediğini gösterir.
Stdout günlüğü etkinleştirilmemişse, şu adımları izleyin:
1. Azure portal, GELIŞTIRME araçları alanındaki Gelişmiş Araçlar dikey penceresini seçin. Git→ düğmesini
seçin. Kudu konsolu yeni bir tarayıcı sekmesi veya penceresinde açılır.
2. Sayfanın üst kısmındaki gezinti çubuğunu kullanarak hata ayıklama konsolu 'nu açın ve cmd' yi seçin.
3. Dosya yolu > sitesindeki klasörleri açın ve listenin altındaki Web. config dosyasını açığa çıkarmak için aşağı
kaydırın.
4. Web. config dosyasının yanındaki kurşun kalem simgesine tıklayın.
5. StdoutLogEnabled olarak ayarlayın ve stdoutLogFile yolunu true olarak değiştirin:
\\?\%home%\LogFiles\stdout .
6. Güncelleştirilmiş Web. config dosyasını kaydetmek için Kaydet ' i seçin.
Tanılama günlüğünü etkinleştirmek için ilerleyin:
1. Azure portal tanılama günlükleri dikey penceresini seçin.
2. Uygulama günlüğü (dosya sistemi) ve ayrıntılı hata iletileriiçin bir anahtar seçin . Dikey pencerenin üst
kısmındaki Kaydet düğmesini seçin.
3. Başarısız istek izlemeyi, başarısız Istek olayı arabelleğe alma (FREB ) günlüğü olarak da bilinen bir şekilde
eklemek için , başarısız istek izlemeanahtarını seçin.
4. Portalda tanılama günlükleri dikey penceresinde hemen listelenen günlük akışı dikey penceresini seçin.
5. Uygulamaya bir istek oluşturun.
6. Günlük akışı verileri içinde hatanın nedeni belirtilir.
Sorun giderme tamamlandığında stdout günlüğünü devre dışı bıraktığınızdan emin olun.
Başarısız istek izleme günlüklerini görüntülemek için (FREB günlükleri):
1. Azure portal sorunları Tanıla ve çöz dikey penceresine gidin.
2. Kenar çubuğunun Destek Araçları alanından başarısız istek izleme günlüklerini seçin.
Azure App Service konusundaki Web uygulamaları için tanılama günlüğünü etkinleştirme ve Azure 'Daki Web
Apps Için uygulama performansı SSS bölümündeki başarısız istek izlemeleri bölümüne bakın: daha fazla bilgi için
nasıl yaparım? başarısız istek izlemeyi açın.
Daha fazla bilgi için bkz. Azure App Service Web Apps için tanılama günlüğünü etkinleştirme.

WARNING
Uygulama veya sunucu başarısızlığı için hata stdout günlüğünü devre dışı bırakmak için yol açabilir. Günlük dosyası boyutunu
sınırlama yok veya oluşturulan günlük dosyası sayısı yoktur.
ASP.NET Core uygulamanızı rutin günlüğü için günlük dosyası boyutunu sınırlar ve günlükleri döndürür bir günlük kitaplığını
kullanın. Daha fazla bilgi için bkz. üçüncü taraf günlüğü sağlayıcıları.

IIS 'de sorun giderme


Uygulama olay günlüğü (IIS )
Uygulama olay günlüğüne erişemedi:
1. Başlat menüsünü açın, Olay Görüntüleyicisiaraması yapın ve ardından Olay Görüntüleyicisi uygulamasını
seçin.
2. Olay Görüntüleyicisi, Windows günlükleri düğümünü açın.
3. Uygulama olay günlüğünü açmak için uygulama ' yı seçin.
4. Başarısız olan uygulama ile ilişkili hataları arayın. Hataların, kaynak sütununda IIS aspnetcore modülünün veya
IIS Express aspnetcore modülünün bir değeri vardır.
Uygulamayı bir komut isteminde aşağıdakini çalıştırın
Başlatma hataları birçok yararlı bilgiler uygulama olay günlüğü'ndeki üretmediği. Bazı hataların nedeni, barındıran
sistemde bir komut isteminde uygulamayı çalıştırarak bulabilirsiniz.
Framework bağımlı dağıtım
Uygulama, çerçeveye bağımlı bir dağıtımise:
1. Bir komut isteminde, dağıtım klasörüne gidin ve uygulamanın derlemesini DotNet. exeile yürüterek uygulamayı
çalıştırın. Aşağıdaki komutta, <assembly_name >: dotnet .\<assembly_name>.dll için uygulama derlemesinin
adını yerine koyun.
2. Konsol çıkışını herhangi bir hata gösteren uygulamadan konsol penceresine yazılır.
3. Uygulamaya bir istek yaparken, hataları meydana gelirse, burada Kestrel dinlediği bağlantı noktası ve ana
bilgisayar için istekte bulunmak. Varsayılan konak ve gönderi kullanarak http://localhost:5000/ bir istek yapın.
Uygulamayı, normalde Kestrel uç nokta adresindeki yanıt verirse, sorun barındırma yapılandırmasında ve büyük
olasılıkla daha az uygulama içinde ilgili daha yüksektir.
Kendi içinde dağıtım
Uygulama, kendinden bağımsız bir dağıtımise:
1. Bir komut isteminde dağıtım klasörüne gidin ve uygulamanın yürütülebilir dosyayı çalıştırın. Aşağıdaki komutta,
<assembly_name >: <assembly_name>.exe için uygulama derlemesinin adını yerine koyun.
2. Konsol çıkışını herhangi bir hata gösteren uygulamadan konsol penceresine yazılır.
3. Uygulamaya bir istek yaparken, hataları meydana gelirse, burada Kestrel dinlediği bağlantı noktası ve ana
bilgisayar için istekte bulunmak. Varsayılan konak ve gönderi kullanarak http://localhost:5000/ bir istek yapın.
Uygulamayı, normalde Kestrel uç nokta adresindeki yanıt verirse, sorun barındırma yapılandırmasında ve büyük
olasılıkla daha az uygulama içinde ilgili daha yüksektir.
ASP.NET Core Module stdout günlüğü (IIS )
Stdout günlükleri görüntülemek ve etkinleştirmek için:
1. Barındıran sistemde sitenin dağıtım klasörüne gidin.
2. Günlükler klasörü yoksa, klasörü oluşturun. MSBuild 'in dağıtımdaki Günlükler klasörünü otomatik olarak
oluşturmak üzere nasıl etkinleştirileceği hakkında yönergeler için, bkz. Dizin yapısı konusu.
3. Web. config dosyasını düzenleyin. StdoutLogEnabled öğesini true olarak ayarlayın ve stdoutLogFile yolunu
Günlükler klasörünü işaret etmek üzere değiştirin (örneğin, .\logs\stdout ). yoldaki stdout günlük dosyası adı
önekidir. Oturum oluşturulduğunda bir zaman damgası, işlem kimliği ve dosya uzantısı otomatik olarak eklenir.
Dosya adı ön eki olarak stdout kullanarak, tipik bir günlük dosyası, stdout_20180205184032_5412. logolarak
adlandırılır.
4. Uygulama havuzunuzun kimliğinin Günlükler klasörü için yazma izinlerine sahip olduğundan emin olun.
5. Güncelleştirilmiş Web. config dosyasını kaydedin.
6. Uygulamaya bir istek oluşturun.
7. Günlükler klasörüne gidin. Bulun ve en son stdout günlüğü'nü açın.
8. Hatalar için günlüğü inceleyin.
Sorun giderme tamamlandığında stdout günlüğünü devre dışı bırak:
1. Web. config dosyasını düzenleyin.
2. false için stdoutLogEnabled ayarlayın.
3. Dosyayı kaydedin.
Daha fazla bilgi için bkz. ASP.NET Core Modülü.

WARNING
Uygulama veya sunucu başarısızlığı için hata stdout günlüğünü devre dışı bırakmak için yol açabilir. Günlük dosyası boyutunu
sınırlama yok veya oluşturulan günlük dosyası sayısı yoktur.
ASP.NET Core uygulamanızı rutin günlüğü için günlük dosyası boyutunu sınırlar ve günlükleri döndürür bir günlük kitaplığını
kullanın. Daha fazla bilgi için bkz. üçüncü taraf günlüğü sağlayıcıları.

ASP.NET Core modülü hata ayıklama günlüğü (IIS )


ASP.NET Core modülü hata ayıklama günlüğünü etkinleştirmek için aşağıdaki işleyici ayarlarını uygulamanın Web.
config dosyasına ekleyin:

<aspNetCore ...>
<handlerSettings>
<handlerSetting name="debugLevel" value="file" />
<handlerSetting name="debugFile" value="c:\temp\ancm.log" />
</handlerSettings>
</aspNetCore>

Günlüğü için belirtilen yolun var olduğundan ve uygulama havuzu kimliğinin konumuna yazma izinlerine sahip
olduğunu doğrulayın.
Daha fazla bilgi için bkz. ASP.NET Core Modülü.
Geliştirici özel durumu sayfasını etkinleştir
ASPNETCORE_ENVIRONMENT ortam değişkeni, uygulamayı geliştirme ortamında çalıştırmak için Web. config dosyasına
eklenebilir . Ortam, ana bilgisayar tasarımcısında UseEnvironment tarafından uygulama başlangıcında geçersiz
kılınmadığı sürece, ortam değişkenini ayarlamak, uygulama çalıştırıldığında Geliştirici özel durum sayfasının
görünmesine izin verir.

<aspNetCore processPath="dotnet"
arguments=".\MyApp.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout"
hostingModel="InProcess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>

<aspNetCore processPath="dotnet"
arguments=".\MyApp.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>

ASPNETCORE_ENVIRONMENT için ortam değişkenini ayarlamak yalnızca Internet 'e açık olmayan hazırlama ve test etme
sunucularında kullanılması önerilir. Sorun giderme işleminden sonra Web. config dosyasından ortam değişkenini
kaldırın. Web. config'de ortam değişkenlerini ayarlama hakkında daha fazla bilgi Için, Aspnetcore 'un
EnvironmentVariables alt öğesibölümüne bakın.
Bir uygulamadan veri alın
Bir uygulama isteklerini yanıtlayabileceği ise, istek, bağlantı ve ek veri terminal satır içi ara yazılımın kullanılması
uygulamayı edinin. Daha fazla bilgi ve örnek kod için bkz. ASP.NET Core projeleri sorunlarını giderme.
Yavaş veya askıda olan uygulama (IIS )
Kilitlenme dökümü , sistem belleğinin bir anlık görüntüsüdür ve uygulama kilitlenmesinin, başlatma hatasının veya
yavaş uygulamanın nedenini belirlemenize yardımcı olabilir.
Uygulama kilitleniyor veya bir özel durumla karşılaşırsa
Windows Hata Bildirimi bir döküm edinin ve çözümleyin (WER ):
1. Kilitlenme döküm dosyalarını c:\dumps tutmak için bir klasör oluşturun. Uygulama havuzunun klasöre
yazma erişimi olmalıdır.
2. Enabledökümler PowerShell betiğiniçalıştırın:
Uygulama, işlem içi barındırma modelinikullanıyorsa, W3wp. exeiçin betiği çalıştırın:

.\EnableDumps w3wp.exe c:\dumps

Uygulama işlem dışı barındırma modelinikullanıyorsa, DotNet. exeiçin betiği çalıştırın:

.\EnableDumps dotnet.exe c:\dumps

3. Uygulamayı kilitlenmenin oluşmasına neden olan koşullar altında çalıştırın.


4. Kilitlenme gerçekleştirildikten sonra, Disabledökümler PowerShell betiğiniçalıştırın:
Uygulama, işlem içi barındırma modelinikullanıyorsa, W3wp. exeiçin betiği çalıştırın:

.\DisableDumps w3wp.exe

Uygulama işlem dışı barındırma modelinikullanıyorsa, DotNet. exeiçin betiği çalıştırın:

.\DisableDumps dotnet.exe

Uygulama kilitlenmeleri ve döküm koleksiyonu tamamlandıktan sonra, uygulamanın normal olarak


sonlandırılmasına izin verilir. PowerShell betiği, WER 'i uygulama başına en fazla beş döküm toplayacak şekilde
yapılandırır.

WARNING
Kilitlenme dökümleri büyük miktarda disk alanı kaplar (her birine kadar çok gigabayt kadar).

Uygulama askıda kalıyor, başlatma sırasında başarısız oluyor veya normal şekilde çalışıyor
Bir uygulama askıda kaldığında (yanıt vermeyi keser ancak kilitlenmez), başlatma sırasında başarısız olur veya
normal şekilde çalışır. Kullanıcı modu döküm dosyaları: döküm oluşturmak için uygun bir aracı seçmek üzere en iyi
aracı seçme.
Dökümü çözümle
Bir döküm çeşitli yaklaşımlar kullanılarak analiz edilebilir. Daha fazla bilgi için bkz. Kullanıcı modu döküm dosyasını
çözümleme.

Paket önbelleklerini temizle


Bazen, geliştirme makinesindeki .NET Core SDK yükseltmeden ya da uygulamadaki paket sürümlerini değiştirirken
çalışan bir uygulama hemen başarısız olur. Bazı durumlarda, ana yükseltme yaparken, bir uygulama tutarsız
paketleri kesilebilir. Bu sorunların çoğu, bu yönergeleri izleyerek düzeltilebilir:
1. Bin ve obj klasörlerini silin.
2. Bir komut kabuğundan dotnet nuget locals all --clear yürüterek paket önbelleklerini temizleyin.
Paket önbelleklerini Temizleme, NuGet. exe aracı ile de gerçekleştirilebilir ve komut nuget locals all -clear
yürütülebilir. NuGet. exe , Windows masaüstü işletim sistemiyle birlikte paketlenmiş bir yüklemedir ve
NuGet Web sitesindenayrı olarak alınmalıdır.
3. Geri yükle ve projeyi yeniden derleyin.
4. Uygulamayı yeniden dağıtmadan önce sunucusundaki dağıtım klasöründeki tüm dosyaları silin.

Ek kaynaklar
ASP.NET Core projeleri sorunlarını giderme
ASP.NET Core ile Azure App Service ve IIS için ortak hatalar başvurusu
ASP.NET Core hataları işleme
ASP.NET Core Modülü
Azure belgeleri
ASP.NET Core için Application Insights
Visual Studio 'Yu kullanarak Azure App Service Web uygulamasının sorunlarını giderme bölümünde uzaktan
hata ayıklama Web Apps bölümü
Azure App Service tanılamada genel bakış
Nasıl yapılır: Azure App Service uygulamaları Izleme
Visual Studio 'Yu kullanarak Azure App Service bir Web uygulamasının sorunlarını giderme
Azure Web uygulamalarınızda "502 hatalı Ağ Geçidi" ve "503 hizmeti kullanılamıyor" HTTP hatalarında sorun
giderme
Azure App Service 'de yavaş Web uygulaması performans sorunlarını giderme
Azure 'da Web Apps için uygulama performansı SSS
Azure Web uygulaması korumalı alanı (App Service çalışma zamanı yürütme sınırlamaları)
Azure Cuma: Azure App Service tanılama ve sorun giderme deneyimi (12 dakikalık video)
Visual Studio belgeleri
Visual Studio 2017 ' de Azure 'da IIS 'de uzaktan hata ayıklama ASP.NET Core
Visual Studio 2017 ' de uzak IIS bilgisayarında uzaktan hata ayıklama ASP.NET Core
Visual Studio kullanarak hata ayıklamayı öğrenin
Visual Studio Code belgeleri
Visual Studio Code ile hata ayıklama
ASP.NET Core ile Azure App Service ve IIS için ortak
hatalar başvurusu
23.11.2019 • 26 minutes to read • Edit Online

Tarafından Luke Latham


Bu konuda yaygın hatalar açıklanmakta ve Azure Apps hizmetinde ve IIS 'de ASP.NET Core uygulamalar
barındırırken belirli hatalar için sorun giderme önerileri sunulmaktadır.
Genel sorun giderme kılavuzu için bkz. Azure App Service ve IIS 'de ASP.NET Core sorunlarını giderme.
Aşağıdaki bilgileri toplayın:
Tarayıcı davranışı (durum kodu ve hata iletisi)
Uygulama olay günlüğü girdileri
Azure App Service – Azure App Service ve IIS 'de ASP.NET Core sorunlarını gidermebakın.
IIS
1. Windows menüsünde Başlat ' ı seçin, Olay Görüntüleyicisiyazın ve ENTERtuşuna basın.
2. Olay Görüntüleyicisi açıldıktan sonra, kenar çubuğundan Windows günlükleri > uygulaması '
nı genişletin.
ASP.NET Core modülü stdout ve hata ayıklama günlüğü girdileri
Azure App Service – Azure App Service ve IIS 'de ASP.NET Core sorunlarını gidermebakın.
IIS – ASP.NET Core modülü konusunun günlük oluşturma ve yeniden yönlendirme ve Gelişmiş tanılama
günlükleri bölümlerindeki yönergeleri izleyin.
Hata bilgilerini aşağıdaki yaygın hatalarla karşılaştırın. Bir eşleşme bulunursa, sorun giderme talimatını izleyin.
Bu konudaki hataların listesi ayrıntılı değildir. Burada listelenmeyen bir hatayla karşılaşırsanız, bu konunun en
altındaki içerik geri bildirim düğmesini kullanarak yeni bir sorun açın ve hatayı yeniden oluşturma hakkında
ayrıntılı yönergeler kullanın.

IMPORTANT
Azure App Service ile Önizleme sürümlerini ASP.NET Core
ASP.NET Core önizleme sürümleri varsayılan olarak Azure App Service dağıtılır. ASP.NET Core Preview sürümü kullanan bir
uygulamayı barındırmak için, bkz. Azure App Service için ASP.NET Core Preview sürümünü dağıtma.

İşletim sistemi yükseltmesi 32-bit ASP.NET Core modülünü kaldırdı


Uygulama günlüğü: C:\windows\system32\inetsrv\aspnetcore.dll modül dll 'si yüklenemedi. Veriler hatadır.
Sorun Giderme:
Bir işletim sistemi yükseltmesi sırasında C:\Windows\SysWOW64\inetsrv dizininde işletim sistemi olmayan
dosyalar korunmaz. ASP.NET Core modülü bir işletim sistemi yükseltmesinden önce yüklendiyse ve sonra
herhangi bir uygulama havuzu bir işletim sistemi yükseltmesinden sonra 32 bit modda çalıştıktan sonra bu sorunla
karşılaşılmıştır. Bir işletim sistemi yükseltmesinden sonra ASP.NET Core modülünü onarın. Bkz. .NET Core
barındırma paketi 'Ni yüklemeyi. Yükleyici çalıştırıldığında Onar ' ı seçin.
Eksik site uzantısı, 32-bit (x86) ve 64-bit (x64) site uzantıları yüklü veya
yanlış işlem bit genişliği ayarlanmış
Azure Uygulama Hizmetleri tarafından barındırılan uygulamalar için geçerlidir.
Tarayıcı: HTTP hatası 500,0-Işlem Içi Işleyici yükleme hatası
Uygulama günlüğü: InProcess istek işleyicisini bulmak için hostfxr çağırma hiçbir yerel bağımlılığı
bulamamadan başarısız oldu. InProcess istek işleyicisi bulunamadı. Hostfxr çağırmadan yakalanan çıkış:
herhangi bir uyumlu çerçeve sürümü bulmak mümkün değildi. Belirtilen ' Microsoft. AspNetCore. App '
çerçevesi, ' {VERSION }-Preview -*' sürümü bulunamadı. '/LM/W3SVC/1416782824/ROOT ' uygulaması
başlatılamadı, hata kodu ' 0x8000FFFF '.
ASP.NET Core modülü stdout günlüğü: Uyumlu bir çerçeve sürümü bulmak mümkün değildi. Belirtilen '
Microsoft. AspNetCore. App ' çerçevesi, ' {VERSION }-Preview -*' sürümü bulunamadı.
ASP.NET Core modülü hata ayıklama günlüğü: InProcess istek işleyicisini bulmak için hostfxr çağırma
hiçbir yerel bağımlılığı bulamamadan başarısız oldu. Büyük olasılıkla uygulamanın yanlış yapılandırılmış olduğu
anlamına gelir, lütfen uygulamanın hedeflediği ve makinede yüklü olduğu Microsoft. NetCore. App ve Microsoft.
AspNetCore. app sürümlerini denetleyin. Başarısız HRESULT döndürüldü: 0x8000FFFF. InProcess istek işleyicisi
bulunamadı. Uyumlu bir çerçeve sürümü bulmak mümkün değildi. Belirtilen ' Microsoft. AspNetCore. App '
çerçevesi, ' {VERSION }-Preview -*' sürümü bulunamadı.
Sorun Giderme:
Uygulamayı bir önizleme çalışma zamanı üzerinde çalıştırıyorsanız, uygulamanın ve uygulamanın çalışma
zamanının bit durumuyla eşleşen 32-bit (x86) veya 64 bit (x64) site uzantısını da yükler. Uzantı veya
birden çok çalışma zamanı sürümünü yüklemeyin.
ASP.NET Core {RUNTIME VERSION } (x86) çalışma zamanı
ASP.NET Core {RUNTIME VERSION } (x64) çalışma zamanı
Uygulamayı yeniden başlatın. Uygulamanın yeniden başlatılması için birkaç saniye bekleyin.
Uygulamayı bir önizleme çalışma zamanında çalıştırmak ve 32-bit (x86) ve 64 bit (x64) site uzantıları
yüklüyse, uygulamanın bit durumuyla eşleşmeyen site uzantısını kaldırın. Site uzantısını kaldırdıktan sonra
uygulamayı yeniden başlatın. Uygulamanın yeniden başlatılması için birkaç saniye bekleyin.
Uygulamayı bir önizleme çalışma zamanında çalıştırmak ve site uzantısının bit kullanımı uygulamayla
eşleşiyorsa, önizleme sitesi uzantısının çalışma zamanı sürümünün uygulamanın çalışma zamanı sürümüyle
eşleştiğini doğrulayın.
Uygulamanın uygulama ayarlarındaki platformunun uygulamanın bit durumuyla eşleştiğinden emin
olun.
Daha fazla bilgi için bkz. ASP.NET Core uygulamalarını Azure App Service dağıtma.

X86 uygulaması dağıtıldı, ancak uygulama havuzu 32-bit uygulamalar


için etkinleştirilmemiş
Tarayıcı: HTTP hatası 500,30-Işlem Içi Işlem başlatma hatası
Uygulama günlüğü: ' {PATH} ' fiziksel köküne sahip '/LM/W3SVC/5/ROOT ' uygulaması beklenmeyen
yönetilen özel duruma ulaştı, özel durum kodu = ' 0xe0434352 '. Daha fazla bilgi için lütfen stderr
günlüklerine bakın. ' {PATH} ' fiziksel köküne sahip '/LM/W3SVC/5/ROOT ' uygulaması clr ve yönetilen
uygulamayı yükleyemedi. CLR Worker iş parçacığından erken çıkıldı
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulur ancak boştur.
ASP.NET Core modülü hata ayıklama günlüğü: Başarısız HRESULT döndürüldü: 0x8007023e
Bu senaryo, kendi içinde bulunan bir uygulama yayımlanırken SDK tarafından yakalanarak yapılır. RID platform
hedefi ile eşleşmezse SDK bir hata üretir (örneğin, proje dosyasında <PlatformTarget>x86</PlatformTarget> ile RID
win10-x64 ).

Sorun Giderme:
X86 çerçevesine bağımlı bir dağıtım ( <PlatformTarget>x86</PlatformTarget> ) için IIS uygulama havuzunu 32 bitlik
uygulamalar için etkinleştirin. IIS Yöneticisi 'nde, uygulama havuzunun Gelişmiş ayarlarını açın ve 32 bitlik
uygulamaları doğruolarak etkinleştir ayarını yapın.

Platform RID ile çakışıyor


Tarayıcı: HTTP hatası 502,5-Işlem hatası
Uygulama günlüğü: ' C:{PATH} ' fiziksel köküne sahip ' MACHıNE/WEBROOT/APPHOST/{ASSEMBLY } '
uygulaması,' ' "C:{PATH} {ASSEMBLY } komut satırı ile işleme başlatamadı. {exe | dll} "', ErrorCode = '
0x80004005: ff.
ASP.NET Core modülü stdout günlüğü: İşlenmeyen özel durum: System. BadImageFormatException: '
{ASSEMBLY }. dll ' dosyası veya bütünleştirilmiş kodu yüklenemedi. Bir programı hatalı biçimde yükleme
girişiminde bulunuldu.
Sorun Giderme:
Uygulamanın Kestrel üzerinde yerel olarak çalıştığını doğrulayın. İşlem hatası, uygulamanın içindeki bir
sorunun sonucu olabilir. Daha fazla bilgi için bkz. Azure App Service ve IIS 'de ASP.NET Core sorunlarını
giderme.
Bu özel durum, bir uygulamayı yükseltirken ve daha yeni derlemeler dağıtıldığında bir Azure Apps dağıtımı
için oluşursa, önceki dağıtımdan tüm dosyaları el ile silin. Kalan uyumsuz derlemeler, yükseltilen bir
uygulama dağıtıldığında System.BadImageFormatException özel durumuyla sonuçlanabilir.

URI uç noktası yanlış veya durdurulmuş Web sitesi


Tarayıcı: ERR_CONNECTION_REFUSED --veya-- bağlantı kurulamıyor
Uygulama günlüğü: Giriş yok
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Günlük dosyası oluşturulmaz.
Sorun Giderme:
Uygulamanın kullanımda olduğu doğru URI uç noktasını onaylayın. Bağlamaları denetleyin.
IIS Web sitesinin durdurulmuş durumda olmadığını doğrulayın.

CoreWebEngine veya W3SVC sunucu özellikleri devre dışı


Işletim sistemi özel durumu: ASP.NET Core modülünü kullanmak için IIS 7,0 CoreWebEngine ve W3SVC
özelliklerinin yüklü olması gerekir.
Sorun Giderme:
Uygun rol ve özelliklerin etkinleştirildiğini doğrulayın. Bkz. IIS yapılandırması.
Yanlış web sitesi fiziksel yolu veya uygulaması eksik
Tarayıcı: 403 Yasak-erişim reddedildi --veya-- 403,14 yasak-Web sunucusu bu dizinin içeriğini listebir
şekilde yapılandırılmıştır.
Uygulama günlüğü: Giriş yok
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Günlük dosyası oluşturulmaz.
Sorun Giderme:
IIS Web sitesi temel ayarları ve fiziksel uygulama klasörü ' ne bakın. Uygulamanın IIS Web sitesi fiziksel
yolundakiklasörde olduğunu doğrulayın.

Yanlış rol, ASP.NET Core modülü yüklü değil veya yanlış izinler
Tarayıcı: 500,19 Iç sunucu hatası-sayfanın ilgili yapılandırma verileri geçersiz olduğundan istenen sayfaya
erişilemiyor. --Veya-- Bu sayfa görüntülenemiyor
Uygulama günlüğü: Giriş yok
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Günlük dosyası oluşturulmaz.
Sorun Giderme:
Doğru rolün etkin olduğunu onaylayın. Bkz. IIS yapılandırması.
Programlar & Özellikler veya uygulamalar & özellikleri açın ve Windows Server barındırma 'nın
yüklü olduğunu doğrulayın. Yüklü programlar listesinde Windows Server barındırma yoksa, .NET Core
barındırma paketi ' ni indirip yükleyin.
Geçerli .NET Core barındırma Paket Yükleyici (doğrudan indirme)
Daha fazla bilgi için bkz. .NET Core barındırma paketini yüklemeye.
Uygulama havuzunun > Işlem modeli > kimliğinin applicationpokaydentity olarak ayarlandığından
emin olun veya özel kimliğin uygulamanın dağıtım klasörüne erişmek için doğru izinlere sahip olduğundan
emin olun.
ASP.NET Core barındırma paketini kaldırdıysanız ve barındırma paketinin önceki bir sürümünü
yüklediyseniz ApplicationHost. config dosyası ASP.NET Core modülü için bir bölüm içermez.
ApplicationHost. config dosyasını % windir%/system32/inetsrv/config konumunda açın ve
<configuration><configSections><sectionGroup name="system.webServer"> bölüm grubunu bulun. Bölüm
grubunda ASP.NET Core modülünün bölümü eksikse, Bölüm öğesini ekleyin:

<section name="aspNetCore" overrideModeDefault="Allow" />

Alternatif olarak, ASP.NET Core barındıran paketin en son sürümünü de yüklersiniz. En son sürüm,
desteklenen ASP.NET Core uygulamalarla geriye dönük olarak uyumludur.

Hatalı processPath, eksik yol değişkeni, barındırma paketi yüklü değil,


sistem/IIS yeniden başlatılmadı, VC + + yeniden dağıtılabilir yüklü değil
veya DotNet. exe erişim ihlali
Tarayıcı: HTTP hatası 500,0-Işlem Içi Işleyici yükleme hatası
Uygulama günlüğü: ' C:{PATH} ' fiziksel köküne sahip ' MACHıNE/WEBROOT/APPHOST/{ASSEMBLY } '
uygulaması,' ' "{...}" komut satırı ile işlem başlatamadı ', ErrorCode = ' 0x80070002:0. ' {PATH} ' uygulaması
başlatılamadı. ' {PATH} ' konumunda yürütülebilir dosya bulunamadı. '/LM/W3SVC/2/ROOT ' uygulaması
başlatılamadı, hata kodu ' 0x8007023e '.
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Olay günlüğü: ' {PATH} ' uygulaması başlatılamadı. '
{PATH} ' konumunda yürütülebilir dosya bulunamadı. Başarısız HRESULT döndürüldü: 0x8007023e

Tarayıcı: HTTP hatası 502,5-Işlem hatası


Uygulama günlüğü: ' C:{PATH} ' fiziksel köküne sahip ' MACHıNE/WEBROOT/APPHOST/{ASSEMBLY } '
uygulaması,' ' "{...}" komut satırı ile işlem başlatamadı ', ErrorCode = ' 0x80070002:0.
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulur ancak boştur.
Sorun Giderme:
Uygulamanın Kestrel üzerinde yerel olarak çalıştığını doğrulayın. İşlem hatası, uygulamanın içindeki bir
sorunun sonucu olabilir. Daha fazla bilgi için bkz. Azure App Service ve IIS 'de ASP.NET Core sorunlarını
giderme.
Çerçeveye bağlı bir dağıtım (FDD ) veya kendi kendine dahil olan bir dağıtım için .\{ASSEMBLY}.exe dotnet
olduğunu doğrulamak için Web. config 'deki <aspNetCore> öğesindeki processPath ÖZNITELIĞINI kontrol
edin (SCD ).
FDD için, DotNet. exe ' nin yol ayarları aracılığıyla erişilebilir olmayabilir. C:\Program Files\dotnet\ sistem
yolu ayarlarında bulunduğunu onaylayın.
FDD için, DotNet. exe ' yi uygulama havuzunun Kullanıcı kimliği için erişilebilir olmayabilir. Uygulama
havuzu Kullanıcı kimliğinin C:\Program Files\dotnet dizinine erişimi olduğunu doğrulayın. C:\Program
Files\dotnet ve uygulama dizinlerindeki uygulama havuzu Kullanıcı kimliği için yapılandırılmış reddetme
kuralı olmadığını doğrulayın.
Bir FDD dağıtılmış ve IIS 'nin yeniden başlatılmasına gerek kalmadan .NET Core yüklenmiş olabilir. Bir
komut isteminden net stop was/y ve ardından net start w3svc ' i yürüterek sunucuyu YENIDEN başlatın ya
da IIS 'yi yeniden başlatın.
Bir FDD, barındırma sistemine .NET Core çalışma zamanı yüklenmeden dağıtılmış olabilir. .NET Core çalışma
zamanı yüklenmemişse, sistemde .NET Core barındırma paketi yükleyicisini çalıştırın.
Geçerli .NET Core barındırma Paket Yükleyici (doğrudan indirme)
Daha fazla bilgi için bkz. .NET Core barındırma paketini yüklemeye.
Belirli bir çalışma zamanı gerekliyse, .net download arşivleri ' nden çalışma zamanını indirin ve sisteme
yükleyin. Bir komut isteminden net stop idi ve ardından net start w3svc ' i yürüterek SISTEMI yeniden
başlatarak veya IIS 'yi yeniden başlatarak yüklemeyi doldurun.

<aspNetCore > öğesinin bağımsız değişkenleri yanlış


Tarayıcı: HTTP hatası 500,0-Işlem Içi Işleyici yükleme hatası
Uygulama günlüğü: InProcess istek işleyicisini bulmak için hostfxr çağırma hiçbir yerel bağımlılığı
bulamamadan başarısız oldu. Büyük olasılıkla uygulamanın yanlış yapılandırılmış olduğu anlamına gelir,
lütfen uygulamanın hedeflediği ve makinede yüklü olduğu Microsoft. NetCore. App ve Microsoft.
AspNetCore. app sürümlerini denetleyin. InProcess istek işleyicisi bulunamadı. Hostfxr çağırmadan
yakalanan çıkış: DotNet SDK komutlarını çalıştırmak mı istediniz? Lütfen '/LM/W3SVC/3/ROOT '
uygulaması başlatılamadı, hata kodu ' 0x8000FFFF ': https://go.microsoft.com/fwlink/?
LinkID=798306&clcid=0x409.
ASP.NET Core modülü stdout günlüğü: DotNet SDK komutlarını çalıştırmak mı istediniz? Lütfen ' dan
DotNet SDK 'Yı yükledikten sonra: https://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
ASP.NET Core modülü hata ayıklama günlüğü: InProcess istek işleyicisini bulmak için hostfxr çağırma
hiçbir yerel bağımlılığı bulamamadan başarısız oldu. Büyük olasılıkla uygulamanın yanlış yapılandırılmış
olduğu anlamına gelir, lütfen uygulamanın hedeflediği ve makinede yüklü olduğu Microsoft. NetCore. App
ve Microsoft. AspNetCore. app sürümlerini denetleyin. Başarısız HRESULT döndürüldü: 0x8000FFFF,
InProcess istek işleyicisi bulamadı. Hostfxr çağırmadan yakalanan çıkış: DotNet SDK komutlarını çalıştırmak
mı istediniz? Lütfen şu kaynaktan DotNet SDK 'Yı yüklersiniz: https://go.microsoft.com/fwlink/?
LinkID=798306&clcid=0x409 başarısız HRESULT döndürüldü: 0x8000FFFF
Tarayıcı: HTTP hatası 502,5-Işlem hatası
Uygulama günlüğü: ' C:{PATH} ' fiziksel köküne sahip ' MACHıNE/WEBROOT/APPHOST/{ASSEMBLY } '
uygulaması' ' "DotNet" komut satırı ile işleme başlatılamadı.{ASSEMBLY }. dll ', ErrorCode = '
0x80004005:80008081.
ASP.NET Core modülü stdout günlüğü: Yürütülecek uygulama yok: ' yol{DERLEMESI}. dll '
Sorun Giderme:
Uygulamanın Kestrel üzerinde yerel olarak çalıştığını doğrulayın. İşlem hatası, uygulamanın içindeki bir
sorunun sonucu olabilir. Daha fazla bilgi için bkz. Azure App Service ve IIS 'de ASP.NET Core sorunlarını
giderme.
Framework 'e bağımlı bir dağıtım (FDD ) için .\{ASSEMBLY}.dll (a) olduğunu doğrulamak üzere Web. config
içindeki <aspNetCore> öğesindeki arguments özniteliğini inceleyin; ya da (b) yok, boş bir dize ( arguments="" )
veya bağımsız bir dağıtım için ( arguments="{ARGUMENT_1}, {ARGUMENT_2}, ... {ARGUMENT_X}" ) uygulamanın
bağımsız değişkenlerinin bir listesi (SCD ).

Eksik .NET Core paylaşılan çerçevesi


Tarayıcı: HTTP hatası 500,0-Işlem Içi Işleyici yükleme hatası
Uygulama günlüğü: InProcess istek işleyicisini bulmak için hostfxr çağırma hiçbir yerel bağımlılığı
bulamamadan başarısız oldu. Büyük olasılıkla uygulamanın yanlış yapılandırılmış olduğu anlamına gelir,
lütfen uygulamanın hedeflediği ve makinede yüklü olduğu Microsoft. NetCore. App ve Microsoft.
AspNetCore. app sürümlerini denetleyin. InProcess istek işleyicisi bulunamadı. Hostfxr çağırmadan
yakalanan çıkış: herhangi bir uyumlu çerçeve sürümü bulmak mümkün değildi. Belirtilen ' Microsoft.
AspNetCore. App ' çerçevesi, ' {VERSION } ' sürümü bulunamadı.
'/LM/W3SVC/5/ROOT ' uygulaması başlatılamadı, hata kodu ' 0x8000FFFF '.
ASP.NET Core modülü stdout günlüğü: Uyumlu bir çerçeve sürümü bulmak mümkün değildi. Belirtilen '
Microsoft. AspNetCore. App ' çerçevesi, ' {VERSION } ' sürümü bulunamadı.
ASP.NET Core modülü hata ayıklama günlüğü: Başarısız HRESULT döndürüldü: 0x8000FFFF
Sorun Giderme:
Çerçeveye bağımlı bir dağıtım (FDD ) için, sistemde doğru çalışma zamanının yüklü olduğunu doğrulayın.
Uygulama havuzu durduruldu
Tarayıcı: 503 Hizmet kullanılamıyor
Uygulama günlüğü: Giriş yok
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Günlük dosyası oluşturulmaz.
Sorun Giderme:
Uygulama havuzunun durdurulmuş durumda olmadığını onaylayın.

Alt uygulama bir <işleyicileri içerir > Bölüm


Tarayıcı: HTTP hatası 500,19-Iç sunucu hatası
Uygulama günlüğü: Giriş yok
ASP.NET Core modülü stdout günlüğü: Kök uygulamanın günlük dosyası oluşturulur ve normal işlemi
gösterir. Alt uygulamanın günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: Kök uygulamanın günlük dosyası oluşturulur ve normal
işlemi gösterir. Alt uygulamanın günlük dosyası oluşturulmaz.
Sorun Giderme:
Alt uygulamanın Web. config dosyasının <handlers> bir bölüm içermediğinden veya alt uygulamanın üst
uygulamanın işleyicilerini almadığından emin olun.
Web. config dosyasının üst uygulamanın <system.webServer> bölümü bir <location> öğesinin içine yerleştirilir.
InheritInChildApplications özelliği, <location > öğesi içinde belirtilen ayarların üst uygulamanın bir alt dizininde
bulunan uygulamalar tarafından devralınmadığını göstermek için false olarak ayarlanır. Daha fazla bilgi için bkz.
ASP.NET Core Modülü.
Alt uygulamanın Web. config dosyasının <handlers> bir bölüm içermediğinden emin olun.

stdout günlük yolu yanlış


Tarayıcı: Uygulama normal olarak yanıt verir.
Uygulama günlüğü: C:\Program Files\IIS\Asp.Net Core Module\v2\aspnetcorev2.dll' de stdout yeniden
yönlendirmesi başlatılamadı. Özel durum iletisi: {PATH}
\aspnetcoremodulev2\commonlib\fileoutputmanager.cpp: 84 konumunda HRESULT 0x80070005
döndürüldü. C:\Program Files\IIS\Asp.Net Core Module\v2\aspnetcorev2.dll' de stdout yeniden
yönlendirmesi durdurulamadı. Özel durum iletisi: HRESULT 0x80070002 {PATH} konumunda döndürüldü.
{PATH} \ aspnetcorev2_inprocess. dll içinde stdout yeniden yönlendirmesi başlatılamadı.
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
ASP.NET Core modülü hata ayıklama günlüğü: C:\Program Files\IIS\Asp.Net Core
Module\v2\aspnetcorev2.dll' de stdout yeniden yönlendirmesi başlatılamadı. Özel durum iletisi: {PATH}
\aspnetcoremodulev2\commonlib\fileoutputmanager.cpp: 84 konumunda HRESULT 0x80070005
döndürüldü. C:\Program Files\IIS\Asp.Net Core Module\v2\aspnetcorev2.dll' de stdout yeniden
yönlendirmesi durdurulamadı. Özel durum iletisi: HRESULT 0x80070002 {PATH} konumunda döndürüldü.
{PATH} \ aspnetcorev2_inprocess. dll içinde stdout yeniden yönlendirmesi başlatılamadı.

Uygulama günlüğü: Uyarı: stdoutLogFile \oluşturulamadı?{yol} \ path_doesnt_exist \ stdout_ {Işlem


KIMLIĞI} _ {zaman DAMGASı}. günlük, hata kodu =-2147024893.
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulmaz.
Sorun Giderme:
Web. config dosyasının <aspNetCore> öğesinde belirtilen stdoutLogFile yolu yok. Daha fazla bilgi için bkz.
ASP.NET Core modülü: günlük oluşturma ve yeniden yönlendirme.
Uygulama havuzu kullanıcısının stdout günlük yoluna yazma erişimi yok.

Uygulama yapılandırması genel sorunu


Tarayıcı: HTTP hatası 500,0-Işlem Içi Işleyici yükleme hatası --veya-- HTTP hatası 500,30-Ancm Işlem Içi
başlatma hatası
Uygulama günlüğü: Değişken
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulur ancak boş veya, uygulamanın noktası
başarısız olana kadar normal girdilerle oluşturulur.
ASP.NET Core modülü hata ayıklama günlüğü: Değişken
Tarayıcı: HTTP hatası 502,5-Işlem hatası
Uygulama günlüğü: ' C:{PATH} fiziksel köküne sahip ' MACHıNE/WEBROOT/APPHOST/{ASSEMBLY } '
uygulaması' ' "C:{PATH}{ASSEMBLY } komut satırı ile oluşturulan işlem oluşturdu. {exe | dll} "', ancak
belirtilen ' {PORT} ' bağlantı noktasında kilitlenen veya yanıt vermeyen ya da bu bağlantı noktası üzerinde
dinleme yapamadı, ErrorCode = ' {ERROR CODE } '
ASP.NET Core modülü stdout günlüğü: Günlük dosyası oluşturulur ancak boştur.
Sorun Giderme:
Büyük olasılıkla uygulama yapılandırması veya programlama sorunu nedeniyle işlem başlatılamadı.
Daha fazla bilgi için aşağıdaki konulara bakın:
Azure App Service ve IIS 'de ASP.NET Core sorunlarını giderme
ASP.NET Core projeleri sorunlarını giderme
ASP.NET Core - Öğreticisi 1. 8'de Entity
Framework Core ile Razor sayfaları
23.11.2019 • 53 minutes to read • Edit Online

Tarafından Tom Dykstra ve Rick Anderson


Bu, bir ASP.NET Core Razor Pages uygulamasında ENTITY Framework (EF ) çekirdeğini nasıl
kullanacağınızı gösteren bir öğretici serisinin ilkisidir. Öğreticiler, kurgusal bir Contoso Üniversitesi
için bir Web sitesi oluşturur. Site, öğrenci giriş, kurs oluşturma ve eğitmen atamaları gibi işlevleri
içerir.
İndirme veya tamamlanmış uygulamayı görüntüleyin. Yükleme yönergeleri.

Önkoşullar
Razor Pages yeni başladıysanız, bu duruma başlamadan önce Razor Pages öğretici serisini
kullanmaya başlayın.
Visual Studio
Visual Studio Code
ASP.net ve Web geliştirme iş yüküyle Visual Studio 2019
.NET Core 3,0 SDK veya üzeri

Veritabanı altyapıları
Visual Studio yönergeleri, yalnızca Windows üzerinde çalışan bir SQL Server Express sürümü olan
SQL Server LocalDB'yi kullanır.
Visual Studio Code yönergeler, platformlar arası bir veritabanı altyapısı olan SQLitekullanır.
SQLite kullanmayı seçerseniz, SQLite Için DB tarayıcısıgibi bir SQLite veritabanını yönetmek ve
görüntülemek için üçüncü taraf bir araç indirip yükleyin.

Sorun giderme
Giderebileceğiniz bir sorunla karşılaşırsanız, kodunuzu Tamamlanan projeylekarşılaştırın. Yardım
almanın iyi bir yolu, ASP.NET Core etiketi veya EF Core etiketikullanılarak StackOverflow.com 'e bir
soru göndererek.

Örnek uygulama
Aşağıdaki öğreticilerde oluşturulan bir uygulamayı bir temel university web sitesidir. Kullanıcılar
görüntüleyebilir ve Öğrenci, kurs ve Eğitmen bilgileri güncelleştirin. Öğreticide oluşturulan ekranlar
birkaçını aşağıda verilmiştir.
Bu sitenin kullanıcı arabirimi stili yerleşik proje şablonlarına dayalıdır. Öğreticinin odağı, Kullanıcı
arabirimini nasıl özelleştireceğinizi değil EF Core kullanma konusunda yer alır.
Tamamlanan projenin kaynak kodunu almak için sayfanın üst kısmındaki bağlantıyı izleyin. Cu30
klasörü, öğreticinin ASP.NET Core 3,0 sürümü için kod içerir. 1-7 öğreticileri için kodun durumunu
yansıtan dosyalar cu30snapshots klasöründe bulunabilir.
Visual Studio
Visual Studio Code
Tamamlanmış projeyi indirdikten sonra uygulamayı çalıştırmak için:
Üç dosyayı ve ad içinde SQLite içeren bir klasörü silin.
Projeyi oluşturun.
Paket Yöneticisi konsolu 'nda (PMC ) aşağıdaki komutu çalıştırın:

Update-Database

Veritabanını temel alarak projeyi çalıştırın.

Web uygulaması projesi oluşturma


Visual Studio
Visual Studio Code
Visual Studio'dan dosya menüsünde yeni > proje.
Seçin ASP.NET Core Web uygulaması.
Projeyi adlandırın ContosoUniversity. Büyük harfler de dahil olmak üzere bu tam adı kullanmak
önemlidir, bu nedenle kod kopyalanıp yapıştırılırken ad alanları eşleşir.
Açılan menüden .NET Core ve 3,0 ASP.NET Core seçin ve ardından Web uygulaması' nı seçin.

Site stili Ayarla


Sayfa/paylaşılan/_Layout. cshtml'yi güncelleştirerek site üst bilgisini, alt bilgisini ve menüsünü
ayarlayın:
"Contoso Üniversitesi" için "ContosoUniversity" her örneğini değiştirin. Üç örnekleri vardır.
Giriş ve Gizlilik menü girişlerini silin ve hakkında, öğrenciler, Kurslar, eğitmenlerve
Departmanlariçin girişler ekleyin.
Değişiklikler vurgulanır.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Contoso University</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-
bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">Contoso University</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-
target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/About">About</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Students/Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Courses/Index">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Instructors/Index">Instructors</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-
page="/Departments/Index">Departments</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<footer class="border-top footer text-muted">


<div class="container">
&copy; 2019 - Contoso University - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>

@RenderSection("Scripts", required: false)


</body>
</html>
Pages/Index. cshtmldosyasında, ASP.NET Core hakkındaki metni bu uygulamayla ilgili metinle
değiştirmek için dosyanın içeriğini aşağıdaki kodla değiştirin:

@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="row mb-auto">


<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 mb-4 ">
<p class="card-text">
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core Razor Pages web app.
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 d-flex flex-column position-static">
<p class="card-text mb-auto">
You can build the application by following the steps in a series of
tutorials.
</p>
<p>
<a href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro"
class="stretched-link">See the tutorial</a>
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row no-gutters border mb-4">
<div class="col p-4 d-flex flex-column">
<p class="card-text mb-auto">
You can download the completed project from GitHub.
</p>
<p>
<a
href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-rp/intro/samples"
class="stretched-link">See project source code</a>
</p>
</div>
</div>
</div>
</div>

Giriş sayfasının göründüğünü doğrulamak için uygulamayı çalıştırın.

Veri modeli
Aşağıdaki bölümler bir veri modeli oluşturur:
Bir öğrenci herhangi bir sayıda kursa kaydolabilir ve bir kurs, kayıtlı sayıda öğrenciye sahip olabilir.

Öğrenci varlık

Proje klasöründe bir modeller klasörü oluşturun.


Aşağıdaki kodla modeller/öğrenci. cs oluşturun:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

ID özelliği, bu sınıfa karşılık gelen veritabanı tablosunun birincil anahtar sütunu olur. Varsayılan
olarak EF Core adlı bir özellik yorumlar ID veya classnameID birincil anahtar olarak. Bu nedenle,
Student sınıfı birincil anahtarı için otomatik olarak tanınan ad StudentID .

Enrollments Özelliği bir gezinti özelliği. Gezinti özellikleri, bu varlıkla ilgili diğer varlıkları tutar. Bu
durumda, bir Student varlığının Enrollments özelliği söz konusu öğrenci ile ilgili Enrollment
varlıkların tümünü barındırır. Örneğin, veritabanındaki bir öğrenci satırında iki ilişkili kayıt satırı varsa,
Enrollments gezinti özelliği bu iki kayıt varlığını içerir.

Veritabanında, bir kayıt satırı, Studentitıd sütunu öğrencinin ID değerini içeriyorsa bir öğrenci satırıyla
ilgilidir. Örneğin, bir öğrenci satırının ID = 1 olduğunu varsayalım. İlgili kayıt satırları Studentitıd = 1
olacaktır. Studentitıd, kayıt tablosundaki bir yabancı anahtardır .
Birden çok ilgili kayıt varlığı olabileceğinden Enrollments özelliği ICollection<Enrollment> olarak
tanımlanır. List<Enrollment> veya HashSet<Enrollment> gibi başka koleksiyon türleri de
kullanabilirsiniz. Zaman ICollection<Enrollment> olduğu EF Core kullanıldığında, oluşturur bir
HashSet<Enrollment> varsayılan olarak koleksiyon.

Kayıt varlık

Aşağıdaki kodla modeller/kayıt. cs oluşturun:

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

EnrollmentID özelliği birincil anahtardır; Bu varlık, ID yerine classnameID modelini kullanır. Bir
üretim veri modeli için bir model seçin ve bunu tutarlı bir şekilde kullanın. Bu öğretici her ikisinin de
yalnızca bir iş olduğunu göstermek için kullanır. classname olmadan ID kullanmak, bazı veri modeli
değişikliklerinin uygulanmasını kolaylaştırır.
Grade Özelliği bir enum . Grade türü bildiriminden sonraki soru işareti, Grade özelliğinin null
yapılabilirolduğunu gösterir. Null olan bir sınıf sıfır bir sınıfa göre farklılık gösterir—null, henüz bir
sınıf bilinmediğini veya henüz atanmadığını belirtir.
StudentID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Student . Bir
Enrollment varlıktır biriyle ilişkili Student tek bir özellik içerecek şekilde varlık Student varlık.

CourseID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Course . Bir
Enrollment varlıktır biriyle ilişkili Course varlık.

EF Core adlandırılmışsa, bu özellik bir yabancı anahtar olarak yorumlar


<navigation property name><primary key property name> . Örneğin, Student varlığın birincil anahtarı
ID olduğundan, Student gezinti özelliği için StudentID yabancı anahtardır. Yabancı anahtar özellikleri
de adı <primary key property name> . Örneğin, CourseID beri Course varlığın birincil anahtarı
CourseID .
Kurs varlık

Aşağıdaki kodla modeller/kurs. cs oluşturun:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Enrollments Özelliktir bir gezinme özelliği. A Course varlık dilediğiniz sayıda ilgili olabileceğini
Enrollment varlıklar.
DatabaseGenerated özniteliği, uygulamanın veritabanını oluşturmak yerine birincil anahtarı
belirtmesini sağlar.
Derleyici hatası olmadığını doğrulamak için projeyi derleyin.

Yapı iskelesi öğrenci sayfaları


Bu bölümde, oluşturmak için ASP.NET Core scafkatlama aracını kullanırsınız:
EF Core bağlamı sınıfı. Bağlam, belirli bir veri modeli için Entity Framework işlevselliği koordine
eden ana sınıftır. Microsoft.EntityFrameworkCore.DbContext sınıfından türetilir.
Student varlık için oluşturma, okuma, güncelleştirme ve silme ( CRUD ) işlemlerini işleyen Razor
sayfaları.
Visual Studio
Visual Studio Code
Sayfalar klasöründe bir öğrenciler klasörü oluşturun.
Çözüm Gezgini, Sayfalar/öğrenciler klasörüne sağ tıklayın ve > yeni yapı iskelesi öğesi Ekle '
yi seçin.
İçinde İskele Ekle iletişim kutusunda Entity Framework (CRUD ) kullanarak Razor sayfaları >
ekleme.
Entity Framework kullanarak Razor Pages Ekle (CRUD ) iletişim kutusunda:
İçinde Model sınıfı açılan listesinde, select Öğrenci (ContosoUniversity.Models) .
Veri bağlamı sınıfı satırında + (artı) işaretini seçin.
Contosouniversity. modeller. Contosoüniversıtycontext olan veri bağlamı adını
Contosouniversity. Data. SchoolContextolarak değiştirin.
Add (Ekle) seçeneğini belirleyin.
Aşağıdaki paketler otomatik olarak yüklenir:
Microsoft.VisualStudio.Web.CodeGeneration.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.Extensions.Logging.Debug
Microsoft.EntityFrameworkCore.Tools

Önceki adımla ilgili bir sorununuz varsa, projeyi derleyin ve yapı iskelesi adımını yeniden deneyin.
Yapı iskelesi işlemi:
Sayfalar/öğrenciler klasöründe Razor sayfaları oluşturur:
. Cshtml ve Create.cshtml.cs oluşturma
Delete. cshtml ve delete.cshtml.cs
Details. cshtml ve details.cshtml.cs
. Cshtml ve Edit.cshtml.cs Düzenle
Index. cshtml ve Index.cshtml.cs
Data/SchoolContext. csoluşturur.
Startup.csiçinde bağımlılık eklenmesine bağlam ekler.
AppSettings. JSONöğesine bir veritabanı bağlantı dizesi ekler.

Veritabanı bağlantı dizesi


Visual Studio
Visual Studio Code
Bağlantı dizesini belirtir SQL Server LocalDB.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"SchoolContext": "Server=
(localdb)\\mssqllocaldb;Database=SchoolContext;Trusted_Connection=True;MultipleActiveResultSets=t
rue"
}
}

LocalDB, SQL Server Express veritabanı Motoru'nu hafif bir sürümüdür ve uygulama geliştirme,
üretim kullanımı için tasarlanmıştır. Varsayılan olarak, LocalDB C:/Users/<user> dizininde . mdf
dosyaları oluşturur.

Veritabanı bağlam sınıfını Güncelleştir


Belirli bir veri modeli için EF Core işlevselliğini koordine eden ana sınıf veritabanı bağlamı sınıfıdır.
Bağlam Microsoft. EntityFrameworkCore. DbContextöğesinden türetilir. Bağlam, veri modeline hangi
varlıkların ekleneceğini belirtir. Bu projede adlı sınıfı SchoolContext .
Güncelleştirme SchoolContext.cs aşağıdaki kod ile:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext (DbContextOptions<SchoolContext> options)
: base(options)
{
}

public DbSet<Student> Students { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}

Vurgulanan kod oluşturur bir olan DB<TEntity > her varlık kümesi özelliği. EF Core terminolojisinde:
Bir varlık kümesi, genellikle bir veritabanı tablosuna karşılık gelir.
Bir varlık tablosunda bir satıra karşılık gelir.
Bir varlık kümesi birden çok varlık içerdiğinden, DBSet özellikleri çoğul adlar olmalıdır. Scafkatlama
aracı bir Student DBSet oluşturduğundan, bu adım bunu plural Students olarak değiştirir.
Razor Pages kodun yeni DBSet adıyla eşleşmesini sağlamak için, tüm _context.Student projesi
genelinde _context.Students için genel bir değişiklik yapın. 8 oluşum vardır.
Derleyici hatası olmadığını doğrulamak için projeyi derleyin.

Startup.cs
ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (EF Core veritabanı bağlamı gibi)
uygulama başlatma sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları)
gerektiren bileşenler bu hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir veritabanı bağlamı
örneğini alan Oluşturucu kodu öğreticide daha sonra gösterilmiştir.
Scafkatlama Aracı, bağlam sınıfını bağımlılık ekleme kapsayıcısına otomatik olarak kaydetti.
Visual Studio
Visual Studio Code
ConfigureServices , vurgulanan satırlar scaffolder tarafından eklenmiştir:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();

services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
}

Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne.
Yerel geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json
dosya.

Veritabanını oluşturma
Mevcut değilse veritabanını oluşturmak için program.cs güncelleştirin:

using ContosoUniversity.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

CreateDbIfNotExists(host);

host.Run();
}

private static void CreateDbIfNotExists(IHost host)


{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Bağlam için bir veritabanı varsa, Ensuyeniden oluşturma yöntemi hiçbir eylemde bulunmaz.
Veritabanı yoksa, veritabanını ve şemayı oluşturur. EnsureCreated , veri modeli değişikliklerini işlemek
için aşağıdaki iş akışına izin vermez:
Veritabanını silin. Mevcut veriler kaybolur.
Veri modelini değiştirin. Örneğin, bir EmailAddress alanı ekleyin.
Uygulamayı çalıştırın.
EnsureCreated yeni şemaya sahip bir veritabanı oluşturur.

Bu iş akışı, verileri korumanıza gerek olmadığı sürece, şema hızlı bir şekilde gelişen zaman geliştirme
aşamasında iyi bir şekilde gerçekleştirilir. Veritabanına girilen verilerin korunması gerektiğinde bu
durum farklıdır. Bu durumda, geçişleri kullanın.
Öğretici serisinde daha sonra, EnsureCreated tarafından oluşturulan veritabanını silin ve bunun
yerine geçişleri kullanın. EnsureCreated tarafından oluşturulan bir veritabanı, geçişler kullanılarak
güncelleştirilemiyor.
Uygulamayı test etme
Uygulamayı çalıştırın.
Seçin Öğrenciler bağlantısını ve ardından Yeni Oluştur.
Ayrıntılar, düzenleme, test edin ve bağlantılarını silin.

Veritabanının çekirdeğini oluşturma


EnsureCreated yöntemi boş bir veritabanı oluşturur. Bu bölüm, veritabanını test verileriyle dolduran
kodu ekler.
Aşağıdaki kodla veri/Dbınizer. cs oluşturun:

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();

// Look for any students.


if (context.Students.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new
Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-01")},
new
Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
new
Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
new
Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-
09-01")},
new
Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
new
Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
new
Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();

var courses = new Course[]


{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}

Kod, veritabanında herhangi bir öğrenci olup olmadığını denetler. Öğrenci yoksa, veritabanına test
verileri ekler. Performansı iyileştirmek için List<T> koleksiyonları yerine diziler halinde test verileri
oluşturur.
Program.cs' de EnsureCreated çağrısını DbInitializer.Initialize çağrısıyla değiştirin:

// context.Database.EnsureCreated();
DbInitializer.Initialize(context);

Visual Studio
Visual Studio Code
Çalışıyorsa uygulamayı durdurun ve Paket Yöneticisi konsolunda (PMC ) aşağıdaki komutu
çalıştırın:

Drop-Database

Uygulamayı yeniden başlatın.


Sağlanan verileri görmek için öğrenciler sayfasını seçin.

Veritabanını görüntüleme
Visual Studio
Visual Studio Code
Açık SQL Server Nesne Gezgini (SSOX) öğesinden görünümü Visual Studio'daki menü.
SSOX 'te, (LocalDB ) \MSSQLLocalDB > veritabanları > SchoolContext-{GUID } öğesini
seçin. Veritabanı adı, daha önce belirttiğiniz bağlam adından ve bir tire ve bir GUID ile oluşturulur.
Genişletin tabloları düğümü.
Sağ Öğrenci tablosu ve'ı tıklatın görünüm verilerini oluşturulan sütunları ve tabloya eklenen
satırları görebilirsiniz.
Student modelinin Student tablo şemasına nasıl eşlendiğini görmek için öğrenci tablosuna sağ
tıklayın ve kodu görüntüle ' ye tıklayın.

Zaman uyumsuz kod


Zaman uyumsuz programlama, ASP.NET Core ve EF Core için varsayılan moddur.
Sınırlı sayıda iş parçacığı kullanılabilir bir web sunucusuna sahip ve yüksek yük durumlarda tüm
kullanılabilir iş parçacıklarının kullanımda olabilir. Bu durum oluştuğunda, sunucunun iş
parçacıklarının serbest bırakılana kadar yeni istekleri işleyemiyor. G/ç tamamlanması bekleniyor
çünkü bunlar herhangi bir iş gerçekten yapmamanız sırasında eş zamanlı kod ile birçok iş parçacığı
bağlanması. İşlemi tamamlamak, g/ç için beklerken zaman uyumsuz kod ile diğer istekleri işlemek
için kullanılacak sunucuyu için kendi iş parçacığı serbest bırakılır. Sonuç olarak, zaman uyumsuz kod
sunucu kaynaklarının daha verimli kullanılmasını sağlar ve sunucu gecikmeksizin daha fazla trafiği
işleyebilir.
Zaman uyumsuz kod, çalışma zamanında az miktarda bir ek yükü sunar. Düşük trafiğe durumlar,
performans düşüşüne yüksek trafik durumlar için göz ardı edilebilir, çalışırken, olası performans
geliştirmesi önemli.
Aşağıdaki kodda, zaman uyumsuz anahtar sözcüğü, Task<T> dönüş değeri, await anahtar sözcüğü
ve ToListAsync yöntemi zaman uyumsuz yürütülen kod olun.

public async Task OnGetAsync()


{
Students = await _context.Students.ToListAsync();
}

async Anahtar sözcüğü, derleyiciye bildirir:


Yöntem gövdesini bölümleri için geri çağırmaları oluşturur.
Döndürülen görev nesnesini oluşturun.
Task<T> dönüş türü devam eden çalışmayı temsil eder.
await Anahtar sözcüğü, derleyicinin yöntemin iki parçalara bölmek neden olur. İlk bölüm ile
zaman uyumsuz olarak başlatıldığında işlemi sonlandırır. İkinci bölümü, işlemi tamamlandıktan
sonra çağrılan bir geri çağırma yöntemi yerleştirilir.
ToListAsync zaman uyumsuz sürümüdür ToList genişletme yöntemi.

EF Core kullanan zaman uyumsuz kodu yazarken dikkat edilmesi gereken bazı noktalar şunlardır:
Yalnızca sorguları veya komutlarının veritabanına gönderilmesine neden olan deyimler zaman
uyumsuz olarak yürütülür. Bu ToListAsync , SingleOrDefaultAsync , FirstOrDefaultAsync ve
SaveChangesAsync içerir. Yalnızca değiştirmek deyimleri içermeyen bir IQueryable , gibi
var students = context.Students.Where(s => s.LastName == "Davolio") .
EF Core bağlam iş parçacığı güvenli olmayan: paralel birden çok işlem yapmak yeniden
denemeyin.
Zaman uyumsuz kodun performans avantajlarından yararlanmak için, veritabanına sorgu
gönderen EF Core yöntemleri çağırıyorsa kitaplık paketlerinin (örneğin, sayfalama için) zaman
uyumsuz olarak kullanılacağını doğrulayın.
. NET'te zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman uyumsuz genel
bakış ve zaman uyumsuz programlama ile async ve await.

Sonraki adımlar

SON RA KI
Ö Ğ R E T IC I

Contoso University örnek web uygulamasını, Entity Framework (EF ) çekirdek kullanarak bir ASP.NET
Core Razor sayfalar uygulamasının nasıl oluşturulacağını gösterir.
Örnek uygulama, kurgusal Contoso üniversite için bir web sitesidir. Öğrenci giriş, kurs oluşturma ve
Eğitmen atamaları gibi işlevleri içerir. Contoso University örnek uygulamasının nasıl oluşturulacağını
açıklayan öğreticileri serisinin ilk sayfadır.
İndirme veya tamamlanmış uygulamayı görüntüleyin. Yükleme yönergeleri.

Önkoşullar
Visual Studio
Visual Studio Code
Visual Studio 2019 aşağıdaki iş yükleri ile:
ASP.NET ve web geliştirme
.NET core platformlar arası geliştirme
.NET core 2.1 SDK veya üzeri
Konusunda Razor sayfaları. Yeni programcılar tamamlamanız gereken Razor sayfaları kullanmaya
başlama Bu seriyi başlatmadan önce.

Sorun giderme
Bir sorunla karşılaşırsanız, çözümleyemiyor çalıştırırsanız, genel olarak çözüm kodunuzda
karşılaştırarak bulabilirsiniz projeyi. Soru göndererek Yardım almak için en iyi yolu olan
StackOverflow.com için ASP.NET Core veya EF Core.
Contoso University web uygulaması
Aşağıdaki öğreticilerde oluşturulan bir uygulamayı bir temel university web sitesidir.
Kullanıcılar görüntüleyebilir ve Öğrenci, kurs ve Eğitmen bilgileri güncelleştirin. Öğreticide
oluşturulan ekranlar birkaçını aşağıda verilmiştir.
Bu sitenin UI Stili yerleşik şablonları tarafından üretilen yakın ' dir. EF çekirdekli Razor sayfaları, UI ile
öğretici odağı açıktır.

ContosoUniversity Razor sayfaları web uygulaması oluşturma


Visual Studio
Visual Studio Code
Visual Studio'dan dosya menüsünde yeni > proje.
Yeni bir ASP.NET Core Web uygulaması oluşturun. Projeyi adlandırın ContosoUniversity.
Projeyi adlandırın önemlidir ContosoUniversity kod kopyalanıp/yapıştırılmış ad alanları
eşleştirmek için.
Seçin ASP.NET Core 2.1 açılır ve ardından Web uygulaması.
Önceki adımlarda görüntüleri için bkz: Razor web uygulaması oluşturma. Uygulamayı çalıştırın.

Site stili Ayarla


Birkaç değişiklik site menü, Düzen ve giriş sayfası ayarlayın. Güncelleştirme
Pages/Shared/_Layout.cshtml aşağıdaki değişikliklerle birlikte:
"Contoso Üniversitesi" için "ContosoUniversity" her örneğini değiştirin. Üç örnekleri vardır.
Menü girdileri eklemek Öğrenciler, kursları, Eğitmenler, ve Departmanlarve silme
başvurun menüsü girişi.
Değişiklikler vurgulanır. (Tüm biçimlendirme değil görüntülenir.)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] : Contoso University</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet"
href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-
fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-
target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">Contoso University</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Students/Index">Students</a></li>
<li><a asp-page="/Courses/Index">Courses</a></li>
<li><a asp-page="/Instructors/Index">Instructors</a></li>
<li><a asp-page="/Departments/Index">Departments</a></li>
</ul>
</div>
</div>
</nav>

<partial name="_CookieConsentPartial" />

<div class="container body-content">


@RenderBody()
<hr />
<footer>
<p>&copy; 2018 : Contoso University</p>
</footer>
</div>

@*Remaining markup not shown for brevity.*@

İçinde sayfalar/dizin.cshtml, dosyanın içeriğini ASP.NET ve MVC hakkında metnin bu uygulama


hakkında metinle değiştirmek için aşağıdaki kodla değiştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core Razor Pages web app.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p>
<a class="btn btn-default"
href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro">
See the tutorial &raquo;
</a>
</p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p>
<a class="btn btn-default"
href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-
rp/intro/samples/">
See project source code &raquo;
</a>
</p>
</div>
</div>

Veri modeli oluşturma


Varlık sınıflarının Contoso University uygulama oluşturun. Aşağıdaki üç varlıklarla başlayın:

Bir-çok ilişkisi arasında Student ve Enrollment varlıklar. Bir-çok ilişkisi arasında Course ve
Enrollment varlıklar. Bir öğrenci herhangi bir sayıda kursları kaydedebilirsiniz. Bir kurs herhangi bir
sayıda Öğrenciler içinde kayıtlı olabilir.
Aşağıdaki bölümlerde, bu varlıkların her biri için bir sınıf oluşturulur.
Öğrenci varlık
Oluşturma bir modelleri klasör. İçinde modelleri klasöründe adlı bir sınıf dosyası oluşturma Student.cs
aşağıdaki kod ile:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

ID Özelliği bu sınıfa karşılık gelen veritabanı (DB ) tablosunun birincil anahtar sütunu duruma gelir.
Varsayılan olarak EF Core adlı bir özellik yorumlar ID veya classnameID birincil anahtar olarak.
İçinde classnameID , classname sınıf adıdır. Alternatif birincil anahtarı otomatik olarak kabul edilen
StudentID önceki örnekte.

Enrollments Özelliği bir gezinti özelliği. Gezinti özellikleri bu varlıkla ilgili diğer varlıkları bağlayın. Bu
durumda, Enrollments özelliği bir Student entity tüm tutan Enrollment olarak ilişkili varlıkları
Student . Örneğin, bir öğrenci satır DB'de iki kayıt satırları ilgili olan Enrollments gezinti özelliği
içerir, bu iki Enrollment varlıklar. İlgili Enrollment satırdır bu öğrencinin birincil anahtar değerini
içeren bir satır StudentID sütun. Örneğin, Öğrenci kimlikli varsayalım = 1 olan iki satır Enrollment
tablo. Enrollment Tablosunda var olan iki satır StudentID = 1. StudentID içinde bir yabancı anahtar
Enrollment içinde Öğrenci belirten tablo Student tablo.

Bir gezinme özelliği birden çok varlık tutarsanız gezinme özelliğini bir liste türü gibi olmalıdır
ICollection<T> . ICollection<T> belirtilebilir, ya da bir tür gibi List<T> veya HashSet<T> . Zaman
ICollection<T> olduğu EF Core kullanıldığında, oluşturur bir HashSet<T> varsayılan olarak
koleksiyon. Birden çok varlık tutun Gezinti özellikleri çoktan çoğa ve bire çok ilişkileri gelir.
Kayıt varlık
İçinde modelleri klasör oluşturma Enrollment.cs aşağıdaki kod ile:

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

EnrollmentID Birincil anahtar özelliğidir. Bu varlığı kullanan classnameID yerine desen ID gibi
Student varlık. Genellikle geliştiriciler bir düzen seçin ve veri modelini kullanın. Bir sonraki
öğreticide, classname Kimliğini kullanarak, veri modelinde aktarma uygulamak daha kolay hale
getirmek için gösterilir.
Grade Özelliği bir enum . Sonra soru işareti Grade türü bildirimi gösterir Grade özelliği boş değer
atanabilir. Boş bir sınıf bir sıfır sınıf farklı--null anlamına gelir bir sınıf bilinen değil veya henüz
atanmamış.
StudentID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Student . Bir
Enrollment varlıktır biriyle ilişkili Student tek bir özellik içerecek şekilde varlık Student varlık.
Student Varlık farklıdır Student.Enrollments içeren birden çok gezinti özelliği Enrollment varlıklar.

CourseID Özelliği olduğundan yabancı anahtar ve karşılık gelen gezinme özelliğini Course . Bir
Enrollment varlıktır biriyle ilişkili Course varlık.

EF Core adlandırılmışsa, bu özellik bir yabancı anahtar olarak yorumlar


<navigation property name><primary key property name> . Örneğin, StudentID için Student gezinti
özelliği bu yana Student varlığın birincil anahtarı ID . Yabancı anahtar özellikleri de adı
<primary key property name> . Örneğin, CourseID beri Course varlığın birincil anahtarı CourseID .

Kurs varlık

İçinde modelleri klasör oluşturma Course.cs aşağıdaki kod ile:


using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Enrollments Özelliktir bir gezinme özelliği. A Course varlık dilediğiniz sayıda ilgili olabileceğini
Enrollment varlıklar.
DatabaseGenerated DB sahip, oluşturmak, yerine özniteliği birincil anahtarı belirtmek için uygulamayı
sağlar.

İskele Öğrenci modeli


Bu bölümde, Öğrenci modeli iskele kurulmuş. Diğer bir deyişle, yapı iskelesi aracı sayfaları için
oluşturma, okuma, güncelleştirme ve silme (CRUD ) işlemlerine yönelik Öğrenci modeli oluşturur.
Projeyi oluşturun.
Oluşturma sayfaları/Öğrenciler klasör.
Visual Studio
Visual Studio Code
İçinde Çözüm Gezgini, sağ tıklayın sayfaları/Öğrenciler klasör > Ekle > yeni iskele kurulmuş
öğe.
İçinde İskele Ekle iletişim kutusunda Entity Framework (CRUD ) kullanarak Razor sayfaları >
ekleme.
Tamamlamak ekleme Razor sayfaları (CRUD ) Entity Framework kullanarak iletişim:
İçinde Model sınıfı açılan listesinde, select Öğrenci (ContosoUniversity.Models) .
İçinde veri bağlamı sınıfının satır, select + (artı) oturum açın ve oluşturulan bir adla değiştirin
ContosoUniversity.Models.SchoolContext.
İçinde veri bağlamı sınıfının açılan listesinde, select
ContosoUniversity.Models.SchoolContext
Add (Ekle) seçeneğini belirleyin.
Bkz: film modeli iskelesini önceki adımı ile ilgili bir sorun varsa.
İskele işlem oluşturulur ve aşağıdaki dosya değişti:
Oluşturulan dosyalar
Sayfa/Öğrenciler oluşturma, silme, Ayrıntılar, düzenleme, dizin.
Data/SchoolContext.cs
Dosya güncelleştirmeleri
Startup.cs : Bu dosyada yapılan değişiklikler sonraki bölümde ayrıntılı.
appSettings.JSON : yerel bir veritabanına bağlanmak için kullanılan bağlantı dizesi eklenir.

Bağımlılık ekleme ile kayıtlı bağlamını İnceleme


ASP.NET Core ile oluşturulmuş bağımlılık ekleme. Hizmetler (örneğin, EF Core DB bağlamı),
uygulama başlatma sırasında bağımlılık ekleme ile kaydedilir. Bu hizmetler (örneğin, Razor sayfaları)
gerektiren bileşenler bu hizmetler Oluşturucu parametresi üzerinden sağlanır. Bir db bağlamı örneği
alır Oluşturucu kodu öğreticinin ilerleyen bölümlerinde gösterilmektedir.
Yapı iskelesi aracı otomatik olarak oluşturulmuş bir veritabanı bağlamını ve bağımlılık ekleme
kapsayıcısını ile kayıtlı.
İnceleme ConfigureServices yönteminde Startup.cs. Vurgulanan satırı iskele kurucu tarafından
eklendi:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for
//non -essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
}

Bağlantı dizesi adı için bağlam üzerinde bir yöntemi çağırarak geçirilen bir DbContextOptions nesne.
Yerel geliştirme için ASP.NET Core yapılandırma sistemi bağlantı dizesinden okur appsettings.json
dosya.

Ana güncelleştir
İçinde Program.cs, değişiklik Main yöntemi aşağıdakileri yapmak için:
Bir DB bağlamı örneği bağımlılık ekleme kapsayıcısını alın.
Çağrı EnsureCreated.
Bağlam dispose olduğunda EnsureCreated yöntemi tamamlar.
Aşağıdaki kod güncelleştirilmiş gösterir Program.cs dosya.
using ContosoUniversity.Models; // SchoolContext
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; // CreateScope
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

EnsureCreated Veritabanı bağlamının var olmasını sağlar. Varsa, hiçbir işlem yapılmaz. Yoksa,
veritabanı ve tüm şema oluşturulur. EnsureCreated veritabanı oluşturmaya geçişleri kullanmaz. İle
oluşturulmuş bir veritabanı EnsureCreated daha sonra geçişleri kullanılarak güncelleştirilemez.
EnsureCreated Aşağıdaki iş akışı sağlayan uygulama Başlat menüsünde çağrılır:
DB silin.
DB şema değiştirme (örneğin, bir EmailAddress alan).
Uygulamayı çalıştırın.
EnsureCreated bir DB ile oluşturur EmailAddress sütun.

EnsureCreated Şema hızla gelişirken erken geliştirme uygundur. Daha sonra öğreticide DB silinir ve
geçişler kullanılır.
Uygulamayı test etme
Uygulamayı çalıştırın ve tanımlama bilgisi ilkesini kabul edin. Bu uygulama, kişisel bilgileri tutmak
değil. Tanımlama bilgisi ilkesi hakkında bilgi edinebilirsiniz AB genel veri koruma yönetmeliği (GDPR )
Destek.
Seçin Öğrenciler bağlantısını ve ardından Yeni Oluştur.
Ayrıntılar, düzenleme, test edin ve bağlantılarını silin.
SchoolContext DB bağlamını İnceleme
Verilen veri modeli için EF Core işlevselliği koordine eden ana DB bağlamı sınıfının sınıftır. Veri
bağlamı türetilir Microsoft.EntityFrameworkCore.DbContext. Veri bağlamı, hangi varlıkları veri
modelinde yer alan belirtir. Bu projede adlı sınıfı SchoolContext .
Güncelleştirme SchoolContext.cs aşağıdaki kod ile:

using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Models
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options)
: base(options)
{
}

public DbSet<Student> Student { get; set; }


public DbSet<Enrollment> Enrollment { get; set; }
public DbSet<Course> Course { get; set; }
}
}

Vurgulanan kod oluşturur bir olan DB<TEntity > her varlık kümesi özelliği. EF Core terminolojisinde:
Bir varlık kümesini genellikle DB tabloya karşılık gelir.
Bir varlık tablosunda bir satıra karşılık gelir.
DbSet<Enrollment> ve DbSet<Course> atlanmış. EF Core içeren bunları örtük olarak çünkü Student
varlık başvuruları Enrollment varlığı ve Enrollment varlık başvuruları Course varlık. Bu öğretici için
tutmak DbSet<Enrollment> ve DbSet<Course> içinde SchoolContext .
SQL Server Express LocalDB
Bağlantı dizesini belirtir SQL Server LocalDB. LocalDB, SQL Server Express veritabanı Motoru'nu
hafif bir sürümüdür ve uygulama geliştirme, üretim kullanımı için tasarlanmıştır. LocalDB, isteğe bağlı
olarak başlar ve karmaşık yapılandırma olduğundan kullanıcı modunda çalışır. Varsayılan olarak
LocalDB oluşturur .mdf DB dosyaları C:/Users/<user> dizin.

Bir veritabanı test verileri ile başlatmak için kod ekleyin


EF Core boş bir veritabanı oluşturur. Bu bölümde, bir Initialize yöntemi test verileriyle doldurma
işlemine yazılır.
İçinde veri klasöründe adlı yeni bir sınıf dosyası oluşturma DbInitializer.cs ve aşağıdaki kodu ekleyin:

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Models
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();

// Look for any students.


if (context.Student.Any())
if (context.Student.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new
Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new
Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new
Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new
Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-
01")},
new
Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new
Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new
Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Student.Add(s);
}
context.SaveChanges();

var courses = new Course[]


{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Course.Add(c);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollment.Add(e);
}
context.SaveChanges();
}
}
}
Note: Yukarıdaki kod Data yerine ad alanı ( namespace ContosoUniversity.Models ) için Models kullanır.
Models , scaffolder tarafından oluşturulan kodla tutarlıdır. Daha fazla bilgi için bkz. GitHub yapı
iskelesi sorunu.
Kod DB'de tüm Öğrenciler olup olmadığını denetler. DB'de Öğrenci varsa, bir veritabanı test verileri
ile başlatılır. Diziye test verileri yükler yerine List<T> performansını iyileştirmek için koleksiyonları.
EnsureCreated Yöntemi DB bağlamı için bir veritabanı otomatik olarak oluşturur. Veritabanı varsa,
EnsureCreated DB değiştirmeden döndürür.
İçinde Program.cs, değişiklik Main çağrılacak yöntem Initialize :

public class Program


{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())


{
var services = scope.ServiceProvider;

try
{
var context = services.GetRequiredService<SchoolContext>();
// using ContosoUniversity.Data;
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}

host.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}

Visual Studio
Visual Studio Code
Çalışıyorsa uygulamayı durdurun ve Paket Yöneticisi konsolunda (PMC ) aşağıdaki komutu
çalıştırın:

Drop-Database

DB görüntüleyin
Veritabanı adı, daha önce belirttiğiniz bağlam adından ve bir tire ve bir GUID ile oluşturulur. Bu
nedenle, veritabanı adı "SchoolContext-{GUID }" olacaktır. GUID her kullanıcı için farklı olacaktır. Açık
SQL Server Nesne Gezgini (SSOX) öğesinden görünümü Visual Studio'daki menü. SSOX 'te,
(LocalDB ) \MSSQLLocalDB > veritabanları > SchoolContext-{GUID } ' a tıklayın.
Genişletin tabloları düğümü.
Sağ Öğrenci tablosu ve'ı tıklatın görünüm verilerini oluşturulan sütunları ve tabloya eklenen
satırları görebilirsiniz.

Zaman uyumsuz kod


Zaman uyumsuz programlama, ASP.NET Core ve EF Core için varsayılan moddur.
Sınırlı sayıda iş parçacığı kullanılabilir bir web sunucusuna sahip ve yüksek yük durumlarda tüm
kullanılabilir iş parçacıklarının kullanımda olabilir. Bu durum oluştuğunda, sunucunun iş
parçacıklarının serbest bırakılana kadar yeni istekleri işleyemiyor. G/ç tamamlanması bekleniyor
çünkü bunlar herhangi bir iş gerçekten yapmamanız sırasında eş zamanlı kod ile birçok iş parçacığı
bağlanması. İşlemi tamamlamak, g/ç için beklerken zaman uyumsuz kod ile diğer istekleri işlemek
için kullanılacak sunucuyu için kendi iş parçacığı serbest bırakılır. Sonuç olarak, sunucu kaynaklarının
daha etkin kullanılması zaman uyumsuz kod sağlar ve sunucu gecikmeler olmadan daha fazla trafik
işlemek için etkinleştirilir.
Zaman uyumsuz kod, çalışma zamanında az miktarda bir ek yükü sunar. Düşük trafiğe durumlar,
performans düşüşüne yüksek trafik durumlar için göz ardı edilebilir, çalışırken, olası performans
geliştirmesi önemli.
Aşağıdaki kodda, zaman uyumsuz anahtar sözcüğü, Task<T> dönüş değeri, await anahtar sözcüğü
ve ToListAsync yöntemi zaman uyumsuz yürütülen kod olun.

public async Task OnGetAsync()


{
Student = await _context.Student.ToListAsync();
}

async Anahtar sözcüğü, derleyiciye bildirir:


Yöntem gövdesini bölümleri için geri çağırmaları oluşturur.
Otomatik olarak oluşturmasını görev döndürülen nesne. Daha fazla bilgi için görev dönüş
türü.
Örtük dönüş türü Task devam eden çalışmayı temsil eder.
await Anahtar sözcüğü, derleyicinin yöntemin iki parçalara bölmek neden olur. İlk bölüm ile
zaman uyumsuz olarak başlatıldığında işlemi sonlandırır. İkinci bölümü, işlemi tamamlandıktan
sonra çağrılan bir geri çağırma yöntemi yerleştirilir.
ToListAsync zaman uyumsuz sürümüdür ToList genişletme yöntemi.
EF Core kullanan zaman uyumsuz kodu yazarken dikkat edilmesi gereken bazı noktalar şunlardır:
Sorguları veya Veritabanına gönderilecek komutları neden deyimleri zaman uyumsuz olarak
yürütülür. İçeren, ToListAsync , SingleOrDefaultAsync , FirstOrDefaultAsync , ve SaveChangesAsync .
Yalnızca değiştirmek deyimleri içermeyen bir IQueryable , gibi
var students = context.Students.Where(s => s.LastName == "Davolio") .
EF Core bağlam iş parçacığı güvenli olmayan: paralel birden çok işlem yapmak yeniden
denemeyin.
Zaman uyumsuz kodun performans avantajlarından yararlanmak için bunlar için bir veritabanı
sorguları göndermek EF Core yöntemleri çağırırsanız kitaplığı paketlerinin (disk belleği
sunamıyoruz gibi) zaman uyumsuz kullandığını doğrulayın.
. NET'te zaman uyumsuz programlama hakkında daha fazla bilgi için bkz. zaman uyumsuz genel
bakış ve zaman uyumsuz programlama ile async ve await.
Sonraki öğreticide, temel CRUD (oluşturma, okuma, güncelleştirme ve silme) işlemleri incelenir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

NEXT
ASP.NET Core-CRUD-2 ' de EF Core ile Razor Pages
20.08.2019 • 34 minutes to read • Edit Online

, Tom Dykstra, Jon P Smithve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, scafkatan CRUD (oluşturma, okuma, güncelleştirme, silme) kodu incelenir ve özelleştirilir.

Depo yok
Bazı geliştiriciler, Kullanıcı arabirimi (Razor Pages) ve veri erişim katmanı arasında bir soyutlama katmanı
oluşturmak için bir hizmet katmanı veya depo deseninin kullanılmasını sağlar. Bu öğretici bunu yapmaz.
Karmaşıklığı en aza indirmek ve öğreticiyi EF Core odaklanmasını sağlamak için EF Core kodu doğrudan sayfa
modeli sınıflarına eklenir.

Ayrıntılar sayfasını Güncelleştir


Öğrenciler sayfaları için yapı iskelesi kodu kayıt verilerini içermez. Bu bölümde, ayrıntılar sayfasına kayıtları
eklersiniz.
Kayıtları oku
Sayfada öğrenciye ait kayıt verilerini göstermek için, onu okumanız gerekir. Pages/öğrenciler/details. cshtml. cs
içindeki scafkatlama kodu, kayıt verileri olmadan yalnızca öğrenci verilerini okur:

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Students.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

OnGetAsync Yöntemi, seçili öğrenci için kayıt verilerini okumak üzere aşağıdaki kodla değiştirin. Değişiklikler
vurgulanır.
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Students


.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

Include ve thenınclude yöntemleri, içeriğin Student.Enrollments gezinti özelliğini yüklemesine ve her


Enrollment.Course kaydın gezinti özelliği içine olmasına neden olur. Bu yöntemler, okuma ilgili verileri
öğreticisinde ayrıntılı olarak incelendi.
Asnotracking yöntemi, döndürülen varlıkların geçerli bağlamda güncelleştirilmediği senaryolarda performansı
geliştirir. AsNoTracking Bu öğreticinin ilerleyen kısımlarında ele alınmıştır.
Kayıtları görüntüle
Sayfalar/öğrenciler/details. cshtml içindeki kodu aşağıdaki kodla değiştirin ve kayıtlar listesini görüntüleyin.
Değişiklikler vurgulanır.
@page
@model ContosoUniversity.Pages.Students.DetailsModel

@{
ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
<h4>Student</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.Enrollments)
</dt>
<dd class="col-sm-10">
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Student.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Student.ID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>

Yukarıdaki kod, Enrollments Gezinti özelliğindeki varlıklar aracılığıyla döngü başlatır. Her kayıt için kurs
başlığını ve sınıfı görüntüler. Kurs başlığı, kayıt varlığının Course gezinti özelliğinde depolanan kurs varlığından
alınır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir öğrenci için Ayrıntılar bağlantısına tıklayın. Seçili
öğrenci için Kurslar ve notlar listesi görüntülenir.
Bir varlığı okuma yolları
Oluşturulan kod, bir varlığı okumak için Firstordefaultasync kullanır. Bu yöntem, hiçbir şey bulunamazsa null
değerini döndürür; Aksi takdirde, sorgu filtresi ölçütlerine uyan bulunan ilk satırı döndürür. FirstOrDefaultAsync
genellikle aşağıdaki alternatiflere göre daha iyi bir seçimdir:
Singleordefaultasync -sorgu filtresini karşılayan birden fazla varlık varsa bir özel durum oluşturur. Sorgu
tarafından birden fazla satır döndürülüp döndürülmeyeceğini anlamak için birden çok satır getirmeyi
SingleOrDefaultAsync dener. Sorgu yalnızca bir varlık döndürebiliyorsanız ve benzersiz bir anahtarda arama
yaptığında bu ek çalışma gereksizdir.
Findadsync -birincil ANAHTARLA (PK) bir varlık bulur. PK 'ye sahip bir varlık bağlam tarafından izleniyorsa,
veritabanına bir istek olmadan döndürülür. Bu yöntem tek bir varlık aramak için en iyi duruma getirilmiştir,
ancak ile Include FindAsync çağrılamaz. Bu nedenle, ilgili veriler gerekliyse, FirstOrDefaultAsync daha iyi bir
seçimdir.
Veri yönlendirme ve sorgu dizesi karşılaştırması
Ayrıntılar sayfasının https://localhost:<port>/Students/Details?id=1 URL 'si. Varlığın birincil anahtar değeri,
sorgu dizesinde bulunur. Bazı geliştiriciler anahtar değerini rota verilerinde geçirmeye tercih eder:
https://localhost:<port>/Students/Details/1 . Daha fazla bilgi için bkz. oluşturulan kodu güncelleştirme.

Oluştur sayfasını Güncelleştir


Oluşturma sayfası için yapı OnPostAsync İskelesi kodu, aşırı nakmeaçıktır. Pages/öğrenciler/Create. cshtml. cs
içindeki yöntemiaşağıdakikodladeğiştirin. OnPostAsync

public async Task<IActionResult> OnPostAsync()


{
var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
_context.Students.Add(emptyStudent);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}

TryUpdateModelAsync
Yukarıdaki kod bir öğrenci nesnesi oluşturur ve ardından, öğrenci nesnesinin özelliklerini güncelleştirmek için,
postalanan form alanlarını kullanır. Tryupdatemodelasync yöntemi:
PagemodelIçindeki pagecontext özelliğinden gönderilen form değerlerini kullanır.
Yalnızca listelenen ( s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate ) özellikleri güncelleştirir.
"Öğrenci" ön ekine sahip form alanlarını arar. Örneğin: Student.FirstMidName . Büyük/küçük harfe duyarlı
değildir.
, Dizelerdeki form değerlerini Student modeldeki türlere dönüştürmek için model bağlama sistemini kullanır.
Örneğin, EnrollmentDate DateTime 'a dönüştürülmesi gerekir.

Uygulamayı çalıştırın ve oluştur sayfasını test etmek için bir öğrenci varlığı oluşturun.
Fazla nakil
Deftere TryUpdateModel nakledilen değerler içeren alanları güncelleştirmek için kullanmak, aşırı nakletmeyi
önlediği için en iyi güvenlik yöntemidir. Örneğin, öğrenci varlığının bu Web sayfasının güncelleştirmesi veya
Secret eklemesi gereken bir özelliği içerdiğini varsayalım:

public class Student


{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}

Uygulama, oluşturma veya güncelleştirme Razor sayfasında Secret bir alana sahip olmasa da, bir korsan
Secret değeri aşırı nakme ile ayarlayabilir. Bir korsan, Fiddler gibi bir araç kullanabilir veya bir Secret form
değeri göndermek için bazı JavaScript yazabilir. Özgün kod, bir öğrenci örneği oluştururken model cildin
kullandığı alanları sınırlamaz.
Secret Form alanı için belirtilen korsanın hangi değeri veritabanında güncelleştirildiği. Aşağıdaki görüntüde,
alanı ("overpost" değeri ile Secret ), postalanan form değerlerine ekleyen Fiddler aracı gösterilmektedir.

"Overpost" değeri eklenen satırın Secret özelliğine başarıyla eklendi. Bu durum, Uygulama Tasarımcısı hiçbir
şekilde Secret özelliği oluştur sayfasıyla ayarlamaya yönelik değildir.
Modeli görüntüle
Model görüntüleme, fazla nakletmeyi önlemenin alternatif bir yolunu sağlar.
Uygulama modeli genellikle etki alanı modeli olarak adlandırılır. Etki alanı modeli genellikle veritabanında ilgili
varlık için gereken tüm özellikleri içerir. Görünüm modeli yalnızca için kullanılan Kullanıcı arabirimi için gereken
özellikleri içerir (örneğin, oluşturma sayfası).
Görünüm modeline ek olarak, bazı uygulamalar Razor Pages sayfa modeli sınıfı ve tarayıcı arasında veri
geçirmek için bir bağlama modeli veya giriş modeli kullanır.
Aşağıdaki Student görünüm modelini göz önünde bulundurun:
using System;

namespace ContosoUniversity.Models
{
public class StudentVM
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}

Aşağıdaki kod, yeni bir StudentVM öğrenci oluşturmak için görünüm modelini kullanır:

[BindProperty]
public StudentVM StudentVM { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var entry = _context.Add(new Student());


entry.CurrentValues.SetValues(StudentVM);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

SetValues yöntemi, başka bir PropertyValues nesnesinden değerleri okuyarak bu nesnenin değerlerini ayarlar.
SetValues Özellik adı eşleştirme kullanır. Görünüm modeli türünün model türüyle ilgili olması gerekmez,
yalnızca eşleşen özellikleri olması gerekir.
Kullanılması StudentVM için StudentVM Create . cshtml kullanılması gerekir. Student

Güncelleştirme düzenleme sayfası


Sayfalar/öğrenciler/Edit. cshtml. cs' de, OnGetAsync ve OnPostAsync yöntemlerini aşağıdaki kodla değiştirin.
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Students.FindAsync(id);

if (Student == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int id)


{
var studentToUpdate = await _context.Students.FindAsync(id);

if (studentToUpdate == null)
{
return NotFound();
}

if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}

Kod değişiklikleri, birkaç özel durum dışında oluşturma sayfasına benzerdir:


FirstOrDefaultAsync , Findadsyncile değiştirilmiştir. İlgili verileri dahil etmeniz gerekmiyorsa, FindAsync daha
etkilidir.
OnPostAsyncbir id parametreye sahiptir.
Geçerli öğrenci boş bir öğrenci oluşturmak yerine veritabanından getirilir.
Uygulamayı çalıştırın ve bir öğrenci oluşturup düzenleyerek test edin.

Varlık durumları
Veritabanı bağlamı, bellekteki varlıkların veritabanında karşılık gelen satırlarıyla eşitlenmiş olup olmadığını izler.
Bu izleme bilgileri, Savechangesasync çağrıldığında ne olacağını belirler. Örneğin, yeni bir varlık Addadsync
yöntemine geçirildiğinde, bu varlığın durumu eklendiolarak ayarlanır. SaveChangesAsync Çağrıldığında,
veritabanı bağlamı bir SQL INSERT komutu yayınlar.
Bir varlık aşağıdaki durumlardanbirinde olabilir:
Added : Varlık veritabanında henüz yok. SaveChanges Yöntemi bir INSERT ifadesini yayınlar.
Unchanged: Bu varlıkla birlikte hiçbir değişiklik kaydedilmesi gerekmiyor. Bir varlık veritabanından
okurken bu durumu içerir.
Modified : Varlığın özellik değerlerinin bazıları veya tümü değiştirildi. SaveChanges Yöntemi bir Update
ifadesini yayınlar.
Deleted : Varlık silinmek üzere işaretlendi. SaveChanges Yöntemi bir DELETE ifadesini yayınlar.
Detached : Varlık, veritabanı bağlamı tarafından izlenmiyor.

Bir masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlık okundu,
değişiklikler yapılır ve varlık durumu otomatik olarak olarak değiştirilir Modified . Çağıran SaveChanges yalnızca
değiştirilen özellikleri güncelleştiren bir SQL Update bildirisi oluşturur.
Bir Web uygulamasında, DbContext bir varlığı okur ve bir sayfa işlendikten sonra verileri görüntüler. Bir sayfanın
OnPostAsync yöntemi çağrıldığında, yeni bir Web isteği oluşturulur ve yeni bir örneğine DbContext sahiptir.
Okuyarak bu yeni bağlamdaki varlığı, masaüstü işlemesini benzetir.

Silme sayfası
Bu bölümde, çağrısı SaveChanges başarısız olduğunda özel bir hata iletisi uygulayacağınızı görürsünüz.
Pages/öğrenciler/delete. cshtml. cs dosyasındaki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır (
using deyimler temizliği dışında).

using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;

public DeleteModel(ContosoUniversity.Data.SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }
public string ErrorMessage { get; set; }

public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Students


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}

if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}

return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}

var student = await _context.Students.FindAsync(id);

if (student == null)
{
return NotFound();
}

try
{
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("./Delete",
new { id, saveChangesError = true });
}
}
}
}

Yukarıdaki kod, isteğe bağlı parametresini saveChangesError OnGetAsync Yöntem imzasına ekler.
saveChangesError öğrenci nesnesini silme hatasından sonra yöntemin çağrılıp çağrılmadığını gösterir. Geçici ağ
sorunları nedeniyle silme işlemi başarısız olabilir. Geçici ağ hataları, veritabanı bulutta olduğunda daha olasıdır.
Sil sayfası OnGetAsync kullanıcı arabiriminden çağrıldığında parametrefalse'tur. saveChangesError Tarafından
çağrıldığında ( silme saveChangesError işlemi başarısız olduğundan), parametresi true olur. OnGetAsync
OnPostAsync

Yöntemi seçili varlığı alır, ardından varlığın durumunu olarak Deleted ayarlamak için Remove yöntemini çağırır.
OnPostAsync SaveChanges Çağrıldığında, bir SQL DELETE komutu oluşturulur. Remove Başarısız olursa:

Veritabanı özel durumu yakalandı.


Sayfaları OnGetAsync Sil yöntemi ile saveChangesError=true çağırılır.

Razor silme sayfasına bir hata iletisi ekleyin (Sayfalar/öğrenciler/delete. cshtml):


@page
@model ContosoUniversity.Pages.Students.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h1>Delete</h1>

<p class="text-danger">@Model.ErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>
<h4>Student</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
</dl>

<form method="post">
<input type="hidden" asp-for="Student.ID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>

Uygulamayı çalıştırın ve Sil sayfasını test etmek için bir öğrenci silin.

Sonraki adımlar

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide, scafkatan CRUD (oluşturma, okuma, güncelleştirme, silme) kodu incelenir ve özelleştirilir.
Karmaşıklığı en aza indirmek ve bu öğreticilerin EF Core odaklanmasını sağlamak için, EF Core kod sayfa
modellerinde kullanılır. Bazı geliştiriciler, Kullanıcı arabirimi (Razor Pages) ve veri erişim katmanı arasında bir
soyutlama katmanı oluşturmak için bir hizmet katmanını veya depo modelini kullanır.
Bu öğreticide, öğrenciler klasöründeki oluşturma, düzenleme, silme ve Ayrıntılar Razor Pages incelenir.
Scafkatlanmış kod, sayfa oluşturma, düzenleme ve silme için aşağıdaki kalıbı kullanır:
HTTP GET yöntemiyle OnGetAsync istenen verileri alın ve görüntüleyin.
HTTP POST yöntemiyle OnPostAsync verilerde yapılan değişiklikleri kaydedin.

Dizin ve ayrıntı sayfaları, HTTP GET yöntemiyle istenen verileri alır ve görüntüler OnGetAsync

SingleOrDefaultAsync ile FirstOrDefaultAsync


Oluşturulan kod, genellikle Singleordefaultasyncüzerinden tercih edilen firstordefaultasynckullanır.
FirstOrDefaultAsync , bir varlık getirenden SingleOrDefaultAsync daha verimlidir:
Kodun sorgudan döndürülen birden fazla varlık olmadığını doğrulaması gerekmiyorsa.
SingleOrDefaultAsync daha fazla veri getirir ve gereksiz işler.
SingleOrDefaultAsync Filtre bölümüne uyan birden fazla varlık varsa bir özel durum oluşturur.
FirstOrDefaultAsync Filtre bölümüne uyan birden fazla varlık varsa oluşturmaz.

Findadsync
Yapı iskelesi kodunun büyük bir kısmında, yerine Findadsync kullanılabilir FirstOrDefaultAsync .
FindAsync :
Birincil anahtarla (PK) bir varlık bulur. PK 'ye sahip bir varlık bağlam tarafından izleniyorsa, VERITABANıNA
bir istek olmadan döndürülür.
Basittir ve kısadır.
Tek bir varlığı aramak için iyileştirilmiştir.
Bazı durumlarda performans avantajlarına sahip olabilir, ancak tipik Web uygulamaları için nadiren meydana
gelir.
, Maleasyncyerine dolaylı olarak firstasync kullanır.
Ancak Include başka varlıklar FindAsync istiyorsanız artık uygun değildir. Bu, uygulamanız ilerledikçe bir
sorguyu iptal FindAsync etmeniz ve bir sorguya taşımanız gerekebileceği anlamına gelir.

Ayrıntılar sayfasını özelleştirme


Pages/Students Sayfaya gidin. Düzenle, Ayrıntılarve Sil bağlantıları, Sayfalar/öğrenciler/Index. cshtml
dosyasındaki tutturucu etiketi Yardımcısı tarafından oluşturulur.

<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>

Uygulamayı çalıştırın ve bir Ayrıntılar bağlantısı seçin. URL, formundadır


http://localhost:5000/Students/Details?id=2 . Öğrenci KIMLIĞI bir sorgu dizesi ( ?id=2 ) kullanılarak geçirilir.

"{id:int}" Yol şablonunu kullanmak için düzenleme, Ayrıntılar ve silme Razor Pages güncelleştirin. Bu
sayfaların her biri için Page yönergesini ' den @page ' e @page "{id:int}" değiştirin.
Bir tamsayı yol değeri içermeyen "{id: Int}" yol şablonuna sahip sayfaya yönelik bir Istek, HTTP 404
(bulunamadı) hatası döndürüyor. Örneğin, http://localhost:5000/Students/Details 404 hatası döndürür. Kimliği
isteğe bağlı yapmak için yol kısıtlamasına ? ekleyin:

@page "{id:int?}"

Uygulamayı çalıştırın, Ayrıntılar bağlantısına tıklayın ve URL 'nin KIMLIĞI yönlendirme verileri (
http://localhost:5000/Students/Details/2 ) olarak geçirdiğini doğrulayın.
' I genel @page olarak değiştirmeyin, bunu yaparak giriş bağlantılarını keser ve sayfa oluşturabilirsiniz.
@page "{id:int}"

İlgili verileri ekleme


Öğrenciler dizin sayfasının yapı iskelesi kodu Enrollments özelliği içermez. Bu bölümde, Enrollments
koleksiyonun içeriği ayrıntılar sayfasında görüntülenir.
Pages/ öğrenciler/details. cshtml. FirstOrDefaultAsync CS yöntemi, tek Student bir varlığı almak için yöntemini
kullanır. OnGetAsync Aşağıdaki vurgulanmış kodu ekleyin:

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Student


.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}
return Page();
}

Include ve thenınclude yöntemleri, içeriğin Student.Enrollments gezinti özelliğini yüklemesine ve her


Enrollment.Course kaydın gezinti özelliği içine olmasına neden olur. Bu yöntemler, okuma ile ilgili veri
öğreticisinde ayrıntılı olarak incelenmelidir.
Asnotracking yöntemi, döndürülen varlıkların geçerli bağlamda güncelleştirilmediği durumlarda, senaryolarda
performansı geliştirir. AsNoTracking Bu öğreticinin ilerleyen kısımlarında ele alınmıştır.
Ayrıntılar sayfasında ilgili kayıtları görüntüleme
Sayfaları/öğrencileri/ayrıntıları. cshtml'yi açın. Kayıtlar listesini göstermek için aşağıdaki vurgulanmış kodu
ekleyin:
@page "{id:int}"
@model ContosoUniversity.Pages.Students.DetailsModel

@{
ViewData["Title"] = "Details";
}

<h2>Details</h2>

<div>
<h4>Student</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd>
@Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Student.Enrollments)
</dt>
<dd>
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Student.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Student.ID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>

Kod yapıştırıldıktan sonra kod girintisi yanlışsa, düzeltmek için CTRL -K-D ' a basın.
Yukarıdaki kod, Enrollments Gezinti özelliğindeki varlıklar aracılığıyla döngü başlatır. Her kayıt için kurs
başlığını ve sınıfı görüntüler. Kurs başlığı, kayıt varlığının Course gezinti özelliğinde depolanan kurs varlığından
alınır.
Uygulamayı çalıştırın, öğrenciler sekmesini seçin ve bir öğrenci için Ayrıntılar bağlantısına tıklayın. Seçili
öğrenci için Kurslar ve notlar listesi görüntülenir.

Oluştur sayfasını Güncelleştir


Pages/öğrenciler/Create. cshtml. cs dosyasındaki yöntemiaşağıdakikodlagüncelleştirin: OnPostAsync

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
_context.Student.Add(emptyStudent);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return null;
}

TryUpdateModelAsync
Tryupdatemodelasync kodunu inceleyin:

var emptyStudent = new Student();

if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{

TryUpdateModelAsync<Student> Önceki kodda, pagemodeliçindeki pagecontext özelliğinden emptyStudent


gönderilen form değerlerini kullanarak nesneyi güncelleştirmeye çalışır. TryUpdateModelAsync yalnızca listelenen (
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate ) özellikleri güncelleştirir.

Yukarıdaki örnekte:
İkinci bağımsız değişken ( "student", // Prefix ), ön ek değerleri aramak için kullanılır. Büyük/küçük harfe
duyarlı değildir.
Postalanan form değerleri model Student bağlamakullanılarak modeldeki türlere dönüştürülür.
Fazla nakil
Deftere TryUpdateModel nakledilen değerler içeren alanları güncelleştirmek için kullanmak, aşırı nakletmeyi
önlediği için en iyi güvenlik yöntemidir. Örneğin, öğrenci varlığının bu Web sayfasının güncelleştirmesi veya
Secret eklemesi gereken bir özelliği içerdiğini varsayalım:
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}

Uygulama, oluşturma/güncelleştirme Razor sayfasında Secret bir alana sahip olmasa da, bir korsan Secret
değeri aşırı nakme ile ayarlayabilir. Bir korsan, Fiddler gibi bir araç kullanabilir veya bir Secret form değeri
göndermek için bazı JavaScript yazabilir. Özgün kod, bir öğrenci örneği oluştururken model cildin kullandığı
alanları sınırlamaz.
Secret Form alanı için belirtilen korsanın hangi değeri veritabanında güncelleştirildiği. Aşağıdaki görüntüde,
alanı ("overpost" değeri ile Secret ), postalanan form değerlerine ekleyen Fiddler aracı gösterilmektedir.

"Overpost" değeri eklenen satırın Secret özelliğine başarıyla eklendi. Uygulama Tasarımcısı hiçbir şekilde hiçbir
Secret özelliği oluştur sayfasıyla ayarlamaya yönelik değildir.

Modeli görüntüle
Bir görünüm modeli, genellikle uygulama tarafından kullanılan modelde bulunan özelliklerin bir alt kümesini
içerir. Uygulama modeli genellikle etki alanı modeli olarak adlandırılır. Etki alanı modeli genellikle
VERITABANıNDAKI karşılık gelen varlık için gereken tüm özellikleri içerir. Görünüm modeli yalnızca UI katmanı
için gereken özellikleri içerir (örneğin, Oluştur sayfası). Görünüm modeline ek olarak, bazı uygulamalar Razor
Pages sayfa modeli sınıfı ve tarayıcı arasında veri geçirmek için bir bağlama modeli veya giriş modeli kullanır.
Aşağıdaki Student görünüm modelini göz önünde bulundurun:
using System;

namespace ContosoUniversity.Models
{
public class StudentVM
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}

Model görüntüleme, fazla nakletmeyi önlemenin alternatif bir yolunu sağlar. Görünüm modeli yalnızca
görüntüleme (görüntüleme) veya güncelleştirme özelliklerini içerir.
Aşağıdaki kod, yeni bir StudentVM öğrenci oluşturmak için görünüm modelini kullanır:

[BindProperty]
public StudentVM StudentVM { get; set; }

public async Task<IActionResult> OnPostAsync()


{
if (!ModelState.IsValid)
{
return Page();
}

var entry = _context.Add(new Student());


entry.CurrentValues.SetValues(StudentVM);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

SetValues yöntemi, başka bir PropertyValues nesnesinden değerleri okuyarak bu nesnenin değerlerini ayarlar.
SetValues Özellik adı eşleştirme kullanır. Görünüm modeli türünün model türüyle ilgili olması gerekmez,
yalnızca eşleşen özellikleri olması gerekir.
Kullanmak StudentVM için createvm gerekir. cshtml , yerine kullanılmak StudentVM üzere güncelleştirilir.
Student

Razor Pages, PageModel türetilmiş sınıf görünüm modelidir.

Güncelleştirme düzenleme sayfası


Düzenleme sayfasının sayfa modelini güncelleştirin. Büyük değişiklikler vurgulanır:
public class EditModel : PageModel
{
private readonly SchoolContext _context;

public EditModel(SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }

public async Task<IActionResult> OnGetAsync(int? id)


{
if (id == null)
{
return NotFound();
}

Student = await _context.Student.FindAsync(id);

if (Student == null)
{
return NotFound();
}
return Page();
}

public async Task<IActionResult> OnPostAsync(int? id)


{
if (!ModelState.IsValid)
{
return Page();
}

var studentToUpdate = await _context.Student.FindAsync(id);

if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}

return Page();
}
}

Kod değişiklikleri, birkaç özel durum dışında oluşturma sayfasına benzerdir:


OnPostAsync isteğe bağlı id bir parametreye sahiptir.
Geçerli öğrenci boş bir öğrenci oluşturmak yerine DB 'den getirilir.
FirstOrDefaultAsync , Findadsyncile değiştirilmiştir. FindAsync birincil anahtardan bir varlık seçerken iyi bir
seçimdir. Daha fazla bilgi için bkz. Findadsync .
Düzenleme ve oluşturma sayfalarını test etme
Birkaç öğrenci varlığı oluşturun ve düzenleyin.

Varlık durumları
DB bağlamı, bellekteki varlıkların VERITABANıNDA karşılık gelen satırlarıyla eşitlenmiş olup olmadığını izler.
VERITABANı bağlamı eşitleme bilgileri, Savechangesasync çağrıldığında ne olacağını belirler. Örneğin, yeni bir
varlık Addadsync yöntemine geçirildiğinde, bu varlığın durumu eklendiolarak ayarlanır. SaveChangesAsync
Çağrıldığında, DB bağlamı bir SQL INSERT komutu yayınlar.
Bir varlık aşağıdaki durumlardanbirinde olabilir:
Added : Varlık, VERITABANıNDA henüz yok. SaveChanges Yöntemi bir INSERT ifadesini yayınlar.
: Bu varlıkla birlikte hiçbir değişiklik kaydedilmesi gerekmiyor. Bir varlık, DB 'den okurken bu
Unchanged
duruma sahip olur.
Modified : Varlığın özellik değerlerinin bazıları veya tümü değiştirildi. SaveChanges Yöntemi bir Update
ifadesini yayınlar.
Deleted : Varlık silinmek üzere işaretlendi. SaveChanges Yöntemi bir DELETE ifadesini yayınlar.
Detached : Varlık DB bağlamı tarafından izlenmiyor.
Bir masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlık okundu,
değişiklikler yapılır ve varlık durumu otomatik olarak olarak değiştirilecek Modified . Çağıran SaveChanges
yalnızca değiştirilen özellikleri güncelleştiren bir SQL Update bildirisi oluşturur.
Bir Web uygulamasında, DbContext bir varlığı okur ve bir sayfa işlendikten sonra verileri görüntüler. Bir sayfanın
OnPostAsync yöntemi çağrıldığında, yeni bir Web isteği oluşturulur ve yeni bir örneğine DbContext sahiptir. Yeni
bağlamdaki varlığı yeniden okumak masaüstü işlemesini benzetir.

Silme sayfası
Bu bölümde, çağrı SaveChanges başarısız olduğunda özel bir hata iletisi uygulamak için kod eklenir. Olası hata
iletilerini içeren bir dize ekleyin:

public class DeleteModel : PageModel


{
private readonly SchoolContext _context;

public DeleteModel(SchoolContext context)


{
_context = context;
}

[BindProperty]
public Student Student { get; set; }
public string ErrorMessage { get; set; }

OnGetAsync Yöntemini aşağıdaki kodla değiştirin:


public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}

Student = await _context.Student


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (Student == null)
{
return NotFound();
}

if (saveChangesError.GetValueOrDefault())
{
ErrorMessage = "Delete failed. Try again";
}

return Page();
}

Önceki kod isteğe bağlı parametresini saveChangesError içerir. saveChangesError öğrenci nesnesini silme
hatasından sonra yöntemin çağrılıp çağrılmadığını gösterir. Geçici ağ sorunları nedeniyle silme işlemi başarısız
olabilir. Geçici ağ hataları, bulutta daha olasıdır. saveChangesError , silme sayfası OnGetAsync kullanıcı
arabiriminden çağrıldığında false 'tur. Tarafından çağrıldığında ( silme saveChangesError işlemi başarısız
olduğundan), parametresi true olur. OnGetAsync OnPostAsync
Sayfaları sil OnPostAsync yöntemi
OnPostAsync Öğesini aşağıdaki kodla değiştirin:

public async Task<IActionResult> OnPostAsync(int? id)


{
if (id == null)
{
return NotFound();
}

var student = await _context.Student


.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);

if (student == null)
{
return NotFound();
}

try
{
_context.Student.Remove(student);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("./Delete",
new { id, saveChangesError = true });
}
}
Önceki kod seçili varlığı alır, ardından varlığın durumunu olarak Deleted ayarlamak için Remove yöntemini
çağırır. SaveChanges Çağrıldığında, bir SQL DELETE komutu oluşturulur. Remove Başarısız olursa:
DB özel durumu yakalandı.
Sayfaları OnGetAsync Sil yöntemi ile saveChangesError=true çağırılır.
Razor Sil sayfasını Güncelleştir
Aşağıdaki Vurgulanan hata iletisini Razor Sil sayfasına ekleyin.

@page "{id:int}"
@model ContosoUniversity.Pages.Students.DeleteModel

@{
ViewData["Title"] = "Delete";
}

<h2>Delete</h2>

<p class="text-danger">@Model.ErrorMessage</p>

<h3>Are you sure you want to delete this?</h3>


<div>

Test silme.

Sık karşılaşılan hatalar


Öğrenciler/dizin veya diğer bağlantılar çalışmaz:
Razor sayfasının doğru @page yönergeyi içerdiğini doğrulayın. Örneğin, öğrenciler/Dizin Razor sayfası bir yol
şablonu içermemelidir:

@page "{id:int}"

Her Razor sayfası @page yönergesini içermelidir.

Ek kaynaklar
Bu öğreticinin YouTube sürümü

ÖN CEKI İleri A S P. N E T C O R E S IR A L A M A , F IL T R E L E M E , S A Y F A L A M A -3 / 8 ' D E E F C O R E R A Z O R


PAGES
ASP.NET Core sıralama, filtreleme, sayfalama-3/8 '
de EF Core Razor Pages
20.08.2019 • 44 minutes to read • Edit Online

By Tom Dykstra, Rick Andersonve Jon P Smith


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğretici, öğrenciler sayfalarına sıralama, filtreleme ve sayfalama işlevselliği ekler.
Aşağıdaki çizimde tamamlanmış bir sayfa gösterilmektedir. Sütun başlıkları sütunu sıralamak için tıklatılabilir
bağlantılardır. Artan ve azalan sıralama düzeni arasında geçiş yapmak için bir sütun başlığına tekrar tekrar
tıklayın.

Sıralama Ekle
Pages/öğrenciler/Index. cshtml. cs içindeki kodu, sıralama eklemek için aşağıdaki kodla değiştirin.
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public IList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentsIQ = from s in _context.Students


select s;

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();


}
}
}

Yukarıdaki kod:
Sıralama parametrelerini içeren özellikleri ekler.
Student Özelliğin adını olarak Students değiştirir.
OnGetAsync Yöntemindeki kodu değiştirir.

Yöntemi, URL 'deki sortOrder sorgu dizesinden bir parametre alır. OnGetAsync URL (sorgu dizesi dahil),
tutturucu etiketi Yardımcısıtarafından oluşturulur.
sortOrder Parametre "ad" ya da "Tarih" dır. Parametre sortOrder , isteğe bağlı olarak azalan sıra belirtmek için
"_DESC" tarafından izlenir. Varsayılan sıralama düzeni artan.
Öğrenciler bağlantısından Dizin sayfası istendiğinde sorgu dizesi yoktur. Öğrenciler, son ada göre artan sırada
görüntülenir. Son ada göre artan sıralama, switch deyimindeki varsayılan (gelen durumdur). Kullanıcı bir
sütun başlığı bağlantısına tıkladığında, sorgu dizesi değerinde uygun sortOrder değer sağlanır.
NameSort ve DateSort Razor sayfası tarafından sütun başlığı köprülerini uygun sorgu dizesi değerleriyle
yapılandırmak için kullanılır:

NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";


DateSort = sortOrder == "Date" ? "date_desc" : "Date";

Kod, C# koşullu işleci kullanıyor ?:. ?: İşleci üçlü bir işleçtir (üç işlenen alır). İlk satır, null veya boş sortOrder
olduğunu belirtir, NameSort "name_desc" olarak ayarlanır. Null veya boş değilseboşbirdizeolarak NameSort
ayarlanır. sortOrder
Bu iki deyim, sayfanın sütun başlığı köprülerini şu şekilde ayarlamanızı sağlar:

GEÇERLI SIRALAMA DÜZENI SON AD KÖPRÜSÜ TARIH KÖPRÜSÜ

Artan son ad descending ascending

Azalan son ad ascending ascending

Artan Tarih ascending descending

Azalan Tarih ascending ascending

Yöntemi, sıralama yapılacak sütunu belirtmek için LINQ to Entities kullanır. Kod, Switch ifadesinden
IQueryable<Student> önce bir başlatır ve Switch ifadesinde onu değiştirir:

IQueryable<Student> studentsIQ = from s in _context.Students


select s;

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();

Bir IQueryable oluşturulduğunda veya değiştirildiğinde, veritabanına hiçbir sorgu gönderilmez. IQueryable
Nesne bir koleksiyona dönüştürülene kadar sorgu yürütülmez. IQueryable , gibi bir yöntemi ToListAsync
çağırarak bir koleksiyona dönüştürülür. Bu nedenle, IQueryable kod, aşağıdaki deyime kadar yürütülemeyen
tek bir sorgu ile sonuçlanır:
Students = await studentsIQ.AsNoTracking().ToListAsync();

OnGetAsync çok sayıda sıralanabilir sütunla ayrıntı alabilir. Bu işlevi kodun alternatif bir yolu hakkında daha fazla
bilgi için, bu öğretici serisinin MVC sürümünde kodu basitleştirmek için dınamık LINQ kullanma konusuna
bakın.
Öğrenci dizini sayfasına sütun başlığı köprüleri ekleme
Öğrenciler/Index. cshtmliçindeki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>
<p>
<a asp-page="Create">Create New</a>
</p>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Yukarıdaki kod:
LastName Ve EnrollmentDate sütun başlıklarına köprüler ekler.
, Ve NameSort DateSort içindeki bilgileri kullanarak geçerli sıralama düzeni değerleriyle köprüler ayarlar.
Sayfa başlığını dizinden öğrencilerle değiştirir.
Üzerinde yapılan değişiklikler Model.Student . Model.Students

Sıralamanın çalıştığını doğrulamak için:


Uygulamayı çalıştırın ve öğrenciler sekmesini seçin.
Sütun başlıklarına tıklayın.

Filtre ekleme
Öğrenciler dizin sayfasına filtre eklemek için:
Razor sayfasına bir metin kutusu ve bir Gönder düğmesi eklenir. Metin kutusu, ad veya soyadı üzerinde bir
arama dizesi sağlar.
Sayfa modeli metin kutusu değerini kullanacak şekilde güncelleştirilir.
OnGetAsync yöntemini güncelleştirme
Öğrenciler/Index. cshtml. cs dosyasındaki kodu, filtreleme eklemek için aşağıdaki kodla değiştirin:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public IList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder, string searchString)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

CurrentFilter = searchString;

IQueryable<Student> studentsIQ = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentsIQ = studentsIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

Students = await studentsIQ.AsNoTracking().ToListAsync();


}
}
}

Yukarıdaki kod:
Yöntemine parametresini ekler ve parametre değerini CurrentFilter özelliğine kaydeder. searchString
OnGetAsync Arama dizesi değeri bir sonraki bölüme eklenen bir metin kutusundan alınır.
LINQ deyimi a Where yan tümcesine ekler. Where Yan tümce yalnızca adı veya soyadı arama dizesini içeren
öğrencileri seçer. LINQ deyimleri yalnızca aranacak bir değer varsa yürütülür.
IQueryable vs. IEnumerable
Kod, Where yöntemi bir IQueryable nesne üzerinde çağırır ve filtre sunucuda işlenir. Bazı senaryolarda,
uygulama bir bellek içi koleksiyonda bir genişletme Where yöntemi olarak yöntemi çağırıyor olabilir. Örneğin,
EF Core DbSet 'den _context.Students bir IEnumerable koleksiyonu döndüren bir depo yöntemine yapılan
değişiklikleri varsayın. Sonuç normalde aynı olur, ancak bazı durumlarda farklı olabilir.
Örneğin, uygulamasının Contains .NET Framework uygulanması varsayılan olarak büyük/küçük harfe duyarlı
bir karşılaştırma gerçekleştirir. SQL Server, Contains büyük/küçük harf duyarlılığı SQL Server örneğinin
harmanlama ayarına göre belirlenir. SQL Server varsayılan olarak büyük/küçük harfe duyarlı değildir. SQLite,
büyük/küçük harfe duyarlı olur. ToUpper testi açık büyük/küçük harfe duyarsız hale getirmek için çağrılabilir:

Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())`

Yukarıdaki kod, Where yöntemin bir veya bir IEnumerable SQLite üzerinde çağrılması durumunda bile filtrenin
büyük/küçük harf duyarsız olmasını güvence altına alır.
Contains Bir IEnumerable koleksiyon üzerinde çağrıldığında .NET Core uygulamasını kullanır. Contains Bir
IQueryable nesne üzerinde çağrıldığında, veritabanı uygulamasını kullanır.

Contains Bir IQueryable üzerinde çağırmak, genellikle performans nedenleriyle tercih edilir. İle IQueryable ,
filtreleme veritabanı sunucusu tarafından yapılır. Önce bir IEnumerable oluşturulduysa, tüm satırların veritabanı
sunucusundan döndürülmesi gerekir.
Çağırmak ToUpper için bir performans cezası vardır. ToUpper Kod, TSQL SELECT ifadesinin WHERE yan
tümcesine bir işlev ekler. Eklenen işlev, iyileştiricinin bir dizin kullanmasını önler. SQL, büyük/küçük harfe
duyarsız olarak yüklendiği için, gerekli olmadığında ToUpper çağrının önüne geçmek en iyisidir.
Daha fazla bilgi için bkz. SQLite sağlayıcı ile büyük/küçük harfe duyarsız sorgu kullanma.
Razor sayfasını güncelleştirme
Sayfalar/öğrenciler/Index. cshtml içindeki kodu, bir arama düğmesi ve assıralanan Chrome oluşturmak için
değiştirin.
@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-primary" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Yukarıdaki kod, arama metin <form> kutusu ve düğme eklemek için etiket yardımcısını kullanır. Varsayılan
olarak, <form> etiket Yardımcısı form verilerini bir gönderiyle gönderir. POST ile parametreler, URL 'de değil
HTTP ileti gövdesine geçirilir. HTTP GET kullanıldığında, form verileri URL 'ye sorgu dizeleri olarak geçirilir.
Verilerin sorgu dizelerine geçirilmesi, kullanıcıların URL 'YI yer işaretine eklemesini sağlar. W3C yönergeleri ,
eylem bir güncelleştirme ile SONUÇLANMAZSA, Get 'in kullanılması önerilir.
Uygulamayı test edin:
Öğrenciler sekmesini seçin ve bir arama dizesi girin. SQLite kullanıyorsanız, filtre yalnızca daha önce
gösterilen isteğe bağlı ToUpper kodu uyguladıysanız, büyük/küçük harfe duyarlıdır.
Ara' yı seçin.
URL 'nin arama dizesini içerdiğine dikkat edin. Örneğin:

https://localhost:<port>/Students?SearchString=an

Sayfa yer işaretiyle, yer işareti sayfanın URL 'sini ve SearchString sorgu dizesini içerir. method="get"
Etiketi,sorgu form dizesinin oluşturulmasına neden oldu.
Şu anda, bir sütun başlığı sıralama bağlantısı seçildiğinde, arama kutusundaki filtre değeri kaybedilir. Kayıp
filtre değeri bir sonraki bölümde düzeltilir.

Sayfalama Ekle
Bu bölümde, sayfalama desteği PaginatedList için bir sınıf oluşturulur. Sınıfı, tablodaki tüm Take satırları
almak yerine, sunucudaki verileri filtrelemek için ve deyimlerini kullanır Skip . PaginatedList Aşağıdaki
çizimde sayfalama düğmeleri gösterilmektedir.

Sayfalı liste sınıfını oluşturma


Proje klasöründe aşağıdaki kodla oluşturun PaginatedList.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)


{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);

this.AddRange(items);
}

public bool HasPreviousPage


{
get
{
return (PageIndex > 1);
}
}

public bool HasNextPage


{
get
{
return (PageIndex < TotalPages);
}
}

public static async Task<PaginatedList<T>> CreateAsync(


IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip(
(pageIndex - 1) * pageSize)
.Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}

Yukarıdaki koddaki Skip Take IQueryable yöntemi sayfa boyutunu ve sayfa numarasını alır ve ' a uygun ve
deyimlerini uygular. CreateAsync ToListAsync Üzerindeçağrıldığında,yalnızcaistenensayfayı IQueryable içeren
bir liste döndürür. Özellikler HasPreviousPage ve HasNextPage önceki ve sonraki sayfalama düğmelerini
etkinleştirmek veya devre dışı bırakmak için kullanılır.
Yöntemi oluşturmak için kullanılır. PaginatedList<T> CreateAsync Oluşturucu PaginatedList<T> nesneyi
oluşturamıyor; oluşturucular zaman uyumsuz kod çalıştıramıyor.
PageModel sınıfına sayfalama ekleme
Öğrenciler/Index. cshtml. cs ' deki kodu, sayfalama eklemek için değiştirin.

using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContosoUniversity.Pages.Students
{
public class IndexModel : PageModel
{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

public PaginatedList<Student> Students { get; set; }

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)
{
CurrentSort = sortOrder;
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

CurrentFilter = searchString;

IQueryable<Student> studentsIQ = from s in _context.Students


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentsIQ = studentsIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentsIQ = studentsIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentsIQ = studentsIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentsIQ = studentsIQ.OrderBy(s => s.LastName);
break;
}

int pageSize = 3;
Students = await PaginatedList<Student>.CreateAsync(
studentsIQ.AsNoTracking(), pageIndex ?? 1, pageSize);
}
}
}
}

Yukarıdaki kod:
Students Özelliğinin türünü PaginatedList<Student> olarak değiştirir. IList<Student>
Sayfa dizinini, geçerli sortOrder currentFilter ve OnGetAsync öğesini Yöntem imzasına ekler.
Sıralama düzenini CurrentSort özelliğine kaydeder.
Yeni bir arama dizesi olduğunda sayfa dizinini 1 olarak sıfırlar.
Öğrenci varlıklarını almak için sınıfınıkullanır. PaginatedList

Şu durumlarda OnGetAsync alan tüm parametreler null:


Sayfa öğrenciler bağlantısından çağrılır.
Kullanıcı bir sayfalama veya sıralama bağlantısına tıklamadı.
Bir sayfalama bağlantısına tıklandığında, sayfa dizin değişkeni görüntülenecek sayfa numarasını içerir.
CurrentSort Özelliği, geçerli sıralama düzeni ile Razor sayfasını sağlar. Disk belleği sırasında sıralama düzenini
korumak için geçerli sıralama düzeni, sayfalama bağlantılarına eklenmelidir.
CurrentFilter Özelliği, Razor sayfasını geçerli filtre dizesiyle birlikte sağlar. CurrentFilter Değer:
Disk belleği sırasında filtre ayarlarını korumak için disk belleği bağlantılarına eklenmelidir.
Sayfa yeniden görüntülendiğinde metin kutusuna geri yüklenmelidir.
Sayfalama sırasında arama dizesi değiştirilirse sayfa 1 ' e sıfırlanır. Yeni filtre farklı verilerin görüntülenmesini
sağladığından sayfanın 1 olarak sıfırlanması. Bir arama değeri girildiğinde ve Gönder seçildiğinde:
Arama dizesi değiştirildi.
searchString Parametre null değil.

Yöntemi PaginatedList.CreateAsync , öğrenci sorgusunu, sayfalama destekleyen bir koleksiyon türündeki tek
bir öğrenci sayfasına dönüştürür. Bu tek öğrenci sayfası Razor sayfasına geçirilir.
Çağrıdan PaginatedList.CreateAsync sonraki pageIndex iki soru işareti, null birleşim işlecinitemsil eder. Null
birleşim işleci, null yapılabilir bir tür için varsayılan değeri tanımlar. İfade (pageIndex ?? 1) , bir değer
pageIndex içeriyorsa değerini döndürür anlamına gelir. pageIndex Değer yoksa 1 döndürün.

Razor sayfasına sayfalama bağlantıları ekleme


Öğrenciler/Index. cshtml içindeki kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Students";
}

<h2>Students</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-primary" /> |
<a asp-page="./Index">Back to full List</a>
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Students[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@{
var prevDisabled = !Model.Students.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.Students.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @nextDisabled">
Next
</a>
Sütun üst bilgisi bağlantıları, geçerli arama dizesini OnGetAsync yönteme geçirmek için sorgu dizesini kullanır:

<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"


asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Students[0].LastName)
</a>

Sayfalama düğmeleri etiket yardımcıları tarafından görüntülenir:

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-primary @nextDisabled">
Next
</a>

Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.


Sayfalama 'nin çalıştığından emin olmak için, farklı sıralama emirlerindeki disk belleği bağlantılarına tıklayın.
Disk belleğinin sıralama ve filtreleme ile düzgün çalıştığını doğrulamak için bir arama dizesi girin ve
sayfalama yapmayı deneyin.

Gruplandırma Ekle
Bu bölüm, her kayıt tarihi için kaç öğrenciye kaydolduğunu görüntüleyen bir hakkında sayfası oluşturur.
Güncelleştirme gruplamayı kullanır ve aşağıdaki adımları içerir:
Hakkında sayfasında kullanılan veriler için bir görünüm modeli oluşturun.
Görünüm modelini kullanmak için hakkında sayfasını güncelleştirin.
Görünüm modeli oluşturma
Modeller/SchoolViewModels klasörü oluşturun.
Aşağıdaki kodla SchoolViewModels/kayıtlarını Mentdategroup. cs oluşturun:

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; }

public int StudentCount { get; set; }


}
}

Razor sayfasını oluşturma


Aşağıdaki kodla bir Pages/about. cshtml dosyası oluşturun:

@page
@model ContosoUniversity.Pages.AboutModel

@{
ViewData["Title"] = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
<tr>
<th>
Enrollment Date
</th>
<th>
Students
</th>
</tr>

@foreach (var item in Model.Students)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

Sayfa modelini oluşturma


Aşağıdaki kodla bir Pages/about. cshtml. cs dosyası oluşturun:
using ContosoUniversity.Models.SchoolViewModels;
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ContosoUniversity.Models;

namespace ContosoUniversity.Pages
{
public class AboutModel : PageModel
{
private readonly SchoolContext _context;

public AboutModel(SchoolContext context)


{
_context = context;
}

public IList<EnrollmentDateGroup> Students { get; set; }

public async Task OnGetAsync()


{
IQueryable<EnrollmentDateGroup> data =
from student in _context.Students
group student by student.EnrollmentDate into dateGroup
select new EnrollmentDateGroup()
{
EnrollmentDate = dateGroup.Key,
StudentCount = dateGroup.Count()
};

Students = await data.AsNoTracking().ToListAsync();


}
}
}

LINQ beyanı, öğrenci varlıklarını kayıt tarihine göre gruplandırır, her bir gruptaki varlıkların sayısını hesaplar ve
sonuçları bir EnrollmentDateGroup görünüm modeli nesneleri koleksiyonunda depolar.
Uygulamayı çalıştırın ve hakkında sayfasına gidin. Her kayıt tarihi için öğrenci sayısı bir tabloda görüntülenir.
Sonraki adımlar
Sonraki öğreticide, uygulama, veri modelini güncelleştirmek için geçişleri kullanır.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide sıralama, filtreleme, gruplama ve sayfalama işlevleri eklenmiştir.


Aşağıdaki çizimde tamamlanmış bir sayfa gösterilmektedir. Sütun başlıkları sütunu sıralamak için tıklatılabilir
bağlantılardır. Sütun başlığına tıklanması, artan ve azalan sıralama düzeni arasında sürekli olarak geçiş yapar.

Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.

Dizin sayfasına sıralama Ekle


Sıralama parametrelerini içerecek şekilde öğrenciler/Index. cshtml. cs PageModel öğesine dizeler ekleyin:

public class IndexModel : PageModel


{
private readonly SchoolContext _context;

public IndexModel(SchoolContext context)


{
_context = context;
}

public string NameSort { get; set; }


public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }

Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:


public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Yukarıdaki kod, URL 'deki sortOrder sorgu dizesinden bir parametre alır. URL (sorgu dizesi dahil), tutturucu
etiketi Yardımcısı tarafından oluşturulur
sortOrder Parametre "ad" ya da "Tarih" dır. Parametre sortOrder , isteğe bağlı olarak azalan sıra belirtmek için
"_DESC" tarafından izlenir. Varsayılan sıralama düzeni artan.
Öğrenciler bağlantısından Dizin sayfası istendiğinde sorgu dizesi yoktur. Öğrenciler, son ada göre artan sırada
görüntülenir. Son ada göre artan sıralama, switch deyimindeki varsayılan (gelen durumdur). Kullanıcı bir
sütun başlığı bağlantısına tıkladığında, sorgu dizesi değerinde uygun sortOrder değer sağlanır.
NameSort ve DateSort Razor sayfası tarafından sütun başlığı köprülerini uygun sorgu dizesi değerleriyle
yapılandırmak için kullanılır:
public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Aşağıdaki kod, C# koşullu ?: işleciniiçerir:

NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";


DateSort = sortOrder == "Date" ? "date_desc" : "Date";

İlk satır, null veya boş sortOrder olduğunu belirtir, NameSort "name_desc" olarak ayarlanır. Null veya boş
değilseboşbirdizeolarak NameSort ayarlanır. sortOrder
, ?: operator Üçlü işleç olarak da bilinir.
Bu iki deyim, sayfanın sütun başlığı köprülerini şu şekilde ayarlamanızı sağlar:

GEÇERLI SIRALAMA DÜZENI SON AD KÖPRÜSÜ TARIH KÖPRÜSÜ

Artan son ad descending ascending

Azalan son ad ascending ascending

Artan Tarih ascending descending

Azalan Tarih ascending ascending

Yöntemi, sıralama yapılacak sütunu belirtmek için LINQ to Entities kullanır. Kod, Switch ifadesinden
IQueryable<Student> önce bir başlatır ve Switch ifadesinde onu değiştirir:
public async Task OnGetAsync(string sortOrder)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";

IQueryable<Student> studentIQ = from s in _context.Student


select s;

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Bir IQueryable oluşturulduğunda veya değiştirildiğinde, veritabanına hiçbir sorgu gönderilmez. IQueryable
Nesne bir koleksiyona dönüştürülene kadar sorgu yürütülmez. IQueryable , gibi bir yöntemi ToListAsync
çağırarak bir koleksiyona dönüştürülür. Bu nedenle, IQueryable kod, aşağıdaki deyime kadar yürütülemeyen
tek bir sorgu ile sonuçlanır:

Student = await studentIQ.AsNoTracking().ToListAsync();

OnGetAsync çok sayıda sıralanabilir sütunla ayrıntı alabilir.


Öğrenci dizini sayfasına sütun başlığı köprüleri ekleme
Öğrenciler/Index. cshtmliçindeki kodu aşağıdaki vurgulanmış kodla değiştirin:
@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>
<p>
<a asp-page="Create">Create New</a>
</p>

<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Student)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Yukarıdaki kod:
LastName Ve EnrollmentDate sütun başlıklarına köprüler ekler.
, Ve NameSort DateSort içindeki bilgileri kullanarak geçerli sıralama düzeni değerleriyle köprüler ayarlar.
Sıralamanın çalıştığını doğrulamak için:
Uygulamayı çalıştırın ve öğrenciler sekmesini seçin.
Son ad' a tıklayın.
Kayıt tarihi' ne tıklayın.
Kodu daha iyi anlamak için:
Öğrenciler/Index. cshtml. csdosyasında, üzerinde switch (sortOrder) bir kesme noktası ayarlayın.
NameSort Ve DateSort için bir izleme ekleyin.
Öğrenciler/Index. cshtml'de, üzerinde @Html.DisplayNameFor(model => model.Student[0].LastName) bir kesme
noktası ayarlayın.
Hata ayıklayıcıda adım adım.

Öğrenciler dizin sayfasına bir arama kutusu ekleyin


Öğrenciler dizin sayfasına filtre eklemek için:
Razor sayfasına bir metin kutusu ve bir Gönder düğmesi eklenir. Metin kutusu, ad veya soyadı üzerinde bir
arama dizesi sağlar.
Sayfa modeli metin kutusu değerini kullanacak şekilde güncelleştirilir.
Dizin yöntemine filtreleme işlevi ekleme
Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync(string sortOrder, string searchString)


{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
CurrentFilter = searchString;

IQueryable<Student> studentIQ = from s in _context.Student


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentIQ = studentIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

Student = await studentIQ.AsNoTracking().ToListAsync();


}

Yukarıdaki kod:
OnGetAsync Yöntemine searchString parametresini ekler. Arama dizesi değeri bir sonraki bölüme eklenen
bir metin kutusundan alınır.
LINQ deyimi bir Where yan tümcesine eklendi. Where Yan tümce yalnızca adı veya soyadı arama dizesini
içeren öğrencileri seçer. LINQ deyimleri yalnızca aranacak bir değer varsa yürütülür.
Not: Yukarıdaki kod, Where metodu bir IQueryable nesne üzerinde çağırır ve filtre sunucuda işlenir. Bazı
senaryolarda, uygulama bir bellek içi koleksiyonda bir genişletme Where yöntemi olarak yöntemi çağırıyor
olabilir. Örneğin, EF Core DbSet 'den _context.Students bir IEnumerable koleksiyonu döndüren bir depo
yöntemine yapılan değişiklikleri varsayın. Sonuç normalde aynı olur, ancak bazı durumlarda farklı olabilir.
Örneğin, uygulamasının Contains .NET Framework uygulanması varsayılan olarak büyük/küçük harfe duyarlı
bir karşılaştırma gerçekleştirir. SQL Server, Contains büyük/küçük harf duyarlılığı SQL Server örneğinin
harmanlama ayarına göre belirlenir. SQL Server varsayılan olarak büyük/küçük harfe duyarlı değildir. ToUpper
testi açık büyük/küçük harfe duyarsız hale getirmek için çağrılabilir:
Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())

Yukarıdaki kod, kodun kullanım IEnumerable için değişiklik yaptığı durumlarda sonuçların büyük/küçük harf
duyarsız olmasını sağlar. Contains Bir IEnumerable koleksiyon üzerinde çağrıldığında .NET Core uygulamasını
kullanır. Contains Bir IQueryable nesne üzerinde çağrıldığında, veritabanı uygulamasını kullanır. IEnumerable
Bir depodan döndürmek önemli bir performans cezasına sahip olabilir:
1. Tüm satırlar DB sunucusundan döndürülür.
2. Filtre, uygulamadaki tüm döndürülen satırlara uygulanır.
Çağırmak ToUpper için bir performans cezası vardır. ToUpper Kod, TSQL SELECT ifadesinin WHERE yan
tümcesine bir işlev ekler. Eklenen işlev, iyileştiricinin bir dizin kullanmasını önler. SQL, büyük/küçük harfe
duyarsız olarak yüklendiği için, gerekli olmadığında ToUpper çağrının önüne geçmek en iyisidir.
Öğrenci dizin sayfasına bir arama kutusu ekleyin
Sayfalar/öğrenciler/Index. cshtml' de, bir arama düğmesi ve asi grafik Chrome oluşturmak için aşağıdaki
vurgulanmış kodu ekleyin.

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name:
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">

Yukarıdaki kod, arama metin <form> kutusu ve düğme eklemek için etiket yardımcısını kullanır. Varsayılan
olarak, <form> etiket Yardımcısı form verilerini bir gönderiyle gönderir. POST ile parametreler, URL 'de değil
HTTP ileti gövdesine geçirilir. HTTP GET kullanıldığında, form verileri URL 'ye sorgu dizeleri olarak geçirilir.
Verilerin sorgu dizelerine geçirilmesi, kullanıcıların URL 'YI yer işaretine eklemesini sağlar. W3C yönergeleri ,
eylem bir güncelleştirme ile SONUÇLANMAZSA, Get 'in kullanılması önerilir.
Uygulamayı test edin:
Öğrenciler sekmesini seçin ve bir arama dizesi girin.
Ara' yı seçin.
URL 'nin arama dizesini içerdiğine dikkat edin.

http://localhost:5000/Students?SearchString=an

Sayfa yer işaretiyle, yer işareti sayfanın URL 'sini ve SearchString sorgu dizesini içerir. method="get"
Etiketi,sorgu form dizesinin oluşturulmasına neden oldu.
Şu anda, bir sütun başlığı sıralama bağlantısı seçildiğinde, arama kutusundaki filtre değeri kaybedilir. Kayıp
filtre değeri bir sonraki bölümde düzeltilir.

Öğrenciler dizin sayfasına sayfalama işlevselliği ekleme


Bu bölümde, sayfalama desteği PaginatedList için bir sınıf oluşturulur. Sınıfı, tablodaki tüm Take satırları
almak yerine, sunucudaki verileri filtrelemek için ve deyimlerini kullanır Skip . PaginatedList Aşağıdaki
çizimde sayfalama düğmeleri gösterilmektedir.

Proje klasöründe aşağıdaki kodla oluşturun PaginatedList.cs :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)


{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);

this.AddRange(items);
}

public bool HasPreviousPage


{
get
{
return (PageIndex > 1);
}
}

public bool HasNextPage


{
get
{
return (PageIndex < TotalPages);
}
}

public static async Task<PaginatedList<T>> CreateAsync(


IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip(
(pageIndex - 1) * pageSize)
.Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}

Yukarıdaki koddaki Skip Take IQueryable yöntemi sayfa boyutunu ve sayfa numarasını alır ve ' a uygun ve
deyimlerini uygular. CreateAsync ToListAsync Üzerindeçağrıldığında,yalnızcaistenensayfayı IQueryable içeren
bir liste döndürür. Özellikler HasPreviousPage ve HasNextPage önceki ve sonraki sayfalama düğmelerini
etkinleştirmek veya devre dışı bırakmak için kullanılır.
Yöntemi oluşturmak için kullanılır. PaginatedList<T> CreateAsync Bir Oluşturucu PaginatedList<T> nesneyi
oluşturamaz, oluşturucular zaman uyumsuz kod çalıştıramıyorum.

Dizin yöntemine sayfalama işlevselliği ekleme


Öğrenciler/Index. cshtml. csdosyasında, türünü Student ile PaginatedList<Student> arasında IList<Student>
güncelleştirin:
public PaginatedList<Student> Student { get; set; }

Öğrenciler/Index. cshtml. cs OnGetAsync ' i aşağıdaki kodla güncelleştirin:

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)
{
CurrentSort = sortOrder;
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

CurrentFilter = searchString;

IQueryable<Student> studentIQ = from s in _context.Student


select s;
if (!String.IsNullOrEmpty(searchString))
{
studentIQ = studentIQ.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
case "name_desc":
studentIQ = studentIQ.OrderByDescending(s => s.LastName);
break;
case "Date":
studentIQ = studentIQ.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
studentIQ = studentIQ.OrderByDescending(s => s.EnrollmentDate);
break;
default:
studentIQ = studentIQ.OrderBy(s => s.LastName);
break;
}

int pageSize = 3;
Student = await PaginatedList<Student>.CreateAsync(
studentIQ.AsNoTracking(), pageIndex ?? 1, pageSize);
}

Yukarıdaki kod, sayfa dizinini, geçerli sortOrder currentFilter ve öğesini Yöntem imzasına ekler.

public async Task OnGetAsync(string sortOrder,


string currentFilter, string searchString, int? pageIndex)

Şu durumlarda tüm parametreler null:


Sayfa öğrenciler bağlantısından çağrılır.
Kullanıcı bir sayfalama veya sıralama bağlantısına tıklamadı.
Bir sayfalama bağlantısına tıklandığında, sayfa dizin değişkeni görüntülenecek sayfa numarasını içerir.
CurrentSort geçerli sıralama düzeninde Razor sayfası sağlar. Disk belleği sırasında sıralama düzenini korumak
için geçerli sıralama düzeni, sayfalama bağlantılarına eklenmelidir.
CurrentFilter geçerli filtre dizesiyle Razor sayfasını sağlar. CurrentFilter Değer:
Disk belleği sırasında filtre ayarlarını korumak için disk belleği bağlantılarına eklenmelidir.
Sayfa yeniden görüntülendiğinde metin kutusuna geri yüklenmelidir.
Sayfalama sırasında arama dizesi değiştirilirse sayfa 1 ' e sıfırlanır. Yeni filtre farklı verilerin görüntülenmesini
sağladığından sayfanın 1 olarak sıfırlanması. Bir arama değeri girildiğinde ve Gönder seçildiğinde:
Arama dizesi değiştirildi.
searchString Parametre null değil.

if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}

Yöntemi PaginatedList.CreateAsync , öğrenci sorgusunu, sayfalama destekleyen bir koleksiyon türündeki tek
bir öğrenci sayfasına dönüştürür. Bu tek öğrenci sayfası Razor sayfasına geçirilir.

Student = await PaginatedList<Student>.CreateAsync(


studentIQ.AsNoTracking(), pageIndex ?? 1, pageSize);

İçindeki PaginatedList.CreateAsync iki soru işareti, null birleşim işlecinitemsil eder. Null birleşim işleci, null
yapılabilir bir tür için varsayılan değeri tanımlar. İfade (pageIndex ?? 1) , bir değer pageIndex içeriyorsa
değerini döndürür anlamına gelir. pageIndex Değer yoksa 1 döndürün.

Öğrenci Razor sayfasına sayfalama bağlantıları ekleme


Öğrenciler/Index. cshtml'de biçimlendirmeyi güncelleştirin. Değişiklikler vurgulanır:

@page
@model ContosoUniversity.Pages.Students.IndexModel

@{
ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
<a asp-page="Create">Create New</a>
</p>

<form asp-page="./Index" method="get">


<div class="form-actions no-color">
<p>
Find by name: <input type="text" name="SearchString" value="@Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-page="./Index">Back to full List</a>
</p>
</div>
</form>

<table class="table">
<thead>
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>
</th>
<th>
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Student)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

@{
var prevDisabled = !Model.Student.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.Student.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @nextDisabled">
Next
</a>

Sütun üst bilgisi bağlantıları, kullanıcının filtre sonuçları içinde sıralama yapabilmesi için geçerli arama dizesini
OnGetAsync yöntemine geçirmek üzere sorgu dizesini kullanır:
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
asp-route-currentFilter="@Model.CurrentFilter">
@Html.DisplayNameFor(model => model.Student[0].LastName)
</a>

Sayfalama düğmeleri etiket yardımcıları tarafından görüntülenir:

<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"
class="btn btn-default @nextDisabled">
Next
</a>

Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.


Sayfalama 'nin çalıştığından emin olmak için, farklı sıralama emirlerindeki disk belleği bağlantılarına tıklayın.
Disk belleğinin sıralama ve filtreleme ile düzgün çalıştığını doğrulamak için bir arama dizesi girin ve
sayfalama yapmayı deneyin.

Kodu daha iyi anlamak için:


Öğrenciler/Index. cshtml. csdosyasında, üzerinde switch (sortOrder) bir kesme noktası ayarlayın.
, NameSort , Ve DateSort CurrentSort için birizlemeekleyin. Model.Student.PageIndex
Öğrenciler/Index. cshtml'de, üzerinde @Html.DisplayNameFor(model => model.Student[0].LastName) bir kesme
noktası ayarlayın.
Hata ayıklayıcıda adım adım.

Öğrenci istatistiklerini göstermek için hakkında sayfasını


güncelleştirin
Bu adımda, Sayfalar/about. cshtml , her bir kayıt tarihi için kaç öğrenciye kaydolduğunu görüntüleyecek şekilde
güncelleştirilir. Güncelleştirme gruplamayı kullanır ve aşağıdaki adımları içerir:
Hakkında sayfasında kullanılan veriler için bir görünüm modeli oluşturun.
Görünüm modelini kullanmak için hakkında sayfasını güncelleştirin.
Görünüm modeli oluşturma
Modeller klasöründe bir SchoolViewModels klasörü oluşturun.
SchoolViewModels klasöründe aşağıdaki kodla bir EnrollmentDateGroup.cs ekleyin:

using System;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models.SchoolViewModels
{
public class EnrollmentDateGroup
{
[DataType(DataType.Date)]
public DateTime? EnrollmentDate { get; set; }

public int StudentCount { get; set; }


}
}

Hakkında sayfa modelini Güncelleştir


ASP.NET Core 2,2 ' deki Web şablonları hakkında sayfasını içermez. ASP.NET Core 2,2 kullanıyorsanız, Razor
hakkında sayfasını oluşturun.
Pages/about. cshtml. cs dosyasını aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ContosoUniversity.Models;

namespace ContosoUniversity.Pages
{
public class AboutModel : PageModel
{
private readonly SchoolContext _context;

public AboutModel(SchoolContext context)


{
_context = context;
}

public IList<EnrollmentDateGroup> Student { get; set; }

public async Task OnGetAsync()


{
IQueryable<EnrollmentDateGroup> data =
from student in _context.Student
group student by student.EnrollmentDate into dateGroup
select new EnrollmentDateGroup()
{
EnrollmentDate = dateGroup.Key,
StudentCount = dateGroup.Count()
};

Student = await data.AsNoTracking().ToListAsync();


}
}
}

LINQ beyanı, öğrenci varlıklarını kayıt tarihine göre gruplandırır, her bir gruptaki varlıkların sayısını hesaplar ve
sonuçları bir EnrollmentDateGroup görünüm modeli nesneleri koleksiyonunda depolar.
Razor hakkında sayfasında değişiklik yapma
Pages/about. cshtml dosyasındaki kodu aşağıdaki kodla değiştirin:
@page
@model ContosoUniversity.Pages.AboutModel

@{
ViewData["Title"] = "Student Body Statistics";
}

<h2>Student Body Statistics</h2>

<table>
<tr>
<th>
Enrollment Date
</th>
<th>
Students
</th>
</tr>

@foreach (var item in Model.Student)


{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
@item.StudentCount
</td>
</tr>
}
</table>

Uygulamayı çalıştırın ve hakkında sayfasına gidin. Her kayıt tarihi için öğrenci sayısı bir tabloda görüntülenir.
Çözemediğiniz sorunlarla karşılaşırsanız, Bu aşama için tamamlanmış uygulamayıindirin.

Ek kaynaklar
2. x kaynağı ASP.NET Core hata ayıklaması
Bu öğreticinin YouTube sürümü
Sonraki öğreticide, uygulama, veri modelini güncelleştirmek için geçişleri kullanır.
ÖN CEKI İleri A S P. N E T C O R E G E Ç IŞ L E R I IL E E F C O R E R A Z O R P A G E S -
4/8
ASP.NET Core geçişleri ile EF Core Razor Pages-4/8
23.11.2019 • 18 minutes to read • Edit Online

, Tom Dykstra, Jon P Smithve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Bu öğreticide, veri modeli değişikliklerini yönetmek için EF Core geçişleri özelliği tanıtılmıştır.
Yeni bir uygulama geliştirildiğinde, veri modeli sıklıkla değişir. Modelin her değiştirilişinde, model veritabanıyla
eşitlenmemiş olur. Bu öğretici serisi, mevcut değilse veritabanını oluşturmak için Entity Framework
yapılandırılarak başlatılır. Veri modelinin her değiştirilişinde veritabanını bırakmalısınız. Uygulamanın bir
sonraki çalıştırılışında, EnsureCreated çağrısı yeni veri modeliyle eşleşecek şekilde veritabanını yeniden
oluşturur. DbInitializer sınıfı, yeni veritabanını temel alarak çalışır.
Veritabanını veri modeliyle eşitlenmiş halde tutmaya yönelik bu yaklaşım, uygulamayı üretime dağıtana kadar
iyi çalışır. Uygulama üretimde çalıştığında genellikle saklanması gereken verileri depolar. Uygulama her
değişiklik yapıldığında (yeni sütun ekleme gibi) bir test veritabanıyla başlayamaz. EF Core geçişleri özelliği,
yeni bir veritabanı oluşturmak yerine EF Core veritabanı şemasını güncelleştirmesine olanak sağlayarak bu
sorunu çözer.
Veri modeli değiştiğinde veritabanını bırakıp yeniden oluşturmak yerine, geçişler şemayı güncelleştirir ve var
olan verileri korur.

NOTE
SQLite sınırlamaları
Bu öğretici, mümkün olduğunda Entity Framework Core geçişleri özelliğini kullanır. Geçişler, veritabanı şemasını veri
modelindeki değişikliklerle eşleşecek şekilde güncelleştirir. Bununla birlikte, geçişler yalnızca veritabanı altyapısının
desteklediği değişiklik türlerini ve SQLite 'un şema değiştirme özellikleri sınırlıdır. Örneğin, bir sütun ekleme desteklenir,
ancak bir sütunu kaldırmak desteklenmez. Bir sütunu kaldırmak için bir geçiş oluşturulduysa, ef migrations add
komut başarılı olur ef database update ancak komut başarısız olur.
SQLite sınırlamalarına yönelik geçici çözüm, tablodaki bir şeyler değiştiğinde tablo yeniden oluşturmak için geçiş kodunu
el ile yazmak için kullanılır. Kod, Up bir geçiş için ve Down yöntemlerine gidip şunları içerir:
Yeni bir tablo oluşturuluyor.
Eski tablodaki veriler yeni tabloya kopyalanıyor.
Eski tablo bırakılıyor.
Yeni tablo yeniden adlandırılıyor.
Bu türün veritabanına özgü kodu yazma, Bu öğreticinin kapsamı dışındadır. Bunun yerine, bu öğretici bir geçiş uygulama
girişimi başarısız olduğunda veritabanını bırakır ve yeniden oluşturur. Daha fazla bilgi için aşağıdaki kaynaklara bakın:
SQLite EF Core veritabanı sağlayıcısı sınırlamaları
Geçiş kodunu özelleştirme
Veri dengeli dağıtımı
SQLite ALTER TABLE ifadesi
Veritabanını bırak
Visual Studio
Visual Studio Code
Veritabanını silmek için SQL Server Nesne Gezgini (ssox) kullanın veya Paket Yöneticisi konsolunda
(PMC ) şu komutu çalıştırın:

Drop-Database

İlk geçiş oluşturma


Visual Studio
Visual Studio Code
PMC 'de şu komutları çalıştırın:

Add-Migration InitialCreate
Update-Database

Yukarı ve aşağı Yöntemler


EF Core migrations add komut, veritabanını oluşturmak için kodu oluşturdu. Bu geçiş kodu geçişleri<zaman
damgasında _InitialCreate. cs dosyasında > . InitialCreate sınıfının Up yöntemi, veri modeli varlık
kümelerine karşılık gelen veritabanı tablolarını oluşturur. Down yöntemi, aşağıdaki örnekte gösterildiği gibi
onları siler:

using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace ContosoUniversity.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});

migrationBuilder.CreateTable(
name: "Student",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
LastName = table.Column<string>(nullable: true),
FirstMidName = table.Column<string>(nullable: true),
EnrollmentDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Student", x => x.ID);
});

migrationBuilder.CreateTable(
name: "Enrollment",
columns: table => new
{
EnrollmentID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
CourseID = table.Column<int>(nullable: false),
StudentID = table.Column<int>(nullable: false),
Grade = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Enrollment", x => x.EnrollmentID);
table.ForeignKey(
name: "FK_Enrollment_Course_CourseID",
column: x => x.CourseID,
principalTable: "Course",
principalColumn: "CourseID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Enrollment_Student_StudentID",
column: x => x.StudentID,
principalTable: "Student",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_Enrollment_CourseID",
table: "Enrollment",
column: "CourseID");

migrationBuilder.CreateIndex(
name: "IX_Enrollment_StudentID",
table: "Enrollment",
column: "StudentID");
}

protected override void Down(MigrationBuilder migrationBuilder)


{
migrationBuilder.DropTable(
name: "Enrollment");

migrationBuilder.DropTable(
name: "Course");

migrationBuilder.DropTable(
name: "Student");
}
}
}

Önceki kod ilk geçişe yöneliktir. Kod:


migrations add InitialCreate komutu tarafından oluşturuldu.
database update komutu tarafından yürütülür.
Veritabanı bağlamı sınıfı tarafından belirtilen veri modeli için bir veritabanı oluşturur.
Dosya adı için geçiş adı parametresi (örnekteki "ınitialcreate") kullanılır. Geçiş adı herhangi bir geçerli dosya adı
olabilir. Geçiş sırasında nelerin yapıldığını özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, bir
departman tablosu ekleyen bir geçişe "AddDepartmentTable" adı verilir.

Geçişler geçmiş tablosu


Veritabanını incelemek için SSOX veya SQLite aracınızı kullanın.
__EFMigrationsHistory tablo ekleme hakkında dikkat edin. __EFMigrationsHistory tablo, hangi geçişlerin
veritabanına uygulandığını izler.
__EFMigrationsHistory tablosundaki verileri görüntüleyin. İlk geçiş için bir satır gösterir.

Veri modeli anlık görüntüsü


Geçişler, geçiş/SchoolContextModelSnapshot. csiçindeki geçerli veri modelinin anlık görüntüsünü oluşturur. Bir
geçiş eklediğinizde, EF geçerli veri modelini Snapshot dosyası ile karşılaştırarak nelerin değiştirildiğini belirler.
Anlık görüntü dosyası veri modelinin durumunu izlediğinden, <timestamp>_<migrationname>.cs dosyasını
silerek bir geçişi silemezsiniz. En son geçişi geri yüklemek için migrations remove komutunu kullanmanız
gerekir. Bu komut, geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar. Daha fazla bilgi için bkz.
DotNet EF geçişleri kaldır.

Yeniden oluşturulmasını kaldır


Bu öğretici serisi EnsureCreated kullanılarak başlatıldı. EnsureCreated geçişler geçmişi tablosu oluşturmaz ve
geçişle birlikte kullanılamaz. Bu, veritabanının düşürülme ve sıklıkla yeniden oluşturulduğu test veya hızlı
prototip oluşturma için tasarlanmıştır.
Bu noktadan sonra öğreticiler, geçişleri kullanacaktır.
Data/Dbınınitializer. csdosyasında aşağıdaki satırı açıklama olarak inceleyin:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve veritabanının çalıştığını doğrulayın.

Üretimde geçişleri uygulama


Uygulama başlangıcında, üretim uygulamalarının Database. Migrate olarak çağırmalarını öneririz. sunucu
grubuna dağıtılan bir uygulamadan Migrate çağrılmamalıdır. Uygulama birden çok sunucu örneğine
ölçekleniyorsa, veritabanı şeması güncelleştirmelerinin birden çok sunucudan oluşmaması veya okuma/yazma
erişimiyle çakışmamasını sağlamak zordur.
Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş
yaklaşımları şunları içerir:
SQL betikleri oluşturmak ve dağıtımda SQL betikleri kullanmak için geçişleri kullanma.
Denetlenen bir ortamdan dotnet ef database update çalıştırılıyor.

Sorun giderme
Uygulama SQL Server LocalDB kullanıyorsa ve aşağıdaki özel durumu görüntülüyorsa:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.

Çözüm, bir komut isteminde dotnet ef database update çalıştırmak olabilir.


Ek kaynaklar
Clı EF Core.
Paket Yöneticisi Konsolu (Visual Studio)

Sonraki adımlar
Sonraki öğreticide, veri modeli, varlık özellikleri ve yeni varlıklar eklenerek oluşturulur.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Bu öğreticide, veri modeli değişikliklerini yönetmek için EF Core geçişleri özelliği kullanılır.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.
Yeni bir uygulama geliştirildiğinde, veri modeli sıklıkla değişir. Modelin her değiştirilişinde, model veritabanıyla
eşitlenmemiş olur. Bu öğretici, mevcut değilse veritabanını oluşturmak için Entity Framework yapılandırılarak
başlatılır. Veri modelinin her değiştirilişinde:
DB bırakılır.
EF, modelle eşleşen yeni bir tane oluşturur.
Uygulama, DB 'yi test verileriyle birlikte oluşturur.
Bu yaklaşım, VERITABANıNı veri modeliyle eşitlenmiş halde tutmak, uygulamayı üretime dağıtana kadar iyi
çalışır. Uygulama üretimde çalıştığında genellikle saklanması gereken verileri depolar. Uygulama her değişiklik
yapıldığında (yeni sütun ekleme gibi) bir test DB ile başlayamaz. EF Core geçişleri özelliği, yeni bir
VERITABANı oluşturmak yerine EF Core DB şemasını güncelleştirmesine olanak sağlayarak bu sorunu çözer.
Veri modeli değiştiğinde VERITABANıNı bırakıp yeniden oluşturmak yerine, geçişler şemayı güncelleştirir ve
mevcut verileri korur.

Veritabanını bırak
SQL Server Nesne Gezgini (ssox) veya database drop komutunu kullanın:
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Drop-Database

Yardım bilgileri almak için PMC 'ten Get-Help about_EntityFrameworkCore çalıştırın.

İlk geçiş oluşturma ve VERITABANıNı güncelleştirme


Projeyi derleyin ve ilk geçişi oluşturun.
Visual Studio
Visual Studio Code

Add-Migration InitialCreate
Update-Database

Yukarı ve aşağı yöntemlerini inceleyin


EF Core migrations add komutu VERITABANıNı oluşturmak için kodu oluşturdu. Bu geçiş kodu
geçişleri<zaman damgasında _InitialCreate. cs dosyasında > . InitialCreate sınıfının Up yöntemi, veri
modeli varlık kümelerine karşılık gelen VERITABANı tablolarını oluşturur. Down yöntemi, aşağıdaki örnekte
gösterildiği gibi onları siler:

public partial class InitialCreate : Migration


{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});

migrationBuilder.CreateTable(
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");

migrationBuilder.DropTable(
name: "Course");

migrationBuilder.DropTable(
name: "Student");
}
}

Geçişler, bir geçiş için veri modeli değişikliklerini uygulamak üzere Up yöntemini çağırır. Güncelleştirmeyi geri
almak için bir komut girdiğinizde, geçişler Down yöntemini çağırır.
Önceki kod ilk geçişe yöneliktir. Bu kod, migrations add InitialCreate komutu çalıştırıldığında
oluşturulmuştur. Dosya adı için geçiş adı parametresi (örnekteki "ınitialcreate") kullanılır. Geçiş adı herhangi bir
geçerli dosya adı olabilir. Geçiş sırasında nelerin yapıldığını özetleyen bir sözcük veya tümcecik seçmek en
iyisidir. Örneğin, bir departman tablosu ekleyen bir geçişe "AddDepartmentTable" adı verilir.
İlk geçiş oluşturulur ve VERITABANı varsa:
DB oluşturma kodu oluşturulur.
DB, veri modeliyle zaten eşleştiğinden, DB oluşturma kodunun çalıştırılması gerekmiyor. DB oluşturma
kodu çalıştırılsa, VERITABANı veri modeliyle zaten eşleştiğinden hiçbir değişiklik yapmaz.
Uygulama yeni bir ortama dağıtıldığında, DB oluşturmak için DB oluşturma kodunun çalıştırılması gerekir.
Daha önce VERITABANı bırakılmıştı ve mevcut olmadığından geçişler yeni DB 'yi oluşturur.
Veri modeli anlık görüntüsü
Geçişler geçişlerde/SchoolContextModelSnapshot. cs' de geçerli veritabanı şemasının anlık görüntüsünü
oluşturur. Bir geçiş eklediğinizde EF, veri modeli Snapshot dosyası ile karşılaştırılarak nelerin değiştirildiğini
belirler.
Bir geçişi silmek için aşağıdaki komutu kullanın:
Visual Studio
Visual Studio Code
Geçişi Kaldır
Geçişleri Kaldır komutu geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar.
Uygulamayı kaldırın ve uygulamayı test edin
Erken geliştirme için EnsureCreated kullanıldı. Bu öğreticide geçişler kullanılır. EnsureCreated aşağıdaki
sınırlamalara sahiptir:
Geçişleri atlar ve DB ve şema oluşturur.
Geçişler tablosu oluşturmaz.
Geçişlerle kullanılamaz.
, DB 'nin bıraktığı ve sıklıkla yeniden oluşturulduğu test veya hızlı prototipleme için tasarlanmıştır.
EnsureCreated kaldır:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve DB 'nin çalıştığını doğrulayın.


Veritabanını inceleyin
DB 'yi denetlemek için SQL Server Nesne Gezgini kullanın. __EFMigrationsHistory tablo ekleme hakkında
dikkat edin. __EFMigrationsHistory tablo, hangi geçişlerin VERITABANıNA uygulandığını izler.
__EFMigrationsHistory tablosundaki verileri görüntüleyin, ilk geçiş için bir satır gösterir. Önceki CLı çıkış
örneğinde yer alan son oturum, bu satırı oluşturan INSERT ifadesini gösterir.
Uygulamayı çalıştırın ve her şeyin çalıştığını doğrulayın.

Üretimde geçişleri uygulama


Uygulama başlangıcında, üretim uygulamalarının Database. Migrate çağrısını yapmanızı öneririz. sunucu
grubundaki bir uygulamadan Migrate çağrılmamalıdır. Örneğin, uygulama bulutu genişleme ile dağıtılmışsa
(uygulamanın birden çok örneği çalışır).
Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş
yaklaşımları şunları içerir:
SQL betikleri oluşturmak ve dağıtımda SQL betikleri kullanmak için geçişleri kullanma.
Denetlenen bir ortamdan dotnet ef database update çalıştırılıyor.
EF Core, herhangi bir geçişin çalıştırılması gerektiğini görmek için __MigrationsHistory tablosunu kullanır. DB
güncel değilse, hiçbir geçiş çalıştırılmaz.

Sorun giderme
Tamamlanmış uygulamayıindirin.
Uygulama aşağıdaki özel durumu oluşturur:

SqlException: Cannot open database "ContosoUniversity" requested by the login.


The login failed.
Login failed for user 'user name'.

Çözüm: dotnet ef database update Çalıştır


Ek kaynaklar
Bu öğreticinin YouTube sürümü
.NET Core CLI.
Paket Yöneticisi Konsolu (Visual Studio)

ÖN CEKI İL E R I
ASP.NET Core veri modelinde EF Core ile Razor
Pages-5/8
23.11.2019 • 86 minutes to read • Edit Online

Tarafından Tom Dykstra ve Rick Anderson


Contoso Üniversitesi web uygulaması, EF Core ve Visual Studio kullanarak Razor Pages Web uygulamaları
oluşturmayı gösterir. Öğretici serisi hakkında daha fazla bilgi için ilk öğreticiyebakın.
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu
oluşturduğunuz şekilde karşılaştırın.
Önceki öğreticiler, üç varlıktan oluşan temel bir veri modeliyle çalışmıştır.Bu öğreticide:
Daha fazla varlık ve ilişki eklenmiştir.
Veri modeli biçimlendirme, doğrulama ve veritabanı eşleme kuralları belirtilerek özelleştirilir.
Tamamlanan veri modeli aşağıdaki çizimde gösterilmiştir:
Öğrenci varlık

Modeller/öğrenci. cs dosyasındaki kodu aşağıdaki kodla değiştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki kod, bir FullName özelliği ekler ve var olan özelliklere aşağıdaki öznitelikleri ekler:
[DataType]
[DisplayFormat]
[StringLength]
[Column]
[Required]
[Display]

FullName hesaplanmış özelliği


FullName , diğer iki özelliği birleştirerek oluşturulmuş bir değer döndüren hesaplanmış bir özelliktir. FullName
ayarlanamaz, bu nedenle yalnızca bir get erişimcisi vardır. Veritabanında FullName sütunu oluşturulmaz.
DataType özniteliği

[DataType(DataType.Date)]

Öğrenci kayıt tarihleri için, tüm sayfalar şu anda tarihle birlikte tarih ile görüntülenir, ancak yalnızca tarihin ilgili
olması gerekir. Veri ek açıklaması özniteliklerini kullanarak, verileri gösteren her sayfada görüntü biçimini
giderecek bir kod değişikliği yapabilirsiniz.
DataType özniteliği, veritabanı iç türünden daha belirgin bir veri türünü belirtir. Bu durumda, tarih ve saat değil
yalnızca tarih görüntülenmelidir. Veri türü numaralandırması , tarih, saat, PhoneNumber, para birimi, emaadresi
vb. gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin:
mailto: bağlantısı DataType.EmailAddress için otomatik olarak oluşturulur.
Tarih Seçici çoğu tarayıcıda DataType.Date için sağlanır.

DataType özniteliği HTML 5 data- (bir veri Dash) öznitelikleri yayar. DataType öznitelikleri doğrulama
sağlamaz.
DisplayFormat özniteliği

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, Tarih alanı sunucunun
CultureInfoöğesine göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır. ApplyFormatInEditMode ayarı,
biçimlendirmenin düzenleme kullanıcı arabirimine de uygulanacağını belirtir. Bazı alanlar
ApplyFormatInEditMode kullanmamalıdır. Örneğin, para birimi simgesi genellikle bir düzenleme metin kutusunda
gösterilmemelidir.
DisplayFormat özniteliği kendisi tarafından kullanılabilir. DataType özniteliğini DisplayFormat özniteliğiyle
kullanmak genellikle iyi bir fikirdir. DataType özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini
tersine alır. DataType özniteliği, DisplayFormat kullanılamayan aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir. Örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını ve istemci tarafı giriş doğrulamasını gösterin.
Varsayılan olarak tarayıcı, verileri yerel ayara göre doğru biçimi kullanarak işler.
Daha fazla bilgi için bkz. giriş > etiketi Yardımcısı belgeleri<.
StringLength özniteliği

[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]

Veri doğrulama kuralları ve doğrulama hatası iletileri özniteliklerle belirtilebilir. StringLength özniteliği, bir veri
alanında izin verilen en düşük ve en fazla karakter uzunluğunu belirtir. Gösterilen kod, adları 50 karakterden
fazla olmayacak şekilde sınırlar. En küçük dize uzunluğunu ayarlayan bir örnek daha sonragösterilmiştir.
StringLength özniteliği de istemci tarafı ve sunucu tarafı doğrulaması sağlar. En küçük değerin veritabanı
şeması üzerinde hiçbir etkisi yoktur.
StringLength özniteliği, kullanıcının bir ad için boşluk girmesini engellemez. Cevap içerisinde
RegularExpression özniteliği, girişe kısıtlamalar uygulamak için kullanılabilir. Örneğin, aşağıdaki kod ilk
karakterin büyük küçük harf olmasını ve geri kalan karakterlerin alfabetik olmasını gerektirir:

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]

Visual Studio
Visual Studio Code
SQL Server Nesne Gezgini (ssox) içinde öğrenci tablosuna çift tıklayarak öğrenci tablosu tasarımcısını açın.

Önceki görüntüde Student tablo şeması gösterilmektedir. Ad alanlarında tür nvarchar(MAX) vardır. Bu
öğreticide daha sonra bir geçiş oluşturulup uygulandığında, ad alanları dize uzunluğu özniteliklerinin bir
sonucu olarak nvarchar(50) olur.
Column özniteliği

[Column("FirstName")]
public string FirstMidName { get; set; }

Öznitelikler sınıfların ve özelliklerin veritabanına nasıl eşlenildiğini denetleyebilir. Student modelinde, Column
özniteliği, FirstMidName özelliğinin adını veritabanında "FirstName" olarak eşlemek için kullanılır.
Veritabanı oluşturulduğunda, model üzerindeki özellik adları sütun adları için kullanılır ( Column özniteliği
kullanıldığı durumlar dışında). Student modeli ilk ad alanı için FirstMidName kullanır, çünkü alan de bir orta ad
içerebilir.
[Column] özniteliğiyle, veri modelindeki Student.FirstMidName Student tablonun FirstName sütunuyla eşlenir.
Column özniteliğinin eklenmesi modeli SchoolContext yedekleyen şekilde değiştirir. SchoolContext yedekleyen
model artık veritabanıyla eşleşmez. Bu tutarsızlık, daha sonra bu öğreticide bir geçiş eklenerek çözümlenir.
Gerekli öznitelik

[Required]

Required özniteliği, ad özellikleri gereken alanları sağlar. Değer türleri gibi null yapılamayan türler için
Required özniteliği gerekmez (örneğin, DateTime , int ve double ). Null olmayan türler otomatik olarak
gerekli alanlar olarak değerlendirilir.
MinimumLength zorlanmak için Required özniteliği MinimumLength ile birlikte kullanılmalıdır.

[Display(Name = "Last Name")]


[Required]
[StringLength(50, MinimumLength=2)]
public string LastName { get; set; }

MinimumLength ve Required , doğrulamanın doğrulanmasını yerine getirmek için boşluk kullanılmasına izin
verir. Dize üzerinde tam denetim için RegularExpression özniteliğini kullanın.
Display özniteliği

[Display(Name = "Last Name")]

Display özniteliği, metin kutularının açıklamalı alt yazısının "ad", "soyadı", "tam ad" ve "kayıt tarihi" olması
gerektiğini belirtir. Varsayılan açıklamalı alt yazıların sözcükleri bölen bir boşluk yoktu, örneğin "LastName".
Geçiş oluşturma
Uygulamayı çalıştırın ve öğrenciler sayfasına gidin. Bir özel durum oluşturulur. [Column] özniteliği, EF 'in
FirstName adlı bir sütun bulmasını beklemesine neden olur, ancak veritabanındaki sütun adı hala FirstMidName .

Visual Studio
Visual Studio Code
Hata iletisi aşağıdaki örneğe benzer:

SqlException: Invalid column name 'FirstName'.

PMC 'de yeni bir geçiş oluşturmak ve veritabanını güncelleştirmek için aşağıdaki komutları girin:

Add-Migration ColumnFirstName
Update-Database

Bu komutlardan ilki aşağıdaki uyarı iletisini oluşturur:

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.

Ad alanları artık 50 karakterle sınırlı olduğundan uyarı oluşturulur. Veritabanındaki bir ad 50


karakterden fazlasına sahipse, son karakter 51 ' i kaybedersiniz.
Öğrenci tablosunu SSOX içinde açın:
Geçiş uygulanmadan önce ad sütunları nvarchar (max)türünde idi. Ad sütunları artık nvarchar(50) .
Sütun adı, FirstMidName FirstName olarak değiştirildi.
Uygulamayı çalıştırın ve öğrenciler sayfasına gidin.
Saatin giriş veya tarih ile birlikte görüntülenmediğine dikkat edin.
Yeni oluştur' u seçin ve 50 karakterden daha uzun bir ad girmeyi deneyin.

NOTE
Aşağıdaki bölümlerde, uygulamanın bazı aşamalardan oluşturulması derleyici hataları oluşturur. Yönergeler uygulamanın
ne zaman derbir olduğunu belirtir.

Eğitmen varlığı

Aşağıdaki kodla modeller/eğitmen. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor
{
public int ID { get; set; }

[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }

[Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get { return LastName + ", " + FirstMidName; }
}

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Birden çok öznitelik tek bir satırda olabilir. HireDate öznitelikleri aşağıdaki gibi yazılabilir:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",


ApplyFormatInEditMode = true)]

Gezinti özellikleri
CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.
Bir eğitmen herhangi bir sayıda kurs öğretebilir, bu nedenle CourseAssignments bir koleksiyon olarak tanımlanır.

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Bir eğitmenin en fazla bir ofisi olabilir, bu nedenle OfficeAssignment özelliği tek bir OfficeAssignment varlık
içerir. Office atanmamışsa OfficeAssignment null olur.

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığı
Aşağıdaki kodla modeller/OfficeAssignment. cs oluşturun:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }

public Instructor Instructor { get; set; }


}
}

Anahtar özniteliği
Özellik adı Classnameıd veya ID dışında bir şey olduğunda, bir özelliği birincil anahtar (PK) olarak tanımlamak
için [Key] özniteliği kullanılır.
Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya arasında bir ilişki vardır. Office ataması,
atandığı eğitmenle ilişkili olarak yalnızca vardır. OfficeAssignment PK Ayrıca, Instructor varlığa ait yabancı
anahtarıdır (FK).
EF Core, InstructorID ID veya Classnameıd adlandırma kuralını izlemediği için, InstructorID
OfficeAssignment PK olarak otomatik olarak tanıyamaz. Bu nedenle, Key özniteliği, InstructorID PK olarak
tanımlamak için kullanılır:

[Key]
public int InstructorID { get; set; }

Varsayılan olarak, EF Core, sütun tanımlayıcı bir ilişki için olduğundan, anahtarı veritabanı olmayan bir şekilde
değerlendirir.
Eğitmen gezintisi özelliği
Instructor.OfficeAssignment gezinti özelliği null olabilir çünkü belirli bir eğitmen için bir OfficeAssignment
satırı olmayabilir. Bir eğitmenin Office ataması olmayabilir.
OfficeAssignment.Instructor gezinti özelliği her zaman bir eğitmen varlığına sahip olur çünkü yabancı anahtar
InstructorID türü int , null olamayan bir değer türüdür. Bir Office ataması, bir eğitmen olmadan bulunamaz.
Instructor bir varlık ilişkili bir OfficeAssignment varlığına sahip olduğunda, her varlığın gezinti özelliğinde
diğer birine bir başvurusu vardır.

Kurs varlığı
Modelleri/kursu. cs aşağıdaki kodla güncelleştirin:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Title { get; set; }

[Range(0, 5)]
public int Credits { get; set; }

public int DepartmentID { get; set; }

public Department Department { get; set; }


public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}

Course varlığın bir yabancı anahtar (FK) özelliği DepartmentID vardır. DepartmentID ilgili Department varlığına
işaret eder. Course varlığın bir Department gezinti özelliği vardır.
EF Core, modelin ilgili bir varlık için gezinti özelliği olduğunda bir veri modeli için yabancı anahtar özelliği
gerektirmez. EF Core, gerektiği yerde otomatik olarak veritabanında FKs 'ler oluşturur. EF Core otomatik olarak
oluşturulan FKs 'ler için gölge Özellikler oluşturur. Ancak, doğrudan veri modelinde FK dahil edilmesi,
güncelleştirmelerin daha basit ve daha verimli olmasını sağlayabilir. Örneğin, FK özelliğinin DepartmentID dahil
olmadığı bir model düşünün. Bir kurs varlığı düzenlemek üzere getirilirken:
Department özelliği açıkça yüklenmediyse null olur.
Kurs varlığını güncelleştirmek için öncelikle Department varlığın getirilmesi gerekir.

FK özelliği DepartmentID veri modeline dahil edildiğinde, güncelleştirmeden önce Department varlığını
getirmeye gerek yoktur.
DatabaseGenerated özniteliği
[DatabaseGenerated(DatabaseGeneratedOption.None)] özniteliği, PK 'nin veritabanı tarafından oluşturulması
yerine uygulama tarafından sağlandığını belirtir.
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, EF Core PK değerlerinin veritabanı tarafından oluşturulduğunu varsayar. Veritabanı


tarafından oluşturulan genellikle en iyi yaklaşım vardır. Course varlıklar için Kullanıcı PK 'yi belirtir. Örneğin,
matematik departmanı için 1000 serisi, Ingilizce departmanı için 2000 serisi gibi bir kurs numarası.
DatabaseGenerated özniteliği varsayılan değerler oluşturmak için de kullanılabilir. Örneğin, veritabanı bir satırın
oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için otomatik olarak bir tarih alanı oluşturabilir. Daha
fazla bilgi için bkz. üretilen Özellikler.
Yabancı anahtar ve gezinti özellikleri
Course varlığındaki yabancı anahtar ( FK ) özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:

Bir kurs bir departmana atanır, bu nedenle bir DepartmentID FK ve Department gezinti özelliği vardır.

public int DepartmentID { get; set; }


public Department Department { get; set; }

Bir kurs, kayıtlı sayıda öğrenciye sahip olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

public ICollection<Enrollment> Enrollments { get; set; }

Bir kurs birden fazla eğitmen tarafından tada olabilir, bu nedenle CourseAssignments gezinti özelliği bir
koleksiyondur:

public ICollection<CourseAssignment> CourseAssignments { get; set; }

CourseAssignment daha sonraaçıklanmaktadır.

Departman varlığı

Aşağıdaki kodla modeller/departman. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Column özniteliği
Daha önce Column özniteliği sütun adı eşlemesini değiştirmek için kullanılmıştır. Department varlığın kodunda,
SQL veri türü eşlemesini değiştirmek için Column özniteliği kullanılır. Budget sütunu, veritabanında SQL
Server para türü kullanılarak tanımlanır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Sütun eşlemesi genellikle gerekli değildir. EF Core, özelliğin CLR türüne göre uygun SQL Server veri türünü
seçer. CLR decimal türü bir SQL Server decimal türüne eşlenir. Budget para birimi için ve para veri türü para
birimi için daha uygundur.
Yabancı anahtar ve gezinti özellikleri
FK ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir departman yönetici olabilir veya olmayabilir.
Yönetici her zaman bir eğitmendir. Bu nedenle InstructorID özelliği, Instructor varlığa FK olarak eklenir.

Gezinti özelliği Administrator olarak adlandırılır ancak bir Instructor varlığı tutar:

public int? InstructorID { get; set; }


public Instructor Administrator { get; set; }

Önceki koddaki soru işareti (?) özelliği null yapılabilir olduğunu belirtiyor.
Bir departmanın birçok kursu olabilir, bu nedenle bir kurs gezintisi özelliği vardır:
public ICollection<Course> Courses { get; set; }

Kural gereği EF Core, null yapılamayan ve çok-çok ilişkiler için basamaklı silme imkanı sağlar. Bu varsayılan
davranış, dairesel basamaklı silme kurallarına neden olabilir. Bir geçiş eklendiğinde dairesel basamaklı silme
kuralları bir özel duruma neden olur.
Örneğin, Department.InstructorID özelliği null yapılamayan olarak tanımlanmışsa EF Core bir basamaklı silme
kuralı yapılandırır. Bu durumda, yönetici olarak atanan eğitmen silindiğinde departman silinir. Bu senaryoda
kısıtlama kuralı daha anlamlı hale getirir. Aşağıdaki Fluent API bir kısıtlama kuralı ayarlar ve art arda silmeyi
devre dışı bırakır.

modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)

Kayıt varlık
Kayıt kaydı, tek bir öğrenci tarafından gerçekleştirilen bir kurs içindir.

Modelleri/kaydı. cs 'yi aşağıdaki kodla güncelleştirin:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

Yabancı anahtar ve gezinti özellikleri


FK özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Kayıt kaydı tek bir kursa yöneliktir, bu nedenle bir CourseID FK özelliği ve Course gezinti özelliği vardır:

public int CourseID { get; set; }


public Course Course { get; set; }

Kayıt kaydı bir öğrenci içindir, bu nedenle bir StudentID FK özelliği ve Student gezinti özelliği vardır:

public int StudentID { get; set; }


public Student Student { get; set; }

Çoktan çoğa Ilişkiler


Student ve Course varlıkları arasında çok-çok ilişkisi vardır. Enrollment varlık, veritabanında Yük ile çoktan
çoğa bir JOIN tablosu olarak çalışır. "Yükle", Enrollment tablosunun birleştirilmiş tablolar (Bu durumda, PK ve
Grade ) gibi ek verileri içerdiği anlamına gelir.

Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğünü gösterilmektedir. (Bu diyagram EF 6.
x için EF güç araçları kullanılarak oluşturulmuştur. Diyagram oluşturmak öğreticinin bir parçası değildir.)

Her ilişki ucu ve bir yıldız işareti (*) 1 diğer sırasında bir-çok ilişkisi belirten bulunur.
Enrollment tablo, sınıf bilgilerini içermiyorsa, yalnızca iki FKs ( CourseID ve StudentID ) içermesi gerekir. Yük
olmadan çoktan çoğa bir JOIN tablosu bazen saf JOIN tablosu (PJT) olarak adlandırılır.
Instructor ve Course varlıkların, saf bir JOIN tablosu kullanılarak çoktan çoğa bir ilişkisi vardır.
Note: EF 6. x, çoktan çoğa ilişkiler için örtük birleştirmeyi destekler, ancak EF Core değildir. Daha fazla bilgi için
EF Core 2,0 ' de çoktan çoğa ilişkilerbölümüne bakın.

Courseatama varlığı
Aşağıdaki kodla modeller/Courseatama. cs oluşturun:

namespace ContosoUniversity.Models
{
public class CourseAssignment
{
public int InstructorID { get; set; }
public int CourseID { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
}
}

Eğitmenden çok-çok ilişkisi için bir JOIN tablosu gerekir ve bu ekleme tablosu için varlık kurs atamasıdır.

EntityName1EntityName2 bir JOIN varlığı adı yaygın olarak vardır. Örneğin, bu model kullanılarak eğitmen-
kurslar JOIN tablosu CourseInstructor . Ancak, ilişkiyi açıklayan bir ad kullanmanızı öneririz.
Veri modelleri basit ve büyümeye başlar. Yük (PJTs) olmayan ekleme tabloları genellikle yükü içerecek şekilde
gelişmektedir. Açıklayıcı bir varlık adıyla başlayarak, ekleme tablosu değiştiğinde adın değiştirilmesi gerekmez.
İdeal olarak, JOIN varlığının iş etki alanında kendi doğal (muhtemelen tek bir kelime) adına sahip olması
gerekir. Örneğin, kitaplar ve müşteriler, derecelendirmeler adlı bir JOIN varlığıyla bağlantı kurulabilir.Eğitmenin
kursa çok-çok ilişkisi için CourseInstructor``CourseAssignment tercih edilir.
Bileşik anahtar
CourseAssignment ( InstructorID ve CourseID ) içindeki iki FKs, CourseAssignment tablosunun her satırını
benzersiz olarak tanımlar. CourseAssignment adanmış bir PK gerektirmez. InstructorID ve CourseID özellikleri
bileşik bir PK olarak çalışır. EF Core bileşik PKs 'leri belirtmenin tek yolu Fluent API' dir. Sonraki bölümde,
bileşik PK 'nin nasıl yapılandırılacağı gösterilmektedir.
Bileşik anahtar şunları sağlar:
Tek bir kurs için birden çok satıra izin verilir.
Birden çok satıra bir eğitmen için izin verilir.
Aynı eğitmen ve kurs için birden çok satıra izin verilmez.
Enrollment JOIN varlığı kendi PK 'yi tanımlar, bu nedenle bu sıralamanın yinelemeleri mümkündür.Bu tür
yinelemeleri engellemek için:
FK alanlara benzersiz bir dizin ekleyin veya
CourseAssignment benzer bir birincil bileşik anahtarla Enrollment yapılandırın. Daha fazla bilgi için bkz.
dizinler.

Veritabanı bağlamını güncelleştirme


Data/SchoolContext. cs öğesini şu kodla güncelleştirin:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}

public DbSet<Course> Courses { get; set; }


public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<CourseAssignment> CourseAssignments { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Department>().ToTable("Department");
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");

modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
}
}
}

Yukarıdaki kod, yeni varlıkları ekler ve CourseAssignment varlığın bileşik PK öğesini yapılandırır.
Tutarlı API 'nin özniteliklere alternatif
Önceki koddaki OnModelCreating yöntemi EF Core davranışını yapılandırmak için Fluent API kullanır. Genellikle
tek bir bildirimde bir dizi yöntem çağrısı olan dize olarak kullanıldığından, API "akıcı" olarak adlandırılır.
Aşağıdaki kod Fluent API bir örneğidir:

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}

Bu öğreticide, Fluent API yalnızca özniteliklerle yapılamadığını veritabanı eşlemesi için kullanılır. Ancak Fluent
API, özniteliklerle yapılabilecek biçimlendirme, doğrulama ve eşleme kurallarının çoğunu belirtebilir.
gibi bazı öznitelikler Fluent API uygulanamaz.
MinimumLength MinimumLength şemayı değiştirmez, yalnızca bir
minimum uzunluk doğrulama kuralı uygular.
Bazı geliştiriciler, varlık sınıflarının "temiz" olmasını sağlamak için Fluent API özel olarak kullanmayı tercih eder.
Öznitelikler ve Fluent API karışık olabilir. Yalnızca Fluent API (bileşik bir PK belirterek) yapılabilecek bazı
konfigürasyonlar vardır. Yalnızca özniteliklerle ( MinimumLength ) yapılabilecek bazı konfigürasyonlar vardır.
Fluent API veya özniteliklerini kullanmak için önerilen uygulama:
Bu iki yaklaşımdan birini seçin.
Seçilen yaklaşımı mümkün olduğunca düzenli olarak kullanın.
Bu öğreticide kullanılan özniteliklerin bazıları için kullanılır:
Yalnızca doğrulama (örneğin, MinimumLength ).
Yalnızca yapılandırma EF Core (örneğin, HasKey ).
Doğrulama ve EF Core yapılandırma (örneğin, [StringLength(50)] ).
Öznitelikler ile Fluent API hakkında daha fazla bilgi için bkz. yapılandırma yöntemleri.

Varlık diyagramı
Aşağıdaki çizimde, tamamlanmış okul modeli için EF Power Tools 'un oluştura diyagramı gösterilmektedir.
Önceki diyagramda şunları gösterir:
Birkaç bire çok ilişki satırı (*1).
Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya-bir ilişki çizgisi (1 ila 0.. 1 ).
Instructor ve Department varlıkları arasında sıfır veya-bire çok ilişki çizgisi (0.. 1 -* ).

Veritabanının çekirdeğini oluşturma


Data/Dbınizer. csdosyasındaki kodu güncelleştirin:

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
//context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}

var students = new Student[]


{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2016-09-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Arturo", LastName = "Anand",
EnrollmentDate = DateTime.Parse("2019-09-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Yan", LastName = "Li",
EnrollmentDate = DateTime.Parse("2018-09-01") },
new Student { FirstMidName = "Peggy", LastName = "Justice",
EnrollmentDate = DateTime.Parse("2017-09-01") },
new Student { FirstMidName = "Laura", LastName = "Norman",
EnrollmentDate = DateTime.Parse("2019-09-01") },
new Student { FirstMidName = "Nino", LastName = "Olivetto",
EnrollmentDate = DateTime.Parse("2011-09-01") }
};

foreach (Student s in students)


{
context.Students.Add(s);
}
context.SaveChanges();

var instructors = new Instructor[]


{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie",
HireDate = DateTime.Parse("1995-03-11") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri",
HireDate = DateTime.Parse("2002-07-06") },
new Instructor { FirstMidName = "Roger", LastName = "Harui",
HireDate = DateTime.Parse("1998-07-01") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
HireDate = DateTime.Parse("2001-01-15") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng",
HireDate = DateTime.Parse("2004-02-12") }
};

foreach (Instructor i in instructors)


{
context.Instructors.Add(i);
}
context.SaveChanges();

var departments = new Department[]


{
new Department { Name = "English", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").ID },
new Department { Name = "Mathematics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID },
new Department { Name = "Engineering", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").ID },
new Department { Name = "Economics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID }
};

foreach (Department d in departments)


foreach (Department d in departments)
{
context.Departments.Add(d);
}
context.SaveChanges();

var courses = new Course[]


{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID
},
new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
},
new Course {CourseID = 1045, Title = "Calculus", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
},
new Course {CourseID = 2021, Title = "Composition", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
new Course {CourseID = 2042, Title = "Literature", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
},
};

foreach (Course c in courses)


{
context.Courses.Add(c);
}
context.SaveChanges();

var officeAssignments = new OfficeAssignment[]


{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
Location = "Thompson 304" },
};

foreach (OfficeAssignment o in officeAssignments)


{
context.OfficeAssignments.Add(o);
}
context.SaveChanges();

var courseInstructors = new CourseAssignment[]


{
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Kapoor").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Fakhouri").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Harui").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
new CourseAssignment {
CourseID = courses.Single(c => c.Title == "Literature" ).CourseID,
InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
},
};

foreach (CourseAssignment ci in courseInstructors)


{
context.CourseAssignments.Add(ci);
}
context.SaveChanges();

var enrollments = new Enrollment[]


{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").ID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").ID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
};

foreach (Enrollment e in enrollments)


{
var enrollmentInDataBase = context.Enrollments.Where(
s =>
s.Student.ID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollments.Add(e);
}
}
context.SaveChanges();
}
}
}

Yukarıdaki kod, yeni varlıklar için tohum verileri sağlar. Bu kodun çoğu yeni varlık nesneleri oluşturur ve örnek
verileri yükler. Örnek veriler test için kullanılır. Çoktan çoğa ekleme tablolarının nasıl çalıştırılabilir olduğunu
gösteren örnekler için Enrollments ve CourseAssignments bakın.

Geçiş Ekle
Projeyi oluşturun.
Visual Studio
Visual Studio Code
PMC 'de aşağıdaki komutu çalıştırın.

Add-Migration ComplexDataModel

Yukarıdaki komut, olası veri kaybı hakkında bir uyarı görüntüler.

An operation was scaffolded that may result in the loss of data.


Please review the migration for accuracy.
To undo this action, use 'ef migrations remove'

database update komutu çalıştırıldıysanız aşağıdaki hata oluşturulur:

The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Course_dbo.Department_DepartmentID". The conflict occurred in
database "ContosoUniversity", table "dbo.Department", column 'DepartmentID'.
Sonraki bölümde, bu hatayla ilgili ne yapılacağını görürsünüz.

Geçişi uygulayın veya bırakıp yeniden oluşturun


Artık var olan bir veritabanınız olduğuna göre, değişikliklere nasıl uygulanacağını düşünmeniz gerekir. Bu
öğreticide iki alternatif gösterilmektedir:
Veritabanını bırakıp yeniden oluşturun. SQLite kullanıyorsanız bu bölümü seçin.
Geçişi mevcut veritabanına uygulayın. Bu bölümdeki yönergeler yalnızca SQL Server için geçerlidir, SQLite
için değildir.
Her iki seçenek de SQL Server için geçerlidir. Apply-Migration yöntemi daha karmaşıktır ve zaman alabilir. Bu,
gerçek dünyada üretim ortamları için tercih edilen yaklaşımdır.

Veritabanını bırakıp yeniden oluşturun


SQL Server kullanıyorsanız ve aşağıdaki bölümde uygulanacak geçiş yaklaşımını yapmak istiyorsanız Bu
bölümü atlayın .
Yeni bir veritabanı oluşturmak için EF Core zorlamak için veritabanını bırakıp güncelleştirin:
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Drop-Database

Geçişler klasörünü silin, ardından aşağıdaki komutu çalıştırın:

Add-Migration InitialCreate
Update-Database

Uygulamayı çalıştırın. Uygulamayı çalıştırmak DbInitializer.Initialize yöntemini çalıştırır.


DbInitializer.Initialize yeni veritabanını doldurur.

Visual Studio
Visual Studio Code
Veritabanını SSOX içinde açın:
Daha önce SSOX açıldıysa Yenile düğmesine tıklayın.
Genişletin tabloları düğümü. Oluşturulan tablolar görüntülenir.
Courseatama tablosunu inceleyin:
Courseatama tablosuna sağ tıklayın ve verileri görüntüle' yi seçin.
Courseatama tablosunun veri içerdiğini doğrulayın.

Geçişi Uygula
Bu bölüm isteğe bağlıdır. Bu adımlar yalnızca SQL Server LocalDB için çalışır ve yalnızca önceki bırakma ve
veritabanını yeniden oluştur bölümünü atladıktan sonra.
Geçişler mevcut verilerle çalıştırıldığında, mevcut verilerin karşılanmadığı FK kısıtlamalar olabilir. Üretim
verileriyle, mevcut verilerin geçirilmesi için adımların alınması gerekir. Bu bölüm, FK kısıtlama ihlallerinin
düzeltilmesiyle bir örnek sağlar. Bu kod değişikliklerini yedekleme olmadan yapmayın. Önceki bırakmayı
tamamlayıp veritabanını yeniden oluşturduktan sonra Bu kod değişikliklerini yapmayın.
{Timestamp } _ComplexDataModel. cs dosyası aşağıdaki kodu içerir:

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
type: "int",
nullable: false,
defaultValue: 0);

Yukarıdaki kod Course tabloya null atanamaz DepartmentID FK ekler. Önceki öğreticideki veritabanı Course
satırları içerir, böylece tablo geçişler tarafından güncelleştirilemez.
ComplexDataModel geçişinin mevcut verilerle çalışmasını sağlamak için:
Yeni sütuna ( DepartmentID ) varsayılan değer vermek için kodu değiştirin.
Varsayılan departman olarak davranacak "Temp" adlı sahte bir departman oluşturun.
Yabancı anahtar kısıtlamalarını çözme
ComplexDataModel geçiş sınıfında Up yöntemini güncelleştirin:
{Timestamp } _ComplexDataModel. cs dosyasını açın.
DepartmentID sütununu Course tablosuna ekleyen kod satırını açıklama satırı yapın.

migrationBuilder.AlterColumn<string>(
name: "Title",
table: "Course",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldNullable: true);

//migrationBuilder.AddColumn<int>(
// name: "DepartmentID",
// table: "Course",
// nullable: false,
// defaultValue: 0);

Aşağıdaki vurgulanmış kodu ekleyin. Yeni kod .CreateTable( name: "Department" bloğundan sonra geçer:

migrationBuilder.CreateTable(
name: "Department",
columns: table => new
{
DepartmentID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Budget = table.Column<decimal>(type: "money", nullable: false),
InstructorID = table.Column<int>(type: "int", nullable: true),
Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
StartDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Department", x => x.DepartmentID);
table.ForeignKey(
name: "FK_Department_Instructor_InstructorID",
column: x => x.InstructorID,
principalTable: "Instructor",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});

migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00,


GETDATE())");
// Default value for FK points to department created above, with
// defaultValue changed to 1 in following AddColumn statement.

migrationBuilder.AddColumn<int>(
name: "DepartmentID",
table: "Course",
nullable: false,
defaultValue: 1);
Önceki değişikliklerle, ComplexDataModel.Up yöntemi çalıştıktan sonra mevcut Course satırları "Temp"
departmanı ile ilişkilendirilir.
Burada gösterilen durumu işlemenin yolu, bu öğretici için basitleştirilmiştir. Bir üretim uygulaması şöyle
olacaktır:
Yeni Department satırlarına Department satırları ve ilgili Course satırlarını eklemek için kod veya komut
dosyaları ekleyin.
"Geçici" Departmanı veya Course.DepartmentID için varsayılan değeri kullanmayın.
Visual Studio
Visual Studio Code
Paket Yöneticisi konsolunda (PMC ), aşağıdaki komutu çalıştırın:

Update-Database

DbInitializer.Initialize yöntemi yalnızca boş bir veritabanıyla çalışacak şekilde tasarlandığından, öğrenci ve
kurs tablolarındaki tüm satırları silmek için SSOX kullanın. (Cascade silme, kayıt tablosundan işlem
gerçekleştirir.)
Uygulamayı çalıştırın. Uygulamayı çalıştırmak DbInitializer.Initialize yöntemini çalıştırır.
DbInitializer.Initialize yeni veritabanını doldurur.

Sonraki adımlar
Sonraki iki öğretici ilgili verilerin nasıl okunacağını ve güncelleştirilmesini gösterir.

ÖN CEKI SON RA KI
Ö Ğ R E T IC I Ö Ğ R E T IC I

Önceki öğreticiler, üç varlıktan oluşan temel bir veri modeliyle çalışmıştır.Bu öğreticide:
Daha fazla varlık ve ilişki eklenmiştir.
Veri modeli biçimlendirme, doğrulama ve veritabanı eşleme kuralları belirtilerek özelleştirilir.
Tamamlanan veri modeli için varlık sınıfları aşağıdaki çizimde gösterilmiştir:
Çözemediğiniz sorunlarla karşılaşırsanız, Tamamlanmış uygulamayıindirin.

Veri modelini özniteliklerle özelleştirme


Bu bölümde, veri modeli öznitelikler kullanılarak özelleştirilir.
DataType özniteliği
Öğrenci sayfaları Şu anda kayıt tarihinin saatini görüntüler. Genellikle, tarih alanları saati değil yalnızca tarihi
gösterir.
Modelleri/öğrenci. cs 'yi aşağıdaki vurgulanmış kodla güncelleştirin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

DataType özniteliği, veritabanı iç türünden daha belirgin bir veri türünü belirtir. Bu durumda, tarih ve saat değil
yalnızca tarih görüntülenmelidir. Veri türü numaralandırması , tarih, saat, PhoneNumber, para birimi, emaadresi
vb. gibi birçok veri türü sağlar. DataType özniteliği Ayrıca uygulamanın türe özgü özellikleri otomatik olarak
sağlamasını da sağlayabilir. Örneğin:
mailto: bağlantısı DataType.EmailAddress için otomatik olarak oluşturulur.
Tarih Seçici çoğu tarayıcıda DataType.Date için sağlanır.
DataType özniteliği HTML 5 tarayıcıların kullandığı HTML 5 data- (bir veri Dash) özniteliklerini yayar.
DataType öznitelikleri doğrulama sağlamaz.
DataType.Date görüntülenen tarihin biçimini belirtmiyor. Varsayılan olarak, Tarih alanı sunucunun
CultureInfoöğesine göre varsayılan biçimlere göre görüntülenir.
DisplayFormat özniteliği, açıkça tarih biçimini belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

ApplyFormatInEditMode ayarı, biçimlendirmenin düzenleme kullanıcı arabirimine de uygulanacağını belirtir. Bazı


alanlar ApplyFormatInEditMode kullanmamalıdır. Örneğin, para birimi simgesi genellikle bir düzenleme metin
kutusunda gösterilmemelidir.
DisplayFormat özniteliği kendisi tarafından kullanılabilir. DataType özniteliğini DisplayFormat özniteliğiyle
kullanmak genellikle iyi bir fikirdir. DataType özniteliği, verilerin semantiğini bir ekranda nasıl işleneceğini
tersine alır. DataType özniteliği, DisplayFormat kullanılamayan aşağıdaki avantajları sağlar:
Tarayıcı HTML5 özelliklerini etkinleştirebilir. Örneğin, bir Takvim denetimini, yerel ayara uygun para birimi
sembolünü, e-posta bağlantılarını, istemci tarafı giriş doğrulamasını vb. göster
Varsayılan olarak tarayıcı, verileri yerel ayara göre doğru biçimi kullanarak işler.
Daha fazla bilgi için bkz. giriş > etiketi Yardımcısı belgeleri<.
Uygulamayı çalıştırın. Öğrenciler dizin sayfasına gidin. Süreler artık görüntülenmiyor. Student modelini
kullanan her görünüm, tarihi zaman içinde görüntüler.
StringLength özniteliği
Veri doğrulama kuralları ve doğrulama hatası iletileri özniteliklerle belirtilebilir. StringLength özniteliği, bir veri
alanında izin verilen en düşük ve en fazla karakter uzunluğunu belirtir. StringLength özniteliği de istemci tarafı
ve sunucu tarafı doğrulaması sağlar. En küçük değerin veritabanı şeması üzerinde hiçbir etkisi yoktur.
Student modelini aşağıdaki kodla güncelleştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki kod, adları 50 karakterden fazla olmayacak şekilde sınırlandırır. StringLength özniteliği, kullanıcının
bir ad için boşluk girmesini engellemez. Cevap içerisinde RegularExpression özniteliği, girişe kısıtlamalar
uygulamak için kullanılır. Örneğin, aşağıdaki kod ilk karakterin büyük küçük harf olmasını ve geri kalan
karakterlerin alfabetik olmasını gerektirir:

[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
Uygulamayı çalıştırın:
Öğrenciler sayfasına gidin.
Yeni oluştur' u seçin ve 50 karakterden daha uzun bir ad girin.
Oluştur' u seçin, istemci tarafı doğrulama bir hata iletisi gösterir.

SQL Server Nesne Gezgini (ssox) içinde öğrenci tablosuna çift tıklayarak öğrenci tablosu tasarımcısını açın.

Önceki görüntüde Student tablo şeması gösterilmektedir. VERITABANı üzerinde geçişler çalıştırılmadığından,
ad alanlarının türü nvarchar(MAX) vardır. Bu öğreticide daha sonra geçişler çalıştırıldığında, ad alanları
nvarchar(50) olur.

Column özniteliği
Öznitelikler sınıfların ve özelliklerin veritabanına nasıl eşlenildiğini denetleyebilir. Bu bölümde, Column
özniteliği, FirstMidName özelliğinin adını VERITABANıNDA "FirstName" olarak eşlemek için kullanılır.
DB oluşturulduğunda, model üzerindeki özellik adları sütun adları için kullanılır ( Column özniteliği kullanıldığı
durumlar dışında).
Student modeli ilk ad alanı için FirstMidName kullanır, çünkü alan de bir orta ad içerebilir.
Student.cs dosyasını aşağıdaki vurgulanmış kodla güncelleştirin:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Yukarıdaki değişiklik ile uygulamadaki Student.FirstMidName , Student tablosunun FirstName sütunuyla


eşlenir.
Column özniteliğinin eklenmesi modeli SchoolContext yedekleyen şekilde değiştirir. SchoolContext yedekleyen
model artık veritabanıyla eşleşmez. Geçiş uygulamadan önce uygulama çalışıyorsa aşağıdaki özel durum
oluşturulur:

SqlException: Invalid column name 'FirstName'.

DB 'yi güncelleştirmek için:


Projeyi oluşturun.
Proje klasöründe bir komut penceresi açın. Yeni bir geçiş oluşturmak ve DB 'yi güncelleştirmek için
aşağıdaki komutları girin:
Visual Studio
Visual Studio Code

Add-Migration ColumnFirstName
Update-Database

migrations add ColumnFirstName komutu aşağıdaki uyarı iletisini üretir:


An operation was scaffolded that may result in the loss of data.
Please review the migration for accuracy.

Ad alanları artık 50 karakterle sınırlı olduğundan uyarı oluşturulur. VERITABANıNDAKI bir ad 50 karakterden
fazlasına sahipse, son karakter 51 ' i kaybedersiniz.
Uygulamayı test edin.
Öğrenci tablosunu SSOX içinde açın:

Geçiş uygulanmadan önce ad sütunları nvarchar (max)türünde idi. Ad sütunları artık nvarchar(50) . Sütun adı,
FirstMidName FirstName olarak değiştirildi.

NOTE
Aşağıdaki bölümde, uygulamanın bazı aşamalardan oluşturulması derleyici hataları oluşturur. Yönergeler uygulamanın ne
zaman derbir olduğunu belirtir.

Öğrenci varlık güncelleştirmesi

Modelleri/öğrenci. cs 'yi aşağıdaki kodla güncelleştirin:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

public ICollection<Enrollment> Enrollments { get; set; }


}
}

Gerekli öznitelik
Required özniteliği, ad özellikleri gereken alanları sağlar. Değer türleri ( DateTime , int , double , vb.) gibi null
yapılamayan türler için Required özniteliği gerekli değildir. Null olmayan türler otomatik olarak gerekli alanlar
olarak değerlendirilir.
Required özniteliği StringLength özniteliğinde minimum length parametresiyle değiştirilebilir:

[Display(Name = "Last Name")]


[StringLength(50, MinimumLength=1)]
public string LastName { get; set; }

Display özniteliği
Display özniteliği, metin kutularının açıklamalı alt yazısının "ad", "soyadı", "tam ad" ve "kayıt tarihi" olması
gerektiğini belirtir. Varsayılan açıklamalı alt yazıların sözcükleri bölen bir boşluk yoktu, örneğin "LastName".
FullName hesaplanmış özelliği
FullName , diğer iki özelliği birleştirerek oluşturulmuş bir değer döndüren hesaplanmış bir özelliktir. FullName
ayarlanamaz, yalnızca bir get erişimcisi vardır. Veritabanında FullName sütunu oluşturulmaz.

Eğitmen varlığı oluşturma


Aşağıdaki kodla modeller/eğitmen. cs oluşturun:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Instructor
{
public int ID { get; set; }

[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }

[Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; }

[Display(Name = "Full Name")]


public string FullName
{
get { return LastName + ", " + FirstMidName; }
}

public ICollection<CourseAssignment> CourseAssignments { get; set; }


public OfficeAssignment OfficeAssignment { get; set; }
}
}

Birden çok öznitelik tek bir satırda olabilir. HireDate öznitelikleri aşağıdaki gibi yazılabilir:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",


ApplyFormatInEditMode = true)]

Courseatamalar ve OfficeAssignment gezinti özellikleri


CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.

Bir eğitmen herhangi bir sayıda kurs öğretebilir, bu nedenle CourseAssignments bir koleksiyon olarak tanımlanır.
public ICollection<CourseAssignment> CourseAssignments { get; set; }

Bir gezinti özelliği birden çok varlık tutuyorsa:


Girişlerin eklenebileceği, silinebileceği ve güncelleştirilebileceği bir liste türü olmalıdır.
Gezinti özelliği türleri şunları içerir:
ICollection<T>
List<T>
HashSet<T>

ICollection<T> belirtilirse EF Core varsayılan olarak bir HashSet<T> koleksiyonu oluşturur.


CourseAssignment varlığı, çoktan çoğa ilişkilerin bölümünde açıklanmaktadır.
Contoso Üniversitesi iş kuralları, bir eğitmenin en fazla bir ofisiniz olabilir. OfficeAssignment özelliği tek bir
OfficeAssignment varlığı barındırır. Office atanmamışsa OfficeAssignment null olur.

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığını oluşturma

Aşağıdaki kodla modeller/OfficeAssignment. cs oluşturun:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }

public Instructor Instructor { get; set; }


}
}

Anahtar özniteliği
Özellik adı Classnameıd veya ID dışında bir şey olduğunda, bir özelliği birincil anahtar (PK) olarak tanımlamak
için [Key] özniteliği kullanılır.
Instructor ve OfficeAssignment varlıkları arasında bire sıfır veya arasında bir ilişki vardır. Office ataması,
atandığı eğitmenle ilişkili olarak yalnızca vardır. OfficeAssignment PK Ayrıca, Instructor varlığa ait yabancı
anahtarıdır (FK). EF Core, şu nedenle InstructorID otomatik olarak OfficeAssignment PK olarak tanıyamaz:
InstructorID , ID veya Classnameıd adlandırma kuralını takip etmez.
Bu nedenle, Key özniteliği, InstructorID PK olarak tanımlamak için kullanılır:

[Key]
public int InstructorID { get; set; }

Varsayılan olarak, EF Core, sütun tanımlayıcı bir ilişki için olduğundan, anahtarı veritabanı olmayan bir şekilde
değerlendirir.
Eğitmen gezintisi özelliği
Instructor varlık için OfficeAssignment gezinti özelliği null yapılabilir, çünkü:

Başvuru türleri (örneğin, sınıflar Nullable).


Bir eğitmenin Office ataması olmayabilir.
OfficeAssignment varlık null atanamaz Instructor bir gezinti özelliğine sahiptir çünkü:
InstructorID null değer atanamaz.
Bir Office ataması, bir eğitmen olmadan bulunamaz.
Instructor bir varlık ilişkili bir OfficeAssignment varlığına sahip olduğunda, her varlığın gezinti özelliğinde
diğer birine bir başvurusu vardır.
[Required] özniteliği Instructor gezinti özelliğine uygulanabilir:

[Required]
public Instructor Instructor { get; set; }

Yukarıdaki kod, ilgili bir eğitmen olması gerektiğini belirtir. InstructorID yabancı anahtar (aynı zamanda PK)
null değer atanamaz olduğundan, yukarıdaki kod gereksizdir.

Kurs varlığını değiştirme

Modelleri/kursu. cs aşağıdaki kodla güncelleştirin:


using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Title { get; set; }

[Range(0, 5)]
public int Credits { get; set; }

public int DepartmentID { get; set; }

public Department Department { get; set; }


public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
}
}

Course varlığın bir yabancı anahtar (FK) özelliği DepartmentID vardır. DepartmentID ilgili Department varlığına
işaret eder. Course varlığın bir Department gezinti özelliği vardır.
EF Core, modelin ilgili bir varlık için gezinti özelliği olduğunda bir veri modeli için FK özelliği gerektirmez.
EF Core, gerektiği yerde otomatik olarak veritabanında FKs 'ler oluşturur. EF Core otomatik olarak oluşturulan
FKs 'ler için gölge Özellikler oluşturur. FK 'in veri modelinde olması, güncelleştirmeleri daha basit ve daha
verimli hale getirir. Örneğin, FK özelliğinin DepartmentID dahil olmadığı bir model düşünün. Bir kurs varlığı
düzenlemek üzere getirilirken:
Department varlığı açık bir şekilde yüklenmediyse null olur.
Kurs varlığını güncelleştirmek için öncelikle Department varlığın getirilmesi gerekir.
FK özelliği DepartmentID veri modeline dahil edildiğinde, güncelleştirmeden önce Department varlığını
getirmeye gerek yoktur.
DatabaseGenerated özniteliği
[DatabaseGenerated(DatabaseGeneratedOption.None)] özniteliği, PK 'nin veritabanı tarafından oluşturulması
yerine uygulama tarafından sağlandığını belirtir.

[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, EF Core PK değerlerinin DB tarafından oluşturulduğunu varsayar. VERITABANı tarafından


oluşturulan PK değerleri genellikle en iyi yaklaşımdır. Course varlıklar için Kullanıcı PK 'yi belirtir. Örneğin,
matematik departmanı için 1000 serisi, Ingilizce departmanı için 2000 serisi gibi bir kurs numarası.
DatabaseGenerated özniteliği varsayılan değerler oluşturmak için de kullanılabilir. Örneğin, VERITABANı bir
satırın oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için otomatik olarak bir tarih alanı oluşturabilir.
Daha fazla bilgi için bkz. üretilen Özellikler.
Yabancı anahtar ve gezinti özellikleri
Course varlığındaki yabancı anahtar (FK) özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir kurs bir departmana atanır, bu nedenle bir DepartmentID FK ve Department gezinti özelliği vardır.

public int DepartmentID { get; set; }


public Department Department { get; set; }

Bir kurs, kayıtlı sayıda öğrenciye sahip olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

public ICollection<Enrollment> Enrollments { get; set; }

Bir kurs birden fazla eğitmen tarafından tada olabilir, bu nedenle CourseAssignments gezinti özelliği bir
koleksiyondur:

public ICollection<CourseAssignment> CourseAssignments { get; set; }

CourseAssignment daha sonraaçıklanmaktadır.

Departman varlığı oluşturma

Aşağıdaki kodla modeller/departman. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }

[StringLength(50, MinimumLength = 3)]


public string Name { get; set; }

[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }

public int? InstructorID { get; set; }

public Instructor Administrator { get; set; }


public ICollection<Course> Courses { get; set; }
}
}

Column özniteliği
Daha önce Column özniteliği sütun adı eşlemesini değiştirmek için kullanılmıştır. Department varlığın kodunda,
SQL veri türü eşlemesini değiştirmek için Column özniteliği kullanılır. Budget sütunu, VERITABANıNDA SQL
Server para türü kullanılarak tanımlanır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Sütun eşlemesi genellikle gerekli değildir. EF Core genellikle özelliğin CLR türüne göre uygun SQL Server veri
türünü seçer. CLR decimal türü bir SQL Server decimal türüne eşlenir. Budget para birimi için ve para veri
türü para birimi için daha uygundur.
Yabancı anahtar ve gezinti özellikleri
FK ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Bir departman yönetici olabilir veya olmayabilir.
Yönetici her zaman bir eğitmendir. Bu nedenle InstructorID özelliği, Instructor varlığa FK olarak eklenir.
Gezinti özelliği Administrator olarak adlandırılır ancak bir Instructor varlığı tutar:

public int? InstructorID { get; set; }


public Instructor Administrator { get; set; }

Önceki koddaki soru işareti (?) özelliği null yapılabilir olduğunu belirtiyor.
Bir departmanın birçok kursu olabilir, bu nedenle bir kurs gezintisi özelliği vardır:
public ICollection<Course> Courses { get; set; }

Note: kurala göre EF Core, null yapılamayan ve çoktan çoğa ilişkiler için art arda silme imkanı sağlar. Basamaklı
silme, dairesel basamaklı silme kurallarına neden olabilir. Döngüsel basamaklı silme kuralları, bir geçiş
eklendiğinde özel duruma neden olur.
Örneğin, Department.InstructorID özelliği null yapılamayan olarak tanımlanmışsa:
EF Core, eğitmen silindiğinde departmanı silmek için bir basamakla silme kuralı yapılandırır.
Eğitmen silindiğinde departmanı silmek amaçlanan davranış değildir.
Aşağıdaki Fluent API Cascade yerine bir kısıtlama kuralı ayarlar.

modelBuilder.Entity<Department>()
.HasOne(d => d.Administrator)
.WithMany()
.OnDelete(DeleteBehavior.Restrict)

Yukarıdaki kod, departman-eğitmen ilişkisindeki basamaklı silmeyi devre dışı bırakır.

Kayıt varlığını güncelleştirme


Kayıt kaydı, tek bir öğrenci tarafından gerçekleştirilen bir kurs içindir.

Modelleri/kaydı. cs 'yi aşağıdaki kodla güncelleştirin:


using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
}

public class Enrollment


{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade { get; set; }

public Course Course { get; set; }


public Student Student { get; set; }
}
}

Yabancı anahtar ve gezinti özellikleri


FK özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:
Kayıt kaydı tek bir kursa yöneliktir, bu nedenle bir CourseID FK özelliği ve Course gezinti özelliği vardır:

public int CourseID { get; set; }


public Course Course { get; set; }

Kayıt kaydı bir öğrenci içindir, bu nedenle bir StudentID FK özelliği ve Student gezinti özelliği vardır:

public int StudentID { get; set; }


public Student Student { get; set; }

Çoktan çoğa Ilişkiler


Student ve Course varlıkları arasında çok-çok ilişkisi vardır. Enrollment varlık, veritabanında Yük ile çoktan
çoğa bir JOIN tablosu olarak çalışır. "Yükle", Enrollment tablosunun birleştirilmiş tablolar (Bu durumda, PK ve
Grade ) gibi ek verileri içerdiği anlamına gelir.

Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğünü gösterilmektedir. (Bu diyagram EF 6.
x için EF güç araçları kullanılarak oluşturulmuştur. Diyagram oluşturmak öğreticinin bir parçası değildir.)
Her ilişki ucu ve bir yıldız işareti (*) 1 diğer sırasında bir-çok ilişkisi belirten bulunur.
Enrollment tablo, sınıf bilgilerini içermiyorsa, yalnızca iki FKs ( CourseID ve StudentID ) içermesi gerekir. Yük
olmadan çoktan çoğa bir JOIN tablosu bazen saf JOIN tablosu (PJT) olarak adlandırılır.
Instructor ve Course varlıkların, saf bir JOIN tablosu kullanılarak çoktan çoğa bir ilişkisi vardır.
Note: EF 6. x, çoktan çoğa ilişkiler için örtük birleştirmeyi destekler, ancak EF Core değildir. Daha fazla bilgi için
EF Core 2,0 ' de çoktan çoğa ilişkilerbölümüne bakın.

Courseatama varlığı

Aşağıdaki kodla modeller/Courseatama. cs oluşturun:


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
public class CourseAssignment
{
public int InstructorID { get; set; }
public int CourseID { get; set; }
public Instructor Instructor { get; set; }
public Course Course { get; set; }
}
}

Eğitmenden kurslar

Eğitmenin kurslardan çok-çok ilişkisi:


Bir varlık kümesiyle temsil etmelidir bir JOIN tablosu gerektirir.
, Saf bir JOIN tablosu (yük içermeyen tablo).
EntityName1EntityName2 bir JOIN varlığı adı yaygın olarak vardır. Örneğin, bu model kullanılarak eğitmen-
kurslar JOIN tablosu CourseInstructor . Ancak, ilişkiyi açıklayan bir ad kullanmanızı öneririz.
Veri modelleri basit ve büyümeye başlar. Yük yükü dahil olmak üzere genellikle yük-yük birleştirmeleri (PJTs)
gelişmektedir. Açıklayıcı bir va

You might also like