cub-e.net

just coding...

Is Microsoft Winning The CRM Race - Microsoft CRM Yarışını Kazanabilecek Mi?



Destination CRM Magazine dergisi Microsoft CEO'su Steve Ballmer ile CRM konusunda Microsoft'un stratejilerini paylaştığı bir söyleşiyi ve Dynamics CRM'in teknik incelemesinin yer aldığı bir yazıyı yayınladı.
Dergiyi çevrimiçi okumak için aşağıdaki linke tıklayabilirsiniz.

---

Did you got chance to read July edition of Destination CRM Magazine? It featured CRM 4.0 and a conversation with Steve Ballmer and Technical Research of Dynamics CRM.
Here is the link to read it online;


http://www.nxtbook.com/nxtbooks/crmmedia/crm0708/#/22

User’s Guide now available in PDF and Word for CRM 4.0 - CRM 4.0 için kullanıcı kitapçığı Word ve PDF biçiminde hazır

CRM 4.0 için kullanıcı kitapçığı son kullanıcı için basit anlatımlı yardımlar ve kısayolladan oluşmakta. Döküman satış,pazarlama ve şikayet yönetimi modülleri için anlatımlar ve adım adım tanımlardan oluşmakta.

----

The Microsoft Dynamics CRM 4.0 User’s Guide includes all of the basic end-user information available in Help, including documentation on sales, marketing, and customer service features, as well as step-by-step instructions on working with Advanced Find and workflow. And it’s in an easily printable format.

 

http://www.microsoft.com/downloads/details.aspx?FamilyId=0DB4D487-1BAA-4619-9BC5-074D73C3997D&displaylang=en

Developer Ramp up Kit for Microsoft Dynamics CRM 4.0

Microsoft yazılım geliştiricilerin CRM Platformu üzerinde nasıl yazılım geliştireceklerini anlatan Developer Ramp up Kit for Dynamics CRM 4.0 isimli eğitim materyallerini yayınladı. Bu materyaller Web Servisleri, Workflow Mimarisi, SSRS ile raporlama gibi birçok konuda bilgi veriyor.

-----

This kit is for .NET based developers who want to ramp up and build on top of the Microsoft Dynamics CRM platform. Microsoft Dynamics CRM 4.0 uses familiar components such as Web Service endpoints, Windows Workflow Foundation, SSRS reporting, and more; making it a general purpose platform for any line-of-business applications. Developers can use their existing .NET skills to take advantage of various features of the Microsoft Dynamics CRM platform. This kit drills into the details of such development and explains how developers can connect, extend, and embed with the Microsoft Dynamics CRM platform. It includes presentations, hands-on labs, and a VPC environment for practicing. This content was delivered earlier as part of the Metro Early Adopter initiative and the video recordings of the ramp-up presentations are included as well.

Familiarity with the .NET Framework, Microsoft Visual C#, Jscript, Microsoft SQL Server and general Web development is recommended.

 http://msdn.microsoft.com/en-us/library/cc720132.aspx

Dynamics CRM 4.0 SDK ver. 4.0.4 (CRM SDK Versiyon 4.0.4 hazır)

Microsoft Dynamics CRM 4.0 SDK Versiyon 4.0.4 indirilmeye hazır. Bu versiyon çok fazla yenilik ve güncelleştirme içermekte. Detayları aşağıda bulabilirsiniz.

---

Version 4.0.4 of the Microsoft Dynamics CRM 4.0 SDK is now available for download! This version contains lots of great new and updated information:

· Offline Plug-in Security  - New information about the additional security restriction for an offline plug-in, which requires that a registry key named after the public key token of the plug-in assembly be added to the system registry. The online/offline plug-in sample code and walkthrough was updated too.

· Plug-in Constructor - Added a topic explaining how to write a constructor for a plug-in that accepts parameters. These strings can be used to pass information to the plug-in at run time.

· Privileges by Message – The appendix showing the required privileges for each message has been updated. There are a few outstanding messages that will be completed in the next SDK release.

· Outlook Sample Code and Programming Reference – The reference topics for the Microsoft.Crm.Outlook.Sdk assembly have been completed. Added new sample code that interacts with Microsoft Dynamics CRM for Microsoft Office Outlook using this assembly.

· Using the Discovery Service in Microsoft Dynamics CRM Live - Added a topic to show how to get the Web reference for Microsoft Dynamics CRM Live.

· SiteMap Sample Code - Added step-by-step instructions for how to change the label text in the navigation pane.

· Scripting Sample Code - Added a new scripting sample that allows you to control which users can update data in a field.

· Report Writers Guide - Added a new topics on linking reports, managing reports offline and new information about publishing reports.

· Other Sample Code 

    • How to Send a Bulk E-mail and Monitor the System Job
    • How to Start an Asynchronous Bulk Delete Job and Review Results
    • Using the BackgroundSendEmail Message
    • Using the QualifyMembersList Message

The online version of the SDK will be available within a few days, so check back to the Microsoft Dynamics CRM Developer Center later this week.

Microsoft Dynamics CRM Hatalarını Yakalamak

CRM web servisi bir web servisinin doğası gereği soap ile iletişim kurmakta ve işlenen hataları da soap içinde xml ile döndürmektedir.


Microsoft Dynamics CRM Web Servisi'nde Request parametresi kullanılarak bir çağrı yaptığınızda hata olarak System.Web.Services.Protocols.SoapException sınıfından ortak bir hata mesaj yapısı döner.

SoapException'ın Message property'si her zaman için "Server was unable to process request." hatasını döndürür.

SoapException içerisinde Detail property'si oluşmuş olan hata hakkında daha fazla bilgi verecektir. Detail property bir XmlNode türündendir ve InnerXml property aşağıdaki formatta hatayı sunmaktadır.

<error>
<description>Error description goes here.</description>
<code>0xABCD1234</code>
<type>Platform</type>
</error>
 

ErrorCode yani xml içerisindeki Number hexadecimal türündedir. Örnek verecek olursak; eğer veritabanında olmayan bir fax'ı çağırmaya kalkalsanır hata aşağıdaki şekilde olacaktır:

<error>
<code>0x80041103</code>
<description>'Lead' entity doesn't contain attribute with Name = 'name'.</description>
<type>Platform</type>
</error>

Standart bir kodlama mantığında catch bloğunda bu hatayı aşağıdaki şekilde yakalabiliriz.

catch (System.Web.Services.Protocols.SoapException ex)
{
   
Message = ex.Message;
   
Detail = ex.Detail.InnerText;
}

Bu şekilde hatayı öğrenebiliriz ama detaylı ve güzel bir hata mesajı olmaz son kullanıcı için. Tabii burada bu hataları loglayacak bir yapı oluşturabiliriz bu tercihinize kalmış ama her durumda detaya ihtiyacımız var.

CRM'in detaylı hata kod listesine buraya tıklayarak ulaşabilirsiniz.

Hata yapısı ve içeriği hakkında bu bilgileri verdikten sonra bu hataları yakalayacak kodu vermek güzel olacak sanırım :) Aşağıda kodu ve açıklamasını bulabilirsiniz.

 

/// <summary>
///
Hatalari yakaliyoruz.
/// </summary>
/// <param name="ex">System Exception</param>
/// <returns>hatanin detayli aciklamasi</returns>
private string HandleException(Exception ex)
{
   
string Error = "Uygulama bir hata ile karsilasti." + System.Environment.NewLine;
    Error +=
"Message : " + ex.Message + System.Environment.NewLine;
   
if (ex.InnerException != null)
        Error += ex.InnerException.Message + System.
Environment.NewLine;
   

    SoapException
se = ex as SoapException;
   
if (se != null)
    {
        Error +=
"Code : " + GetError(se.Detail, "//code") + System.Environment.NewLine;
        Error +=
"Desription : " + GetError(se.Detail, "//description") + System.Environment.NewLine;
        Error +=
"Type : " + GetError(se.Detail, "//type") + System.Environment.NewLine;
    }
   
return Error;
}

/// <summary>
/// SoapException.Detail icerisindeki hatayi dondurur
/// </summary>
/// <param name="errorInfo">hatayi iceren XmlNode'u.</param>
/// <param name="item">geri dondurulecek hata.</param>
/// <returns>hata detayi ya da bos icerik.</returns>
private string GetError(XmlNode errorInfo,string item)
{
   
XmlNode code = errorInfo.SelectSingleNode(item);
   
if (code != null)
   
    return code.InnerText;
   
else
        return
"";
}
  1. Burada dikkat edilmesi gereken şey hatanın SoapException sınıfı türünden olup olmadığını kontrol ettiğimiz kısım;

        SoapException se = ex as SoapException;

    eğer içerik SoapException türünden ise detayını öğrenmek isityoruz. ( "as" ifadesi hakkında daha fazla bilgi almak için buraya tıklayınız.)
  2. Yukarıda hata durumunda dönecek Xml içeriğini verdim. Bu bir Xml olduğu için XmlNode'larına erişerek istediğimiz bilgiyi alalım. İşte GetError bu işe yarıyor. Soap Exception'ın Detail'ını ve istediğimiz node'u söylüyoruz bize geri dönüyor.

        GetError(se.Detail, "//code")

Bu kod sonucunda elde ettiğimiz hata mesajı;

 

Uygulama bir hata ile karsilasti.
Message : Server was unable to process request.
Code : 0x80041103
Desription : 'Lead' entity doesn't contain attribute with Name = 'name'.
Type : Platform

 

Bir makalemizin daha sonuna geldik umarım faydalı olmuştur.


Barış KANLICA

Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net
forum.cub-e.net

Microsoft Dynamics CRM Web Servisi ve Performans

Benim yazılarımı takip edenler hatırlayacaklardır. Daha önce CRM üzerinde veri sorgulama yöntemleri isimli yazı dizimin 1. bölümü web servislerini kullanarak veri sorgulama yöntemleriydi. O makalede web servisleri hakkında bilgi vermiştim ama şimdi CRM 4.0 çıkınca, CRM 4.0'ın web servisinin ek özelliklerini anlatmak ve performans konularına değinmek istedim.

CRM Web Servisi performans düşüklüğü nedeniyle programcılar tarafından pek sevilmemektedir. Bu makalede sizlere web servisin yapısını ve performans attırıcı bir yöntemlerden bahsedeceğim. Ayrıca CRM 3.0 ve 4.0 arasındaki servis yapısındaki değişikliklere göz atacağız.

WebServis’leri ise bize özellikle veri yazarken büyük kolaylıklar sağlasa da veri okurken bazen karışık olabiliyor. Web Servisleri class(sınıf) mimarisinde olduğundan nesne paylaşımına dayalı bir altyapı sunuyor. Bu doğru kullanıldığında, bize, program yazarken uzun uzun attribute ve property hazırlamak derdinden kurtarıyor.

Microsoft CRM’in 2 adet temel Web Servisi bulunmakta;

  1. CRM Service : istediğiniz entity üzerinde Create(Oluşturma),Update(Güncelleme) , Delete(Silme) gibi işlemleri yapmanızı sağlıyor. Adresi;
    CRM 3.0 : http://<yourservername(:port)>/mscrmservices/2006/crmservice.asmx
    CRM 4.0 : http://<yourservername(:port)>/mscrmservices/2007/crmservice.asmx
    alternatif olarak http://<yourservername(:port)>/MSCRMServices/2007/CrmServiceWsdl.aspx
  2. Metadata Service : CRM’in entity ve picklist mimarisi gibi metadata veritabanında bulunan veriler üzerinde yine Create(Oluşturma),Update(Güncelleme) ,Delete(Silme) gibi işlemleri yapmanızı sağlıyor. Metadata verisi içerisinde bir picklist(yani combobox-dropdownbox)’in içeriği, bir alanın türü gibi sistem üzerinde kullandığımız nesnelere yönelik bilgileri tutmaktadır. Adresi;
    CRM 3.0 : http://<yourservername(:port)>/mscrmservices/2006/metadataservice.asmx
    CRM 4.0 : http://<yourservername(:port)>/mscrmservices/2007/metadataservice.asmx

Web Servisini Projemize Eklemek :



Visual Studio’da açtığımız uygulamamızın adı üzerinde sağ tuşa tıklayarak getirdiğimiz menüde aşağıdaki gibi “Add Web Reference”’a tıklıyoruz.


Açılan pencereye eklemek istediğimiz servisin url’ini yazıyoruz ve “go” düğmesine tıklıyoruz.

Servis credential yani kimlik doğrulamak için bizden kullanıcı adı ve şifre isteyecek. Bunu geçtikten sonra “Web reference name”’e servise verecegimiz ismi yazıyoruz. Burada ben “MyService” ismini veriyorum. “Add Reference” düğmesine tıklıyoruz.Artık servisimizi projemize eklemiş durumdayız.

  1. CRM servisimizin oluşturuyoruz.

            CrmService MyService = new CrmService();

  2. Servise network'te kim olduğumuzu söyleyelim eğer CRM serverın bulunduğu domainde oturum açmadıysak bunu yapmak zorundayız.

            System.Net.
    NetworkCredential MyCredential = new System.Net.NetworkCredential();
            MyCredential.UserName =
    ""
            MyCredential.Password = "";
            MyCredential.Domain =
    "";
            MyService.Url =
    "http:// i p : port/MSCrmServices/2007/CrmService.asmx";
            MyService.Credentials = MyCredential;

    Bu kod ile servise bağlandığımız zaman sistem üzerinde yaptığımız bütün hareketlerde yani güncelleme ve kayıt işlemlerinde burada vereceğiniz kullanıcı adı ve şifrenin ait olduğu kullanıcı created ve modified user olarak gözükecektir. Yani sistemde bizim uygulamamzı kullanan bütün kullanıcıları teke indirmiş olacağız.
    Bunun olmasını istemiyorsak aşağıdaki kodu kullanmamız gerekir;

        MyService.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Bu kod sayesinde IIS üzerinde Integrated Windows Authentication ile oturum açmış olan kullanıcıyı yani CRM'e girmiş olan kullanıcının yetkileri ile işlem yapmış oluruz. Burada hatırlanması gereken en önemli şey uygulamamızın işlem yaptığı entityler üzerinde kullanıcının yetkilerine göre web servisin bize cevap vereceğidir.
  3. işte burası servisi hızlandırdığımız nokta. Nasıl mı oluyor adı üzerinde aslında güvensiz bağlantı paylaşımı yani yukarıda bahsettiğimiz güvenlik yöntemlerinden biri ile IIS üzerinde oturum açan bir kullanıcı olduğu zaman IIS talepte bulunan diğer kullanıcılar için doğrulama yapmıyor yani Kerberos devreye girmiyor Active Directory'e gidilmiyor. Bunlar sonucunda performansta gözle görülür bir artış oluyor.

            MyService.UnsafeAuthenticatedConnectionSharing = true;

    Ama işte burası önemli aması var :) sisteme ilk kim giriş yaparsa IIS o kullanıcı ile devam ettiğinden her işi sanki birinci kullanıcı yapmış gibi görünüyor. CRM'in performansını arttırmakla ilgili daha detaylı makalelere bu linkten ulaşabilirsiniz : Performans Arttırmak
  4. CRM 4.0 bildiğiniz gibi farklı hosting modelleri ile birlikte geliyor. Tabii bu hosting modellerini programatik olarak da kontrol etmek gerek. Artık crm serverine bağlanırken bir AuthenticationToken'a ihtiyacımız var bu olmadan servis bağlantı yapmanıza izin vermeyecektir.
    Token nesnesi içerisinde bulunan AuthenticationType isimli Property 0,1,2 değerlerinden birini almaktadır. Bunların anlamları ise;

    Alan Değer Tanım
    AD 0 Standart Active Directory authentication.
    Passport 1 Passport authentication. Şu an için Amerika ve Kanada'da kullanılacak olan windows live id ile Microsoft tarafından yapılacak olan hostinglerde geçerli olacak.
    Spla 2 Specifies Internet Facing Deployment authentication (formerly known as SPLA). Firmanızının CRM hosting yapacağı zaman kullanacağınız doğrulama biçimi.

    Bütün bunların yanında hosting yapsanız da yapmasanız da kullanmanız gereken bir property var adı OrganizationName. Hangi CRM organization için sisteme giriş yaptığınızın bilgisidir.

            CrmAuthenticationToken token = new CrmAuthenticationToken();
            token.AuthenticationType = 0;
            token.OrganizationName = "CRMVPC";
            MyService.CrmAuthenticationTokenValue = token;

private
CrmService service(bool isUnsafe)
{
   
try
    {
       
CrmService MyService = new CrmService();
       
// servise network'te kim oldugumuzu soyluyoruz. (Eger CRM Server'i ile ayni domainde degilseniz
        // bunu yapmak zorundasiniz yoksa "The request failed with HTTP status 401: Unauthorized." hatasini alirsiniz)
        System.Net.NetworkCredential MyCredential = new System.Net.NetworkCredential();
        MyCredential.UserName =
""
        MyCredential.Password =
"";
        MyCredential.Domain =
"";
        MyService.Url =
"http:// i p : port/MSCrmServices/2007/CrmService.asmx";
        MyService.Credentials = MyCredential;
       
// Eger crm server ile ayni domainde iseniz ve sizin crm'de bir rolunuz varsa asagida parantezler icerisinde
        // belirttigim komutu yukaridaki 5 satir yerine kullanabilirsiniz
        // ( MyService.Credentials = System.Net.CredentialCache.DefaultCredentials; )
       
        // servisi hizlandirmak icin true degerini atiyabiliriz.
        MyService.UnsafeAuthenticatedConnectionSharing = isUnsafe;
       
        ///
CRM 4.0 ile gelenler

        CrmAuthenticationToken token = new CrmAuthenticationToken();
        token.AuthenticationType = 0;

        token.OrganizationName = "CRMVPC";
        MyService.CrmAuthenticationTokenValue = token;

        return
MyService;
    }
    catch (Exception ex)
    {
        HandleException(ex);
        return null;
    }
}

Bir makalemizin daha sonuna geldik.


Barış KANLICA
Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net
forum.cub-e.net   

Update Rollup 3 for Microsoft Dynamics CRM 3.0 (KB 935364) - Türkçe

Microsoft CRM 3.0 Server ve Microsoft Dynamics CRM 3.0 Client for Microsoft Office Outlook için Update Rollup 3'ü (Güncelleme Paketi 3) çıkardığını duyurdu.

Daha detaylı bilgi için aşağıdaki adrese bakabilirsiniz:

http://www.microsoft.com/downloads/details.aspx?displaylang=tr&FamilyID=d5b1fbbe-dfc2-4a33-b5fd-cae99e8e9dab

---

Microsoft has released Update Rollup 3 for Microsoft Dynamics CRM 3.0 Server and Microsoft Dynamics CRM 3.0 client for Microsoft Office Outlook.

For more information about this release, see Microsoft Knowledge Base article 935364:

Update Rollup 3 is available for Microsoft Dynamics CRM 3.0

CRM Üzerinde Null Değerini Kullanmak

Dynamics CRM üzerinde web servisleri ile çalışırken bir değişkene null değerini atamanız gerekebilir. Ama CRM içerinde attribute'lar kendine has olduğundan attribute'a değil onun  IsNull ve IsNullSpecified değerlerine true vermeniz gerekmektedir. Servis bunu arka tarafta veritabanına yazarken o attribute için null vermesi gerektiğini böyle anlamaktadır. Bunu sql ile ifade etmeye kalkarsak;

" update xxx set yyy = null "

demenin yolu CRM'de aşağıda örnekleri verilen şekilde olmalıdır.

( String türü için durum biraz farklı, String.Empty değerini vermeniz gerekmekte.
)

Aşağıdaki kod örneği size tüm attribute'lar için nasıl null değer atanacağını gösterecektir.


CrmDecimal
dec = new CrmDecimal();
dec.IsNull =
true;
dec.IsNullSpecified =
true;

PickList list =
new PickList();
list.IsNull =
true;
list.IsNullSpecified =
true;

CrmFloat
f = new CrmFloat();
f.IsNull =
true;
f.IsNullSpecified =
true;

CrmMoney
money = new CrmMoney();
money.IsNull =
true;
money.IsNullSpecified =
true;

CrmBoolean
boolean = new CrmBoolean();
boolean.IsNull =
true;
boolean.IsNullSpecified =
true;

Owner
owner = new Owner();
owner.IsNull =
true;
owner.IsNullSpecified =
true;

CrmNumber number = new CrmNumber();
number.IsNull =
true;
number.IsNullSpecified =
true;

Lookup
lookup = new Lookup();
lookup.IsNull =
true;
lookup.IsNullSpecified =
true;

Status
status = new Status();
status.IsNull =
true;
status.IsNullSpecified =
true;

Bir makale daha burada biter. Hepiniz hoşçakalın.

Barış KANLICA
Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net

CRM Attribute Tür Sınıfları

Microsoft Dynamics CRM için program yazarken bilinmesi gereken en temel şey CRM'in her entity(tablo) üzerinde bulunan ve kullanılmakta olan bir attribute(özellik) sınıf mimarisine sahip olduğudur. CRM mimarisini kullanarak program yazmak istediğinizde bunları mutlaka kullanmanız gerekmektedir.  Çoğu kişi kullanım konusunda ilk anda hataya düşmektedir. Nedeni ise standart olarak şöyle bir tanımlama yapmaya çalışmalarıdır;

CrmNumber
number = 5;

Fakat bu yanlış bir tanımlama biçimidir. Doğru olan ise;

CrmNumber number = new CrmNumber();
number.Value = 5;


Yani sınıf türetildikten sonra ".Value" kullanılarak değer ataması yapılmalıdır.
Bu noktada çok sık yapılan başka bir yanlışlığa değinmek istiyorum. CRM üzerinde bir veriyi güncellerken doğal güncellemek istediğiniz kaydın ID'sini yani Guid'ini vermeniz gerekmektedir. Sanıyorum sql ile anlatmak daha anlaşılır olacaktır.

update .. set .. xxx = '{7649FD8B-D4D2-DB11-90C4-000423CA2056}'

tarzında bir güncelleme cümlesini servis ile ifade ederken "Key" attribute'unu kullanmamız gerekmektedir.
 
lead _lead = new lead();
......
arada istediğimiz attribute'a yeni değerini atıyoruz.
......
_lead.leadid = new Key();
_lead.leadid.Value = new Guid("{7649FD8B-D4D2-DB11-90C4-000423CA2056}");
.....
Artık Update hangi kayıdı update edeceğini biliyor.
.....
MyService.Update(_lead);

Aşağıdaki tabloda bu sınıfların isimleri verilmiştir.
 

Sınıf Adı Tanım
CrmBoolean boolean.
CrmDateTime date/time.
CrmDecimal decimal.
CrmFloat float.
CrmMoney money.
CrmNumber number ya da integer.
CrmReference Başka bir entity'i referans göstermek için kullanılır. Bu özelliği kullandığınız zaman value ve type atamak zorundasınız.
Customer customer class'ini refere eder. CrmReference classının subclass'ıdır.
EntityNameReference Entity ismi için kullanılır.
Key primary key
Lookup Başka bir entity'i referans gösterir. CrmReference classının subclass'ıdır.
Owner Sahip entitysini referans eder. CrmReference classının subclass'ıdır.
Picklist picklist
Status status
UniqueIdentifier GUID

Aşağıdaki örnek kod bu türlere nasıl değer atayacağınızı göstermektedir. Yanlarındaki değerler öylesine verilmiştir.

CrmBoolean boolean = new CrmBoolean();
boolean.Value =
true;

CrmDateTime
dateTime = new CrmDateTime();
dateTime.Value =
"20080129 00:00:00";

CrmDecimal
dec = new CrmDecimal();
dec.Value = (
decimal)5.5;

CrmFloat
f = new CrmFloat();
f.Value = (
float)5.5;

CrmMoney
money = new CrmMoney();
money.Value = (
decimal)5.00;

CrmNumber
number = new CrmNumber();
number.Value = 5;

Lookup
lookup = new Lookup();
lookup.Value =
new Guid("{7649FD8B-D4D2-DB11-90C4-000423CA2056}");
lookup.type =
EntityName.account.ToString();

Owner
owner = new Owner();
owner.type =
EntityName.systemuser.ToString();
owner.Value = user.UserId;

Picklist
list = new Picklist();
list.Value = 2;

Status
status = new Status();
status.Value = 4;

EntityNameReference
reference = new EntityNameReference();
reference.Value =
EntityName.account.ToString();

Key
key = new Key();
key.Value =
new Guid("{7649FD8B-D4D2-DB11-90C4-000423CA2056}");

Bir makale daha burada biter. Hepiniz hoşçakalın. Web stiemi ziyaret etmeyi unutmayın :-)

Barış KANLICA
Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net