Pazar, Şubat 14, 2010

WF - Parallel Activity

Windows Workflow (WF) teknolojisini kullanarak uygulama geliştirmek istediğimizde kullanabileceğimiz adımları incelemeye devam ediyoruz. Şu ana kadar incelemiş olduğumuz iş akışı tipleri sürekli olarak tek sequence activty 'den oluşmakta ve tek yönlü bir iş akışı süreci oluşmaktadır. Eğer ki şu ana kadar görmüş olduğumuz yöntemler de akış esnasında herhangi bir adım sonrasında aynı anda iki akış başlatmak istediğimizde bu durumu gerçekleştirme şansımız olmayacaktı. Eğer ki bir şekilde yapmaya çalışırsakta oldukça uğraştırıcı bir yöntem olacaktır. Bu tür ihtiyaçlarımızı karşılamak için toolbox 'ımızın içeriğini incelediğimizde parallel activity bileşenini görüyor olacağız. Bu bileşen yardımı ile herhangi bir adımdan sonra uygulamamıza ya da tasarladığımız akış esnasında birden fazla işlemi aynı anda yapabilmemize olanak tanıyacaktır. Bu yazımızda ilk olarak paralel activity 'i tanıyacağız. Sonrasında örnekler ile nasıl kullanabileceğimize göz attıktan sonra nelere değindiğimizi özet olarak göz attıktan sonra yazımızı tamamlamış olacağız.

Parallel Activity 'ler iki ya da daha fazla Sequence Activity 'lerden oluşmaktadır. Bu aktivite bileşeni birden fazla sequence activity 'i ve içerisinde yapılmış olan işlemlerin teorik olarak aynı anda başlamasını planlamaktadır. Ancak teorik olarak yer olan bütün sequence activity lerin aynı anda başlayacağı söylense de gerçekte böyle bir durum oluşmaz. Belirsiz bir rastgelelik ile birbirilerini takip ederek gerçekleşmektedir. Yani a aktivitesi tamamlandıktan sonra b aktivitesi başlar ve sonrasında yeniden a aktivitesinin başlayabileceği gibi b aktivitesi de başlayıp tamamlanabilir. Ancak bu rastgelelik iki işleminde sorunsuzca gerçekleşmesini ve tamamlanmasında herhangi bir engel taşımamaktadır. İşlemin en sonunda her iki aktiviteninde sorunsuzca tamamlandığı gözlemlenecektir.

Parallel activity 'lerin ektileyici özelliklerinden biri de dallarda yer alan sequence aktivitelerden herhangi biri Delay Activity yer alırsa, bunun bitmesi beklenmez ve bir diğer daldaki activiteye geçilir ve akışın sorunsuzca işlemesi sağlanmış olur. Bu işlemlerin bu şekilde çalışmasının en basit açıklaması ise bizim hazırlamış olduğumuz uygulamaların işletim sistemleri üzerinde çalışıyor olması ve işletim sistemi de üzerinde çalışan işlemleri thread 'ler ile işletmesinden kaynaklanmaktadır. Thread 'lerde birbirlerinin tamamlanmasını beklemek yerine herhangi bir rastgelelik ile çalışmasından ötürü uygulamanın beklemesi ya da herhangi bir sebepten ötürü bozulması durumunda sırada bekleyen diğer iş parçacığına geçerek işlemi devam ettiriyor olmasıdır.

Delay Activity, iş akışını belirli bir süre duraklamasını ve sonrasında da çıkmasına olanak tanımaktadır. TimeoutDuration ve TimeSpan özelliklerini kullanılır.

Parallel Activity sınıfı System.Workflow.Activities isim alanı altında yer almaktadır. Parallel aktiviteleren sık olarak while döngüsünün kullanılması gereken durumlarda görülmektedir.

Genel olarak paralel actviteyi tanıdığımıza göre artık örneklere geçiş yapabiliriz. Bu yazımızda geliştireceğimiz örneği Visual Studio 2010 RC1 sürümünde geliştiriyor olacağız. Ancak .Net Framework 3.0 sürümünü kullanacağımız için Visual Studio 2008 ya da gerekli eklentileri yüklenmiş 2005 sürümünde de sorunsuzca geliştirilebilir.

Projemizi Workflow seçeneği altında yer alan Sequential Workflow Console Application proje şablonu üzerinde geliştiriyor olacağız. Proje oluştulduğunda karşımıza Sequential Workflow tasarım ekranı gelecektir.


Örneğimizi paralel atvitileer ile yapacağımız için bir adet bu aktivite tipinden tasarım ekranına sürükleyoruz.



Göreceğiniz üzere paralel aktiviteyi tasarım ekranına eklediğimizde iki tane sequence acticity 'nin eklendiğini göreceğiz. Peki iki değilde daha fazla akışı aynı anda çalıştırmak istediğimizde nasıl bir yol izlememiz gerekmektedir. Bunun için paralel aktivite üzerinde sağ tıklama yaptıktan sonra açılan menüden Add Branch seçeneğine tıklamamız yeterli olacaktır. Bu işlem sonrasında artık karşımızda aynı anda çalıştıracağımız üç adet akış olacaktır. Bu işlemi tekrarlayarak ihtiyacımız kadar akış ekleyebilmemiz mümkündür.



Ayrıca paralel aktiviteler içerisinde de akışın iptal olması ya da bozulması durumunda yapılacak işlemler için gerekli özellikler yer almaktadır.

Şimdi uygulama geliştirmek için gerekli olan bileşenleri ekliyoruz ve tasarım ekranında geliştirmiş olduğumuz akış aşağıdaki görünüme kavuşuyor.


Şimdi ise eklemiş olduğumuz CodeActivity lerin arka plan kodlarını yazarak işlemlerimize devam ediyoruz.

using System;

using System.Workflow.Activities;

namespace ParallelActivity
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Sol taraf çalıştı.");
            solTarafSay++;
        }

        private void codeActivity2_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Sag taraf çalıştı.");
            sagTarafSay++;
        }

        private int solTarafSay;
        private int sagTarafSay;
    }
}

Ayrıca while döngüleri içerisinde kullanacak olduğumuz özellikleri de tanımladık. Sonrasında while bileşenin üzerinde sağ tıkladıktan sonra özelliklerinden condition değerine System.Workflow.Activities.Rules.RuleConditionReference değerini atıyoruz. Condition özelliğine ise aşağıda belirtiğimiz şekilde tanımlıyoruz.



Hem sol tarafı hem de  sağ tarafı tanımladıktan sonra while döngülerinin özelliklerinde yer alan condition seçeneğine baktığımızda aşağıdaki görünüme benzer bir hal alması gerekmektedir.



SoSon olarak aktivitenin dallarına delay activity eklerek bekleme durumunda nasıl bir işlem yapacağını gözlemleyeceğiz. Ayrıca tamamlandığını belirtmesi için akışın en sonuna bir tane daha kod aktivitesi ekliyoruz ve geliştirme işlemini tamamlıyoruz.



Sol taraftaki bekleme değerini bir saniye, sağ taraftaki bekeleme değerini iki saniye olarak verdiğimizi hatıralatarak hazırlamış akışı çalıştırıyoruz.



Oluşan program çıktısından da göreceğiniz üzere paralel aktivite bizim belirtmiş olduğumuz bekleme sürelerinin aksine ilk başta sıra ile çalışmasının aksine rastgelelik ile çalıştığını da bu sayede gözlemlemiş oluyoruz.

Sonuç olarak yazımızı toparlamak gerekirse, paralel aktivitelerin birden fazla iş akışını çalıştırabildiğini ve bu akışları aynı anda değil thread lere bağlı olarak rastgele bir sıradanlıkla çalıştırdığını öğrendik. Sonrasında hazırlamış olduğumuz örnek yardımı ile bu anlattış olduğumuz bilgileri doğrulyarak yazımızı tamamladık. Bir sonraki WWF yazımızda Condition kavramına değiniyor olacağız.

Umarım yararlı olabilmiştir.

Turhal Temizer
info@turhaltemizer.com

Salı, Şubat 02, 2010

WF - Parametre Kullanımı

Windows Workflow (WF) teknolojisini şu ana kadar temel uygulama tipleri ve istisnai durumlar (Exceptions) konularını inceledik. WF ile uygulama geliştirirken hangi adımlara dikkat etmemiz gerektiği ve kafamıza takılan geliştirme işlemlerini nasıl yapabileceğimizi detaylı bir şekilde inceleyerek yazılarımıza devam ediyor olacağız. Bu sefer ise WF 'da parametre kullanılmasını inceliyor olacağız.

Son kullanıcının kullanımına açılacak uygulamalar çok büyük oranda istek cevap mantığına göre çalışmaktadır. Bu istekleri taşıyabilmek için ise uygulamalarda parametrelerden yararlanılmaktadır. Bu parametreler hem uygulama içerisinden herhangi bir değerden gelirken dış veri giriş ya da istek controlleri yardımı ile de kullanılabilmektedir. Özellikle portal sistemlerinde iş akışı kullanımı çok yoğundur ve gönderilen parametreler doğrultusunda izin talepleri, araç istekleri, döküman paylaşımları ve akla gelmeyen diğer iş akışlarının hazırlanmasında parametre kullanımı çok ama çok fazladır. Bu sebepten ötüdür ki bu konu WF teknolojisi ile uygulama geliştiren geliştiriciler de çok önceliklidir.

Şimdi biz bu işlemleri WF teknolojisi üzerinde nasıl kullanabilceeğimizi incelemeye başlayalım. Visual Studio 2010 (VS2008 ya da WF eklentileri yüklenmiş VS2005 'te olabilir. Aynı özellikler her ikisinde de geçerlidir.) üzerinde Workflow seçeneği seçili iken .Net Framework 3.0 sürümü altında yer alan Sequential Workflow Console Application proje şablonunu seçiyor ve ismini ParameterParsing vererek  projeyi oluşturuyoruz. Sonrasında karşımıza alışık olduğumuz WF tasarım ekranı ve bileşenlerimiz gelecektir.

Tasarım ekranı üzerine Code Activity bileşenini sürüklüyor ve ExecuteCode olayınına parametre alabilmesi için gerekli işlemleri uygulamaya başlıyoruz.


Sonrasında kod tarafına basit bir string özellik oluşturup codeActivity bileşeninin içerisinde kullanılmak üzere ekliyoruz.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    Console.WriteLine("Bulunan string değer: [{0}]",StringToPrint);
}

private string _stringToPrint;

public string StringToPrint
{
    get { return _stringToPrint; }
    set { _stringToPrint = value; }
}

Eklemiş olunan CodeActivity bileşeni üzerinde parametre kullanılması için gerekli hazırlıklar tamamlandı. Peki, parametreler nereden gelecek? Bu örneğimiz için Program.cs içerisinde yer alan WorkflowRuntime.CreateWorkflow metodunun içerisine Dictionary<> olarak bir parametre daha vereceğiz. Bu parametre bizim hazırlamış olduğumuz Workflow tasarım ekranını hazırlarken belirlemiş olduğumuz özelliklerin isimlerini ve alacakları değerleri vermemiz durumunda onlar global olarak değişkenleri kabul edecek ve gerekli değerleri tanımlayacaktır.

Yukarıda belirttiğimiz şekilde Program.cs dosyasının içerisini düzenledikten sonraki son görünüm aşağıdaki gibi olacaktır.

using System;
using System.Collections.Generic;

using System.Threading;
using System.Workflow.Runtime;

namespace ParameterParsing
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
               {
                   Console.WriteLine(e.Exception.Message);
                   waitHandle.Set();
               };
               Dictionary<string, object> parameters = new Dictionary<string, object>();
                    parameters.Add("StringToPrint", "Parametreleri kullanarak sonuçları elde ettik...");
               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ParameterParsing.Workflow1),parameters);
               instance.Start();

               waitHandle.WaitOne();
            }
        }
    }
}

Workflow1.cs dosyasına eklemiş olduğumuz StringToPrint özelliğini program.cs dosyasında bir koleksiyonun içerisinde tanımladıktan sonra iş akışı başladığında çağırılacak parametrelerin arasında olması için intance 'ın parametreleri arasına ekledikten sonra işlemimizi tamamlamış oluyoruz.

Yapmış olduğumuz işlemler sonrasında uygulamamızı çalıştırdığımızda karşımıza aşağıdaki gibi bir ekran çıktısı çıkacaktır.



Daha önce de bahsettiğimiz gibi WorkflowInstance 'a atayacağımız değeleri CreateWorkflow metodunun sonucunda dönecek olanlardan elde ediyorduk. Bu metotta birden fazla aşırı yüklemeden oluşmaktadır. Bunlardan biri de kolleksiyonla birlikte işlem yapandır. Biz de bu metottan yararlanarak oluşturmuş olduğumuz Dictionary koleksiyonunu ekleyerek işlemimizi yaptık.

Şimdi örneğimizi biraz daha karmaşıklaştırarak parametre kullanımını incelemeye devam edelim. Bu sefer bir kullanıcı sınıfı oluşturalım. Sonrasında bu sınıfın içerisine Adı ve Soyadı diye iki adet eleman tanımlayalım. Sonrasında ise oluşturmuş olduğumuz bu sınıfın içerisinde yer alan elemanları Workflow tasarım ekranı üzerinde eklemiş olduğumuz CodeActivity bileşeninin çalışma esnasında görüntülenecek şekilde hazırlayalım.

Eklemiş olduğumuz işlem sonrasında Workflow1.cs 'nin içeriği aşağıdaki gibi olacaktır.

using System;
using System.Workflow.Activities;
using System.Collections.Generic;

namespace ParameterParsing
{
    public class Kullanici
    {
        public Kullanici(string ad, string soyAd)
        {
            this.adi = ad;
            this.soyAdi = soyAd;
        }

        private string adi;

        public string Adi
        {
            get { return adi; }
            set { adi = value; }
        }
        private string soyAdi;

        public string SoyAdi
        {
            get { return soyAdi; }
            set { soyAdi = value; }
        }
    }

    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            foreach (Kullanici k in Insan)
            {
                Console.WriteLine("İsminiz [{0},{1}] 'dir.", k.Adi, k.SoyAdi);
            }
        }

        private List<Kullanici> insan;

        public List<Kullanici> Insan
        {
            get { return insan; }
            set { insan = value; }
        }
    }
}

Kod parçasını yukarıdaki şekilde oluşturduk ve iş akışının çalışması esnasında oluşacak işlemleri de hazırladık. Şimdi program.cs üzerinden gerekli parametreleri oluşturabiliriz.

using System;
using System.Collections.Generic;

using System.Threading;
using System.Workflow.Runtime;

namespace ParameterParsing
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
               {
                   Console.WriteLine(e.Exception.Message);
                   waitHandle.Set();
               };
               Dictionary<string, object> parameters = new Dictionary<string, object>();
                    List<Kullanici> insan = new List<Kullanici>();
                    insan.Add(new Kullanici("Tur", "Tem"));
                    insan.Add(new Kullanici("Ser", "Tur"));

                    parameters.Add("Insan", insan);
               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ParameterParsing.Workflow1),parameters);
               instance.Start();

               waitHandle.WaitOne();
            }
        }
    }
}


Oluşturulan sınıfa ait varlıklara değerleri atadık ve sonrasında uygulamayı çalıştırdığımızda bu değerleri sorunsuzca göreceğiz.



Bir önceki örneğimizde string bir değeri tutan bir parametreyi akış bileşenin nasıl kullanacağımızı gördük. Bu örneğimizde de Oluşturduğumuz bir sınıfı (Veri tabanı tablosu gibi de düşünebilirsiniz) içerisinde yer alan varlıklardan yararlanarak buna değerler atadık ve yine codeactivity bileşenin içerisinde sorunsuzca gösterebildik.

Sonuç olarak Workflow Foundation ile geliştirilen uygulamlarda parametreleri el ile atayıp kullanabileceğimiz gibi bir veri topluluğu içerisinde de çekip kullanabiliriz. Ayrıca bu parametreleri kullanabilmemiz için program.cs sınıfının içerisinde CreateWorkflow metoduna parametre olarak  generic tipten bir parametre ekleyerek parametrelerin kullanılmasına olanak tanıyabiliriz.

Bir sonraki yazımızda Workflow Foundation ' da Paralel Aktiviteleri inceliyor olacağız.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com
turhal.temizer@csharpnedir.com

Cumartesi, Ocak 23, 2010

Bill Gates kendi web sitesini açtı

Dünya üzerinde neredeyse herkesin Bill Gates hakkında bir fikri vardır. Kimileri onun kar etmekten başka bir amacı olmayan biri olduğunu düşünürken, diğerleri onun bir dahi olduğuna inanıyor. Fakat Gates'in notlarını paylaştığı The Gates Notes adlı sitesinde onu yakından tanıyıp, insani yönünü de görme şansına erişiyoruz. Bu site Gates'in, iş hayatında edindiği tecrübeleri, emeklilik yaşantısına nasıl adapte ettiğini görmek mümkün.

Gates, açtığı yeni sitesinde yazılım ve teknoloji dünyasından ziyade eşiyle beraber kurduğu yardım vakfı Bill & Melinda Foundation'da gerçekleştirdiği aktiviteleri okurlarıyla paylaşıyor. AIDS ile ilgili yapılan son araştırmalarla ilgili fikrini paylaşan Gates, küresel ısınmadan Haiti'de meydana gelen depreme kadar dünya gündemini meşgul eden konularla ilgilifikirlerini okurlarına ulaştırıyor.

Kendi ve eşi dışında pek çok eski Microsoft çalışanın da görev aldığı vakıftaki işlerin kendisi için yepyeni bir alan olduğunu ve adeta bunun yeniden okula başlamak gibi olduğunu söyleyen Gates, bu "hayat okulunda" öğrendiklerini okurları ile paylaşmak için bu siteyi kurduğunu söylüyor.

Siteye http://www.thegatesnotes.com/ adresinden erişebilirsiniz...

Cuma, Ocak 22, 2010

WF - Exception İşlemleri

Günümüzde iş akışı teknolojilerini sayar mısınız şeklinde bir soru geldiğinde bu çözümün Microsoft kanadında ki ürünü olarak aklımıza ilk olarak Windows Workflow Foundation çözümü gelmektedir. Özellikle insanlar tarafından tetiklenen (Human Workflow) iş akışı yapıları arasında çok kullanışlı bir teknoloji olarak bulunmaktadır.

Workflow Foundation teknolojisi incelemeye hem kod yardımı ile hem de tasarım ekranı üzerinden yapmış olduğumuz basit bir uygulama ile başlamıştık. Bu yazı dizimizde ki ana amaç iş akışı ile ilgili uygulama geliştirmek istediğimizde nasıl aklımızda nasıl yapacağız şeklinde bir soru işareti kalmadan rahatlıkla yapmaktadır.

Geliştirilen bütün uygulama tiplerinde ortaya çıkan istinai durumları (Exception) tespit edip kontrol ediyor olabilmek en önemli özelliklerden birisidir. Bu yazımızda Workflow uygulamalarında istisnaları nasıl kontrol edebileceğimizi incelemeye çalışıyor olacağız.

WF 'te Exception kavramını örnek üzerinden incelersek çok daha akılda kalıcı olacaktır. Örneği, Visual Studio 2010 Beta 2 IDE 'sinde .Net Framework 3.0 sürümü üzerinde geliştiriyor olacağız. Peki, neden .Net 4.0 dururken 3.0 üzerinde geliştiriyoruz. Sharepoint uygulamaları (2010 sürümü dahil olmak üzere), daha önceden geliştirilen uygulamaları  ve .Net 3.0 ile geliştirilecek olan yeni uygulamaları göz önünde tutarak bu teknoloji üzerinde inceliyoruz.

Uygulamamız için proje şablonlarından Workflow seçeneğini ve Framework sürümü olarakta .Net 3.0 'ı seçtikten sonra Sequential Workflow Console Application 'ı seçerek çalışmaya başlayabiliriz.



Exception örneğini basitçe inceleyebilmek için karşımıza çıkan dizayn ekranına Code Activity bileşeni ekliyoruz.



Sonrasında eklemiş olduğumuz kontrolün üzerine sağ tıklama yaptıktan sonra properties ekranından events (olaylar) seçeneğinden ExecuteCode seçeneğine çift tıklayarak arka plana kod oluşturuyor ve aşağıdaki basit kod parçasını ekliyoruz.



private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    throw new ApplicationException("Başarısız oldu...");
}

Code Activity kontrolünün çalıştığı anda çalışacak olan olayına uygulamanın istisnai duruma düşmesi için gerekli kod parçasını ekliyoruz. Bir önceki yazımızdan da hatırlayacağınız üzere WorkflowRuntime sınıfının altında yer alan WorkflowTerminated özelliğinden düşen istisnai durumları görüntüleyebilmemiz mümkündür. Eğer ki uygulamayı çalıştırır ve olayı bulunduğu delegate 'in içerisinde yer alan kod parçasının içerine breakpoint eklememiz durumunda debug anında düştüğünü ve bizim eklemiş olduğumuz mesajın yazıldığını göreceğiz.



Basit anlamda ilk istisna yakalanması işlemini sağladık. Hata durumlarını daha spesifik yakayabilmemiz için workflow ortamında iki adet daha exception tipi bulunmaktadur. Bunlar Cancel Handler ve Fault Handler 'dır.


Bizim şimdi değineceğimiz bölüm ise View Fault Handlers olacaktır. İşlemin sonuçlanamadığı durumlar için bu bölüm kullanılmakta ve istisnaları yakalamak için Fault Handler bileşeni kullanılmaktadır.



Bu bileşeni Fault Handlers bölümüne sürükledikten sonra karşımıza çıkan ekranın üzerine sağ tıklama yaptıktan sonra properties ekranına geliyor ve FaultType 'a biraz önce CodeActivity içerisinde kullanmış olduğumuz ApplicationException sınfını bularak seçiyoruz.

Not: Bu tip mscorlib 'in içerisinde yer alan System isim alanında yer alır.



Sonrasında view fault handlers ekranında eklemiş olduğumuz FaultHandler bileşeninin içerisine Code Activity sürükledikten sonra properties ekranından ExecuteCode olayına istediğimiz hata mesajını yazdırıyoruz.

 
Eklemiş olduğumuz kod parçası aşağıdaki gibi olacaktır.

private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
    Console.WriteLine("Olamaz... Yakaladın beni.");
    Console.ReadLine();
}

Daha sonra uygulamayı derleyip debug modda çalıştırdığımızda iş akışı içerisine eklemiş olduğumuz code activity 'de ilk olarak hataya düşecek ve sonrasında da faulthandler içerisine düşücektir.



Düşündüğümüz senaryolar sorunsuzca çalışıyor. Şimdi ise iş akışı tasarım ekranına Sequence ekliyoruz ve daha önce oluşturmuş olduğumuz codeActivity1 isimli kontrolü bu bileşenin içerisine ekliyoruz.


Sonrasında daha önce fault handlers durumunda yapmış olduğumuz işlemlerin hepsini tekrarlayarak aşağıdaki durumu sağlıyoruz.


Sonradan eklemiş olduğumuz sequence 'in içerisine eklemiş olduğumuz FaultHandler bileşeninin içerisine düşen istisnai durumları artık gözlemleyebiliriz. Projemizi derledikten ve hatasız olduğunu anladıktan sonra debug mod ile çalıştırdıktan sonra sequence içerisine eklemiş olduğumuz hata bilgisine geldiğini ve bu mesajı gösterdiğini gözlemleyeceğiz.


Ayrıca uygulama çalıştırılırken gözlemleneceği gibi ilk olarak en iç tarafta yer alan yerel iş akışları tamamlanmakta ve sonrasında dış akışlara geçilmektedir. Bu mantıktan ötürüde en son eklediğimiz sequnce bileşeninin içerisinde bulunan FaultHandler 'a girecek ve akışı burada kesecektir. Bu sayede iç kontroller esnasında eğer ki akışta bir problem çıkarsa akışı durdurup hata mesajını en son adımı beklemeden verdirebilme olanağımız olacaktır.

Hazırlanmış olan proje çalışırken herhangi bir aksaklık (Fault) ortaya çıkması durumunda istediğimiz mesajları gösterebileceğimizi gördük. Ancak daha önceden de değindiğimiz gibi uygulama esnasında ortaya çıkan sorunlar ApplicationException sınıfında tutulmaktadır. Bu sebepten ötürü iş akış diyagramına eklemiş olduğumuz FaultHandler bileşeninin özellikler kısmında yer alan Fault kısmını kullanarak belirtmiş olduğumuz hata mesajını verdiyor olacağız. Hatırlayacağınız üzere yazımıza ilk başladığımızda ApplicationException sınıfını kullanmış,  WorkflowRuntime sınıfının workflowTerminated olayını tetiklemiş ve oluşan uygulama aksaklıklarında "Başarısız oldu..." mesajını verdirmiştik. Bu durumu şimdi FaultHandler bileşenini eklemiş olduğumuz yerlerde nasıl kullanacağımıza göz atalım.

FaultHandler bileşenin üzerinde sağ tıklama yaptıktan sonra karşımıza çıkan ekrandaki özelliklerden Fault özelliğine değeri atayacağız.

Bu değer için ApplicationException sınıfında bir özellik (property) tanımlayıp kullanıyor olacağız.

private ApplicationException myException;

public ApplicationException MyException
{
    get { return myException; }
    set { myException = value; }
}

Özelliği tanımladıktan sonra biraz önce göstermiş olduğumuz yere yol olarak MyException özelliğini veriyoruz.



Artık uygulamamızı çalıştırıp hata mesajımızı olabilirim. Debug modda çalıştırdığımız karşımıza çıkan durum tam istediğimiz gibi olacaktır. Daha önceden MyException sınıfını kullanarak belirttiğimiz hata mesajını belirttiğimiz her yerde görebilme olanağımız vardır.


Gözlemlediğimiz üzere istediğimiz mesaj değer olarak karşımıza çıkmıştır.

Şimdi yapacağımız işlemde ise Sequence içerisinde yer alan codeActivity 1 'i silmek ve yerine Throw bilşenini eklemek olacaktır. Bu sayede proje çalışırken karşılaşılan herhangi bir istisnai durumda fırlatılan hatayı kontrol etmiş ve istediğimiz mesajı verebilmiş olacağız.

Throw bileşeninde kullanılmak üzere ApplicationException sınfından yararlanılarak bir özellik oluşturuyoruz.

public ApplicationException ExceptionToThrow
{
    get { return (new ApplicationException("Pardon!")); }
}


Throw bilşeninde özelliği aşağıdaki gibi kullanabiliriz.


ThrowActivity bileşenine sağ tıklama yaptıktan sonra Fault özelliğine daha önceden tanımlamış olduğumuz özelliği atıyoruz.



Bu işlem sonrasında artık projemizi oluşturup hazırlanan property 'ler yardımı throw bilşenini kontrol edebiliriz. Debug ile breakpoint noktasına geldikten sonra MyException.Message 'dan dönecek olan değere ExceptionToThrow a atamış olduğumuz değeri görürüz.


Görüldüğü üzere istediğimiz hata mesajını göstermiş oluyoruz.

Bu örnek ile geldik bir yazımızın daha sonuna, bu yazımızda Windows Workflow Foundation 3.0 ile Exception kavramını detaylı bir şekilde incelemeye çalıştık. Hem kod yardımı ile hemde gerekli WF bileşenlerinin kullanarak nasıl kullanabileceğimize değinmiş olduk.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com
turhal.temizer@csharpnedir.com

Cuma, Aralık 18, 2009

WF - Kod ve Tasarım Ekranı ile İş Akışlarına Giriş

Microsoft 'un yaklaşık 4 yıl önce yapmış olduğu vizyon değişikliği ile .Net 3.0 Framework sürümü ortaya çıktı. Bu sürümde çok fazla yenilik geliyordu. Özellikle yapılan geliştirmeler windows formların iyileştirilmesi ve görselleştirilmesi anlamında Windows Presentation Foundation (WPF), web servislerinin ve SOA mimarisinin daha etkili kullanılabilmesi için Windows Communication Foundation (WCF), web sayfalarında ve kimlik kontrolleri gerektiren formlarda daha güvenli bir şekilde kayıt işlemleri ve üye girişlerinin yapılabilmesi için Cardspace ve iş akışlarının yönetilebilmesi ve rahartlıkla kullanılabilmesi için Windows Workflow Foundation (WF) olarak gözümüze çarpmaktadır. Zaman ilerledikçe bu teknolojiler üzerinde yapılan gelişmeler ile çok daha stabil ve kullanılabilirliğini arttırarak tercih sebebi olmuşlardır. Özellikle .Net Framework 4.0 ile gelen yenilikler geliştiricileri oldukça memnun etmiştir.

Bu yazımızda ve bundan sonraki takip eden yazılarımızda Windows Workflow Foundation (WF) teknolojisini nasıl daha etkili bir biçimde kullanabilirizi inceliyor olacağız. İnternet üzerinde ve alınan kitaplardan incelendiği kadarıyla genellikle WF teknolojinin yetilerini ve neler yapılabileceği anlatılmaktadır. Bizim ana amacımız ise WF teknolojisini örnekler yardımı ile nasıl kullanabileceğimizi açıklamak olacaktır.

WF 'un kısaca hangi ortamlarda kullanılabileceğine değinmek gerekirse;
• Asp.Net ile hazırlanmış olan web uygulamalarında herhangi bir işlemin iş akışı yardımıyla tetiklenmesi ve o akışa bağlı olarak hareket edebilmesi esnasında,
• Windows From ile hazırlanmış olan uygulamalarda herhangi bir işlemin iş akışı yardımıyla tetiklenmesi ve o akışa bağlı olarak hareket edebilmesi esnasında,
• Biztalk Server ile hazırlanmış olan uygulamalarda,
• Microsoft Sharepoint Portal üzerinde hazırlanmış olan formlar üzerinde yapılan işlemler sonrasında tetiklenecek olan işlemler esnasında,
• Microsof CRM ve Dynamics üzerinde hazırlanmış olan formlar üzerinde yapılan işlemler sonrasında tetiklenecek olan işlemler esnasında
kullanıldığını gözlemleyebiliriz.

.Net Framework 4.0 'a doğru giderken, WF yapısında çok fazla değişiklik olduğunu gözlemleriz. Hem kullanımı kolaylaştıran hem de geliştiricilerin daha rahat geliştirme yapabilecekleri başarılı bir teknoloji durumunu almıştır. Ancak biz bu yazılarımızda .Net Framework 3.0 ve 3.5 ile kullanım yöntemlerinin anlatıyor olacağız. Çünkü Sharepoint ve CRM gibi teknolojilerin yeni sürümlerinden WF4.0 kullanılmayacaktır. Ülkemizde Sharepoint uygulama geliştiriciliğinin ve projelerininde arttığını ön planda tuttuğumuzda böyle bir karara varmış oluyoruz.

Daha önceki yazılarımızda WF ile ilgili mimari ve teknik bilgilere erişebilirsiniz. Biz yazımızda direk örnek yardımıyla başlıyor olacağız. Örneklerimizi geliştirirken Visual Studio 2010 IDE 'sinden yararlanırken framework olarak .Net 3.0 'ı seçiyor olacağız.

İnceleyeceğimiz ilk örnek bütün programcılık tekniklerinde en temel örnek olan "Merhaba Dünya" olacaktır.

Uygulamamızı WF mimarisi kullanıldığında nasıl yapı içerisinde kullanıldığını daha iyi anlayabilmek için konsol uygulaması üzerinde gerekli *.dll 'leri projeye referans ederek kullanıyor olacağız.



İş akışı uygulamalarını kullanırken bu eklemiş olduğumuz üç isim alanını muhakkak olması gerekmektedir.

Sequential(sıralı) Workflow, iş akışı tipinin özelliği içerisinde bulundurduğu aktiviteleri(activity) sıralı(adım adım) olarak çalıştırmasıdır. Sequential Workflow’lar bir tetikleyici ile başlayan ve bir daha önceden tanımlanmış bir adımdan diğer bir adıma geçerek ilerleyen iş sırası olarak da tanımlanabilir. Bu iş içerisinde kontrol ya da karar yapısı içerebilir. If bloğu ya da while döngüsü gibi…

Sequential Workflow işlemlerini Visuak Studio ortamında yer alan proje şablonları ile de yapılabilmektedir. Biz bu projemizde kendimiz sequential workflow yapısını oluşturacağız. Bunun için oluşturduğumuz konsol uygulamasında ki program.cs dosyasının içerisine aşğıdaki kodları ekliyoruz.

program.cs
class MyWorkflow : SequentialWorkflowActivity
{
    public MyWorkflow()
    {
        CodeActivity code = new CodeActivity();
        code.ExecuteCode += delegate
        {
             Console.WriteLine("Merhaba Dünya");
        };
        this.Activities.Add(code);
    }
}

CodeActivity ile kod üzerinden bir aktivite başlatılacağı belirtilir. Bu sınıf arayüz üzerinden geliştirilmesinden yardımcı bileşenlerden CodeActivity 'dir.

Bu sınıf bize codeactivity tetiklendiğinde ekrana Merhaba dünya yazmasını sağlayacaktır.

Sonrasında kod uygulama çalıştığından iş akışını da aktifleştirebilmek için aşağıdaki kod parçasını projeye ekliyoruz.

program.cs
class Program
{
    static void Main(string[] args)
    {
        WorkflowRuntime runtime = new WorkflowRuntime();
           runtime.StartRuntime();
        WorkflowInstance instance = runtime.CreateWorkflow(typeof(MyWorkflow));

        instance.Start();
        Console.WriteLine("Bir tuşa basmadığın sürece akış sonlanmayacaktır...");
        runtime.StopRuntime();
        Console.ReadLine();
    }
}

WorkflowRuntime sınıfını kullanarak çalışma anında iş akışının tetiklenebilmesi için ilk olarak oluşturulması sonrasında da başlatılması gerekmektedir. Sonrasında ise tetiklenecek olan sınıfı WorkflowInstance içerisinde tanımlarız. Instance 'i başlattığımızda artık iş akışı başlamış ve istediğimizi karşılamış durumdadır. Sonrasında ise açılmış olan iş akışı sürecisini durdurmak gerekmektedir. Bunun için ise WorkflowRuntime sınıfının StopRuntime() sınıfını kullanmak yeterli olacaktır.

Bu işlemler sonrasında projemizi çalıştırdığımızda aşağıdaki gibi bir sonuç elde ederiz.




İstediğimiz sonuca başarı ile ulaşmış bulunuyoruz.

Sonuç olarak bu yazımızda WF uygulamalarına giriş yapmış oluyoruz ve kod yardımı ile bir iş akışı aktivitesi nasıl oluşturup sonrasında bunu nasıl tetikleyebileceğimizi incelemiş oluyoruz.

Yazımızın bu kısmanda ise Workflow 'un arayüzünden yararlanarak bir iş akışını nasıl tetikleyebileceğimizi ce kullanabileceğimizi inceliyor olacağız.

Visual Studio ortamında (VS2005 eklentiler yardımı ile, VS2008 ve VS2010 direk kullanım) yeni proje oluştur dedikten sonra Sequential Workflow Console Application seçeneğini seçiyoruz.



Sonrasında oluşturulan projenin tasarım ekranına toolbox yardımı ile Code bileşenini ekliyoruz.


Eklenmiş olan kontrol sonrasında özellikler ekranından ExecuteCode olayını yaklamak gerekmetedir. Ancak biz bu olayı yaklamadan önce bizim için otomatik olarak oluşturulan kodlara göz atalım. İlk olarak proje şablonunda oluşturulmuş olan program.cs dosyasına göz atıyoruz.
using System;
using System.Threading;
using System.Workflow.Runtime;

namespace WorkflowTasarim
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
                workflowRuntime.WorkflowTerminated += delegate(object sender,  WorkflowTerminatedEventArgs e)
               {
                   Console.WriteLine(e.Exception.Message);
                   waitHandle.Set();
               };

               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowTasarim.Workflow1));
               instance.Start();

               waitHandle.WaitOne();
           }
        }
    }
}

Bir önceki örneğimizde de kullandığımız üzere WorkflowRuntime ile akışın oluşturulabilmesi ve başlatılabilmesi için gerekli süreçleri başlattıktan sonra WorkflowInstance yardımı ile akış tetiklenir ve işlem yapılır.

Şimdi ise code activity 'i kullanmak için yapmamız gereken kısma geldi. Biraz önce code bileşenin execute_code olayının yakalanması esnasında yapacak olduğumuz işlemlerin sorunsuzca gerçekleşeceğinden bahsetmiştik. Şimdi bu işlem için tasarım ekranına eklemiş olduğumuz Code bileşenin üzerine sağ tıklama yaparak özelliklerine gidiyoruz. Karşımıza çıkan ekrandan Execute_Code olayına çift tıklanması sonrasında oluşan kod bloğunun içerisine "Merhaba Dünya" kodunumuzu yazarak çalıştırılması için hazır duruma getiriyoruz.

using System;
using System.Workflow.Activities;

namespace WorkflowTasarim
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Merhaba Dünya");
        }
    }
}

Hazırlamış olduğumuz bu basit akışı çalıştırdığımızda sonuç aşağıdaki gibi olacaktır.



Sonuç istediğimiz gibidir.

WF ile uygulama geliştirirken daha doğrusu herhangi bir teknoloji ile uygulama geliştirirken biz yazılımcılar için en büyük yardımcısı debug 'tır. WF ile uygulama geliştirirken kod üzerinden alışık olduğumuz şekilde debug yapabilmekle birlikte tasarım üzerine ekleyeceğimiz debug noktalarında da aktivite bazlı olarak debug edebilmemiz mümkündür. Ayrıca aktivite bazlı debug esnasında belirlenen noktaya akış yakalandıktan sonra arka planda yer alan kod parçasına girerek debuga burada devam edecek ve hazırlamış olduğumuz işlemler gerçekleşecektir.



Sonuç olarak bu yazımızda WF uygulamalarına giriş yapmış oluyoruz ve tasarım ekranı yardımı ile bir iş akışı aktivitesi nasıl oluşturup sonrasında bunu nasıl tetikleyebileceğimizi incelemiş oluyoruz.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com

Cumartesi, Kasım 28, 2009

SQL Server 2008 R2 November CTP

SQL Server 2008 R2'nin November CTP'si (Community Technology Preview) çıktı. İlk bağlantı R2 için, ikinci bağlantı ise Feature Pack'i için... http://www.microsoft.com/downloads/details.aspx?FamilyID=fe0c6a31-5ad6-4eea-a865-73bbe2608bd1&displaylang=en http://www.microsoft.com/downloads/details.aspx?familyid=020EE0D5-BCE4-4A45-9D64-B0C49C8831E5&displaylang=en

Salı, Kasım 03, 2009

Sharepoint - Dinamik Olarak MasterPage Değiştirmek

Microsoft Sharepoint Server ve MOSS teknolojisi günümüzde portal sistemleri denince akla ilk gelen ve şirket yöneticilerinin aklına gelen ilk teknolojidir. Esnek yapısı ve alt yapı mimarisi ile geliştiricilerin işlerini kolaylaştıran araçları ile insanların ilgilisini çok kısa zamanda çekti ve çekmeyede devam edecektir. 

Bu yazımızda Sharepoint teknolojileri kullananan kurumlardan en çok istenen isteklerden birinin nasıl çözüleceğini incelemeye çalışacağız. Örneklemek gerekirse, bir kurumun içinde üç farklı çalışma grubu var yöneticinizin bu çalışma gruplarından hangisi sisteme girdiyse ona özel bir tasarım görünmesini istiyorum şeklinde isteği olabilir. Bu durumda bizim yapmamız gereken gerekli çözümleri üretip işi sonuca ulaştırmaktır.

Sharepoint Server ile MOSS üzerinde geliştirme yapılmaya başlandığında ilk olarak default.master ve CSS dosyası bizlerin kullanımına sunulmaktadır. Farklı kullanıcı gruplarından hangi grup girerse farklı bir masterpage 'in açılmasına olanak tanıyabilmek için ilk olarak bu masterpage 'leri sharepoint e uygun şekilde düzenlemek gerekmektedir. Şimdi masterpage 'leri sisteme dahil olan kullanıcı grubuna göre nasıl değiştirebileceğimizi incelemeye başlayalım.

ASP.NET Sayfasının İçerisinde MasterPage Nasıl Değiştirilir?

ASP.NET uygulama geliştiriciler sisteme dahil olan üyelere göre rahatlıkla masterpage ve sayfa içerisinde yer alan öğeleri değiştiebiliyorlar. Sisteme dahil olan kullanıcıları kontrol etmek için masterpage 'in içerisinde yer alan PreInit event 'ından yararlanmak gerekmektedir. Fakat unutulmaması gereken bir nokta var. Hazırlanmış olan uygulama da yalnızca üç beş tane asp.net sayfa olmayacak. Yüzlerce sayfa olacaktır. Bu durumda her sayfaya ve masterpage 'e PreInit olayını yakalamak ve belirteceğimiz kodları yazmak sistemi yavaşlatacak bir etken olacaktır. Bu sebepte her sayfa için taban bir sınıf oluşturup yapacak olduğumuz işlemleri bunun içerisinde yaparsak işlerimiz biraz daha kolaylayacaktır. Bu sebeple MyCustomBasePage isimli bir sınıf oluşturuyoruz ve Page sınıfından bu sınıfı türetiyoruz. Sonrasında ise, Page_PreInit olayına aşağıdaki kodları ekliyoruz.

public class MyCustomBasePage : System.Web.UI.Page
{
    protected void Page_PreInit(object sender, EventArgs e)
    {
        if (CurrentUser.UserType == UserType.Admin)
        {
            MasterPageFile = "~/MasterPages/AdminMaster.master";
        }
        else if (CurrentUser.UserType == UserType.NormalAuthenitcated)
        {
            MasterPageFile = "~/MasterPages/NormalAuthenticatedMaster.master";
        }
        else
        {
            MasterPageFile = "~/MasterPages/AnonymouskMaster.master";
        }
    }
}

Bu sınıfın içerisinde üç farklı kullanıcı grubu için master page ayarladık. Admin, Normal ve sistem tarafından tanınmayan kullanıcılara göre farklı masterpage ler çalışacak ve görsel olarak farklı bir görünüm ile karşılacaklardır.

Şimdi bu sınıfı oluşturduğumuza göre işimiz biraz daha kolaylaştı. Artık oluşturulan bütün sayfalardan MyCustomBasePage sınıfını kullanarak bu hazırlamış olduğumuz kontrolün aktifleşmesine olanak tanırız.

public partial class HomePage : MyCustomBasePage
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
}

Sharepoint İçerisinde MasterPage Nasıl Değiştirilir?

Ana mantık olarak web uygulamalarında her kullanıcı grubuna ya da değişik faktörlere göre masterpage 'i nasıl değiştrebileceğimizi biliyoruz. Biraz öncede incelemiştik. Harici bir sınıf oluşurulur ve sayfanın PreInit olayı yakalanılarak değişiklikler yapılabilirdi. Ancak Sharepoint içerisinde bu direk PreInit olayından yakalayabilmek dire mümkün değildir. Ancak bizden çözüm bekleniyor ve gerekli işlemleri yapmamız gerekmektedir. Sharepoint Sayfaları içerisinde PreInit olayını yakalayabilmek için HttpModule 'ün kullanılması gerekmektedir.

Asp.Net Pipeline Süreci

Asp.Net istek süreçleri pipeline mantığına göre işlemlerini sürdürmektedir. Aşağıdaki şekilde de göreceğiniz üzere her isteğe yanıt veren bir modül bulunmaktadır. İstekler yakalandıktan sonra gerekli modülün kullanılmasına olanak tanınır.



Genellikle istekler pipeline içerisinde yer alan modüller isteklere göre yanıt vermektedir. Eğer ki bir den fazla modüle istek yapılırsa da tek bir işleyici tarafında işlem yapılacaktır. Ancak bizim istediğimiz her modüle tek bir işleyicinin işlem yapmasıdır. Bu işlemide asp.net sayfasında PreInit olayı ile gerçekleştiririz.

HttpModule 'den yararlanarak PreInit Olayı İşlenmesinin Geliştirilmesi

HttpModule den yararlanarak bir sınıf geliştirilirken System.Web.IHttpModule sınıfı miraslanarak kullanılır. IHttpModule 'in iki tane metodu vardır. Bunlar Dispose ve Init 'dir. Init metodu başlatıldığında diğer aktif olan Initleri iptal ederek kendisini kullanmaya başlayacaktır.

public class DynamicMasterPageModule : IHttpModule
{
    public void Dispose()
    {
    }
    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
    }
    void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
                Page page = HttpContext.Current.CurrentHandler as Page;
           if (page != null)
           {
               page.PreInit += new EventHandler(page_PreInit);
           }
    }
    void page_PreInit(object sender, EventArgs e)
    {
    }
}

Init metodunun içerisinde yer alan PreRequestHandlerExecute event 'ını yakalıyoruz. Asp.net sayfa başlarken bu olay tetiklenir. Sonrasıda açılacak olan sayfanın null olup olmadığının kontrolü sonrasında asp.net 'ten alışık oluğumuz PreInit olayının tetiklenmesi işlemini gerçekleştirebilmemize olanak tanınır.

Sharepoint MasterPage

Sharepoint 'in kendi varsayılan bir masterpage 'i vardır. Eğer bu masterpage üzerinde bir değişiklik ya da düzenleme yapmak istersek Sharepoint içeriğini görüntülemeye olanak tanıyan Sharepoint Designer içerisinde düzenleme yapmak gerekmektedir. Eğer ki oluşturulan ya da düzenlenen masterpage 'i kod tarafından çağırmak istersek Page.MasterPageFile özelliğini kullanmak gerekmektedir.

Page.MasterPageFile = "Masterpage 'in uygulama içerisindeki yolu";

Ancak dikkat edilmesi gereken bir nokta vardır. Masterpage sharepoint içerisinde farklı yerlerde bulıunabilir. Peki neden? Varsayılan sitenin içerisindeki olabilir, site koleksiyonunda olabilir gibi yerlerde olabilmektedir. Bunları örneklemek gerekirse,

"~site/MasterPageName.master"
Site klasörünün içerisinde yer alan masterpage 'in yolunu birden fazla masterpage olacağı için ~site/MasterPages/Masterpagename.master şeklinde güncellemelidir. MasterPage 'in yolunu adres çubuğunda görüntülemek için ise, http://sitecollection/site1 'in altında yer alan masterpage adresinden http://sitecollection/site1/masterpages/MyMaster.master yoluna göre güncelleriz.

"~sitecollection/MasterPageName.master"
Burada ise masterpage ~sitecollection yolunun içerisinden erişilebilmektedir. Ana sitenin yolu http://sitecollection iken http://sitecollection/MasterPageName.master yolu ile erişebilmek mümkündür.

Sharepoint İçerisinde Özel MasterPage Kullanımı

Eğer Sharepoint ile uygulama geliştirirken Sharepoint Designer yardımı ile yaparız. Özel bir masterpage oluşturmanın en kolay yolu var olan bir masterpage i tekrardan kopyalayarak yapıştırdıktan sonra gerekli düzenlemeleri yaparız.

Özel bir masterpage 'i oluşturduktan sonra diğer otomatik olarak bunun özel olarak oluşturulan bir masterpage olduğunu Sharepoint direkt anlamaz. Bu işlemi yapabilmek için Sharepoint Designer üzerinden de hazırlanan masterpage 'in üzerinde sağ tıklama yaparak bunu özel bir masterpage olduğunu belirten "Set as Custom Master Page" 'e tıklayarak belirtiriz.



Artık PreInit olayını yakaladıktan sonra web.config içerisinde MasterPage numarasını alıyoruz. Sonrasında eğer gelen sayfa numarası 1 ise custom1.master eğer gelen sayfa numarası 2 ise custom2.master 'ı aktif duruma getiriyoruz.


void page_PreInit(object sender, EventArgs e)
{
    Page page = sender as Page;
    string pageNo = ConfigurationManager.AppSettings["MasterPageNo"];


    if (page != null)
    {
        if (pageNo.Equals("1"))
            {
                page.MasterPageFile = "~masterurl/custom.master";
                if (SPContext.Current != null)
                {
                    SPContext.Current.Web.CustomMasterUrl = "/_catalogs/masterpage/custom1.master";
                }
            }
            else if (pageNo.Equals("2"))
           {
               page.MasterPageFile = "~masterurl/custom.master";
               if (SPContext.Current != null)
               {
                    SPContext.Current.Web.CustomMasterUrl = "/_catalogs/masterpage/custom2.master";
               }

           }
           else
           {
                page.MasterPageFile = "~masterurl/default.master";
                if (SPContext.Current != null)
               {
                    SPContext.Current.Web.MasterUrl = "/_catalogs/masterpage/default.master";
               }
       }

}

web.config 'den gelen değere göre hangi masterpage 'in geleceği dinamik olarak görüntülenmektedir. Bu işlemi işinizi görecek şekilde güncelleyerek sorunlarınızı kolayca çözebilirsiniz.

Sonuç olarak bu yazımızda belirli kriterler doğrultusunda sharepoint server portal in masterpage 'ini dinamik olarak nasıl değiştirebileceğimizi incelemeye çalıştık.

Umarım yararlı olabilmiştir.

Pazar, Kasım 01, 2009

CodeProject.com Makale Yazarlığı

Merhabalar, 
Benim için mutlul bir haber vereceğim. Bildiğiniz üzere Türkiye içerisinde adı bilinen topluluklarda editörlük ve yazarlık görevinde bulunmaktayım. Artık dünyada yazılımcılarında en çok ziyeret ettiği topluluklardan biri olan CodeProject.com sitesinde de makale yazarlığı yapmaya başladım ve ilk yazım yayınlandı. Umarım burada da çok fazla sayıda yazılar yayınlayarak dünya üzerinde ki insanlara yardımcı olabilirim.

Herkese iyi çalışmalar diliyorum.

Cumartesi, Ekim 31, 2009

WPF - Tooltip Özelliği

Windows Presentation Foundation ile uygulama geliştirirken kullanabileceğimiz kontrol paleti işlerimizi rahatlıkla yürütebileceğimiz kadar geniştir. Araç kutusu içerisinde yer alan kontroller Framework sürümünü arttırdıkça ve codeplex, code.msdn gibi sitelerde yer alan projeler yardımı ile daha da artmaya devam etmektedir. WPF 'in grafiksel ve görsel gücüne günlük yaşantı da kullanılan kontrollerin de kullanılabilir olması sayesinde en basit uygulamalardan en karmaşık uygulamalara kadar geliştirilebilme olanağı tanınıyor.

Bu yazımızda WPF üzerinde kullanılan en temel kontrollerin Tooltip özelliğini özelliklerini inceliyor ve nasıl kullanıldığını, özellikleri incelemeye çalışıyor olacağız.

WPF - Tooltip
WPF ile son kullanıcılar için uygulama geliştirirken bileşen paletinde yer alan bileşenlerden bir çoğunu kullanır ve düzenleriz. Yapmış olduğumuz işlemler sonrasında her kontrolün ne işe yaradığını ve tıklanması sonrasında ne işe yaradığını açıklayan bir döküman hazırlarız. Ancak dünyanın değişmeyen gerçekleri arasındadır. Son kullanıcılar kolay kolay hazırlanan dökümanları okumazlar. Bu sebepten ötürüdür ki tıklanacak kontrolerin üzerinde yazan metinleri çok dikkatli seçer ve kolayca algınacak metinler yazmaya çalışırız. Ancak en fazla iki üç kelime ile neler anlatabiliriz ki gibi sözler aklınıza gelmektedir. Bu durumda yardımımıza Tooltip yetişiyor. Bir kontrolün üzerinde fare üle durduğumuzda gerekli açıklamaları yazabildiğimiz, resimleri gösterebildiğimiz çok güzel bir özelliktir. Şimdi bu özelliğini nasıl kullanabileceğimizi örnekler yardımı ile açıklamaya başlayalım.

Neredeyse bütün kontrollerin özelliklerinde yer alan Tooltip özelliği fare ile bir kontrolün üzerine geldiğimizde açıklama bilgisi göstermeye yarayan hoş bir özelliktir. Kullanabilmek için Tooltip yazıp istediğimiz değeri atamak yeterli olacaktır.

<Button Content="Gönder">
    <Button.ToolTip>
        <ToolTip>
            <StackPanel>
                <TextBlock FontWeight="Bold">İstek Kabulu</TextBlock>
                <TextBlock>Sunucuya isteğiniz gönderilecektir..</TextBlock>
             </StackPanel>
        </ToolTip>
    </Button.ToolTip>
</Button>

Buton kontrolünün Tooltip özelliğine iki adert TextBlock kontrolü ekledik ve fare üzerine geldiğinde görüntülenmesine olanak tanıyacağız. Şimdi test amaçlı olarak projeyi çalıştırıyor ve sonuca bir göz atıyoruz.



İstediğimizi gerçekleştirmiş gibi görünüyoruz. Kullanıcı Gönder butonunun üzerine geldiğinde butonun ne işe yaradığını açıklayan çok kısa bir açıklama görüyor.

Tabii uygulama içerisinde her zaman bütün kontorllerin aktif olacağı şeklinde bir kural hiç bir zaman yoktur. Bazı durumlarda kontroller pasif durumda gösteriliyor olabilir. Ancak biz bu pasif olmuş olan kontrol içinde bir Tooltip hazırlamışız ve bunun herzaman görüntülenmesini istiyoruz. İşte bu durumda yapılması gereken TooltipService 'lerini devreye sokarak kontroler Disable olduğu durumlarda da gösterilmesine olanak tanırız.

IsEnabled="False" olan konroller olduğu durumda TooltipService.ShowOnDisable="True" özelliğini kullanarak Tooltip 'in görüntülenmesine olanak tanırız.

<Button IsEnabled="False" ToolTip="Bütün alanları doldurunuz..." ToolTipService.ShowOnDisabled="True" Content="Kaydet" />

Buton kontrolü pasif durumdayken fareyi üzerine getirdiğimizde ekran görüntüsü aşağıdaki gibi olur.


Gayet güzel. Buton aktif olduğu durumda da Tooltip görüntülenmeye devam edecektir. Ancak çağırdığımız servisi iptal edersek Tooltipin görüntülenmediğini gözlemleyeceksiniz. Tooltip 'in bir diğer özelliği de ne kadar bir zaman süresince görüntülenebileceğini belirleyebilmemiz mümkündür. Bunun için yine TooltipService. 'in ShowDuration özelliğinden yararlanmak yeterli olacaktır.

<Button ToolTip="Bütün alanları doldurunuz..." ToolTipService.ShowDuration="20" Content="Kaydet" />

Tooltip içerisine yazmış olduğumuz metin iki saniye boyunca ekranda görüntülendikten sonra kaybolacaktır.


Tooltip özelliğini çok kolay birşekilde farklı senaryolarda kullanbildiğimizi gördük. Şimdi ise işin görsellik yanı ile ilgilenelim. Bu kullandığımız tip leri zaten windows formlar üzerinde de rahatlıkla kullanabiliyorduk. Ancak unutmayalım ki biz uygulamalarımız WPF ile geliştiriyoruz ve bu teknlojinin bize sunduğunu görsellik ve esnekliğin hepsini kullanabilmemiz mümkündür. İşte bizde bu esneklikten yararlanarak tooltip i biraz daha görsel bir duruma dönüştüreceğiz. İçerisinde resim olan ve standart boyutların dışında bir tooltip olacaktır.

<Button Width="100" Height="30">Yaklaştır Fareyi
    <Button.ToolTip>
        <StackPanel Background="Honeydew" Height="200" Width="200">
            <StackPanel Background="BurlyWood" Height="30" Width="200" Orientation="Horizontal"                     HorizontalAlignment="Left" VerticalAlignment="Top" >
                <Image VerticalAlignment="Top" Width="30" Height="30" Source="Images/Copy.png"                         Name="image1" />
                    <TextBlock FontFamily="Aharoni" FontSize="24" FontWeight="Bold"                 Foreground="Black" TextWrapping="Wrap" VerticalAlignment="Top" Height="30" HorizontalAlignment="Right" Width="143">
                        <Run FontFamily="Andalus" FontSize="18" FontWeight="Normal" Text="Merhabalar,                             Renkliler."/>
                    </TextBlock>
                </StackPanel>
                <StackPanel Width="200" Orientation="Horizontal" HorizontalAlignment="Left"         VerticalAlignment="Top" >
                    <TextBlock TextWrapping="Wrap" Foreground="#FFF9F4F4" TextAlignment="Center"     Background="{x:Null}" HorizontalAlignment="Right" VerticalAlignment="Top" Width="181" Height="98">
                        <Run FontFamily="Verdana" FontSize="11" FontWeight="Normal" Foreground="#FF151514"
                        Text="Kontorllerin Tooltip lerine resim, video, müzik ve daha bir çok özellik ekleyebilmeniz mümkündür. Tek yapmanız gereken hayal edip uygulamak olacaktır."/>
                    </TextBlock>
                </StackPanel>
            </StackPanel>
      </Button.ToolTip>
</Button> 

Yaptığımız işlemler sonrasında ekran görüntüsü aşağıdaki gibi olacaktır.


Çok basit bir şekilde WPF 'in gücünü kullanarak çok şık bir Tooltip oluşturmuş olduk. Sizlerin hayal gücüne göre bu örnekleri arttırabilme olanağınız vardır.

Sonuç olarak bu yazımızda son kullanıcıya kontrollerin ne iş yaptığını anlatmakta yardımcı özelliklerden biri olan Tooltip kontrolünü WPF 'in gücünden yararlanarak incelemeye çalıştık.

Umarım yararlı olabilmiştir.

WPF - DataGrid Pratikleri - II

Windows Presentation Foundation ile uygulama geliştirirken kullanabileceğimiz kontrol paleti işlerimizi rahatlıkla yürütebileceğimiz kadar geniştir. Araç kutusu içerisinde yer alan kontroller Framework sürümünü arttırdıkça ve codeplex, code.msdn gibi sitelerde yer alan projeler yardımı ile daha da artmaya devam etmektedir. WPF 'in grafiksel ve görsel gücüne günlük yaşantı da kullanılan kontrollerin de kullanılabilir olması sayesinde en basit uygulamalardan en karmaşık uygulamalara kadar geliştirilebilme olanağı tanınıyor.

Windows Presentation Foundation ile ilgili kontrolleri özellikle de .Net Framework 4.0 ile çok daha sık kullanacak olduklarımızı incelmeye devam ediyoruz. Bir önceki yazımızda WPF DataGrid kontrolünün nasıl kullanabileceğini ve özelliklerinden nasıl yararlanabileceğimizi anlatmaya çalışmıştık. Bu yazımızda yine DataGrid kontrolünü incelerken detaylı bir şekilde proje geliştirme esnasında DataGrid kontrolünü nasıl kullanabileceğimizi açıklamaya çalışıyor olacağız.

Son kullanıcıya veri göstermek istenildiğinde akla gelen ilk kontrollerdendir DataGrid kontrolü. Asp.Net uygulamalarında DataGrid, Windows Form uygulamalarında DataGridView kontrolü olarak geçmektedir. Ayrıca üçüncü parti kontrol geliştiren yazılım firmalarınında ilk olarak değindikleri ve özelleştirdikleri kontroldür. Bu durumda bu kontrolün WPF ilk çıktığı zamanlarda bileşen panelinin içerisinde yer almaması oldukça büyük bir eksiklik olarak hissediliyordu. .Net Framework 3.5 'in SP1 sürümünün çıkması ve sonrasında WPF Toolkitin iyice kullanılabilir hale gelmesi ile WPF için yeni yeni kontroller geliştiricilere sunulmaya başladı. Bu geliştirilen kontrollerden şu anda için en sık kullanılan DataGrid, DateTimePicker ve Calendar kontrolleri özelleştirilebilir halleri ile .Net Framwork bünyesine de eklenmiştir. Zaman içerisinde kontrol panelinin içeriğinin artacağından kimsenin şüphesi yoktur.

DataGrid kontrolünün temel özelliklerini ve DataSet yardımı ile veri tabanı işlemlerimizi nasıl yapabileceğimizi incelemiştik. Şimdi ise LinqToSQL ile DataGrid üzerinde CRUD işlemlerinin nasıl yapabileceğimize göz atıyor olacağız. Bu işlemler için olarak bir WPF projesi açıyor ve sonrasında LinqToSQL Modeli projemize ekliyoruz.

LinqToSQL denilince akla Nesne ilişkili tasarım (Object Relation Designer) kelimeleri akla gelmektedir. Alışagelmiş olduğumuz SQL sorgularının aksine nesne olarak INummrable, IQueryble ve diğer ilişkisel arayüzleri taban alınarak hazırlanmış kullanımı çok kolay bir veri modelidir. Bizde bu kolaylıktan yararlanabilmek için projemizde LinqToSQL kullanıyoruz.

Projemiz oluştu ve LinqToSQL Classes 'i projeye ekliyoruz.



Veri modelini projeye ekledikten sonra Microsoft 'un SQL örnek veritabanlarından Northwind 'den yararlarak Customers tablosunu ekliyoruz.


Bu işlemi gerçekleştirdikten sonra projeyi bir kez derliyoruz. Sonrasında sıra verileri gösterecek olduğumuz DataGrid kontrolüne geldi. Eğer ki VS2008 SP1 kullanıyorsanız CodePlex sitesi üzerinden indirmiş olduğunuz WPF Control Toolkit içerisinde yer alan WPFToolkit.dll 'i projeye referans ediyoruz. Eğer ki VS2010 kullanıyorsanız ise bu işlemi yapmanıza gerek yoktur. Çünkü .NET Framework 4.0 bünyesinde WPF DataGrid kontrolü yer almaktadır.

DataGrid kontrolünü proje içerisinde kullanılabilir duruma getirdikten sonra Customer tablosunun içeriğini grid içerisinde gösterilecek şekilde ekliyor ve sonrasında düzenleme ve silme işlenin yapılabilmesi için DataGrid 'in template column özelliğinden yararlanıyoruz.

DataGrid.xaml
<Button Content="Kullanıcıları Yükle" Name="LoadButton" VerticalAlignment="Top" Click="LoadButton_Click"/>
<DataGrid AlternationCount="2" SelectionMode="Single" AutoGenerateColumns="False" Height="252" HorizontalAlignment="Left" Margin="0,31,0,0" x:Uid="dataGrid1" x:Name="dataGrid1" VerticalAlignment="Top"    Width="584">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=CustomerID}" IsReadOnly="True" Header="CustomerID" Width="SizeToHeader"/>
        <DataGridTextColumn Binding="{Binding Path=CompanyName}" Header="Company" Width="SizeToHeader" />
        <DataGridTextColumn Binding="{Binding Path=ContactName}" Header="Name" Width="SizeToHeader" />
        <DataGridTextColumn Binding="{Binding Path=City}" Header="City" Width="SizeToHeader" />
        <DataGridTextColumn Binding="{Binding Path=Country}" Header="Country" Width="SizeToHeader" />
        <DataGridTextColumn Binding="{Binding Path=Phone}" Header="Phone" Width="SizeToHeader" />
        <DataGridTemplateColumn Header="Düzenleme">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Content="Düzenle" Click="EditButton_Click"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Sil">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Content="Sil" Click="DeleteButton_Click"/>
                 </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

XAML üzerindeki değişiklikleri tamamladıktan sonra şimdi kod tarafında kullanıcıları doldur butonuna tıklanıldığı zaman gerçekleşecek olan işlemleri ayalarlayalım.

DataGrid.xaml.cs
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
    LoadCustomer();
}

private void LoadCustomer()
{
    DataClasses1DataContext cd = new DataClasses1DataContext();
    var customers = (from p in cd.Customers select p).Take(10);
    dataGrid1.ItemsSource = customers;
    LoadButton.Content = "Kullanıcılar Yüklendi";
}

Yapmış olduğumuz işlemler sonrasında artık LinqToSQL yardımı ile veri tabanından kullanıcı bilgilerini getirerek gird üzerinde gösterebiliriz. Test etmek gerekirse sonuç aşağıdaki gibi olacaktır.



Şu ana kadar herşey istediğimiz gibi ilerlemektedir. Şimdi yapacak olduğumuz işlem ise seçilen bir kayıtın düzenlenmesi olacaktır. Bunun için en gerekli bilgi seçilmiş olan satırdaki CustomerID 'ye erişmek olacaktır. Diğer işlemler ise alışık olduğumuz seçilen kaydın ID 'sinden yararlanarak güncelleme işlemlerinin yapılması olacaktır.

DataGrid.xaml.cs
private void EditButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        DataClasses1DataContext dataContext = new DataClasses1DataContext();
        Customer customerRow = dataGrid1.SelectedItem as Customer;
        string m = customerRow.CustomerID;
        Customer customer = (from p in dataContext.Customers where p.CustomerID == m select p).Single();
        customer.CompanyName = customerRow.CompanyName;
        customer.ContactName = customerRow.ContactName;
        customer.Country = customerRow.Country;
        customer.City = customerRow.City;
        customer.Phone = customerRow.Phone;
        dataContext.SubmitChanges();
        MessageBox.Show("Satır Güncellenmiştir");
        LoadCustomer();
    }
    catch (System.Exception ex)
    {
        MessageBox.Show(ex.Message);
        return;
    }
}

Artık DataGrid üzerinden veri güncelleyebilir duruma gelmiş bulunuyor. LinqToSQL kullanırken veri içerisinde yer alan değişiklikler için SubmitChanges metodunu kullanmak gerekmektedir. Test etmek gerekirse sonuç aşağıdaki gibi olacaktır.



Son olarak silme işlemini nasıl yapabileceğimizi inceleyeceğiz. Yine seçili olan satırın CustomerID 'sinden yararlanarak silme işlemini gerçekleştireceğiz.

DataGrid.xaml.cs
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
    DataClasses1DataContext cd = new DataClasses1DataContext();
    Customer customerRow = dataGrid1.SelectedItem as Customer;
    var customer = (from p in cd.Customers where p.CustomerID == customerRow.CustomerID select p).Single();
    cd.Customers.DeleteOnSubmit(customer);
     cd.SubmitChanges();
    MessageBox.Show("Satır silinmiştir.");
    LoadCustomer();
}

DataGrid üzerinde silme işlemini de başarı ile gerçekkleştirdik. LinqToSQL ile seçilmiş olan CustomerID yardımıyla veri tabanından kaydın silinmesine olanak tanıdık.

Sonuç olarak bu yazımızda basit olarak LinqToSQL yardımı ile ve WPF DataGrid kullanılarak temel CRUD işlemlerini nasıl yapabileceğimizi incelemeye çalıştık.

Umarım yararlı olabilmiştir.