Arşiv

‘ASP.NET’ ile etiketlenmiş yazılar

ASP.NET Dynamic Data Web Site ile File Upload İşlemleri

30 Nisan 2010

 

 


MetaData üzerinden öznitelik ataması yapılarak doğrulama, biçimleme ve özel alan şanlonlarını(FieldTemplates) nasıl kullanacağımızdan bahsetmiştik.

Bu makale özel özniteliklerin ve alan şablonlarının geliştirilmesi konusunu içerecektir. Bu nedenle FileUpload kontrolünün kullanımı ve alan şablonlarının çalışma mantığıyla özel özniteliklerin kullanımı hakkında bilgi sahibi olacağız.

Önceki makalemde bahsettiğim gibi ASP.NET Dynamic Data Web Site ile FileUpload işlemlerini klasik yöntemlerle kullanamıyoruz.

ASP.NET Dynamic Data Web Sitesinde Ajax Toolkit ile birlikte kullanıyorsanız ve FileUpload bileşeniniz UpdatePanel içerisinde yer alıyorsa ScriptManager nesnesinin EnablePartialRendering özelliğini false olarak atamanız gerekiyor.

Kodlamaya başlamadan önce yapılması gereken işlemleri özetlemenin faydalı olduğunu düşünüyorum. Kodlama detayları ilgili sınıfların içinde yer almaktadır.

  1. Zorunlu olmasa da dosyanın sunucuya yükleme işleminin gerçekleştirileceği yardımcı bir sınıf.
  2. Her bir dosya yükleme alanı için dosya türü, boyutu vb. bildirimleri yapmak için öznitelik tabanlı bir sınıf
  3. Dosya yükleme alanlarının ekleme ve güncelleme ekranı için FileUpload kontrolü listeleme ve detay sayfaları için ise dosya türüne göre yüklenen dosyaya uygun simge, önizleme vb. için alan şablonlarının(FieldTemplate) gerekli hazırlanması.
  4. İşlevin kazandırılacağı alanlara gerekli öznitelik tanımlamasının yapılması

Temel düzeyde dosya yükleme işlemini gerçekleştirmek üzere aşağıdaki sınıfı kullanacağız

FileUploadUtil.cs

using System;
using System.Web;
using System.IO;
using Eposta.Core.CustomAttributes;
using Eposta.Core.Extentions;
using System.Text.RegularExpressions;

namespace Eposta.Core.Utils
{
    /// <summary>
    /// Ömer Faruk ZORLU
    /// </summary>
    public class FileUploadUtil
    {
        private string _fileName;

        /// <summary>
        /// Dosyanın yükleneceği fiziksel konum
        /// Örnek kullanım: HttpContext.Current.Server.MapPath("~/Uploads/")
        /// </summary>
        public string UploadDictionaryPath { get; set; }

        /// <summary>
        /// Yükleme işlemi başarısız olmuşsa bu değer
        /// üzerinden hata mesajı okunabilir
        /// </summary>
        public string ErrorMessage { get; private set; }

        /// <summary>
        /// Değer atama işleminin ardından güvenlik, tekillik gibi
        /// nedenler gereği isim değiştirilmelidir.
        /// </summary>
        public string FileName
        {
            get { return _fileName; }
            set
            {
                string strExtention = Path.GetExtension(value);

                // ToSEFString methodu gönderilen string değeri arama
                // motoru dostu karakterler ile değiştirir
                //
                // RandomHelper sınıfı doğru rasgele karakterler ve
                // sayılar üretmek için kullanılıyor
                // Bağlantı: http://tinyurl.com/y8of6sn
                _fileName = Path.GetFileNameWithoutExtension(value).ToSEFString()
                + RandomHelper.RandomString(10, true)
                + strExtention;
            }
        }

        /// <summary>
        /// ctor
        /// </summary>
        public FileUploadUtil()
        {
            _fileName = string.Empty;
        }

        /// <summary>
        /// Dosya yükleme işleminin tetiklenmesi için bu method çağırılmalıdır.
        /// </summary>
        /// <param name="postedFile">
        /// Bu değişken klasik html input alanları tarafından post edilen
        /// verilerinde methodu kullanabilmeleri için bu tipte tanımlanmıştır.
        /// FileUpload kontrolü kullanılacaksa PostedFile özelliği gönderilebilir.
        /// </param>
        /// <param name="fuAttribute">
        /// Dosya yükleme işleminin gerçekleşmesi ile ilgili bilgiler içeren sınıftır
        /// Attribute sınıfından türetilmiştir. MetaColumn ile kullanılacaksa ilgili
        /// alan üzerinde tanımlı özniteliğin gönderilmesi yeterlidir.
        /// </param>
        /// <returns></returns>
        public bool UploadFile(HttpPostedFile postedFile, FileUploadAttribute fuAttribute)
        {
            #region Checks
            if (postedFile.ContentLength <= 0)
            {
                this.ErrorMessage = "Veri akışı bulunamadı";
                return false;
            }

            // Maksimum dosya boyutu öznitelikte atanan değere göre kontrol ediliyor.
            long FileSize = postedFile.ContentLength;
            if (FileSize > (fuAttribute.MaximumFileSize * 1024000))
            {
                this.ErrorMessage = string.Format("Maksimum dosya boyutu izin verilenden fazla olamaz. İzin verilen maksimum dosya boyutu: {0}", fuAttribute.MaximumFileSize);
                return false;
            }

            // Dosya uzantısı öznitelikte atanan değere göre kontrol ediliyor.
            // İçerik türüne(MIME) görede kontrol edilebilir.
            if (!Regex.IsMatch(Path.GetExtension(_fileName), fuAttribute.AllowedFileFormats, RegexOptions.IgnoreCase))
            {
                this.ErrorMessage = string.Format("Dosya türüne izin verilmiyor. İzin verilen dosya formatları: {0}", fuAttribute.AllowedFileFormats);
                return false;
            }
            #endregion

            // Klasör yoksa oluştur.
            DirectoryInfo DInfo = new DirectoryInfo(this.UploadDictionaryPath);
            if (!DInfo.Exists)
                DInfo.Create();

            #region WriteStreamToFile
            // Dosyayı kaydet
            string strFullFileName = this.UploadDictionaryPath + this._fileName;
            postedFile.SaveAs(strFullFileName);
            #endregion

            return true;
        }
    }
}

Yukarıdaki sınıf içinde kullanılan FileUploadAttribute sınıfını dosya yükleme işleminin gerçekleşmesini istediğimiz kolon için gerekli bildirimlerin yapılması için kullanacağız . Bu sınıfın kodlaması aşağıdaki gibidir.

using System;

namespace Eposta.Core.CustomAttributes
{
    /// <summary>
    /// Ömer Faruk ZORLU
    /// </summary>
    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    public class FileUploadAttribute : Attribute
    {
        /// <summary>
        /// Yüklenecek dosyanın maksimum boyutunun megabyte karşılığıdır.
        /// </summary>
        public short MaximumFileSize { get; set; }

        /// <summary>
        /// Bu özellik adının kontrol edilmesi için kullanılır.
        /// Kontrol işlemi RegularExpressions(Regex) sınıfı ile
        /// gerçekleştirilir.
        ///
        /// Örnek Kullanım: “jpg|gif|png|JPG|GIF|PNG”
        /// </summary>
        public string AllowedFileFormats { get; set; }

        /// <summary>
        /// Yükleme işleminin gerçekleştirileceği klasörün fiziksel
        /// yolunu saklar.
        ///
        /// Örnek Kullanım: HttpContext.Current.Server.MapPath(“~/Uploads/”)
        /// </summary>
        public string UploadDictionaryPath { get; set; }
    }
}

Buraya kadarki kodlamalarla iş katmanı için yükleme işini üstlenecek sınıfların kodlamasını tamamlamış olduk. Sırada bu katmanı istediğimiz kolon üzerinde kullanabilmek için gerekli alan şablonunu tasarlama işi var.  Daha önceki makalelerde belirttiğim gibi güncelleme, ekleme ve listeleme, detay sayfa şablonları için iki adet alan şablonu hazırlanmalıdır. Ekleme ve günnceleme için gerekli alan şablonunun kodları aşağıdaki gibidir.

MyFileUpload_Edit.ascx

<%@ Control Language="C#" CodeFile="MyUpload_Edit.ascx.cs" Inherits="MyUpload_Edit" %>
<asp:Label ID="Label1" runat="server" Text='<%# FieldValueEditString %>'></asp:Label><br />
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:CustomValidator ID="CustomValidator1" runat="server"
    ErrorMessage="CustomValidator"></asp:CustomValidator>

MyFileUpload_Edit.ascx.cs

using System;
using System.Collections.Specialized;
using System.Web.UI;
using System.Linq;
using Eposta.Core.CustomAttributes;
using Eposta.Core.Utils;

public partial class MyUpload_Edit : System.Web.DynamicData.FieldTemplateUserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected override void OnDataBinding(EventArgs e)
    {
        base.OnDataBinding(e);
    }

    protected override void ExtractValues(IOrderedDictionary dictionary)
    {
        // DataControl nesnesi olarak Label1 atandığı için
        // dosya yüklemenmesede varsayılan olarak zaten kayıtlı olan
        // veri dönüş değerinde kullanılmak üzere atanıyor
        dictionary[Column.Name] = ConvertEditedValue(Label1.Text);

        // Bu kolon üzerinde atanması zorunlu olan FileUploadAttribute
        // özniteliği alınıyor.
        var fuAttribute = base.Column.Attributes.OfType<FileUploadAttribute>().FirstOrDefault();
        // FileUploadAttribute ataması yoksa dön
        if (fuAttribute == null)
            return;

        // Dosya seçilmişse
        if (FileUpload1.HasFile)
        {
            try
            {
                FileUploadUtil fuUtil = new FileUploadUtil();
                // Atama işleminin ardından dosyaya yeni isim atanıyor.
                fuUtil.FileName = FileUpload1.FileName;
                fuUtil.UploadDictionaryPath = fuAttribute.UploadDictionaryPath;

                // Dosyayı yükle ve yeni dosya adını dönüş değeri olarak ata.
                // Hata kontrolüne karşı ilgili değişken(string ErrorMessage)
                // kontrol edilebilir.
                if (fuUtil.UploadFile(FileUpload1.PostedFile, fuAttribute))
                    dictionary[Column.Name] = fuUtil.FileName;
            }
            catch (Exception Ex)
            {
                // Denetlenmemiş herhangi bir hata oluşursa sayfanın tamamen
                // hata vermesi yerine hata mesajını hata özetlerinde ve atama
                // işleminin yapıldığı alanın yanında görünmesi için CustomValidator1
                // nesnesinden yararlanılıyor.
                CustomValidator1.IsValid = false;
                CustomValidator1.ErrorMessage = Ex.Message;
            }
        }
    }

    public override Control DataControl
    {
        get
        {
            return Label1;
        }
    }
}

Listeleme ve detay sayfa şablonlarında kullanılacak alan şablonu kodları aşağıdaki gibidir. Yüklenen dosyaların(ilgili verilerin) yalnızca    resim dosyası olduğu öngörülerek yazılmıştır. Dosya tipi yada türüne göre özelleştirilmiş görüntüleme tekniği kullanılabilir.

MyUpload.ascx.cs

using System;
using System.Web.UI;

public partial class MyUpload : System.Web.DynamicData.FieldTemplateUserControl
{
    public override Control DataControl
    {
        get
        {
            return imgThumbnail;
        }
    }

    public string GetSrcUrl()
    {
        // Veri boş ya da null ise NoImage.gif dönder
        if (String.IsNullOrEmpty(FieldValueString)) return "NoImage.gif";

        // Veri http, ftp vb herhangi bir protokolü kullanıyor ise
        // olduğu gibi değilse upload klasörünü kök dizin alarak dönder
        if (-1 < FieldValueString.IndexOf("://"))
            return FieldValueString;
        else
            return "~/uploads/" + FieldValueString;
    }
} 

Dynamic Data’nın en sevdiğim kısımı tabiki MetaData üzerinde yapılan tanımlamalardır. O kadar çok kod yazmak gerekiyorki daha ne yapalım birde diyenleri duyar gibiyim.

Dynamic Data ile yapılan her geliştirme tasarruf niteliği taşır.

Geliştirdiğimiz dosya yükleme aracı için klasik kodlama kullansaydık benzer kodları kullanmak istediğimiz sayfalarda(aynı sayfada pek çok kere de olabilir) harcanan efor göz önüne alınmalıdır. Yapılan geliştirme bir sonraki proje için yatırımdır. Ayrıca geriye dönük olarak yapılan projelerde kullan/a/mamak için bir neden söz konusu değildir.

Şimdi en zevkli kısıma gelelim. Bundan böyle dosya yükleme(FileUpload) işlemi ile çalışmasını istediğiniz herhangi bir kolon için meta data üzerinde aşağıdaki gibi bir tanımlama yapmanız yeterli oluyor.

NORTWIND veritabanında bulunan Employee tablosundaki PhotoPath kolonu için yapılan örnek tanımlama:

using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(EmployeeMetaData))]
public partial class Employee
{

}

public class EmployeeMetaData
{
    [Eposta.Core.CustomAttributes.FileUpload(
        AllowedFileFormats = "jpg|gif|png|JPG|GIF|PNG",
        MaximumFileSize = 1, // MB
        UploadDictionaryPath = "~/uploads/"
        )]
    [UIHint("MyUpload")]
    public string PhotoPath { get; set; }
} 

Ekran görüntüleri
Listemele ve detay sayfa şablonlarında:

Ekleme ve Güncelleme sayfa şablonlarında:

Meraklısından meraklılarına faydalı olması dileğiyle. Mutlu kodlar.

Ömer Faruk ZORLU

 

ASP.NET , ,

ASP.NET Dynamic Data – Gelişmiş Scaffolding

30 Nisan 2010

 

 

Merhabalar, daha önce ASP.NET Dynamic Data(yazının devamında DD kısaltmasını kullanacağım) hakkında bazı bilgileri yayınlamıştım. Yeni bir makale konusunda düşünürken makale konusu olarak gerçek bir DD projesinde kullanıcı tarafından gelebilecek isteklerin hızlı bir şekilde nasıl karşılanabilineceğinden bahsetmenin uygun olduğuna karar verdim.
Yazılımcı gözüyle değerlendirmek gerekirse kullanıcı gereksinimleri konusunda gözden kaçan bir çok gereksinimi görülmeyebilir.  Örneğin bir tablo içindeki kayıtların listelenmesi yazılımcı için gayet yeterlidir ancak kullanıcı gözüyle bakıldığında her şeyin listelenmesi çoğu zaman gereksiz olacaktır. Bu kapsamda kullanıcı isteklerine karşılık sorun çözümüyle alakalı makalele dizisinin ilkini yazmaya başlıyorum. Daha önceki makalelerde bahsettiğim isimlendirme, biçimlendirme vb. gibi temel işlemlere bu makalede değinmeyeceğim.

Kullanıcı tarafında tablo üzerindeki her alanın(column) görüntülenmesi istenmeyebilir. Bazı durumlarda ise tüm kayıtların listelenmesi kullanım kolaylığı açısından sıkıntılı olabilir.

Scaffolding tekniğiyle istenilen alanların tüm şablonlarda görüntülenmesini engelleyebiliyoruz. Özellikle listeleme sayfalarında tüm alanların sayfada görünür halde olması yatay olarak uzayan bir sayfaya neden olur ancak bu alanları klasik scaffolding tekniği ile gizlersek diğer şablonlardanda kayboluverir.  İşte burada asıl sorun ortaya çıkıyor: Gizlenen alanların kullanıcı tarafından düzenlenmesi gerekiyorsa yada detaylı görüntüleme şablonunda tüm alanların görüntülenmesi gerekiyorsa ne yapacağız?

 

  Aletleri geliştirmek DD için her zaman kazanımdır. Bu senaryoda scaffolding tekniğini sayfa şablonlarına göre nasıl özelleştirebileceğimizi öğreneceğiz.

 

Kullanabileceğimiz veri bileşenleri(GridView, FormView, DetailsView vb.) veri listeleme sırasında listeleme işlemi için IAutoFieldGenerator arayüzünü uygulayan bir sınıf ile veri alanları üzerindeki kararını verir. Varsayılan alan oluşturucularda verideki tüm alanlar DD bildirimleri uygunlandıktan sonra(scaffolding gibi kısıtlamalar vb.) listelenir. Yapılması gereken şey ise veri listeleme işini gerçekleştirme görevini yazacağımız bir sınıfın üstlenmesidir.

IAutoFieldGenerator arayüzünü uygulayan sınıfımız:

namespace Eposta.Core.CustomFieldGenerator{    using System.Collections.Generic;    using System.Web.UI;    using System.Web.DynamicData;     

    /// <summary>    /// Bu sınıf veri listelemesini işlemlerini    /// özelleştirmek amacıyla yazılmıştır.     /// </summary>    public class CustomColumnGenerator : IAutoFieldGenerator    {        /// <summary>        /// Veri listelemesi için incelenecek        /// tablo değişkenini tutar        /// </summary>        protected MetaTable mTable = null;        #region IAutoFieldGenerator Members        /// <summary>        /// Listeleme işlemini gerçekleştirecek method        /// </summary>        /// <param name="control"></param>        /// <returns></returns>        public System.Collections.ICollection GenerateFields(Control control)        {            // Uygun kolonların biriktirildiği koleksiyon            List<DynamicField> dynFieldList = new List<DynamicField>();            // MetaTable atanmışsa            if (mTable != null)            {                // Her bir MetaColumn için                foreach (MetaColumn mColumn in this.mTable.Columns)                {                    // Scaffolding ataması yapılmışsa koleksiyona eklenmesi                    // uygun değildir. Eğer bu kontrol yapılmazsa ilgili                    // alan görüntülenecektir. Çünkü tüm sorumluluğu almış                    // bulunuyoruz                    if (                            !mColumn.Scaffold                        )                        continue;                     DynamicField dynField = new DynamicField();                    dynField.DataField = mColumn.Name;                    dynFieldList.Add(dynField);                }            }            return dynFieldList;        }        #endregion    }}

Scaffolding tekniğini denetleyerek görüntüleme işlemini üstlenen sınıfımız artık hazır. Şimdi sıra şablonlara göre bu denetleme işlemine geldi. Varsayılan şablonlar için bir enum tanımlayıp GenerateFields methodunda şablona görede bir denetleme yapmamız gerecektir.

namespace Eposta.Core.Enums{    public enum PageTemplateType    {        Details,        Edit,        Insert,        List,        ListDetails    }}

Özelleştirme işlemlerinin uygulanabilmesi için özel bir öznitelik geliştirip bildirimlerin bu öznitelik üzerinden gerçekleştirmesi gerekiyor bunun için aşağıdaki sınıfı kullanabiliriz.

[more]

using System;using Eposta.Core.Enums;

namespace Eposta.Core.CustomAttributes{    [AttributeUsage(AttributeTargets.Property)]    public class CustomHiddenColumnAttribute : Attribute    {        /// <summary>        /// İlgili alanın gizlenmesi gereken sayfa şablonları belirleniyor        /// </summary>        public PageTemplateType[] PageTemplateTypes { get; private set; }        /// <summary>        /// Parametresiz bir constructor yazılması mecburi ancak        /// kullanılmaması için hata fırlatılması daha uygun        /// </summary>        public CustomHiddenColumnAttribute()        {            throw new InvalidOperationException();        }        /// <summary>        /// Sayfa şablonlarının atama işleminin kolaylaştırılması        /// nedeniyle params yöntemi kullanılmıştır. Öznitelik         /// tanımlamasında AllowMultiple=true atamasıda yapılabilir        /// </summary>        /// <param name="PageTemplateParams"></param>        public CustomHiddenColumnAttribute(params PageTemplateType[] PageTemplateParams)        {            this.PageTemplateTypes = PageTemplateParams;        }    }}

Bu özniteliğin örnek tanımlaması aşağıdaki gibidir. Daha öncede belirttiğim gibi öznitelik yazmayı çok severim :) Bundan böyle sadece aşağıdaki kodu kullarak tüm kodu yazmadan işimizi halledebiliriz.

[CustomHiddenColumn(        PageTemplateType.List, PageTemplateType.ListDetails)]public string SmtpHost { get; set; }

Madem bu kadar kod yazdık birde MetaColumn nesneleri için genişletilmiş bir method yazarak kolonda ve şablona göre gizlilik bildirimi yapılmışmı diye kontrol edelimki her seferinde bir yığın kod yazmaktan kurtulalım.

using System.Linq;using Eposta.Core.CustomAttributes.UIHint;using Eposta.Core.CustomAttributes;using Eposta.Core.Enums;/// <summary> /// Ömer Faruk ZORLU/// </summary>namespace Eposta.Core.Extentions{    public static class MetaColumnExtentions    {        /// <summary>        /// Sayfa şablonuna göre alanın gizlilik durumunu dönderir        /// </summary>        /// <param name="mColumn"></param>        /// <param name="pTemplateType"></param>        /// <returns></returns>        public static bool IsHidden(this System.Web.DynamicData.MetaColumn mColumn, PageTemplateType pTemplateType)        {            // Kolon üzerinde atanmış ustomHiddenColumn özniteliği alınıyor            // Eğer çoklu tanımlama(AllowMultiple) ya izin verilmişse bir            // döngü içerisinde kontrol edilmesi gerekir            CustomHiddenColumnAttribute chCAttr =                mColumn.Attributes.OfType<CustomHiddenColumnAttribute>().FirstOrDefault();               //  Herhangi bir öznitelik ataması yoksa gizli değildir            if (chCAttr == null)                return false;             // İlgili alan için yapılan gizlilik bildirimleri parametrede            // gönderilmiş sayfa şablonunu içeriyorsa gizlidir            return chCAttr.PageTemplateTypes.Contains(pTemplateType);;        }    }}

Artık daha önce yazdığımız alan oluşturucu sınıf üzerinde özel gizleme yapımızı denetleyen kodlar yazabiliriz. Yukarıda yazdığımız sınıfa yeni eklenen kodlar kalın olarak yazılmıştır.

using System.Collections.Generic;using System.Web.DynamicData;using System.Web.UI;using Eposta.Core.Extentions;using Eposta.Core.Enums; namespace Eposta.Core.CustomFieldGenerator{    /// <summary>    /// Bu sınıf veri listelemesini işlemlerini    /// özelleştirmek amacıyla yazılmıştır.     /// </summary>    public class CustomFieldGenerator : IAutoFieldGenerator    {        /// <summary>        /// Veri listelemesi için incelenecek        /// tablo değişkenini tutar        /// </summary>        protected MetaTable mTable = null;

        protected PageTemplateType pTemplateType;         #region ctor         public CustomFieldGenerator(MetaTable _mTable, PageTemplateType _pTemplateType)        {            this.mTable = _mTable;            this.pTemplateType = _pTemplateType;        }         #endregion         #region IAutoFieldGenerator Members        /// <summary>        /// Listeleme işlemini gerçekleştirecek method        /// </summary>        /// <param name="control"></param>        /// <returns></returns>        public System.Collections.ICollection GenerateFields(Control control)        {            // Uygun kolonların biriktirildiği koleksiyon            List<DynamicField> dynFieldList = new List<DynamicField>();            // MetaTable atanmışsa            if (mTable != null)            {                // Her bir MetaColumn için                foreach (MetaColumn mColumn in this.mTable.Columns)                {                    // Scaffolding ataması yapılmışsa koleksiyona eklenmesi                    // uygun değildir. Eğer bu kontrol yapılmazsa ilgili                    // alan görüntülenecektir. Çünkü tüm sorumluluğu almış                    // bulunuyoruz                    if (                            !mColumn.Scaffold                        )                        continue;                     // List ve ListDetails şablonları için IsHidden                    // genişletilmiş methodu ve IsLongString methodunu                    // kontrol ediyoruz ancak Details şablonu için                    // IsLongString methodunu kontrol edip gizlersek                    // uzun metin alanlar görüntülenmeyecek yani ufak bir                    // bug oluşacaktır.                    switch (this.pTemplateType)                    {                        case PageTemplateType.Details:                            if (mColumn.IsHidden(this.pTemplateType))                                continue; // foreach                            break;                        case PageTemplateType.List:                            if (mColumn.IsHidden(this.pTemplateType) ||                                    mColumn.IsLongString)                                continue; // foreach                            break;                        case PageTemplateType.ListDetails:                            if (mColumn.IsHidden(this.pTemplateType) ||                                    mColumn.IsLongString)                                continue; // foreach                            break;                        default:                            break;                    }                     // Varsayılan şablonların haricinde uzun metinlerin                    // görüntülenmesini engellemek amacıyla bu kontrol                    // yapılıyor                    if (mColumn.IsLongString)                        continue;                     DynamicField dynField = new DynamicField();                    dynField.DataField = mColumn.Name;                     dynFieldList.Add(dynField);                }            }            return dynFieldList;        }        #endregion    }}

Son adımında ise ilgili veri kontrolüne veri listeleme işlemini bizim üstleneceğimizi bildirmek gerekiyor. GridView nesnesi için ColumnGenerator DetailsView içinse RowGenerator parametresi kullanılıyor. Son haliyle List.aspx.cs ve Details.aspx.cs şablon kodları aşağıdaki gibi tanımlanmalıdır.

List.aspx.cs kodları:

using System;using System.Web.DynamicData;using Eposta.Core.CustomFieldGenerator;using Eposta.Core.Extentions; public partial class List : System.Web.UI.Page{    protected MetaTable table;    protected void Page_Init(object sender, EventArgs e)    {        DynamicDataManager1.RegisterControl(GridView1, true /*setSelectionFromUrl*/);        table = GridDataSource.GetTable();        GridView1.ColumnsGenerator = new CustomFieldGenerator(table, Eposta.Core.Enums.PageTemplateType.List);    }    protected void Page_Load(object sender, EventArgs e)    {        Title = table.DisplayName;        InsertHyperLink.NavigateUrl = table.GetActionPath(PageAction.Insert);         // Disable various options if the table is readonly        if (table.IsReadOnly)        {            GridView1.Columns[0].Visible = false;            InsertHyperLink.Visible = false;        }    }    protected void OnFilterSelectedIndexChanged(object sender, EventArgs e)    {        GridView1.PageIndex = 0;    }}


Details.aspx.cs kodları:

using System;using System.Linq;using System.Web.DynamicData;using System.Web.UI.WebControls;using Eposta.Core.CustomFieldGenerator;using Eposta.Core.CustomAttributes; public partial class Details : System.Web.UI.Page {    protected MetaTable table;    protected void Page_Init(object sender, EventArgs e) {        DynamicDataManager1.RegisterControl(DetailsView1);    }    protected void Page_Load(object sender, EventArgs e) {        table = DetailsDataSource.GetTable();        DetailsView1.RowsGenerator = new CustomFieldGenerator(table, Eposta.Core.Enums.PageTemplateType.Details);

        Title = table.DisplayName;

        ListHyperLink.NavigateUrl = table.ListActionPath;    }    protected void DetailsView1_ItemDeleted(object sender, DetailsViewDeletedEventArgs e) {        if (e.Exception == null || e.ExceptionHandled) {            Response.Redirect(table.ListActionPath);        }    }}

Çözüm itibari ile Grup tablosunda yapılan tanımlalarla listeleme sayfa şablonlarında bazı alanların gizlenmesini güncelleme ve detaylı görüntüleme sayfa şablonlarında ise kullanıcının verileri görüntülemesine ve düzenlemesine imkan tanımış olduk. Ekran görüntüleri aşağıdaki gibidir.

Güncelleme ekranı:

Listeleme ekranı:

Bir yazının daha sonuna geldik. Kullanıcı gereksinimleriyle alakalı makaleler devam edecektir. Bir sonraki makalede görüşmek üzere. Yaşasın dinamizm!

Ömer Faruk ZORLU

 

ASP.NET , ,