Aracılığıyla paylaş


İç İçe Veri Web Denetimleri (VB)

tarafından Scott Mitchell

PDF'i indirin

Bu öğreticide, başka bir Repeater'ın içinde yer alan bir Repeater'ın nasıl kullanılacağını inceleyeceğiz. Örnekler, iç Repeater'ın bildirim temelli ve programlı olarak nasıl doldurulacağını gösterir.

Giriş

Şablonlar, statik HTML ve veri bağlama söz dizimine ek olarak Web denetimleri ve Kullanıcı Denetimleri de içerebilir. Bu Web denetimlerinin özellikleri bildirim temelli, veri bağlama söz dizimi yoluyla atanabilir veya uygun sunucu tarafı olay işleyicilerinde program aracılığıyla erişilebilir.

Denetimleri bir şablona ekleyerek, görünüm ve kullanıcı deneyimi özelleştirilebilir ve geliştirilebilir. Örneğin, GridView Denetimindeki TemplateField'leri Kullanma öğreticisinde , bir çalışanın işe alma tarihini göstermek için TemplateField'a Takvim denetimi ekleyerek GridView görünümünü özelleştirmeyi gördük; Düzenleme ve Ekleme Arabirimlerine Doğrulama Denetimleri Ekleme veVeri Değiştirme Arabirimini Özelleştirme öğreticilerinde, doğrulama denetimleri, TextBoxes, DropDownLists ve diğer Web denetimleri ekleyerek arabirimleri düzenleme ve ekleme işlemlerini özelleştirmeyi gördük.

Şablonlar başka veri Web denetimleri de içerebilir. Başka bir ifadeyle, şablonları içinde başka bir DataList (veya Repeater, GridView veya DetailsView vb.) içeren bir DataList'imiz olabilir. Böyle bir arabirimle ilgili zorluk, uygun verileri iç veri Web denetimine bağlamaktır. ObjectDataSource kullanarak bildirim temelli seçeneklerden programlı seçeneklere kadar değişen birkaç farklı yaklaşım vardır.

Bu öğreticide, başka bir Repeater'ın içinde yer alan bir Repeater'ın nasıl kullanılacağını inceleyeceğiz. Dış Repeater, veritabanındaki her kategori için kategorinin adını ve açıklamasını görüntüleyen bir öğe içerir. Her kategori öğesinin iç Yineleyicisi, madde işaretli bir listede söz konusu kategoriye ait her ürünün bilgilerini görüntüler (bkz. Şekil 1). Örneklerimizde iç Repeater'ın bildirim temelli ve programlı olarak nasıl doldurulacağı gösterilmektedir.

Her Kategori, Ürünleriyle birlikte Listelenir

Şekil 1: Her Kategori ve Ürünleri Listelenir (Tam boyutlu görüntüyü görüntülemek için tıklayın)

1. Adım: Kategori Listesini Oluşturma

İç içe veri Web denetimlerini kullanan bir sayfa oluştururken, iç içe denetim konusunda endişelenmeden en dıştaki veri Web denetimini tasarlamayı, oluşturmayı ve test etme konusunda yararlı buluyorum. Bu nedenle, her kategorinin adını ve açıklamasını listeleyen sayfaya bir Repeater eklemek için gerekli adımları izleyerek başlayalım.

NestedControls.aspx klasöründeki DataListRepeaterBasics sayfasını açarak başlayın ve ID özelliğini CategoryList olarak ayarlayıp sayfaya bir Repeater denetimi ekleyin. Repeater'ın akıllı etiketinden adlı CategoriesDataSourceyeni bir ObjectDataSource oluşturmayı seçin.

Yeni ObjectDataSource'ı CategoriesDataSource Olarak Adlandırın

Şekil 2: Yeni ObjectDataSource CategoriesDataSource adını verin (Tam boyutlu görüntüyü görüntülemek için tıklayın)

ObjectDataSource'un verilerini CategoriesBLL sınıfının GetCategories yönteminden çekebilmesi için yapılandırın.

ObjectDataSource'ı CategoriesBLL Sınıfının GetCategories Yöntemini Kullanacak Şekilde Yapılandırma

Şekil 3: ObjectDataSource'un CategoriesBLL Sınıf Yöntemini Kullanacak Şekilde Yapılandırılması GetCategories (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Repeater öğesinin şablon içeriğini belirtmek için Kaynak görünümüne geçerek deklaratif söz dizimini el ile girmemiz gerekir. Bir ItemTemplate öğesi ekleyin, bu öğede kategori adı bir <h4> öğesinde ve kategori açıklaması bir paragraf öğesinde (<p>) görüntülensin. Ayrıca, her kategoriyi yatay bir kuralla (<hr> ) ayıralım. Bu değişiklikleri yaptıktan sonra sayfanız Repeater ve ObjectDataSource için aşağıdakine benzer bildirim temelli söz dizimi içermelidir:

<asp:Repeater ID="CategoryList" DataSourceID="CategoriesDataSource"
    EnableViewState="False" runat="server">
    <ItemTemplate>
        <h4><%# Eval("CategoryName") %></h4>
        <p><%# Eval("Description") %></p>
    </ItemTemplate>
    <SeparatorTemplate>
        <hr />
    </SeparatorTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Şekil 4'de tarayıcı üzerinden görüntülendiğinde ilerleme durumumuz gösterilmektedir.

Her Kategorinin Adı ve Açıklaması Yatay Kuralla Ayrılmış Olarak Listelenir

Şekil 4: Her Kategorinin Adı ve Açıklaması Yatay Kuralla Ayrılmış Olarak Listelenir (Tam boyutlu resmi görüntülemek için tıklayın)

2. Adım: İç İçe Ürün Yineleyicisini Ekleme

Kategori listesi tamamlandıktan sonra, bir sonraki görevimiz uygun kategoriye ait ürünlerle ilgili bilgileri görüntüleyen bir Repeater CategoryListItemTemplate eklemektir. Bu iç Repeater'ın verilerini almanın birkaç yolu vardır ve bunlardan ikisi de kısa süre içinde incelenir. Şimdilik CategoryList Repeater'ının ItemTemplate içinde ürün Repeater'ı oluşturalım. Özellikle, ürün Yineleyicisi'nin her ürünü, ürün adı ve fiyatı dahil olmak üzere her liste öğesiyle birlikte madde işaretli bir listede görüntülemesini sağlayın.

Bu Repeat Edicisi'ni oluşturmak için, iç Repeat Edicisi'nin bildirimsel söz dizimini ve şablonlarını CategoryList'ün ItemTemplate'ine el ile girmemiz gerekir. Repeater s CategoryListiçine aşağıdaki işaretlemeyi ItemTemplate ekleyin:

<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
    runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong>
            (<%# Eval("UnitPrice", "{0:C}") %>)</li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

3. Adım: Category-Specific Ürünlerini ProductsByCategoryList Repeater'a Bağlama

Bu noktada sayfayı bir tarayıcı üzerinden ziyaret ederseniz, yine de Repeater'a herhangi bir veri bağlamadığımız için ekranınız Şekil 4'tekiyle aynı görünür. Uygun ürün kayıtlarını alıp Repeater'a bağlamanın birkaç yolu vardır ve bazıları diğerlerinden daha verimlidir. Buradaki temel zorluk, belirtilen kategori için uygun ürünleri geri almaktır.

İç Repeater denetimine bağlanacak verilere, Repeater'daki CategoryListbir ObjectDataSource ItemTemplate aracılığıyla bildirim temelli olarak veya program aracılığıyla, ASP.NET sayfasının arka planda kod sayfasından erişilebilir. Benzer şekilde, bu veriler iç Repeater'a bildirimsel olarak bağlanabilir; iç Repeater'ın DataSourceID özelliği aracılığıyla veya bildirimsel veri bağlama söz dizimi kullanılarak veya olay işleyicisinin CategoryList iç Repeater'ına atıfta bulunarak, ItemDataBound özelliğini programlı bir şekilde ayarlayıp DataSource yöntemini çağırarak programla bağlanabilir. Şimdi bu yaklaşımların her birini inceleyelim.

ObjectDataSource Denetimi veItemDataBoundOlay İşleyicisi ile Verilere Bildirimli Olarak Erişme

Bu öğretici serisi boyunca ObjectDataSource'ı yoğun bir şekilde kullandığımızdan, bu örnekteki verilere erişmek için en doğal seçenek ObjectDataSource'a bağlı kalmaktır. sınıfı, ProductsBLL belirtilen GetProductsByCategoryID(categoryID)öğesine ait olan ürünler hakkında bilgi döndüren bir categoryID yönteme sahiptir. Bu nedenle, CategoryList Repeater'lara bir ObjectDataSource ekleyebilir ve ItemTemplate bu sınıfın yönteminden verilerine erişecek şekilde yapılandırabiliriz.

Ne yazık ki Repeater şablonlarının Tasarım görünümü aracılığıyla düzenlenmesine izin vermez, bu nedenle bu ObjectDataSource denetimi için bildirim temelli söz dizimini el ile eklememiz gerekir. Aşağıdaki sözdizimi, bu yeni ObjectDataSource (CategoryList) eklendikten sonra ItemTemplateRepeaterProductsByCategoryDataSource öğesini gösterir:

<h4><%# Eval("CategoryName") %></h4>
<p><%# Eval("Description") %></p>
<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
        DataSourceID="ProductsByCategoryDataSource" runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong> -
                sold as <%# Eval("QuantityPerUnit") %> at
                <%# Eval("UnitPrice", "{0:C}") %></li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsByCategoryDataSource" runat="server"
           SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
   <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
   </SelectParameters>
</asp:ObjectDataSource>

ObjectDataSource yaklaşımını kullanırken Repeater'ın ProductsByCategoryList özelliğini ObjectDataSource'un DataSourceID'sine ID olarak ayarlamamız gerekir (ProductsByCategoryDataSource). Ayrıca, ObjectDataSource'umuzun <asp:Parameter> yöntemine geçirilecek categoryID değerini belirten bir GetProductsByCategoryID(categoryID) öğesi olduğuna dikkat edin. Peki bu değeri nasıl belirteceğiz? İdeal olarak, veri bağlama söz dizimini DefaultValue kullanarak öğesinin <asp:Parameter> özelliğini ayarlayabiliriz, örneğin:

<asp:Parameter Name="CategoryID" Type="Int32"
    DefaultValue='<%# Eval("CategoryID")' />

Ne yazık ki, veri bağlama söz dizimi yalnızca olay DataBinding içeren denetimlerde geçerlidir. Sınıfında Parameter böyle bir olay olmadığından yukarıdaki söz dizimi geçersizdir ve çalışma zamanı hatasına neden olur.

Bu değeri ayarlamak için Repeater CategoryList olayı için bir olay işleyicisi ItemDataBound oluşturmamız gerekir. Olayın Repeater'a ItemDataBound bağlı her öğe için bir kez tetiklendiğini unutmayın. Bu nedenle, bu olay dış Repeater için her tetiklendiğinde geçerli CategoryID değerini ProductsByCategoryDataSource ObjectDataSource'ın CategoryID parametresine atayabiliriz.

Repeater CategoryList olayını ItemDataBound için aşağıdaki kodla bir olay işleyicisi oluşturun:

Protected Sub CategoryList_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) _
    Handles CategoryList.ItemDataBound
    If e.Item.ItemType = ListItemType.AlternatingItem _
        OrElse e.Item.ItemType = ListItemType.Item Then
        ' Reference the CategoriesRow object being bound to this RepeaterItem
        Dim category As Northwind.CategoriesRow = _
            CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
                Northwind.CategoriesRow)
        ' Reference the ProductsByCategoryDataSource ObjectDataSource
        Dim ProductsByCategoryDataSource As ObjectDataSource = _
            CType(e.Item.FindControl("ProductsByCategoryDataSource"), _
                ObjectDataSource)
        ' Set the CategoryID Parameter value
        ProductsByCategoryDataSource.SelectParameters("CategoryID").DefaultValue = _
            category.CategoryID.ToString()
    End If
End Sub

Bu olay işleyicisi, üst bilgi, alt bilgi veya ayırıcı öğe yerine bir veri öğesiyle ilgilendiğimizi güvence altına alarak başlar. Ardından, geçerli CategoriesRow öğesine bağlı olan gerçek RepeaterItem örneğine başvuracağız. Son olarak, ItemTemplate içindeki ObjectDataSource'a başvuruyoruz ve CategoryID parametre değerini geçerli CategoryID öğesine RepeaterItem atanıyoruz.

Bu olay işleyicisi ProductsByCategoryList ile, her bir RepeaterItem içindeki Repeater, RepeaterItem kategorisi ürünlerine bağlıdır. Şekil 5'de sonuçta elde edilen çıkışın ekran görüntüsü gösterilmektedir.

Dış Yineleyici her kategoriyi listeler; İçTe Bu Kategorinin Ürünleri Listelenir

Şekil 5: Dış Yineleyici her kategoriyi listeler; İçTe bu Kategorinin Ürünleri Listelenir (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Ürünlere Kategori Verilerine Göre Program Aracılığıyla Erişme

ASP.NET sayfasının kod arkası sınıfında (veya App_Code klasöründe ya da ayrı bir Sınıf Kitaplığı projesinde), bir CategoryID iletildiğinde uygun ürün listesini döndüren bir yöntem oluşturabiliriz. Bu, geçerli kategoriye ait ürünleri almak için bir ObjectDataSource kullanmak yerine yapılabilir. ASP.NET sayfamızın code-behind sınıfında böyle bir yöntemimiz olduğunu ve bunun GetProductsInCategory(categoryID) olarak adlandırıldığını düşünün. Bu yöntem kullanıldığında, aşağıdaki bildirim temelli söz dizimini kullanarak geçerli kategoriye ilişkin ürünleri iç Repeater'a bağlayabiliriz:

<asp:Repeater runat="server" ID="ProductsByCategoryList" EnableViewState="False"
      DataSource='<%# GetProductsInCategory(CType(Eval("CategoryID"), Integer)) %>'>
  ...
</asp:Repeater>

Repeater'ın DataSource özelliği, verilerinin GetProductsInCategory(categoryID) yönteminden geldiğini belirtmek için veri bağlama sözdizimini kullanır. Eval("CategoryID") türünde bir Object değeri döndürdüğünden, nesneyi Integer yöntemine geçirmeden önce bir GetProductsInCategory(categoryID)'e dönüştürürüz. CategoryID Burada veri bağlama söz dizimi aracılığıyla erişilen CategoryID, dış Repeater (CategoryList) içindeki ve tablodaki kayıtlara bağlı olan Categories olduğuna dikkat edin. Bu nedenle, CategoryID bir veritabanı NULL değeri olamaz, bu yüzden bir Eval ile ilgili kontrol yapmadan DBNull yöntemini direkt dönüştürebiliriz.

Bu yaklaşımla, bir yöntem oluşturmamız GetProductsInCategory(categoryID) ve sağlanan categoryID verilerine göre uygun ürün kümesini almasını sağlamalıyız. Bunu, sınıfın ProductsDataTableProductsBLL yönteminin döndürdüğü GetProductsByCategoryID(categoryID)'yı geri döndürerek yapabiliriz. Kod-arkası sınıfında GetProductsInCategory(categoryID) yöntemini NestedControls.aspx sayfamız için oluşturalım. Bunu aşağıdaki kodu kullanarak yapın:

Protected Function GetProductsInCategory(ByVal categoryID As Integer) _
    As Northwind.ProductsDataTable
    ' Create an instance of the ProductsBLL class
    Dim productAPI As ProductsBLL = New ProductsBLL()
    ' Return the products in the category
    Return productAPI.GetProductsByCategoryID(categoryID)
End Function

Bu yöntem yalnızca yönteminin bir örneğini ProductsBLL oluşturur ve yönteminin GetProductsByCategoryID(categoryID) sonuçlarını döndürür. Yöntemin Public veya Protected olarak işaretlenmesi gerektiğini unutmayın; bir yöntem Private olarak işaretlenirse, ASP.NET sayfasının deklaratif işaretlemesinden erişilemez.

Bu yeni tekniği kullanmak için bu değişiklikleri yaptıktan sonra, sayfayı bir tarayıcı üzerinden görüntülemek için biraz zaman ayırın. ObjectDataSource ve ItemDataBound olay işleyicisi yaklaşımı kullanılırken çıkış çıkışla aynı olmalıdır (ekran görüntüsünü görmek için Şekil 5'e geri bakın).

Uyarı

ASP.NET sayfasının kod arkası sınıfında GetProductsInCategory(categoryID) yöntemini oluşturmak gereksiz bir uğraş gibi görünebilir. Sonuçta, bu yöntem yalnızca sınıfının bir örneğini ProductsBLL oluşturur ve yönteminin GetProductsByCategoryID(categoryID) sonuçlarını döndürür. Neden bu yöntemi doğrudan iç Repeater'daki veri bağlama söz diziminden çağırmıyor, örneğin: DataSource='<%# ProductsBLL.GetProductsByCategoryID(CType(Eval("CategoryID"), Integer)) %>'? Bu söz dizimi, ProductsBLL yöntemi bir örnek yöntemi olduğundan, sınıfın geçerli uygulamamızla GetProductsByCategoryID(categoryID) çalışmasa da, sınıfın yeni bir ProductsBLL sınıf örneği döndürmek için statik GetProductsByCategoryID(categoryID) bir yöntem içermesini sağlayabilir veya Instance()'yi statik ProductsBLL bir yöntem içerecek şekilde değiştirebilirsiniz.

Bu tür değişiklikler, ASP.NET sayfasının arka planda kod sınıfında yönteminin gereksinimini GetProductsInCategory(categoryID) ortadan kaldırsa da, arka planda kod yöntemi, kısa süre içinde göreceğimiz gibi alınan verilerle çalışma konusunda daha fazla esneklik sağlar.

Tüm Ürün Bilgilerini Aynı Anda Alma

İncelediğimiz iki önceki teknik, sınıfın ProductsBLL yöntemine çağrı yaparak mevcut kategori için bu ürünleri elde eder (ilk yaklaşım ObjectDataSource aracılığıyla, ikinci yaklaşım ise kod arka planda sınıftaki GetProductsByCategoryID(categoryID) yöntem aracılığıyla). Bu yöntem her çağrıldığında, İş Mantığı Katmanı, Veri Erişim Katmanı'na ulaşarak veritabanına bir SQL deyimi gönderir. Bu SQL deyimi, Products alanı sağlanan giriş parametresiyle eşleşen CategoryID tablosundan satırlar döndürür.

Sistemdeki N kategori göz önüne alındığında, bu yaklaşım, kategorilerin tamamını almak için veritabanında tek bir sorgu ve her kategoriye özel ürünleri almak için N adet çağrı yapar. Ancak, yalnızca iki veritabanı çağrısında tüm gerekli verileri alabiliriz: biri kategorilerin tamamını almak ve bir diğeri de tüm ürünleri almak için. Tüm ürünlere sahip olduktan sonra, bu ürünleri filtreleyebiliriz, böylece yalnızca geçerli CategoryID ürünle eşleşen ürünler bu kategorinin iç Repeater'ine bağlı olur.

Bu işlevi sağlamak için yalnızca ASP.NET sayfasının arka planda kod sınıfındaki yönteminde küçük bir değişiklik GetProductsInCategory(categoryID) yapmamız gerekir. Sınıf yönteminin ProductsBLL sonuçlarını körü körüne döndürmek yerine, bunun yerine önce GetProductsByCategoryID(categoryID) ürünlere erişebilir (henüz erişilmemişse) ve ardından yalnızca geçirilen öğesine dayalı olarak ürünlerin filtrelenmiş görünümünü döndürebiliriz.CategoryID

Private allProducts As Northwind.ProductsDataTable = Nothing
Protected Function GetProductsInCategory(ByVal categoryID As Integer) _
    As Northwind.ProductsDataTable
    ' First, see if we've yet to have accessed all of the product information
    If allProducts Is Nothing Then
        Dim productAPI As ProductsBLL = New ProductsBLL()
        allProducts = productAPI.GetProducts()
    End If
    ' Return the filtered view
    allProducts.DefaultView.RowFilter = "CategoryID = " & categoryID
    Return allProducts
End Function

Sayfa düzeyi değişkeninin eklenmesine dikkat edin. allProducts Bu, tüm ürünlerle ilgili bilgileri tutar ve yöntem ilk kez GetProductsInCategory(categoryID) çağrıldığında doldurulur. Nesnenin allProducts oluşturulduğundan ve dolduruldığından emin olduktan sonra, yöntem DataTable sonuçlarını yalnızca belirtilenle CategoryID eşleşen satırların CategoryID erişilebilir olmasını sağlayacak şekilde filtreler. Bu yaklaşım, veritabanına N + 1'den ikiye kadar erişim sayısını azaltır.

Bu geliştirme, sayfanın işlenmiş işaretlemesinde herhangi bir değişiklik yapmaz ve diğer yaklaşımdan daha az kayıt getirmez. Yalnızca veritabanına yapılan çağrı sayısını azaltır.

Uyarı

Veritabanı erişimlerinin sayısının azaltılmasının performansı artıracağı konusunda sezgisel bir neden olabilir. Ancak, durum bu olmayabilir. Birçok ürününüzün CategoryIDNULL olması durumunda, GetProducts yöntemine yapılan çağrı, örneğin, hiçbir zaman görüntülenmeyen bazı ürünler döndürür. Üstelik, kategorilerin yalnızca bir alt kümesini gösteriyorsanız, tüm ürünlerin iade edilmesi israf olabilir, ki bu durum sayfalandırma uyguladıysanız söz konusu olabilir.

Her zaman olduğu gibi, iki tekniğin performansını analiz etmek söz konusu olduğunda, tek kesin sonuç ölçüsü uygulamanızın yaygın durum senaryoları için uyarlanmış denetimli testler çalıştırmaktır.

Özet

Bu öğreticide, bir veri Web denetimini başka bir veri denetimi içine nasıl yerleştirebileceğimizi inceledik. Özellikle, dış Repeater'ın her kategori için bir öğe gösterdiği ve iç Repeater'ın her kategori için ürünleri madde işaretli bir listede listelediği şekilde nasıl çalıştığını ele aldık. İç içe kullanıcı arabirimi oluşturmanın temel zorluğu, doğru verilere erişmek ve iç veri Web denetimine bağlamaktır. Bu öğreticide incelediğimiz çeşitli teknikler vardır; bunlardan ikisini ele aldık. İncelenen ilk yaklaşım, dış veri Web denetiminde ItemTemplate kullanılan ObjectDataSource'un, DataSourceID özelliği aracılığıyla iç veri Web denetimine bağlanmasıydı. İkinci teknik, ASP.NET sayfasının arka planda kod sınıfındaki bir yöntem aracılığıyla verilere erişildi. Bu yöntem daha sonra veri bağlama söz dizimi aracılığıyla iç veri Web denetimi özelliğine DataSource bağlanabilir.

Mevcut öğreticide incelenen iç içe kullanıcı arabirimi, Repeater içinde bir başka Repeater kullanarak oluşturulmuş olsa da, bu teknikler diğer veri Web kontrollerine de uygulanabilir. Bir Repeater'ı bir GridView içinde, veya bir GridView'ı bir DataList içinde iç içe yerleştirebilirsiniz.

Mutlu Programlama!

Yazar Hakkında

Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışır. Son kitabı Sams Teach Yourself ASP.NET 24 Hours 2.0'dır. Ona adresinden mitchell@4GuysFromRolla.comulaşabilirsiniz.

Özel Teşekkürler

Bu eğitim serisi, birçok yararlı kişi tarafından incelendi. Bu öğreticinin baş gözden geçirenleri Zack Jones ve Liz Shulok oldu. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, mitchell@4GuysFromRolla.com'a bir mesaj bırakın.