Geçersiz görünüm durumu sorunlarını giderme

Bu makalede, Microsoft ASP.NET uygulamalarında hata ayıklama ve viewstate ile ilgili sorunları çözmeye yönelik teknikler tanıtlanmaktadır.

Orijinal ürün sürümü: ASP.NET
Özgün KB numarası: 829743

Giriş

Viewstate, ASP.NET'de sayfaların sunucu durumuna (örneğin, oturum durumu) bağlı kalmadan otomatik olarak durum korumasına olanak tanıyan bir özelliktir. Ancak, viewstate ile ilgili sorunların hatalarını ayıklamak zor olabilir. Çoğu durumda, viewstate ile ilgili sorunlar oluştuğunda, web tarayıcısında aşağıdaki hata iletisini alırsınız ve soruna neyin neden olabileceğinin çok az göstergesi olur:

Görünüm durumu bu sayfa için geçersiz ve bozulmuş olabilir.

Bu makalede, hata ayıklama ve viewstate ile ilgili sorunları çözmek için kullanılabilecek bazı teknikler açıklanmaktadır.

Web grubunda çalıştırıyorsanız validationKey özniteliğini ayarlama

Bir Web grubunda, her istemci isteği her geri göndermede farklı bir makineye gidebilir. Bu davranış nedeniyle özniteliğiniMachine.config dosyasında olarak AutoGenerate bırakamazsınızvalidationKey. Bunun yerine, özniteliğin değerini Web grubundaki validationKey tüm makineler tarafından paylaşılan sabit bir dize olarak ayarlamanız gerekir.

Dinamik olarak oluşturulan türleri bir Web grubunda viewstate içinde depolamayın

ASP.NET dosyaları dinamik olarak derlediğinde, dosyalar rastgele adlarla derlemeler halinde oluşturulur (örneğin, dosya adı jp395dun.dll). Bir Web grubu çalıştırıyorsanız, aynı dosyalar farklı rastgele adlara sahip derlemeler halinde derlenir. Normalde bu bir sorun değildir çünkü kimse bu derleme adlarında varsayımda bulunmaz. Ancak ikili serileştirme kullanarak viewstate içine dinamik olarak derlenmiş bir tür koyarsanız, derlemenin adı viewstate verilerinin bir parçası olarak eklenir. Bu görünüm durumu daha sonra Web grubundaki farklı bir sunucuya gönderildiğinde, görünüm durumu farklı derleme adları kullandığından seri durumdan çıkarılamaz.

En iyi çözüm ikili serileştirme kullanmaktan kaçınmaktır. İkili serileştirme, bu sorunla karşılaşmıyor olsanız bile birçok kaynak kullanır. Bunun yerine, viewstate'e yerleştirdiğiniz öğeleri diziler, çiftler, üçlüler ve basit türlerin (örneğin, dizeler, int ve diğer türler) birleşimiyle sınırlayın. System.Web.UI.Pair ve System.Web.UI.Triplet viewstate altyapısının verimli bir şekilde işleyebileceği basit sarmalayıcı türleridir.

Bu sorundan kaçınmak için alternatif bir düzeltme, viewstate içinde depoladığınız türleri klasörünüzde Bin veya önbellekte önceden derlenmiş bir derlemeye Global Assembly taşımaktır. Bu düzeltme performansı ele almaz, ancak derlemenin tüm bilgisayarlarda aynı ada sahip olduğunu garanti eder.

Not

Karmaşık veri türlerini viewstate içinde depolar ve bu sorunla karşılaşırsanız, çağrı yığını bilgileri aşağıdakine benzer yığınlar içerir:

[FileNotFoundException: Could not load file or assembly 'App_Web_fx--sar9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.]
 System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName) +0
System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +72
System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) +58
System.Type.GetType(String typeName, Boolean throwOnError) +57
System.Web.UI.ObjectStateFormatter.DeserializeType(SerializerBinaryReader reader) +192 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +943 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +384 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +210 
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +198 
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +142

Viewstate makine kimlik doğrulama kodu (MAC) özelliğinin amacı, istemcilerin kötü amaçlı bir görünüm durumu içeren bir istek göndermesini imkansız hale getirmektir. Varsayılan olarak, bu özellik Machine.config dosyasında aşağıdaki bayrakta etkinleştirilir.

enableViewStateMac="true"

Ilgilendiğiniz sorunun MAC özelliğiyle ilgili olup olmadığını belirlemenin en basit yolu özelliği kapatmaktır. Bunu yapmak için Machine.config dosyasındaki bayrağını aşağıdaki kodla değiştirin.

enableViewStateMac="false"

Artık viewstate hataları almezseniz, sorun MAC özelliğiyle ilgilidir.

Önemli

Sorunu tanılamaya yardımcı olması için yalnızca viewstate MAC özelliğini kapatın. Sorunu geçici olarak çözmek için MAC görünüm özelliğini kapalı tutmamalısınız. Eğer bunu yaparsanız, güvenlik açıkları açabilirsiniz. Daha fazla bilgi için bkz. Güvenli ASP.NET Uygulamaları Oluşturma: Kimlik Doğrulaması, Yetkilendirme ve Güvenli İletişim.

VIEWSTATE MAC özelliğini kapatır ve ardından HTML kodlaması olmayan denetimler için viewstate kullanırsanız (örneğin, etiket denetimi), saldırganlar viewstate verileriyle oynanabilir ve viewstate'e rastgele veriler ekleyebilir. Bu rastgele verilerin kodu çözülerek gönderilen sayfayı işlerken denetimler tarafından kullanılır. Sonuç olarak, saldırıyı önlemek için çalışmadığınız sürece saldırganlar uygulamaya betik ekleyebilir. Örneğin, bir saldırgan verilerin kodunu çözebilir, etiket denetiminin bulunduğu verilere betik ekleyip bir web sitesinden bu verilere bağlanabilir. Bağlantıya tıklayan herkes, kimlik doğrulama tanımlama bilgilerini veya oturum kimliğini çalabilecek bir betik ekleme saldırısının kurbanı olabilir. Betik, bir saldırganın viewstate kullanan denetimler için durum verilerini değiştirmesine ve bunun sonucunda uygulamaya özgü saldırılar oluşmasına da izin verebilir.

Genel olarak Microsoft, çıkışlarını (örneğin, DataGrid denetimleri, DataList denetimleri, Etiket denetimleri ve diğer denetimler) HTML olarak kodlamamış tüm denetimler için viewstate özelliğini devre dışı bırakmadığınızdan veya her istekteki değerlerini her zaman açıkça güvenli olduğu bilinen bir değere ayarladığınızdan emin değilseniz viewstate MAC özelliğini kapatmamanızı önerir.

Hata iletisini aldığınızda tam olarak hangi özel durumun oluştuğuna karar verin

Ne yazık ki, bu makalenin Giriş bölümünde belirtilen geçersiz görünüm durumu hata iletisi bilgilendirici değildir. Hata iletisi, viewstate işlenirken bazı özel durumların oluşturulmasından kaynaklanır. Sorun, özel durumun tüketiliyor olması ve hata iletisinde ayrıntılarının kaybolmasıdır.

Hata ayıklayıcı kullanarak özgün özel durumu belirleyebilirsiniz. Bunu yapmak için, ASP.NET işlemine (Aspnet_wp.exe veya W3wp.exe) bir hata ayıklayıcı eklemeniz ve ardından tüm özel durumları yakalayacak şekilde ayarlamanız gerekir. Hata ayıklayıcı büyük olasılıkla ilgili olmayan birkaç özel durumda durur, ancak sonunda viewstate özel durumuna isabet eder ve sorun giderme için yararlı bilgiler sağlar.

Aşağıdaki adımlar, Çalışma Zamanı Hata Ayıklayıcısını (Cordbg.exe) kullanan bir örnektir.

  1. Komut isteminde, size iyi bir başlangıç noktası sağlanmış olduğundan emin olmak için komutunu çalıştırın iisreset ve ardından sitenizdeki bir sayfaya göz atın.

  2. Çalıştır cordbg.exe.

  3. yazın <pro>ve ENTER tuşuna basın. Yönetilen işlemlerin listesi görüntülenir. Aspnet_wp.exe veya W3wp.exe işlemini görmeniz gerekir. PID değerini not edin.

  4. bir <PID>yazın.

    Not

    PID değerini 3. adımda belirtilen PID ile değiştirin.

  5. Cordbg.exe tüm özel durumlarda kesmesini bildirmek için ca e yazın ve ardından işlemi çalıştırın yazın<gto>.

  6. Her özel durum aldığınızda, yığını görmek için yazın <w> . Yığın bir viewstate özel durumuysa (yığında arayın LoadPageStateFromPersistenceMedium ), komut penceresinden tüm özel durumları ve yığın bilgilerini kopyalayın ve ardından bilgileri kaydedin. Bu bilgiler sorunu anlamanıza yardımcı olabilir. Özel durum ilişkisizse yazın <g>.

Viewstate'i oturumda depolamayı deneyin

Varsayılan olarak, görünüm durumu tarayıcıya gönderilen bir <input type=hidden> alanla yuvarlanmış durumdadır. Ardından tarayıcı, sonraki istekte alanı sunucuya geri gönderir. Bazı durumlarda, bu görünüm durumu büyük olabilir ve olası bir sorun kaynağı olabilir. Bazı tarayıcılar bu kadar büyük bir gizli alanı (ve sonuçta elde edilen büyük isteği) işleyemiyor ve tarayıcılar viewstate'i kesebilir. Görünüm durumu kesildiğinde "viewstate bozuk" hata iletisine neden olur. Bu davranış büyük olasılıkla daha basit tarayıcılarda ortaya çıkar. Örneğin, bu davranış PDA'daki bir tarayıcıda oluşabilir.

Böyle bir sorunla karşılaşıp karşılaşmayacağınızı belirlemek için viewstate'i oturumda depolamayı deneyin. Aşağıdaki örnek bunun nasıl yapılacağını göstermektedir.

<%@ language=c# debug=true %> 

<script runat=server> 
protected override object LoadPageStateFromPersistenceMedium() 
{ 
    return Session["_ViewState"]; 
}

protected override void SavePageStateToPersistenceMedium(object viewState) 
{ 
    Session["_ViewState"] = viewState; 
}

void TextChanged(object o, EventArgs e) 
{ 
    Response.Write("TextChanged"); 
} 
</script> 
<form runat=server> 
<asp:button text=Test runat=server/> 
<asp:textbox ontextchanged=TextChanged runat=server/> 
<input type=hidden name=__VIEWSTATE> 
</form> 

Sorunun çalışan işlemi geri dönüşümünden kaynaklanıp kaynaklanmadığını belirleme

Aşağıdaki senaryoyu inceleyin.

  • Microsoft Internet Information Services (IIS) 6.0 altında ASP.NET çalıştıracaksınız.
  • Uygulama havuzu Yerel Sistem hesabı, Ağ Hizmeti hesabı veya yönetim düzeyinde bir hesap dışında bir kimlik altında çalışıyor.
  • validationKey öğesinin <machineKey> özniteliği yapılandırma dosyasında olarak AutoGenerate ayarlanır.

Bu senaryoda, aşağıdaki yordam viewstate hatasının oluşmasına neden olur:

  1. Kullanıcı bir sayfaya göz atar.
  2. ASP.NET uygulamasını barındıran çalışan işlemi geri dönüştürülebilir.
  3. Kullanıcı sayfayı geri gönderir.

Bu senaryo için geçici bir çözüm olarak yapılandırma dosyasında açık validationKey bir öznitelik kullanın.

Başvurular