ASP.NET’te yapılmaması gerekenler ve bunların yerine yapılması gerekenler

Bu konu başlığında, kişilerin web projelerinde ASP.NET sık yapılan bazı hatalar açıklanmaktadır. Bu yaygın hatalardan kaçınmak için yapmanız gerekenlere yönelik öneriler sağlar. Norveç Geliştiriciler Konferansı'nda Damian Edwards tarafından yapılan bir sunuyu temel alır.

Disclaimer

Bu konu, uygulamanızın güvenli ve verimli olduğundan emin olmak için eksiksiz bir kılavuz olarak tasarlanmamıştır. Yine de bu konuda ana hatlarıyla belirtilmeyen en iyi güvenlik ve performans yöntemlerini izlemeniz gerekir. Yalnızca .NET sınıfları ve işlemleriyle ilgili yaygın hatalardan kaçınmayı önerir.

Genel Bakış

Bu konu aşağıdaki bölümleri içermektedir:

Standart Uyumluluğu

Denetim bağdaştırıcıları

Öneri: Uyarlamalı işleme için denetim bağdaştırıcılarını kullanmayı bırakın ve bunun yerine CSS medya sorgularını ve standartlara uygun HTML'yi kullanın.

Denetim Bağdaştırıcıları, farklı cihazlar ve ortamlar için özelleştirilmiş sunu kodunu işlemek için .NET 2.0'da kullanıma sunulmuştur. Artık bu uyarlamalı işleme CSS ve HTML ile gerçekleştirilebilir. Denetim Bağdaştırıcıları'nı kullanmayı durdurmalı ve mevcut bağdaştırıcıları CSS ve HTML'ye dönüştürmelisiniz.

Daha fazla bilgi için bkz. Medya Sorguları ve Nasıl Yapılır: ASP.NET Web Forms/MVC Uygulamanıza Mobil Sayfa Ekleme.

Denetimlerde stil özellikleri

Öneri: Denetim işaretlemesinde stil değerlerini ayarlamayı durdurun ve bunun yerine CSS stil sayfalarında biçimlendirme değerlerini ayarlayın.

Web sunucusu denetimleri, satır içi stil özelliklerini ayarlamak için kullanılabilecek onlarca özellik içerir. Örneğin, ForeColor özelliği denetimin metninin rengini ayarlar. Aynı etkiyi CSS stil sayfaları aracılığıyla daha verimli bir şekilde gerçekleştirebilirsiniz. Stil sayfaları, stil değerlerini merkezileştirmenize ve bu değerleri uygulamanız genelinde ayarlamaktan kaçınmanıza olanak tanır.

Aşağıdaki örnekte, metni kırmızıya ayarlı bir CSS sınıfı gösterilmektedir.

.CautionRow {
    color: red;
}

Sonraki örnekte CSS sınıfının dinamik olarak nasıl uygulanacağı gösterilmektedir.

protected void CustomersGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.Cells[2].Text == "Unconfirmed")
    {
        e.Row.CssClass = "CautionRow";
    }
}

Sayfa ve denetim geri çağırmaları

Öneri: Sayfa ve denetim geri çağırmalarını kullanmayı durdurun ve bunun yerine aşağıdakilerden birini kullanın: AJAX, UpdatePanel, MVC eylem yöntemleri, Web API'si veya SignalR.

önceki ASP.NET sürümlerinde, Page ve Control geri çağırma yöntemleri, sayfanın tamamını yenilemeden web sayfasının bir bölümünü güncelleştirmenizi sağlar. Artık kısmi sayfa güncelleştirmelerini AJAX, UpdatePanel, MVC, Web API veya SignalR aracılığıyla gerçekleştirebilirsiniz. Kolay URL'ler ve yönlendirme ile ilgili sorunlara neden olabileceği için geri çağırma yöntemlerini kullanmayı durdurmalısınız. Varsayılan olarak denetimler geri çağırma yöntemlerini etkinleştirmez, ancak bu özelliği bir denetimde etkinleştirdiyseniz devre dışı bırakmanız gerekir.

Tarayıcı özelliği algılama

Öneri: Statik tarayıcı özellik algılamayı kullanmayı bırakın ve bunun yerine dinamik özellik algılamayı kullanın.

ASP.NET'ın önceki sürümlerinde, her tarayıcı için desteklenen özellikler bir XML dosyasında depolanıyordu. Statik arama aracılığıyla özellik desteğini algılamak en iyi yaklaşım değildir. Artık Modernizr gibi bir özellik algılama çerçevesi kullanarak tarayıcının desteklenen özelliklerini dinamik olarak algılayabilirsiniz. Özellik algılama, bir yöntem veya özellik kullanmaya çalışarak ve ardından tarayıcının istenen sonucu oluşturup oluşturmadığını denetleyerek desteği belirler. Modernizr varsayılan olarak Web uygulaması şablonlarına eklenir.

Güvenlik

İstek doğrulama

Öneri: Kullanıcı girişini doğrulayın ve kullanıcılardan gelen çıkışı kodlar.

İstek doğrulama, her isteği inceleyen ve algılanan bir tehdit bulunduğunda isteği durduran bir ASP.NET özelliğidir. Uygulamanızı siteler arası betik saldırılarına karşı korumak için istek doğrulamasına bağımlı değildir. Bunun yerine, kullanıcılardan gelen tüm girişleri doğrulayın ve çıkışı kodlayabilirsiniz. Bazı sınırlı durumlarda, girişi doğrulamak için normal ifadeler kullanabilirsiniz, ancak daha karmaşık durumlarda değerin izin verilen değerlerle eşleşip eşleşmediğini belirleyen .NET sınıflarını kullanarak kullanıcı girişini doğrulamanız gerekir.

Aşağıdaki örnekte, bir kullanıcı tarafından sağlanan Uri'nin geçerli olup olmadığını belirlemek için Uri sınıfında statik bir yöntemin nasıl kullanılacağı gösterilmektedir.

var isValidUri = Uri.IsWellFormedUriString(passedUri, UriKind.Absolute);

Ancak, Uri'yi yeterince doğrulamak için veya httpsdeğerini belirttiğinden http emin olmak için de denetlemeniz gerekir. Aşağıdaki örnek, Uri'nin geçerli olduğunu doğrulamak için örnek yöntemlerini kullanır.

var uriToVerify = new Uri(passedUri);
var isValidUri = uriToVerify.IsWellFormedOriginalString();
var isValidScheme = uriToVerify.Scheme == "http" || uriToVerify.Scheme == "https";

Kullanıcı girişini HTML olarak işlemeden veya SQL sorgusuna kullanıcı girişi eklemeden önce, değerleri kodlayın ve kötü amaçlı kodun dahil edilmediğinden emin olun.

Aşağıda gösterildiği gibi, %: %> söz dizimi ile biçimlendirmedeki değeri HTML ile <kodlayabilirsiniz.

<span><%: userInput %></span>

Veya Razor söz diziminde, aşağıda gösterildiği gibi @ ile HTML kodlaması yapabilirsiniz.

<span>@userInput</span>

Sonraki örnekte, HTML'nin arka planda bir değeri kodlama işlemi gösterilmektedir.

var encodedInput = Server.HtmlEncode(userInput);

SQL komutları için bir değeri güvenli bir şekilde kodlamak için SqlParameter gibi komut parametrelerini kullanın.

Tanımlama bilgisi olmayan formlar kimlik doğrulaması ve oturumu

Öneri: Tanımlama bilgileri iste.

Sorgu dizesinde kimlik doğrulama bilgilerinin geçirilmesi güvenli değildir. Bu nedenle, uygulamanız kimlik doğrulaması içerdiğinde tanımlama bilgileri gerektirir. Tanımlama bilginiz hassas bilgileri depolarsa, tanımlama bilgisi için SSL gerektirmeyi göz önünde bulundurun.

Aşağıdaki örnekte, Web.config dosyasında Forms Kimlik Doğrulaması'nın SSL üzerinden iletilen bir tanımlama bilgisi gerektirdiğini belirtme işlemi gösterilmektedir.

<authentication mode="Forms">
  <forms loginUrl="member_login.aspx"
    cookieless="UseCookies"
    requireSSL="true"
    path="/MyApplication" />
</authentication>

Enableviewstatemac

Öneri: Hiçbir zaman false olarak ayarlanmadı.

Varsayılan olarak, EnableViewStateMac true olarak ayarlanır. Uygulamanız görünüm durumunu kullanmıyor olsa bile EnableViewStateMac'i false olarak ayarlamayın. Bu değeri false olarak ayarlamak, uygulamanızı siteler arası betiklere karşı savunmasız hale getirir.

çalışma zamanı, ASP.NET 4.5.2'den başlayarak EnableViewStateMac=true'yu zorunlu kılabilir. False olarak ayarlasanız bile çalışma zamanı bu değeri yoksayar ve değeri true olarak ayarlar. Daha fazla bilgi için bkz. ASP.NET 4.5.2 ve EnableViewStateMac.

Aşağıdaki örnekte EnableViewStateMac değerinin true olarak nasıl ayarlanacağı gösterilmektedir. Varsayılan olarak true olduğundan bu değeri true olarak ayarlamanız gerekmez. Ancak, uygulamanızın herhangi bir sayfasında false olarak ayarladıysanız, bu değeri hemen düzeltmeniz gerekir.

<%@ Page language="C#" EnableViewStateMac="true" %>

Orta güven

Öneri: Güvenlik sınırı olarak Orta Güven'e (veya başka bir güven düzeyine) bağımlı değildir.

Kısmi güven uygulamanızı yeterince korumaz ve kullanılmamalıdır. Bunun yerine, Tam Güven'i kullanın ve güvenilmeyen uygulamaları ayrı uygulama havuzlarında yalıtabilirsiniz. Ayrıca, her uygulama havuzunu benzersiz bir kimlik altında çalıştırın. Daha fazla bilgi için bkz. Kısmi Güven ASP.NET uygulama yalıtımını garanti etmez.

<Appsettings>

Öneri: appSettings> öğesinde <güvenlik ayarlarını devre dışı bırakma.

appSettings öğesi, güvenlik güncelleştirmeleri için gereken birçok değer içerir. Bu değerleri değiştirmemeli veya devre dışı bırakmamalısınız. Bir güncelleştirmeyi dağıtırken bu değerleri devre dışı bırakmanız gerekiyorsa, dağıtımı tamamladıktan sonra hemen yeniden etkinleştirin.

Ayrıntılar için bkz. ASP.NET appSettings Öğesi.

UrlPathEncode

Öneri: Bunun yerine UrlEncode kullanın.

UrlPathEncode yöntemi, çok özel bir tarayıcı uyumluluk sorununu çözmek için .NET Framework eklendi. Bir URL'yi yeterli şekilde kodlamaz ve uygulamanızı siteler arası betiklere karşı korumaz. Bunu uygulamanızda hiçbir zaman kullanmamalısınız. Bunun yerine UrlEncode kullanın.

Aşağıdaki örnekte, köprü denetimi için sorgu dizesi parametresi olarak kodlanmış bir URL'nin nasıl geçir yapılacağı gösterilmektedir.

string destinationURL = "http://www.contoso.com/default.aspx?user=test";
NextPage.NavigateUrl = "~/Finish?url=" + Server.UrlEncode(destinationURL);

Güvenilirlik ve performans

PreSendRequestHeaders ve PreSendRequestContent

Öneri: Bu olayları yönetilen modüllerle kullanmayın. Bunun yerine, gerekli görevi gerçekleştirmek için yerel bir IIS modülü yazın. Bkz . Native-Code HTTP Modülleri Oluşturma.

PreSendRequestHeaders ve PreSendRequestContent olaylarını yerel IIS modülleriyle kullanabilirsiniz.

Uyarı

ve'i PreSendRequestContent uygulayan IHttpModuleyönetilen modüllerle kullanmayınPreSendRequestHeaders. Bu özelliklerin ayarlanması zaman uyumsuz isteklerle ilgili sorunlara neden olabilir. Uygulama İstenen Yönlendirme (ARR) ve web yuvalarının birleşimi, w3wp'nin kilitlenmesine neden olabilecek erişim ihlali özel durumlarına yol açabilir. Örneğin, iiscore! W3_CONTEXT_BASE::GetIsLastNotification+68 iiscore.dll erişim ihlali özel durumu (0xC0000005) neden oldu.

Web formlarıyla zaman uyumsuz sayfa olayları

Öneri: Web Forms, Sayfa yaşam döngüsü olayları için zaman uyumsuz void yöntemleri yazmaktan kaçının ve bunun yerine zaman uyumsuz kod için Page.RegisterAsyncTask kullanın.

Bir sayfa olayını zaman uyumsuz ve geçersiz olarak işaretlediğinizde, zaman uyumsuz kodun ne zaman bittiğini belirleyemezsiniz. Bunun yerine, zaman uyumsuz kodu tamamlanmasını izlemenizi sağlayan bir şekilde çalıştırmak için Page.RegisterAsyncTask kullanın.

Aşağıdaki örnekte, zaman uyumsuz kod içeren bir düğme tıklama işleyicisi gösterilmektedir. Bu örnek, yalnızca zaman uyumsuz bir görevin basitleştirilmiş bir örneği olarak sağlanan ve önerilen bir uygulama olarak sağlanmayan bir dize değerini zaman uyumsuz olarak okumayı içerir.

protected void StartAsync_Click(object sender, EventArgs e)
{
    Page.RegisterAsyncTask(new PageAsyncTask(async() =>
    {
        string stringToRead = "Long text value";

        using (StringReader reader = new StringReader(stringToRead))
        {
            string readText = await reader.ReadToEndAsync();
            Result.Text = readText;
        }
    }));
}

Zaman uyumsuz Görevler kullanıyorsanız http çalışma zamanı hedef çerçevesini Web.config dosyasında 4.5 (veya üzeri) olarak ayarlayın. Hedef çerçevenin 4.5 olarak ayarlanması, .NET 4.5'e eklenen yeni eşitleme bağlamını açar. Bu değer Visual Studio'daki yeni projelerde varsayılan olarak ayarlanır, ancak mevcut bir projeyle çalışıyorsanız ayarlanmaz.

<system.web>
    <httpRuntime TargetFramework="4.5" />
</system.web>

Yangın ve unutan iş

Öneri: ASP.NET içinde bir isteği işlerken, fire-and-forget işini başlatmaktan kaçının (ThreadPool.QueueUserWorkItem yöntemini çağırmak veya tekrar tekrar temsilci çağıran bir zamanlayıcı oluşturmak gibi).

Uygulamanızın ASP.NET içinde çalışan fire-and-forget çalışması varsa, uygulamanız eşitlenmemiş olabilir. Herhangi bir anda uygulama etki alanı yok edilebilir, bu da devam eden işleminizin artık uygulamanın geçerli durumuyla eşleşmeyebileceği anlamına gelir.

Bu tür işleri ASP.NET dışına taşımalısınız. Devam eden işleri gerçekleştirmek ve bu kodu başka bir işlemden çalıştırmak için Azure'da Bir Web İşleri, Windows Hizmeti veya Çalışan rolü kullanabilirsiniz.

Bu işi ASP.NET içinde gerçekleştirmeniz gerekiyorsa, kodu çalıştırmak için WebBackgrounder adlı Nuget paketini ekleyebilirsiniz.

İstek varlığı gövdesi

Öneri: İşleyicinin yürütme olayından önce Request.Form veya Request.InputStream okumaktan kaçının.

Request.Form veya Request.InputStream'den en erken okumanız gereken, işleyicinin yürütme olayı sırasındadır. MVC'de Denetleyici işleyicidir ve yürütme olayı eylem yöntemi çalıştırıldığında gerçekleştirilir. Web Forms'de Page işleyicidir ve yürütme olayı Page.Init olayı tetiklendiğindedir. Yürütme olayından önce istek varlığı gövdesini okursanız, isteğin işlenmesini engellersiniz.

Yürütme olayından önce istek varlığı gövdesini okumanız gerekiyorsa Request.GetBufferlessInputStream veya Request.GetBufferedInputStream kullanın. GetBufferlessInputStream kullandığınızda, istekten ham akışı alır ve isteğin tamamını işleme sorumluluğunu üstlenirsiniz. GetBufferlessInputStream çağrıldıktan sonra, ASP.NET tarafından doldurulmadıkları için Request.Form ve Request.InputStream kullanılamaz. GetBufferedInputStream kullandığınızda, istekten akışın bir kopyasını alırsınız. request.Form ve Request.InputStream, diğer kopyayı ASP.NET dolduracağından isteğin ilerleyen bölümlerinde kullanılabilir.

Response.Redirect ve Response.End

Öneri: Response.Redirect(String) çağrıldıktan sonra iş parçacığının nasıl işlendiğinde farklılıklara dikkat edin.

Response.Redirect(String) yöntemi, Response.End yöntemini çağırır. Zaman uyumlu bir işlemde Request.Redirect çağrısı geçerli iş parçacığının hemen durdurulmalarına neden olur. Ancak, zaman uyumsuz bir işlemde Response.Redirect çağrısı geçerli iş parçacığını durdurmaz, bu nedenle istek için kod yürütme devam eder. Zaman uyumsuz bir işlemde, kod yürütmeyi durdurmak için yönteminden Görevi döndürmeniz gerekir.

MVC projesinde Response.Redirect'i çağırmamalısınız. Bunun yerine RedirectResult değerini döndürebilirsiniz.

EnableViewState ve ViewStateMode

Öneri: Hangi denetimlerin görünüm durumunu kullandığı üzerinde ayrıntılı denetim sağlamak için EnableViewState yerine ViewStateMode kullanın.

Page yönergesinde EnableViewState değerini false olarak ayarladığınızda, görünüm durumu sayfadaki tüm denetimler için devre dışı bırakılır ve etkinleştirilemez. Görünüm durumunu sayfanızdaki yalnızca belirli denetimler için etkinleştirmek istiyorsanız, Sayfa için ViewStateMode'u Devre Dışı olarak ayarlayın.

<%@ Page ViewStateMode="Disabled" . . . %>

Ardından ViewStateMode'u yalnızca görünüm durumuna ihtiyaç duyan denetimlerde Etkin olarak ayarlayın.

<asp:GridView ViewStateMode="Enabled" runat="server">

Görünüm durumunu yalnızca ihtiyacı olan denetimler için etkinleştirerek, web sayfalarınızın görünüm durumunun boyutunu küçültebilirsiniz.

SqlMembershipProvider

Öneri: Evrensel Sağlayıcılar kullanın.

Geçerli proje şablonlarında, SqlMembershipProvider'ın yerini NuGet paketi olarak kullanılabilen ASP.NET Evrensel Sağlayıcılar almıştır. Şablonların önceki bir sürümüyle oluşturulmuş bir projede SqlMembershipProvider kullanıyorsanız Evrensel Sağlayıcılar'a geçmeniz gerekir. Evrensel Sağlayıcılar, Entity Framework tarafından desteklenen tüm veritabanlarıyla çalışır.

Daha fazla bilgi için bkz. ASP.NET Evrensel Sağlayıcılara Giriş.

Uzun süre çalışan istekler (>110 saniye)

Öneri: Bağlı istemciler için WebSockets veya SignalR kullanın ve zaman uyumsuz G/Ç işlemleri kullanın.

Uzun süre çalışan istekler, web uygulamanızda öngörülemeyen sonuçlara ve düşük performansa neden olabilir. İstek için varsayılan zaman aşımı ayarı 110 saniyedir. Oturum durumunu uzun süre çalışan bir istekle kullanıyorsanız, ASP.NET 110 saniye sonra Session nesnesinde kilidi serbest bırakır. Ancak, kilit serbest bırakıldığında uygulamanız Session nesnesindeki bir işlemin ortasında olabilir ve işlem başarıyla tamamlanmayabilir. İlk istek çalışırken kullanıcıdan gelen ikinci bir istek engellenirse, ikinci istek Session nesnesine tutarsız bir durumda erişebilir.

Uygulamanız engelleme (veya zaman uyumlu) G/Ç işlemleri içeriyorsa, uygulama yanıt vermez.

Performansı geliştirmek için .NET Framework zaman uyumsuz G/Ç işlemlerini kullanın. Ayrıca, istemcileri sunucuya bağlamak için WebSockets veya SignalR kullanın. Bu özellikler, uzun süre çalışan istekleri verimli bir şekilde işlemek için tasarlanmıştır.