logo Unutmayayım diye yazdıklarım...

Süper Hızlı Web Deployment Tool Kullanımı

19.07.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.

Nedir?

Web Deployment Tool basitçe web sitesnizi IIS üzerinde yüklemenizi, paketlemenizi ve yönetmenizi sağlayan IIS extension'ıdır. Visual Studio 2010'un one-click Publish özelliği ile entegre çalışabilir ve web uygulamalarınızı tek harekette uzak sunucuya gönderip yayınlanmasını sağlayabilirsiniz. Süper!

Gereksinimler?
  •     .NET Framework 2.0 SP1 veya Üzeri
  •     IIS 6.0 ama tavsiye edilmez
  •     IIS 7.0 ve Üzeri.
Kurulum?

  1. Iis.net üzerinden Web Deployment Tool'u indirin => http://www.iis.net/download/webdeploy
  2. Custom Installation'ı seçin.
  3. Remote Service'i seçin ve kurumu bitirin.
Kurulum bittikten sonra Windows Services'e (Services.msc) "msdepsvc" isminde eklenecektir. Çalışıp çalışmadığından emin olun yada "net start msdepsvc" komutunu bilgisayara verin.

Servis çalışmaya başladıktan sonra aşağıdaki adresi örnekleyerek erişebilrisiniz.

    http://DOMAIN/MSDEPLOYAGENTSERVICE
   
    örnek
   
    http://178.18.193.88/MSDEPLOYAGENTSERVICE veya http://oguzhan.info/MSDEPLOYAGENTSERVICE
   
Size kullanıcı adı ve şifre soracatır. Deploy edeceğiniz web sitesinin IIS üzerinde belirtilmiş credantials'ını veya windows local userlarından sitenize erişim hakkı olan kullanıcı bilgisini girebilirsiniz.

VS.NET 2010'da Nasıl Oluyor?
  1. View / Tool Bars / Web One Click Publish tool'unu aktif edin.
  2. Yeni bir Publish profile oluşturun.
  3. Publish method olarak "Web Deploy" seçin. (FPSE seçeneği ile göndermeyi denemyin yoksa FrontPage extensionları için bir kaç takla atmanız gerekiyor)
  4. Service URL : http://DOMAIN/MSDEPLOYAGENTSERVICE gibi bir şey.
  5. Site/Application : site ismini girmeniz yeterli veya IIS'te oluşturduğunuz Application ismi
  6. Site için tanımladığınız Windows Local User veya IIS User olmadı Administrator hesabını girin.
Her şey yolundaysa direkt çalışır ve hızlıca web sitenizi IIS üzerine paketleyip gönderir.

Daha fazla hareket:


absmiddle Yorum

ReportViewer ve Reporting Services R2

15.07.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.

Projenin raporlama evrensini çok seviyorum, çünkü yazdığınız programın ne kadar işe yaradığını, neler yapabildiğini ve hatta neleri eksik yaptığını görebilmenizi sağlıyoru. Birde teknik işin çoğu drag&drop olduğu için biraz daha eğlenceli geliyor. Yine bir e-ticaret projesinin raporlama evresinde bir kaç sorunla karşılatık ve nasıl aştığımızı hatta bir tanesini aşamadığımızı paylaşmak istiyorum.

Report Builder 3.0'ın ve SQL Server 2008 R2'nin piyasaya çıkmasından doğal olarak gaza gelip raporlarımızı Reporting Services R2 üzerinden yayınlamaya ve oluşturmaya karar verdik.

Report Builder 3.0 çok kolay kullanılabilen ve hazırladığınız raporu direkt sunucuya göndermenizi sağlayan özelliklerle donatılmış. Raporlarınızı hemen oluşturup sunucuya gönderip servis üzerinden ister Web ister Windows Ugulamalarında kullanabiliyorsunuz. Müthiş rahatlık! ama bir kaç problem var.

Raporlarımızı oluşturup yayına hazır hale getirdikten sonra sıra kendi sistemimize implemente etmeye geldi .Net'in native kontrollerinden ReportViewer'ı kullanarak işe başladık. Karşımıza çıkan ilk sorun sunucudaki rapor'a ulaşırken Reporting Services'in kimlik doğrulama istemesiydi (Gerçi bunu kaldırabiliyorsunuz ama güvenlik nedeni ile pek yanaşmadık). ReportViewer kontorolünün içindeki "ServerReport.ReportServerCredentials" özelliğini kullanarak bu sorunu hallettik ama bunun için aşağıdaki kendi sınıfımızı hazırlamamız gerektir.

using System.Net;
using System.Security.Principal;
using Microsoft.Reporting.WebForms;

public class ReportServerCredentials : IReportServerCredentials
{
private string _username;
private string _password;
private string _domain;

public ReportServerCredentials(string UserName, string Password, string Domain)
{
_username = UserName;
_password = Password;
_domain = Domain;
}

public bool GetFormsCredentials(out Cookie authCookie, out string user, out string password, out string authority)
{

authCookie = null;
user = password = authority = null;

return false;
}

public WindowsIdentity ImpersonationUser
{
get
{
return null;
}
}

public ICredentials NetworkCredentials
{
get
{
return new NetworkCredential(_username, _password, _domain);
}
}
}


Aslında çok bir şey yok IReportServerCredentials Interface'ini implemente edip gerekli boşlukları doldurmanız yeterli. Bu class'ı kullanarak aşağıdaki şekilde ReportViewer'ın sunucudaki Repor'a erişmesini sağaladık.

ReportViewer1.ServerReport.ReportServerCredentials = new ReportServerCredentials("user","pass","domain");

Bu sayede kullanıcının herhangi bir şifre girmesine gerek kalmadan rapor'u görmesini sağlayabildik.
Akabinde karşımıza çıkan başka bir sorunda SQL Server 2008 R2 ile gelen Reporting Services'in raporları yayınlamak için kullandığı ReportViewer kontrolünün versionu oldu. Reporting Services'in kullandığı kontrolün versionu 10.50.1600.1 fakat VS.NET 2010 ile gelen ReportViewer kontrolünün versionu 10.0.0.0'dı böyle olunca bazı yeniliklerden faydalanamıyorsunuz ve raportunuzdaki ileri, geri, arama ve yeni çıkan "Export to Data Feed" butonu çalşmıyordu biraz uğraşıp Reporting Services'deki kontrolleri local projemde çalıştırmayı denedim fakat fazla zamanımız olmadığından vaz geçtik ve bir sonraki refactoring'e bıraktık.

Burdan çıkabilecek ufak bir ipucu vermek gerekirse. Reporting Services'i çalıştığı dizin : C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer şeklindeydi. Şimdilik direkt sunucu üzerinden raporları çağırıyoruz. Sanırım VS.NET 2010'un SP1'i ile ReportViewer kontrolünün versionu 10.50.1600.1'e yükselir ve direkt projemize implemente edebiliriz.

Not: Report Builder 3.0 aracı sadece SQL Server R2 ile gelen Reporting Services ile entegre çalışabiliyor. Reporting Services'ın içinden çıkıyor setup'ı ama yinede burdan çekebilirsiniz.

absmiddle Yorum

iOS 4 Yenilikleri

22.06.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.

Iphone'u 4.0'a upgrade ederken önüme aşağıdaki döküman çıktı neler yeni diye  merak edenler için paylaşayım dedim.

  • Üçüncü parti uygulamalar için çoklu görev desteği*
    • Uygulamalar arasında hızlı bir şekilde geçiş yapmak için çoklu görev kullanıcı arayüzü
    • Ses uygulamalarını arkaplanda çalma desteği
    • VoIP uygulamaları arkaplanda veya aygıt uyku durumundayken aramaları alabilir ve sürdürebilir
    • Uygulamalar konumu izleyebilir ve arkaplanda çalışırken işlem yapabilir
    • Uyarılar ve mesajlar, anında ilet bildirimleri ve yerel bildirimler kullanılarak uygulamalara anında iletilebilir
    • Uygulamalar görevleri arkaplanda tamamlayabilir
  • Uygulamaları daha iyi düzenlemek ve onlara erişmek için klasörler
  • Ana ekran duvar kağıdı*
  • Mail iyileştirmeleri
    • Tüm hesaplardaki e-postaları tek bir yerde görüntülemek için birleştirilmiş gelen kutusu
    • Farklı e-posta hesapları arasında hızlı bir şekilde geçiş yapmak için hızlı gelen kutusu değişimi
    • Aynı yazışmadaki birden fazla e-postayı görüntülemek için konularına göre gruplandırılmış iletiler
    • İlişikler, uyumlu üçüncü parti uygulamalarla açılabilir
    • Arama sonuçları artık dosyalanabilir veya silinebilir
    • Fotoğraf ilişiklerinin boyutunu seçme seçeneği
    • Giden Kutusu'ndaki iletiler düzenlenebilir veya silinebilir
  • iBooks ve iBookstore desteği (App Store'da bulunur) 
  • Fotoğraf ve Kamera iyileştirmeleri
    • Fotoğraf çekerken 5x sayısal büyütme**
    • Video kaydı sırasında odaklamak için dokunma**
    • Yüzleri iPhoto'dan eşzamanlayarak aktarabilme
    • Coğrafi etiketli fotoğraflar, Fotoğraflar'daki bir haritada görünür
  • Aygıtta liste yaratabilme ve düzenleyebilme
  • Takvim davetleri, desteklenen CalDAV sunucularla kablosuz olarak gönderilebilir ve kabul edilebilir
  • MobileMe takvimi paylaşma desteği
  • Web'de arama sırasında öneriler ve son yapılan aramalar görünür
  • Aranabilir SMS/MMS mesajları**
  • Spotlight araması Web üzerinde ve Wikipedia'da sürdürülebilir
  • Geliştirilmiş konum gizliliği
    • Durum çubuğunda yeni Konum Servisleri simgesi
    • Son 24 saatte konumunuzu isteyen uygulamaların belirtimi
    • Konum Servisleri, uygulamalar için ayrı ayrı açılabilir veya kapatılabilir
  • Otomatik yazım denetimi
  • Bluetooth klavye desteği*
  • Uyumlu arabalardaki iPod arayüzü yoluyla müzikler, podcast'ler ve sesli kitaplar arasında dolaşmak için iPod çıkışı
  • Uygulamaları iTunes yoluyla hediye etme desteği
  • Notları, IMAP tabanlı posta hesaplarıyla kablosuz olarak eşzamanlama
  • Anında ilet bildirimlerini almak için sürekli WiFi bağlantısı*
  • Yalnızca hücresel veriyi açmak/kapatmak için yeni ayar**
  • Yeni SMS/MMS oluştururken karakter sayısını görüntüleme seçeneği**
  • Visual Voicemail mesajları sunucudan silinmiş olsa bile yerel olarak tutulabilir**
  • Düşey yöne kilitleme denetimi*
  • iPod ve üçüncü parti ses uygulamaları için ses çalma denetimleri*
  • Yeni diller, sözlükler ve klavyeler
  • Erişilebilirlik geliştirmeleri*
  • Bluetooth iyileştirmeleri
  • Aygıt parolasını şifreleme anahtarı olarak kullanarak daha iyi veri koruma* (Tam geri yükleme gerektirir.)
  • Üçüncü parti Mobil Aygıt Yönetimi çözümleri desteği
  • Kurumsal uygulamaların kablosuz olarak dağıtılmasını etkinleştirir
  • Exchange Server 2010 uyumluluğu
  • Birden fazla Exchange ActiveSync hesabı desteği
  • Juniper Junos Pulse ve Cisco AnyConnect SSL VPN uygulamaları desteği (App Store'da bulunur)
  • Geliştiriciler için 1500'den fazla yeni API
  • Hata düzeltmeleri

Bu yazılım güncellemeyle uyumlu ürünler:
  • iPhone 3G
  • iPhone 3GS
  • iPhone 4
  • iPod touch 2. nesil
  • iPod touch 3. nesil (2009 sonlarında çıkan 32 GB veya 64 GB modelleri)

* iPhone 3GS, iPhone 4 veya iPod touch 3. nesil gerektirir.
** iPhone 3G, iPhone 3GS veya iPhone 4 gerektirir. SMS/MMS mesajlaşmayı ve Visual Voicemail’i kablosuz iletişim operatörünüzün desteklemesi gerekir.


absmiddle Yorum

Özellik Manyağı Olmayın

05.06.2010 tarihinde yazıldıktan sonra, 2 kişi yorum yazmış.

Daha önce bir çok kez uzaktan gözlem yaparak keşfettiğim ve teorik olarak bildiğim bir kavramın işleyişini gerçekten içinde yaşayarak deneyimledim.

Proje aslında ufak bir micro-site projesiydi (vargonenvds.com) burdan vargonen olarak virtual dedicated server satmaya karar verdik ve projelendirmeye başladık.

Projenin istediğimiz gibi işlemesi için gerekli olacak özellikler ne olmalıydı? Hangi özellikler olursa hem müşterinin hemde bizim ihtiyaçlarımızı en doğru ve hızlı şekilde karşılardı? gibi soruları Development Takımı (ben), ScrumMaster (Bu yine ben) ve Product Owner (Ali Vargonen) ile tartışıp cevaplarını bulmaya çalıştık.

Toplantı sonucunda önümüzde 28 maddelik bir liste vardı ve hepsini bitirmek 15 günümüzü alacaktı (karşımıza en başta düşünemediğimiz ve gerekli olacak bir sürü özellik daha çıkacak tabiki).
Projeyi tasarlayıp kodlama aşamasına geçtikten sonra 28 maddelik base listemize bir 12 madde daha eklendi ve 40 madde oldu, ürün özelliklerimiz giderek artıyordu ve buna bir yerde dur demek gerekiyordu çünkü ürüne her yeni özellik eklendiğinde yayınlama tarihimizide ertelemek zorunda kalıyorduk ve böylece bir refleks olarak Release Backlog oluşturmaya karar verdik.

Ürünün istediğimiz işi yapabilmesi için minimum özellikleri belirledikten sonra diğer özelliklerin hepsini bir kerana attık, hatta üründe olmazsa olmaz "kredi kartı ile tahsilat" özelliğini bile release backlog'umuz içine almadık.
En nihayetinde ürünümüzü minimum özelliklerle yayınlayıp duyuyrularını yaptık ve merakla siparişlerin gelmesini bekledik :)

Sonuç Olarak;

  • Ürün minimum özelliklerde umduğumuzdan daha iyi yorumlar ve geribildirimler aldı.
  • Yapılan geribildirimlerle front-end ve back-end 'de ki bug'ları kısa sürede belirleyip düzelttik.
  • Ürün "İndirim" ve "Kredi Kartı Tahsilat" özelliği olmadan 12 adet VDS siparişi aldık ve ücretlerini tahsil ettik.
  • Bu geçen zamanda, diğer önemli özellikleri ekledik.
  • Bu geçen zamanda bizim daha önce düşünemediğimiz ihtiyaçları gördük ve "Product Backlog"'umuza ekledik.

..Ve böylece bilinen bir gerçeği farkında olmadan tekrardan kanıtlayıp "haa demek bundan dolayı insanlar yazılım geliştirme süreçlerini oluşturmuşlar" gibi sözlerle saçmaladık.

fakat biz ilk belirlediğimiz özellikleri bitirip ürünü piyasaya 25 gün sonra çıkarsaydık ne sipariş alabilirdik, ne daha kararlı bir sistemimiz olurdu nede şimdi insanlar bu servisten yararlanıyor olurdu. Bu yazının konusunda daha karamsar ve isyankar olmuş olurdu.

Alaka:
http://www.vargonenvds.com
http://en.wikipedia.org/wiki/Scrum_%28development%29



absmiddle Yorum

C# da ki Action.Action(void () target)

02.05.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.

Her geçegün .Net Framework bataklığında daha da derinlere batıyoruz :) İhtiyaçlar gün geçtikce değişiyor ve buna bağlı olarak developer'ında program yazma şekli, ihtyaçları değişiklik gösteriyor en son developer ihtiyaçlarına göre de .Net Framework değişiyor, gelişiyor. İşle bu arz-talep zincirinden çıkmış güzel bir tip daha Action Delegate.

Action .NET 3.0 ile birlikte developer'ın hayatına girmiş çok kullanışlı ve güclü bir delegate'tir. Genelde void tipindeki method'larla kullanılır ve geri dönüş değerini geriye döndürmez.
Ben genelde Collection nesnelerinde ForEach() methodunda kullanıyordum ama aşağıdaki gibi seksi yerlerde'de kullanma fırsatı buldum.

Not: Action'ın benzeri ve geriye değer döndüren delegate arıyorsanız Func Delegate'ine bakabilirsiniz => http://msdn.microsoft.com/en-us/library/bb534960.aspx

Action'ın ne olduğu zaten bir çok sitede yazıyor. Benim aktarmak istediğim nokta ise kullanım çeşitleri.

Hemen kod'a zıplayalım :

Örneğin bir hesap makinesı yapmaya kalkalım ve tasarlarkende Action delegate'ini kullanalım. Bir hesap makinasında bir çok fonksiyon vardır.
Kimi fonksiyonlar tek parametre alır, kimisi çift, kimisi belirsiz sayıda parametre alır yani Signature'ları farklıdır. Action burda yardımımıza koşuyor ve burdaki kod yönetim sıkıntısını aşmamızı sağlıyor.
class Islemler
{
public void Topla(int X, int Y)
{
Console.WriteLine("Toplama İşlemi: {0}", X + Y);
}

public void Cikar(int X, int Y)
{
Console.WriteLine("Çıkarma İşlemi: {0}", X - Y);
}

public void Karekok(double X)
{
Console.WriteLine("Kare Kök İşlemi: {0:N2}", Math.Sqrt(X));
}
}

static void Main(string[] args)
{
Islemler islem = new Islemler();

Action action = delegate() { islem.Cikar(10, 5); };
action();

action = delegate() { islem.Karekok(10d); };
action();

action = delegate() { islem.Topla(15,15); };
action();
}
Hesapmakinesinin fonksiyonlarının tanımlı olduğu Islemler sınıfının method'larını Action delegate'imize tanımladık. Burda yine .NET 3.0 ile gelen Anonymous delegate'lerden faydalandık. Örnek çok etkil olmadı ama en azından kullanımı ve ne işe yaradığı konusunda bilgi veriyor. Sonuçta farklı isimlerde ve farklı signature'da methodları tek bir delegate ile çalıştırabiliyoruz. Action'a method tanımlamasını Lambda kullanarak aşağıdaki şekilde de yapabiliyoruz ve hatta yazının sonuna doğru biraz daha değişik syntax'ta Action tanımlaması yaptım.
Islemler islem = new Islemler();

Action action = () => islem.Cikar(10, 5);
action();
Şimdi biraz daha seksi bir senaryo ele alalım. Örneğin: Birçok method'unuzun içerisinde hep aynı pattern'i kullanacaksınız. Tüm methodlarınız farklı işler yapacak, farklı tipten ve farklı sayıda parametreler alıyor olacak. Bu methodlarınız içinde hep aynı işlem kalıbını (pattern'ini veya rutini) kullanmanız gerektiğini varsayalım. Bu methodların her birine ayrı ayrı belirlediğiniz pattern'i yazmak yerine Action delegate'ini kullanarak global bir method üzerinden pattern'i belirleyip methodlarımızı çağırabiliriz. Yine işlemler sınıfımız üzerinden örnek vermek gerekirse :
class Islemler
{
public void Topla(int X, int Y)
{
Console.WriteLine("Toplama İşlemi: {0}", X + Y);
}

public void Cikar(int X, int Y)
{
Console.WriteLine("Çıkarma İşlemi: {0}", X - Y);
}

public void Karekok(double X)
{
Console.WriteLine("Kare Kök İşlemi: {0:N2}", Math.Sqrt(X));
}
}

static void Main(string[] args)
{

Islemler islem = new Islemler();
Exception ex = null;
var action = new Action(() => islem.Cikar(10, 10)); //Syntax'ı bu şekilde de olabiliyor ;)
bool state = GlobalInvoker(action, out ex);

if (state)
Console.WriteLine("Gerçekleşti");
else
Console.WriteLine("Gerçekleşmedi: {0}", ex.Message);
}


static bool GlobalInvoker(Action action, out Exception ex)
{
bool cstate = true;

try
{
action();
ex = null;
}
catch (Exception e)
{
ex = e;
cstate = false;
}

return cstate;
}
İşte gördüğünüz gibi GlobalInvoker methodunun içindeki tek bir desen ile tüm methodların düzgün çalışıp, çalışmadığını anladık ve hatta çalışmıyorsa debug için Exception'ımızı da sakladık.

Normalde Action delegate'ini kullanmasaydık tüm method'larımız bool değer döndürecekti ve hepsinde try-cacht blog'u kullanacaktık. Buda ek kod yazmamıza ve tabiki ek zamana mal olacaktı. Birde bu class'ın 100 kadar method'u olduğunu düşünün!! Abov!


absmiddle Yorum

SHOUTcast için ufak bir ipucu.

28.03.2010 tarihinde yazıldıktan sonra, 2 kişi yorum yazmış.

Power grubun yayınlarını yaptığımız için sık sık SHOUTcast, Wowza ve Windows Media Server  gibi streaming yapan sunucularla muhatap oluyoruz. Sunucular da ki ve radyolar da ki genel durumu görmek ve bazı bilgileri toplamak için ufak çapta bir uygulama hazırlamaya karar verdik. Bizim için en önemli veri'de radyo'nun anlık dinleyici sayısıydı.

Wowza'nın ve Windows Media'nin anlık user durumuna kolayca erişebildim fakat SHOUTcast'in anlık kullanıcı durumuna erişmek o kadar da kolay olmadı.
Bu işi yaptıracak external bir tool yazmak içinde her zamanki gibi zaman yoktu. Onun için SHOUTcast 'ın web sayfasına bağlanıp basit bir HttpRequest nesnesi ile işi halledebilirim diye düşündüm.

Fakat SHOUTcast 'ın Web server'ı belirli standartlara göre tasarlanmadığı için çeşitli hatarlarla karşılatım

birinci kronik hata:

"The server committed a protocol violation. Section=ResponseStatusLine"

Bu sorunun nedeni .Net Framework'ün security anlayışı ile alakalıymış .Net 2.0'dan sonra useUnsafeHeaderParsing diye bir config ayarı koymuşlar. Bunla developer'ın bilerek saçma header'lar almasını sağlamışlar.
Aşağıdaki ayarı yaptıktan sonra bu hatayı atladım.
xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing = "true"/>
settings>
system.net>
configuration>

ikinci kronik hata:

Stream oluşturup GetRequestStream() ile bellek'e yerleştirdiğim zamanda Stream'in bilmediğim bazı şeyleri desteklememesinden dolayı aşağıdaki hata ile karşılaştım.

"Cannot send a content-body with this verb-type"

Daha sonra Request'i GetResponse() ile HttpWebResponse'u alıp onunda GetResponseStream() metodunu StreamReader'a alınca (burdaki Stream o bilmediğim bazı şeyleri destekliyormuş sanırım).
Bu sorunuda geçtik ve o güzelim SHOUTcast HTML'sini parse etmek için string nesneme aldım.

Sonuç olarak aşağıda ki kod ortaya çıktı.
        static string SHOUTcastHtml(string uri)
{
String html_data = String.Empty;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "GET";
request.ContentType = "text/html";
request.Headers.Clear(); // Default header'larýn temizlenmesi gerekiyor.
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 (.NET CLR 3.5.30729)";

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader s_stream = new StreamReader(response.GetResponseStream()))
{
html_data = s_stream.ReadToEnd();
}
response.Close();

return html_data;
}
Bir gün SHOUTcast bilgilerine ihtiyacınız olursa kullanabilirsiniz.

absmiddle Yorum

Bankaların sanal pos hizmetleri sandığınız kadar stabil değil.

07.03.2010 tarihinde yazıldıktan sonra, 3 kişi yorum yazmış.

Goldmaster firması için yaptığımız bayi tahsilat sistemini nihayet bitirdik ve bayilerin kullanımına açtık. Her projede olduğu gibi bu porjede'de öngörülemeyen sorunlar hemen kendini gösterdi.

Bu sorunlardan en önemlisi sistemin bankalarla haberleşen modülü ile ilgiliydi.
Sistemi kullanıma açtıktan sonra tahminimden fazla sanal pos transaction'ı gerçekleşmeye başladı ve sıklıkla "operation time-out" hataları ile karşılaşır oldum.

İşlemi debug edip simule ettiğimde ise bankanın sanal pos API'lerine erişim kurarken kullandığım HttpRequest sınıfının time out özelliğinin süresini 8 saniye verdiğimden kaynaklandığnı gördüm ve http isteğinin zaman aşım süresini 15 saniye olarak yeniden düzenledim ve publish ettim.
Sonuç, "Operation Time-out" hataları gözle görülecek şekilde azaldı fakat yinede işlemlerin %5'i time-out'a düşüyordu. Durumdan sıkılıp sanal pos modülün muhatap olduğu tüm sanal pos Uri'lerini monitor etmeye başladım.
Monitor'u şirket içinde kullandığımız PRTG programına devrettim. Bir kaçgün http üzerinden tüm web serverları geriye döndürdükleri cevap sürelerine göre izledim ve çok stabil olmayan bir tablo ile karşılaştım.

Bankaların sanal pos hizmeti verdikleri sunucuları gün içinde bir çok kez ya erişilemiyordu yada olağan dışı erişim süreleri ile hizmet vermeye çalışıyorlardı. Aksi daha detaylı incelemelerimde ise çok önemli bir sorunla karşılaştım. Şöyle ki;

Sanal Pos modülüm bankaya "parayı çek" emri gönderdikten sonra banka emri alıp işliyor fakat bana çok geç cevap verdiği için veya web sunucusunda ki anlık kesintilerden dolayı herhangi bir cevap dönemiyordu.
Böyle olunca işlemi banka gerçekleştiriyor ve müşterinin kredi kartından para çekiyor fakat bizim sistemin haberi olmuyordu! arkasından sistem müşteriye para çekilemedi hatası döndürüyordu. Nedeni de "Operation time-out"!

Konu ile ilgili bir kaç banka ile görüştüm. Durumu açıkladığımda hepsi bana cross-check yapabilirsiniz dedi. Yani gün sonunda bendeki ve bankada ki kayıtları karşılaştırıp farklıları bulduktan sonra sisteme ekleyeceğim?
Bunun işime yaramayacağını anlatım çünkü müşteriye işlemin sonucu kesin olarak işlem sonunda anlık bildirmem gerekiyordu. "Time-out exeption'ına düştüğümüzde kullanabileceğimiz bir validasyon yönteminiz var mı?" diye sorduğumda. Bu durum için geliştirdikleri bir tasarımlarının olmadıklarını söylediler.

Bana çok ilginç geldi... Böyle bir sorun varsa, bu kadar teknolojik bankaların bu sorunu bu zamana kadar çözebilmiş olduklarını düşünürdüm hep.
Halbuki işlemin doğrulamasını farklı bir sunucudan yaptırabilirlerdi veya başka sunucu benim sunucuma bir http post geçebilirdi (Paypal bunu yapıyor)
Bunun için sanal pos hizmetlerine ek ücret bile ekleyebilirlerdi ama hala bir çözüm üretemediklerine göre kredi kartı faizlerinden çok para kazandıklarından olsa gerek para saymaktan böyle şeyleri düşünecek vakitleri yok sanırım.

Sonuçta banka Uri'lerini izlemeyi 31 gün boyunca sürdürdüm ve sonuç olarak aşağıdaki gibi bir tablo çıktı karşıma.

Sanal Pos Uptime Süreleri


Tabloyu yorumlayacak olursak;

İlk üç bankanın downtime süreleri kabul edilebilir nitelikte olduğunu düşünüyorum. Bir saatin üzerindeki downtime oranları insanı biraz düşündürüyor. Fakat 8 saat ve üzeri kesinti ile hizmet veren bankalardan kesinlikle uzak durulması gerekiyor diye düşünüyorum.

Farklı bir yönden bakarsak olaya  bankaların Uptime'ları (Sürekli Açık Kalma Durumları) %97'nin üzerinde. Doğru kulağa çok yüksek bir rakam geliyor ama %97.91 ile en berbat uptime süresine sahip Deniz Bank bile 31 günde 15 saat 58 dakika  15 saniye kapalı kalmış. Bu çok kabul edilebilir dir durum değil. Tabi bütün suçu bankaya yüklememek gerekiyor bağlı oldukları internet servis sağlayıcısının çeşitli ağ problemleride neden olmuş olabilir ama bunların hepsi günümüzde çözülmü olan problemler.

30 günlük izlemeye göre Türkiye'de en stabil ve hızlı sanal pos hizmetini Yapı Kredi bankası veriyor. Sana Pos API'lerininde kod tarafından yönetilebilir ve kolay entegre edilebilir olduğu düşüncesindeyim.

Yapı Kredi'nin 30 günlük http grafiği aşağıdaki gibi. En yüksek erişim süresi olarak 1.413ms görünüyor, en düşük 14ms. (Bu web server'ın client'a cevap verdiği süredir.)



Tabi en iyi bankayı söyledik. En berbat bankayıda söylemeden geçmeyelim.
Deniz Bank'ın sanal pos hizmeti gerçekten berbat. Umarım bu durumu en kısa sürede düzeltirler ve insanlardan aldıkları paraların hakkını verirler.

Aşağıdaki grafikte'de görüldüğü gibi kapalı olmadığı zamanlarda web server'ın cevap verme süresi 7.445 milisaniye'ye kadar çıkmış en iyi cevap verme süresi ise 37 milisaniye, bu zaten diğer bankaların ortalama rakamı. :)



Ek olarak bankaların sanal pos hizmeti verdikleri web serverların kapalı olmadıkları zamanda cevap verme sürelerininde daha iyi olduğu düşünülebilir ama o kadarda iyi değil. Aşağıdaki grafik tüm bankaları grupladığından çok anlaşılır değil ama yinede istek ve yüzde olarak fikir verebilir.



Sonuç olarak bu 30 günlük verilere göre'de konuşmak doğru olmaz ama duruma şöyle bir anlık bakış attığımızı düşünürsek dikkat çekici bir husus.
Daha farklı raporlar almakta mümkün ama benim ilgilendiklerim bunlardı. İlgilenen olursa XML veri dosyalarını gönderebilirim, zaman bazlı daha ayrıntılı raporlarda alınabilir.


absmiddle Yorum

Logo Unity API'de SqlClause Kullanımı

14.01.2010 tarihinde yazıldıktan sonra, 5 kişi yorum yazmış.

Daha önce yazmış odluğum Logo API' ile ilgili yazıyı referans göstererek yazılmış bir çok e-posta alıyorum. Genelde e-posta içeriği SqlClause kullanımı ile alakalı olduğu için genel bir örnek yapıp burdan paylaşayım dedim.

Senaryomuz şöyle;

Logo üzerindeki bir carinin logo üzerindeki kodu ve ismini getiren bir sorgu yazmak istiyoruz. Bunun için de Logo api'sinde ki veritabanını bozmamak ve stabil, iyi sorgular oluşturmak için tasarlanmış SqlClause sorgu sınıfını kullanacağız. Bu sınıf'ı kullanarak yazdığınız sorgular kesinlikle logo'nun seveceği sorgular olup, sistem üzerinde herhangi bir probleme neden olmaz, kendileride zaten bu yöntemi öneriyorlar.

"Unity Object kullanıcılara query yazmak için IQuery nesnesini sağlamıştır. IQuery nesnesi ile Select tipindeki queryleri çalıştırmak hem çok kolay hemde çok hızlıdır. Querylerle veri ilişkisini bozabileceğinden insert, update veya delete tipindeki queryleri çalıştırma tavsiye edilmez, fakat IQuery nesnesi bu tür queryleri çalıştırmanızada izin verecektir.

 

IQuery nesnesini kullanarak iki şekilde SQL cümleleri oluşturabiliriz. İlk yöntem SQL cümlesini direct olarak Statement özelliğine geçip OpenDirect veya Execute metodlarıyla çalıştırmak veya SQL Clause'lar yardımıyla oluşturmak. Statement özelliğini kullanarak SQL cümlelerini oluşturursak veri tabanına bağımlı hale geliriz. MS SQL Server için yazdığımız bir sorgu ORACLE veya LBS UNITY programının desteklediği başka bir sunucuda çalışmayabilir. Veri tabanına bağımlılığı ortadan kaldırmak için SQL Clause'lar oluşturulmuştur. Clause'lar yardımıyla sorgumuzun belli kısımlarını tanımlar, sorgunun birleştirilme kısmını UnityObject'e bırakırız. UnityObject tanımlarımızı alır, UConfig programımızda belirtiğimiz veritabanı formatına kendisi çevirir. Clauseları kullanmak biraz işyükü getirmekle beraber veritabanı bağımlılığını ortadan kaldırır. Tanımladığınız sorgular LBS Unity programının desteklediği ve ilerde destekleyebileceği ortamlara ek bir işlem yapmanıza gerek kalmadan sorunsuz çevrilip çalıştırılacaktır"

Gelelim kod örneğine;

Ben .Net üzerinde C# kullanarak bir console uygulaması olarak geliştirdim.

    class Program
    {
        static void Main(string[] args)
        {
            ARP_List();
        }

        static void ARP_List()
        {
            bool eof = false;

            //COM bileşeni referansı oluşturuluyor
            UnityApplication unity = new UnityApplication();
            if (unity.Connect())
            {
                // Logo kullanıcısı ile giriş yapılıyor
                if (unity.UserLogin("LOGO_KULLANICISI", "SIFRE"))
                {
                    // Hangi firma üzerinde işlem yapılacağı "firma no" ile belirleniyor.
                    if (unity.CompanyLogin(310))
                    {
                        //Yeni bir sql sorgusu çalıştırmak istediğimizi belirtiyoruz.                       
                        Query qr = unity.NewQuery();                       

                        // Gerekli olan alanları (field) SelectClause ile belirtiyoruz.
                        qr.SQLClause.SelectClause.New("A.CODE", "code");
                        qr.SQLClause.SelectClause.New("A.DEFINITION_", "def");

                        // Hangi tablo ile veri işleyeceğimizi belirtiyoruz.
                        qr.SQLClause.FromClause.NewTable("LG_310_CLCARD", "A");

                        // Sorgumuzun kriterlerini belirtiyoruz.
                        // Burda CODE'u 100'e eşit olan firmalar listeleniyor.
                        qr.SQLClause.WhereClause.New("A.CODE", RelationalOperator.roEqual, "100", LogicalOperator.loNone);

                        //SQLClause ile oluşturulan sorgunun çıktısı Statement özelliğine atanıyor.
                        qr.Statement = qr.SQLClause.SQL;

                        // Sorguyu çalıştırıyoruz.
                        if (qr.OpenDirect())
                        {                           
                            eof = qr.First(); //İlk kayıt isteniyor. Yoksa false döner;

                            //First(); ile alınan ilk kayıt bilgisi okunuyor.
                            while (eof)
                            {
                                Console.WriteLine("{0}\t{1}", qr.QueryFields[0].Value,
                                    qr.QueryFields[1].Value);

                                eof = qr.Next(); // Sonraki kayıt isteniyor. Yoksa false döner;
                            }
                        }

                        qr.Close(); // Sorgumuzu kapatıyoruz.
                    }
                    unity.CompanyLogout();
                }
                unity.UserLogout();
            }
            unity.Disconnect();
        }       
    }

Açıklamaları kodun içine yazdığım için tekrardan açıklamak gereği duymadım.

Umarım yardımcı olur...


absmiddle Yorum

Struct'dan haberdar olmanız yetmez, kullanmanız gerekir

11.01.2010 tarihinde yazıldıktan sonra, 0 kişi yorum yazmış.

Yazılım geliştirirken bizi sırtlayan programlama çatısının özelliklerini tek tek ve çok ayrıntılı bilmemiz her zaman mümkün olmuyor, fakat bazı özellikler var ki hem geliştirilen programın kalitesini, hem de performansını büyük ölçüde etkileyebiliyor. Bu etkiyi C# programlama dilinde yaratabilecek özelliklerden bir tanesi de Struct (Yapı) veri tipidir ve konuda budur.

Bilindiği gibi Struct ile yapılabilen her işlemi ve daha fazlasını Class ilede yapılabiliyor. Peki neden Struct kullanalım? diye sorabilirsiniz. Aşağıda bu sorunun cevabını kendi tecrübelerime dayanarak vermeye çalıştım.

  • Struct bir değer türü olduğu için oluşturulduğunda Stack bellek bölgesinde tutulur. Stack bellek bölgesinde yeni bir nesne tanımlamak ve nesneye erişmek, class'ların tutulduğu Heap bölgesinden daha hızlıdır.
  • Programın struct nesnesi ile işi bittiğinde Garbage Collector anında devreye girip lazım olmayan struct nesnelerini temizler. Böylece siz programcı olarak bu kaynağı işi bitti diye tekrar serbest bırakmak zorunda kalmazsınız.
  • Algoritmanızda Birden fazla değişkeniniz varsa bunları tek tek yönetmek yerine Struct ile bu değişkenleri tek bir veritipi haline getirebilirsiniz.
  • Ben OOP'nin tüm nimetlerinden yararlanmak istiyorum ama struct kadar performanslı da olsun diyorsanız yine struct içinde method, constructor, değişken ve indexleyici kullanabilrisiniz.
  • Struct, aynı class gibi private, public, internal, protected, protected internal değerlerini alabilir.
  • Struct'lar İçiçe tanımlanabilir (Nested Structure) hemde çok zevkli olur.

Tabi Struct'ı her zaman kullanacağız diye bir şey yok, sadece işimize geldiği zaman kullanalım. Bazı durumlarda da aşağıdaki nedenlerden dolayı hiç kullanmamalıyız.

  • Struct'lar bir birlerinden türeyemez (Inheritance) ama birden fazla Interface'den türeyebilir.
  • Struct'lar da yapıcı (Constructor) method varsayılan olarak parametresizdir ama yinede siz kendi parametrik yapıcı metodlarınızı tanımlamayabilirsiniz. Herhalükarda varsayılan yapıcı metod çalışacaktır.
  • Programınız içinde nesneler arası bağlantı, kompleks ilişkiler varsa struct kullanmamalısınız.
  • Struct'lar da statik üye tanımlayabilirsiniz ama nesneyi yarattıktan sonra erişemezsiniz.

Struct'lar neredeyse her yönü ile Class'lara benzerler yalnız class'lardan biraz daha kısıtlıdır ama daha da hızlıdır. Yukarıdaki maddeler size nerede struct kullanmanız gerektiği hakkında az çok fikir verebilir ama doğru karar vermeniz için tecrübeniz olması gerekir çünkü bu meslekte tecrübe herşeydir ;)

Class ve Struct'ı basitçe karşılaştırıp aradaki farkı performans açısından ele almak için basit bir test programı hazırladım bakalım sonuç nasıl çıkacak.?

    class Program
    {
        class clsHayvanlar
        {
            public string a { get; set; }
        }

        struct srtHayvanlar
        {
            public string a { get; set; }
        }

        static void Main(string[] args)
        {
            string tmp_ = string.Empty;            
            Stopwatch s1 = new Stopwatch();
            s1.Start();

            List cls_list = new List();
            for (int i = 0; i < 1000000; i++)
            {
                cls_list.Add(new clsHayvanlar() { a = "value" });// Heap bellek bölgesinde yer ayrılıyor.
                tmp_ = cls_list[i].a; // Heap bölgesinden okunuyor.
            }
            s1.Stop();

            Console.WriteLine("class\t: {0:N2}",s1.ElapsedMilliseconds);


            Stopwatch s2 = new Stopwatch();
            s2.Start();

            List str_list = new List();
            for (int i = 0; i < 1000000; i++)
            {
                str_list.Add(new srtHayvanlar() { a = "value" }); // Stack bellek bölgesinde yer ayrılıyor.
                tmp_ = str_list[i].a; // Stack bölgesinden okunuyor.
            }
            s2.Stop();

            Console.WriteLine("struct\t: {0:N2}",s2.ElapsedMilliseconds);
        }
    }


-----------------
class   : 232,00 ms
struct  : 90,00 ms

Görüldüğü gibi Struct lehine bariz fark var ama bu durumun tam tersi olduğu zamanlarda olabiliyor tabi bu ayrı bir yazı konusu.

Ben genelde Struct'ı dağınık verileri toparlamak, çoğu zamanda yeni bir veri türü oluşturmak için kullanıyorum, gerisi zaten GC'a ve Framework'e kalıyor. Genelde kullandığım yapı aşağıdaki gibi. Yeni bir veri türüne ihtiyacım varsa bu türü yaratırken Struct kullanmam işimi fazlasıyla görüyor.

    class Program
    {
        static List d_list;
        static void Main(string[] args)
        {
            d_list = new List(Directory.GetFiles(".\\").Length);

            foreach (var item in Directory.GetFiles(".\\"))
            {
                d_list.Add(new sistem_dosyasi(
                    new FileInfo(item)));
            }
        }

        struct sistem_dosyasi
        {
            public long size;
            public string name;

            public sistem_dosyasi(FileInfo fi)
            {
                this.size = fi.Length;
                this.name = fi.Name;
            }
        }
    }





absmiddle Yorum

C#'da Operator'lerin Performansı

02.01.2010 tarihinde yazıldıktan sonra, 3 kişi yorum yazmış.

Yine opensource bir uygulamanın kodlarını incelerken bazı yerleri refactor ettiğimde daha hızlı çalıştığını gördüm. Revize ettiğim yerlerde genelde operator'lerin kullanımı ile alakalıydı. Böyle bir kaç gereksiz ve performans düşürücü kod ile karşılaşınca da operatör performans'ı ile ilgli birşeyler yazmaya kadar verdim ;)

Sık sık kullandığım ve kullanmaya dikkat ettiğim karar verici operatörlerin kullanım yerleri ve karşılaştırmalarını basit olarak gösteren giriş seviyesi bir yazı oldu.

C# Condition'lar

Condition'dan kastımız if, switch, :?, ?? gibi operatörlerin yerine göre kullanı mı, karar verme mekanizmalarınızın hızlı olmasını sağlayacaktır. Örnek vermek gerekirse aşağıdaki gibi string karşılaştırması yapacaksanız switch kullanmanız en performanslı sonucu almanızı sağlayacaktır.


        static void switchCondition(string hayvan)
        {
            switch (hayvan)
            {
                case "At":
                    break;
                case "Öküz":
                    break;
                case "Eşşek":
                    break;
                case "Kedi":
                    break;
                case "Köpek":
                    break;
                case "Ejderha":
                    break;
                default:
                    break;
            }
        }

Bu kodun aynısını if blok'u ile de yapmanız mümkün fakat her ne olursa olsun switch bu durumda çok daha hızlı çalışacaktır. Gel gelelim switch'inde kötü performans verdiği yerler var. Aşağıdaki if kullanımı da switch'den daha performanslı çalışacaktır.

        static bool IfOrCondition(string hayvan)
        {
            return (hayvan == "At" || hayvan == "Öküz" || hayvan == "Eşşek" || hayvan == "Kedi" || hayvan == "Köpek" || hayvan == "Ejderha");
            
        }

Bu kodun birde switch karşılığını elealırsak aşağıdaki gibi yapı çıkıyor. Burda da if daha hızlı karar veriyor.

        static bool switchOrCondition(string hayvan)
        {
            switch (hayvan)
            {
                case "At":
                case "Öküz":
                case "Eşşek":
                case "Kedi":
                case "Köpek":
                case "Ejderha":
                    return true;
                default:
                    return false;
            }
        }

Bire bir değer karşılatırırken de == (Eşittir) operatörü yerine Equals metodunu kullanmanız performansınızı hızlandıracak bir harekettir. Bunu ufak bir test programı yazarak karşılaştırdım ve aşağıdaki gibi bir sonuç çıktı.

        static void EqualsCondition(string hayvan)
        {
            if (hayvan.Equals("At"))
            {

            }
            else if (hayvan.Equals("Öküz"))
            {

            }
            else if (hayvan.Equals("Eşşek"))
            {

            }
            else if (hayvan.Equals("Kedi"))
            {

            }
            else if (hayvan.Equals("Köpek"))
            {

            }
            else if (hayvan.Equals("Ejderha"))
            {

            }
        }

==         : 9,7233 ms
Equals    : 0,8875 ms

Özellikle string karşılaştırırken Equals kullanmanız performans açısından yararınıza olacaktır.

Bazı durumlarda da ne if, nede switch kullanmanız gerekmez, Diğer dillerde olduğu gibi C#'da da Inline kullanılabilecek operatörler vardır ve gerektiğinde kullanılırsa hem kodunuz daha kolay okunur hemde performans kazanırsınız. If kullanarak uzun uzun oluşturduğunuz bu kod bloğunu.

        static bool IfConditional(string hayvan)
        {
            if (hayvan.Equals("Ejderha"))
                return true;
            else
                return false;
        }

Inline bir conditional operatör kullanarak aşağıdaki şekilde az kod ile ve daha hızlı çalışır vaziyete getirebilirsiniz.

        static bool Conditional(string hayvan)
        {
            return hayvan.Equals("Ejderha") ? true : false;
        }

Bu iki kod arasındaki karşılaştırma sonucunda da aşağıdaki gibi bir sonuç çıktı.

If    : 0,9262ms
:?    : 0,4659ms

Inline kullanabileceğimiz diğer bir operatörde ?? operatörü'dür. Herhangi bir nesnenin null olup olmadığını kontrol eder eğer null ise belirleyeceğiniz değeri nesnenin değerine atar. Bu operatörü yine if ile karşılşatırırsak aşağıdaki gibi bir If kullanımını.

        static string IfAssigmentOp(string hayvan)
        {
            if (hayvan == null)
                return "Ejderha";
            else
                return hayvan;
        }

?? operatörü kullanarak refactor edebiliriz.

        static string AssigmentOp(string hayvan)
        {
            return hayvan ?? "Ejderha";
        }

Tahmin edeceğiniz gibi bu kod'da if bloğu kullanarak oluşturulmuş kod'dan hızlı ve kısa'dır.



absmiddle Yorum

Sosyal Ağ Antenleri
Blog RSSLinkedinFacebookFlickrTwitterFriendfeedGoogle ReaderYoutubegit
  • Açılış
  • Projelerim
  • Arşiv
  • İletişim
  • En çok ilgi görenler...

    HP IPAQ 914c
    Mikrotik
    NETSH'dan faydalanmak
    Togi Twitter Client
    Mikrotik ADSL Bridge.
    Netsis SQL Raporları.
    SQL Server Optimizasyonu.
    VBScript.Encode - Encode
    C# ile DataGridView den Excel 'e
    C# ile mail gönder
    Netsis SQL Server Değişikliği.
    Windows Sunucularda SYN Atakları.

    Rastgele birşeyler...

    Sipariş Numarası...
    Fanstastik Hata :)...
    Tor: çevrimiçi anoni...
    SQL Server 2008 Notl...
    DNS Server...
    PPPoE Client ile Mik...
    LOG :) Semih...
    Exchange ve POP3 Con...
    Log :)...
    OpenRPT...
    Kışlaya Dönüş....
    Fotoğrafım (semih - ...
    Yeni Msn Eklentim : ...
    İzmir Kent Kart Efsa...
    TBY İzmir Buluşması ...
    TaskSwitchXP...

    Şebeke

    WHT, Fıroİş, Denizİş, Serkan, Semih, Sewgi, Beşir, İzgençvos, Erkan, Mumin, Aliİş, Lütfü, Alper, Yusuf

    [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

    2003 - Oğuzhan YILMAZ
    Bir şey alıntıladığınız zaman kaynak göstermeniz yeterli.


    Web Hosting Sponsor Vargonen Technologiies