Dotnet Core HttpClient Kullanımı

29 Eki

Dotnet core veya .Net Framework uygulamalarında bir Web servisine erişmek için HttpClient sınıfından bir nesne oluşturulur ve kullanılır. Buraya kadar her şey normal. İşlem bittikten sonra kullanılan bu nesne yok edilir. İşte bu durumda işler biraz karışmaya başlar.

HttiClinet using blok ile kullanımı

public class ToDoClient : IToDoClient
{
	public async Task<Todo> Get(int id)
	{
		using(var client = new HttpClient())
		{
			BaseAddress = new Uri(
				"https://jsonplaceholder.typicode.com");
		}
		
		return await client.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

HttpClient sınıfı, IDisposible interface uyguladığı için, using bloğu ile kullanılabilir. Using bloğunda oluşturulan nesneler, blok sonunda ortadan kaldırılır. Ancak nesnenin kullandığı soket hemen serbest bırakılmaz. Ağır yük altında kullanılabilir soket sayısı azalır hatta tükenebilir. Burada konu ile ilgili bir yazı bulunmaktadır.

Yeniden kullanılabilir HttpClient nesnesi

Bu durumun önüne geçmek için tek bir kez singleton olarak oluşturulan ve paylaşılan bir HttpClient nesnesi kullanılabilir.

public class ToDoClient : IToDoClient
{
   private readonly HttpClient client = new ()
	{
		 BaseAddress = new Uri(
			"https://jsonplaceholder.typicode.com");
	};

	public async Task<Todo> Get(int id)
	{		
		return await client.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

Bu çözüm ise, az sayıda kullanılan kısa ömürlü console uygulamaları için uygun olabilir. Ancak geliştiricilerin karşılaştığı diğer bir sorun, uzun süren işlemlerde paylaşılan bir HttpClient örneği kullanırken ortaya çıkar. HttpClient’in tekil veya statik bir nesne olarak başlatıldığı bir durumda, DNS ip değişiklikleri yapılırsa uygulama hata alır. Örneğin load balancer ile bir DNS birden fazla ip de bulunan sunuculara sırayla yönlendiriliyor olabilir.

builder.Services.AddSingleton<IToDoClient, ToDoClient>();

Bu arada ToDoClient Program.cs içerisinde singleton olarak tanımlanabilir. Eğer Transient veya Scoped olarak kullanılırsa her request sırasında yeniden nesne oluşturacaktır. Bu durumun önüne geçmek için HttpCleint nesnesi static olarak tanımlanabilir.

public class ToDoClient : IToDoClient
{
    private static readonly HttpClient client = new ()
	{
		 BaseAddress = new Uri(
			"https://jsonplaceholder.typicode.com");
	};

	public async Task<Todo> Get(int id)
	{		
		return await client.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

Ancak bu durumda BaseAddress ile tanımlanan DNS TTL süresi bittiğinde domain adı yeni bir ip adresini işaret eder. Ancak kod restart olmadan yeni ip adresini bilemez. Çünkü default HttpClient içerisinde bunu yakalayan bir mekanizma bulunmaz. Bu durumun yakalayabilmek için SockeHttpHandler kullanılabilir.

public class ToDoClient : IToDoClient
{
	private SocketsHttpHandler socketHandler = new()
	{
		PooledConnectionLifetime = TimeSpan.FromMinutes(5)
	};
	
    private static readonly HttpClient client = new (socketHandler)
	{
		 BaseAddress = new Uri(
			"https://jsonplaceholder.typicode.com");
	};

	public async Task<Todo> Get(int id)
	{		
		return await client.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

Ancak bu yöntem de en iyi çözüm yolu değildir. En iyi çözüm yolu  .NET Core 2.1 ile birlikte gelen IHttpClientFactory interface kullanmaktır.

IHttpClientFactory Kullanımı

Bu interface kullanmadan önce Program.cs içerisinde bir tanımlama yapılması gerekmektedir.

builder.Services.AddSingleton<IToDoClient, ToDoClient>();
builder.Services.AddHttpClient<IToDoClient, ToDoClient>(client =>
{
   client.BaseAddress = new Uri(
			"https://jsonplaceholder.typicode.com");
});

Bu düzenleme ile artık HttpClient aşağıdaki gibi kullanılabilir.

public class ToDoClient : IToDoClient
{
    private readonly HttpClient _httpClient;
	
	public ToDoClient(HttpClient httpClient)
	{
		_httpClient = httpClient;
	}
	
	public async Task<Todo> Get(int id)
	{		
		return await _httpClient.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

Bu durumda HttpClient nesnesi IHttpClientFactory tarafından yönetilmektedir. Çünkü ortak bir havuzdaki HttpMessageHandler nesneleri, birden çok HttpClient örneği tarafından yeniden kullanılabilen nesnelerdir. Bu sayede DNS sorunu çözülmektedir.

Named Client kullanımı

Servis binding sırasında AddHttpClient() metoduna bir isim vererk kullanmak mümkündür.

builder.Services.AddSingleton<IToDoClient, ToDoClient>();
builder.Services.AddHttpClient("TodoApi",client =>
{
   client.BaseAddress = new Uri(
			"https://jsonplaceholder.typicode.com");
});
public class ToDoClient : IToDoClient
{
    private readonly IHttpClientFactory _httpClientFactory;
	
	public ToDoClient(IHttpClientFactory httpClientFactory)
	{
		_httpClientFactory = httpClientFactory;
	}
	
	public async Task<Todo> Get(int id)
	{		
	    var client = _httpClientFactory.CreateClient("ToDoApi");
		
		return await client.GetFromAsync<ToDo>(
			$"/todos/{id}");
	}
}

Bu sayede doğrudan IHttpClientFactory interface nesneleri ile HttpClient request’leri en verimli şekilde gerçekleştirilebilmektedir.

Kaynaklar

  • https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
  • https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

Javascript ile sunucuya dosya yükleme sürecini kontrol etmek

21 Nis

Sunucuya doysa yükleme(File Upload) işlemi, küçük boyutlu dosyalar için kısa zamanda sonuçlanan bir işlemdir. Birkaç KB veya MB boyutundaki dosyaların sunucuya  yüklenmesi çok fazla zaman alamayacağından kullanıcı sabrını fazla zorlamaz. Ancak büyük boyutlu dosyaların yüklenmesi sırasında, yükleme işleminin kullanıcıya süreç olarak ifade edilmesi gerekmektedir. Aksi halde sunucudan uzun süre cevap alamayan kullanıcılar, internet tarayıcısının kilitlendiğini zannederek işlemi sonlandırabilir. Bu durumda yüklemi işlemi yarıda kesilir. Böyle durumların yaşanmaması için dosya yükleme sürecini bir şekilde kontrol altına alarak kullanıcıya işlemin hangi aşamada olduğunu grafiksel veya sözel bir şekilde bildirmemiz gerekmektedir. Tam da bu noktada imdadımıza javascript asenkron programlama yetişmektedir.

Javascript kullananların sıkça başvurduğu asenkron işlemler, dosya yükleme işleminde de etkili bir şekilde kullanıldığında geliştiriciye büyük kolaylık sağlamaktadır.

Dosya yükleme işlemini basit bir şekilde ifade edecek olursak bir form yardımıyla bilgisayarımızdan seçilen dosyaların (resim, müzik, video, veri, v.s) sunucuya aktarılmasıdır diyebiliriz. Bu kısa özetin ardından işlemin nasıl yapıldığına dair bir örnek uygulama göstermek faydalı olacaktır.

File Upload
File Upload

Örnek uygulama ile resimden anlaşıldığı üzere dosya yükleme süreci takip edilmektedir.

Kod tarafında Javascript ile yapılan işlem sadece XMLHttpRequest nesnesine ait olayların(events) yakalanmasıdır. XMLHttpRequest  nesnesi süreci asenkron olarak işletmektedir. Belli durumları olaylar yardımıyla bize bildirmektedir. Örneğin Yükleme sürecini progress event ile, işlemin bittiğini load event ile yakalayabilmekteyiz.

  this.ajax = new XMLHttpRequest();
  this.ajax.upload.addEventListener("progress", onProgressChanged, false);
  this.ajax.addEventListener("load", onFileUploadSuccess, false);
  this.ajax.addEventListener("error", onFileUploadFailed, false);

Bu şekilde event’leri sıralayabiliriz. Arayüz (HTML) tarafında belirlenen progress bar, button gibi elementlerin güncellenerek sürecin kullanıcıya yansıtılması bize kalmıştır. Bu noktada çeşitli yöntemlerle çalışmak mümkündür. Doğrudan javascript tarafından DOM elementlere ulaşıp içerik güncellemesi yapabildiğimiz gibi, JQuery gibi kütüphaneler kullanabiliriz. Ben bu uygulamada MVVM(Model View ViewModel) prensibini de etkin şekilde kullanabilmek açısından Knockoutjs kütüphanesini kullandım.

Sunucu tarafında uygulama Asp.net MVC4 ile oluşturulmuştur. Sunucu tarafında dosyaları diske yazma işini şimdilik kodlamadan bıraktım. Zaten yazının konusu değil.

Örnek uygulamayı GitHub hesabıma yükledim.  MVC4-knockoutjs-fileupload adresinden uygulamaya ulaşabilir, isterseniz katkıda bulunabilirsiniz.

Microsoft’un Çöpe Giden Yazılım Teknolojileri

25 Ara
  • Silverlight
  • WCF
  • WPF
  • Windows Forms
  • Web Forms

Microsoft teknolojilerinde son yıllarda önemli gelişmeler yaşanıyor. Takip etmekte zorlandığımız bu değişiklikler şüphesiz olması gereken şeylerdir. Yukarıda listelediğim teknolojiler, Microsoft’un  bir dönem parlayan yıldızlarıydı. Geçen zaman içinde yazılım dünyasında yaşanan evrim sonucu , Microsoft tarafında bir takım sorunlara çözüm bulmak ve bazı teknolojilerle rekabeti yakalayabilmek adına bir takım gelişmelere neden oldu. Yazılım dünyasındaki her yeni gelişme, karşımıza yeni bir ürün olarak çıktı. Gelişme ilerledikçe evrim, bir takım organların sonunu getirdi. Şunu da belirtmeliyim ki bu yazı Microsoft teknolojilerine karşı durmak için değil, bazı teknolojilerin zamanla yerini başka teknolojilere bıraktığını anlatmak amacıyla kaleme alınmıştır. Serbest pazar ortamında her firma ürününü ortaya koyar ve herkes istediği teknolojiyi dilediğince seçmekte özgürdür.

Silverlight

Adobe Flash, Java Flex v.b gibi client taraflı uygulamalara alternatif olarak üretilen zengin içerik ürünü Silverlight, mobil internet tarayıcılar tarafında yetersiz kalınca ve geliştiricilerin Javascript gibi tüm tarayıcılarda çalışabilen bir teknolojiyi tercih etmesiyle fişi çekilen teknolojilerden biri oldu. Ülkemizde ve diğer ülkelerde Silverlight düşkünü yazılımcılar için adeta bir hayal kırıklığı oldu. Çünkü bu gelişme birçok yatırımın güncelliğini yitirip zamanla çöpe gitmesi demekti.

WCF

Servis odaklı altyapı sistemleri için geliştirilen WCF teknolojisi SOAP ve RESTful servisler oluşturmak için bir altyapı sunmaktadır. HTTP tabanlı REST servislarinin yaygınlaşmasıyla ivme kaybeden ve durma noktasına gelen hatta bitti denilebilecek teknolojilerden birisi. WCF teknolojisi SOAP servisleri oluşturmak için ideal bir seçimdir. Ancak RESTful servisler oluşturma konusunda liderliğini WEB API teknolojisine kaptırmıştır. (Güncelleme: WCF servislerinin REST ve SOAP ayrımına vurgu yapıldı. 21.02.2015)

Windows Forms

Masaüstü programlama araçlarından Windows Forms teknolojisi ise WPF teknolojisinin gelmesiyle silikleşen teknolojiler arasında. WPF teknolojisini Windows Forms teknolojisine göre makul kılan özelliklerin başında View tarafı ile Model tarafının birbirinden ayrılmasını sağlamasıydı. Windows Froms, kod arayüzü ve grafik arayüzü ile çalışmaktadır. WPF ise kod arayüzü, grafik arayüzü ve grafik arayüzünü şekillendirebilen XAML arayüzü ile ortaya çıkmıştır. Bu durumda MVVM (Model-View-ViewModel) yazılım desenlerinin uygulanması kolaylaşmakta ve daha kolay yönetilebilir uygulamalar geliştirilebilmektedir.

WPF

Windows 8 ile birlikte bizi işletim sistemi düzeyinde şaşırtan Microsoft, XAML teknolojisini .Net framework tarafından işletim sistemi üzerine alarak bizi tekrar şaşırttı. Bu da demek oluyor ki artık masaüstünde artık WinRT teknolojisi yer alacak. Bu durumda WPF teknolojisi de yıkılmak üzere demektir.

Web Forms

Microsoft’un Web geliştirme tarafında sihirli çubuğu olan Web Forms teknolojisi de MVC uygulama mimarisine yenik düştmüştür diyebiliriz. Web Forms ile oluşturulmuş birçok popüler web sitesi bu günlerde MVC teknolojisine geçiş yapmaya başladı bile. Web Forms teknolojisinin hakkını yememek lazım ki çok sayıda popüler uygulamaya temel oluşturmuştur. Ancak MVC teknolojisinin iş birimlerinin birbirinden ayrılmasını sağlayan mimarisi ve bu sayede geliştirici hakimiyetini ön plana çıkarması ayrıca birim test yazmaya olanak  sağlaması zamanla onu popüler hale getirmiştir. Şahsen ben Web uygulamalarına direk MVC tarafından başlayanlardanım. (Güncelleme: 21.02.2015)

Microsoft gelişime, yeniliğe önem veren bir şirket. Ancak insanların yıllarca üzerinde çalışıp yatırım yaptığı teknolojilerin birden yok olması geliştiricileri ve şirket yöneticilerini sıkıntıya sokabiliyor. Bu durumda şu soru akıllara geliyor. Bu teknoloji de son bulursa ne yapacağız? Gelişim oldukça bir şeylerin sonu gelecek elbette.

Çöpe giden teknolojiler sadece Microsoft tarafıyla sınırlı değildir. Open source tarafında da çok fazla proje çöpe gitmiştir. Örneğin java tarafında da MVC yaygınlaşınca Serve taraflı bileşen teknolojiler pek tercih edilmez hale gelmiştir.

Bu durumda öngörülü olmak önem arz etmektedir. Spesifik teknolojiler yerine platform bağımsız teknolojilere eğilim göstermek her zaman faydalı olacaktır. Hangi programlama dili olursa olsun, yapılan iş genele hitap edecek şekilde tasarlanmalıdır. Bu sayede genişletilebilirlik(extensibility) ilkesi ile hareket etmiş oluruz ve hiç bir teknolojiye sıkı sıkıya bağımlı kalmayız.

Asp.Net Web API verileri ile Google Charts kullanımı

19 Tem

Farklı platformların birbiri ile konuşabilmesi biz yazılımcılar için gerçekten büyük bir nimet. Bunu ASP.NET Web API verilerini kullanarak Google Chart API grafiklerini kolay bir şekilde çizdirebildiğimde bir kez daha anlamış oldum.

Geliştiriciler için birçok kullanışlı ürün ortaya koyan Google Google Chart API uygulaması ile grafik kullanmak isteyenlere yeni bir kapı açmıştır. Platform bağımsız uygulamalar konusunda çok iyi ürünler ortaya koymaya devam etmektedir. Bende bu grafik ürününü incelerken hemen bir Web API oluşturup kullanmak istedim. Başarılı sonuca ulaşınca da bunu sizlerle paylaşmak istedim.

Örnek bir Web API uygulaması üzerinden Google Grafiklerini çizdirmeye çalışalım. Hemen boş bir ASP.NET MVC uygulaması oluşturarak işe başlayalım. Örnek uygulamamızda hedeflenen buradaki Google sütun grafiğini çizmektir. Uygulama çalıştığında ulaşacağımız grafik aşağıdaki gibi olacaktır.

ASP.NET WEB API ve Google Charts

Grafikte kullanılacak olan veri modelini aşağıdaki şekilde oluşturarak işe başlayalım.

public class CompanyReport
{
    public string Year { get; set; }
    public double Sales { get; set; }
    public double Expense { get; set; }
 }

Model sınıfımız yıllara göre satış ve giderleri veren bir özet niteliğinde olup grafikte olması gereken verileri tutmaktadır.

Şimdi de bu veri tipine uygun verileri servis edecek olan bir Api Controller oluşturmalıyız.

public class CompanyController : ApiController
{
    public IEnumerable Get()
    {
         var result = new List
         {
             new CompanyReport{Year = "2008&", Sales = 1000, Expense = 452},
             new CompanyReport{Year = "2009", Sales = 1150, Expense = 652},
             new CompanyReport{Year = "2010", Sales = 950, Expense = 1052},
             new CompanyReport{Year = "2011", Sales = 1150, Expense = 252},
         };

         return result;
     }
 }

Api Controller sınıfımız olan CompanyController sınıfının Get() metodu CompanyReport verilerini içeren JSON tipinde bir veri seti döndürmektedir. Google Chart API aynı şekilde grafik çizim verilerini JSON tipinde almaktadır. Bu sayede en başa dönecek olursak, iki ayrık sistemi JSON ortak noktasında buluşturmuş olacağız.

Grafik çizim işlemini View tarafında bir Script içerisinde gerçekleştirmeye çalışalım. Scrip içerisine referans olan Google Char ve JQuery Javascript dosyalarını Google CDN üzerinden çağırmaktayım.

<script src="https://www.google.com/jsapi" type="text/javascript">// <![CDATA[
  <script type='text/javascript'
          src='https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'/>
  <script type="text/javascript">

        function drawChart() {
           $.getJSON(&quot;/api/Company&quot;, null, function (items) {
               var table = new google.visualization.DataTable();
               table.addColumn('string', 'Yıllar');
               table.addColumn('number', 'Satışlar');
               table.addColumn('number', 'Giderler');

               for (var i = 0; i < items.length; i++) {
                     table.addRow([items[i].Year, items[i].Sales,items[i].Expense]);
               }

               var options = { title: 'Şirket Raporları' };
               var chart = new google.visualization.ColumnChart(
                                document.getElementById('chart_div'));
               chart.draw(table, options);
           });
        }
  google.load(&quot;visualization&quot;, &quot;1&quot;, { packages: [&quot;corechart&quot;] });
  google.setOnLoadCallback(drawChart);
// ]]></script>

Artık uygulamamızı çalıştırdığımızda Api verileriyle Google grafikleri çizilmiş olacaktır.

Bir sonraki yazıda görüşmek dileğiyle.

Kaynak Kod: Burada

Asp.Net MVC Web API Projesinde Ninject ile Dependency Injection

5 Tem

Bir önceki yazılarımdan biri olan MVC Projesinde Dependency Injection başlıklı yazıda MVC uygulamasında Controller sınıfı içerisine dışarıdan bağımlılıkların enjekte edilmesini incelemeye çalışmıştık. Bu yazımızda ise Asp.Net MVC Web Api uygulaması üzerinde Dependency Injection işlemini uygulamaya çalışacağız.

MVC uygulamasında Controller sınıfları System.Web.Mvc.Controller tipinden türetilirken API Controller sınıfları System.Web.Http.ApiController tipinden türetilmiştir. Bu nedenle Web API üzerinde Dependency Injection uygularken bir önceki örnek uygulamadaki yöntemden daha farklı bir yöntem kullanacağız.

public class ValuesController : ApiController
{
     readonly IProductRepository productRepository;
     public ValuesController(IProductRepository productRepository)
     {
          this.productRepository = productRepository;
     }

     public IEnumerable<string> Get()
     {
         return productRepository.GetValues();
     }
}

API içerisine bağımlılıkları enjekte ederken IProductRepository interface tipini uygulayan(implemente eden) sınıfları göndermeye dikkat edeceğiz.

WEB API içerisinde Dependency Injection işlemini gerçekleştirmek için yine MVC’de olduğu gibi IoC container kütüphanelerinden faydalanmamız gerekiyor.

WEB API projelerinde Controller sınıflarının parametreli şekilde çalışabilmesi için bazı ayarlamaları yapmamız gerekecek. Bu ayarlamalardan biri, System.Web.Http alanında bulunan GlobalConfiguration statik sınıfındaki DependencyResolver özelliğinin düzenlenmesi olacaktır. Bu sayede WEB API, resolver mekanizmasını tanıyacaktır. Bu ayarlama Global.asax.cs dosyası içerisinde yapılmaktadır. Tanımlama:

public class WebApiApplication : HttpApplication
{
     protected void Application_Start()
     {
         // Diğer kodlar...
         GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(CreateKernel());
     }

     private IKernel CreateKernel()
     {
         IKernel kernel = new StandardKernel();

         kernel.Bind<IProductRepository>().To<ProductRepository>();

         return kernel;
     }

}

NinjectDependencyResolver adında bir sınıf hazırlıyoruz ve yukarıdaki gibi DependencyResolver özelliğine atıyoruz. DependencyResolver özelliği IDependencyResolver tipindedir. Bu sebeple NinjectDependencyResolver sınıfı da IDependencyReolver tipini uygulamalıdır.

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
      private readonly IKernel kernel;

      public NinjectDependencyResolver(IKernel kernel): base(kernel)
      {
          this.kernel = kernel;
      }

      public IDependencyScope BeginScope()
      {
          return new NinjectDependencyScope(kernel.BeginBlock());
      }
}

NinjectDependencyResolver sınıfını aynı zamanda NinjectDependencyScope sınıfından türetiyoruz. Bunun sebebi ise IDependencyResolver interface tipinin barındırdığı BeginScope() metodudur. Bu metodun bir şekilde doldurulması gerekmektedir. NinjectDependencyScope tipi de kendi oluşturmuş olduğumuz bir sınıf olacaktır. Bu sınıfı de şu şekilde oluşturabiliriz.

public class NinjectDependencyScope : IDependencyScope
{
    IResolutionRoot resolver;

    public NinjectDependencyScope( IResolutionRoot resolver)
    {
        this.resolver = resolver;
    }

     public void Dispose()
     {
        IDisposable disposable = resolver as IDisposable;

        if (disposable!=null)
        {
            disposable.Dispose();
        }

        resolver = null;
     }

     public object GetService(Type serviceType)
     {
         if (resolver==null)
         {
             throw new ObjectDisposedException("this", "This scope has been disposed");
         }

         return resolver.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
         if (resolver == null)
         {

              throw new ObjectDisposedException("this", "This scope has been disposed");
         }

         return resolver.GetAll(serviceType);
     }

}

Son aşamayı da bu şekilde tamamladıktan sonra projemiz çalışabilir hale gelmiş demektir.

WEB API Sonuç
WEB API Sonuç

Projenin örnek kodlarını SkyDrive üzerinden paylaşıyorum.

Kaynak Kod: Burada

Asp.Net MVC JSON Model Bining

7 May

Asp.Net MVC mimarisinde yer alan model binding konusunu daha önceki yazılarda ele almıştık. Bu yazıda ise model binding işlemini JSON nesneleri ile uygylamaya çalışacağız. Web projelerinde ihtiyaç duyduğumuz  javascript tabanlı sorguları gerçekleştirmek için JSON nesnelerini .NET nesnelerine dönüştürmemiz gerekebilir. Request data olarak JSON nesnelerini POST edebilmeliyiz.

Örnek Uygulama

Örnek uygulama olarak bir ürün arama işlemini JSON formatındaki verileri bir Action metoda POST edeceğiz.

Öncelikli olarak Request ile gelen JSON fromatındaki veriyi deserialize ederek .Net nesnelerine dönüştürecek olan ModelBinder sınıfımızı oluşturmalıyız.

public class JsonModelBinder : IModelBinder
{
     public object BindModel(ControllerContext controllerContext,
                             ModelBindingContext bindingContext)
     {
          if (controllerContext == null)
             throw new ArgumentNullException("controllerContext");

          if (bindingContext == null)
             throw new ArgumentNullException("bindingContext");

          var serializer = new DataContractJsonSerializer(bindingContext.ModelType);
          var deSerialized = serializer.ReadObject(
                             controllerContext.HttpContext.Request.InputStream);

          return deSerialized;
    }

}

DataContractJsonSerializer sınıfının ReadObject metodu Request üzerinden ile gelen veriyi (InputStream), ModelBindingContext sınıfının ModelType parametresine göre uygun .Net tipine dönüştürür.

Şimdi de ModelBindingContext sınıfına gönderilecek olan tipi hazırlamalıyız.

[DataContract]
[ModelBinder(typeof(JsonModelBinder))]
public class JsonProductSearchRequest
{
     [DataMember]
     public string Name { get; set; }
     [DataMember]
     public string Color { get; set; }
}

System.Runtime.Serialization isim alanına dahil olan DataContract ve DataMember attribute tipleri sınıfları ve sınıf üyelerini serileştirilebilir hale getirmek için kullanılırlar. (Yeri gelmişken söylemekte fayda var; Bir tipi serileştirmek JSON, XML veya Binary şekillerde olabilmektedir. Biz örneğimizde JSON serileştirme üzerinde duracağız). JSonProductSearchRequest sınıfımızı, model binding sırasında ihtiyaç duyulan attribute olan ModelBinder ile imzalıyoruz, parametre olarak ise daha önceden hazırladığımız JsonModelBinder tipini gönderiyoruz.

Artık Controller tarafında ihtiyaç duyulan Action Metodları hazırlayabiliriz.

public class ProductController : Controller
{
   [HttpPost]
   public JsonResult JsonSearch(JsonProductSearchRequest request)
   {
       return null;
   }
}

JsonSearch Action metodu, daha önceden hazırladığımız JsonProductSearchRequest tipinde bir parametre almaktadır.

Şimdi hazırladığımız bu metoda fiddler yardımıyla bir istek (request) göndererek durumu incelemeye çalışalım.

Fiddler Json POST
Fiddler Json POST

Fiddler aracında Composer sekmesinden Request Tipini POST olarak seçiyoruz. Sunucudaki uygulama linkimizi girerek Request Body kısmına uygun JSON verisini giriyoruz. Execute butonuyla çalıştırdığımızda kodumuza geçip “break point” ile takip edersek:

Json Model Binder
Json Model Binder

Gönderdiğimiz verinin POST edildiğini rahatlıkla görebiliriz.

Bu şekilde etkili sonuç veren bir çözüme ModelBinding nimetlerinden faydalanarak ulaşmayı başardık. JSON tabanlı arama işlemlerini rahatlıkla bu şekilde gerçekleştirebiliriz. Ben bu örnekte View sayfalarıyla uğraşmamak adına fiddler aracından faydalanmayı uygun gördüm.

Bir sonraki yazıda görüşmek üzere.

Asp.Net MVC Custom Controller Factory

4 May

Asp.net MVC mimarisini benim için değerli kılan özelliklerinden başında genişletilmeye uygun olarak tasarlanmış olması gelmektedir.

Bu yazımızda Asp.Net MVC yaşam alanına giren bir isteği(request) ilk karşılayan Controller mekanizmasının özelleştirilmesi üzerinde duracağız. MVC mimarisinde Controller tipleri belli kurallar dahilinde tanımlanmıştır. Bu kuralların dışına çıkmak istediğimizde kendi isteğimize göre özel kurallar oluşturarak sisteme dahil etmemiz gerekmektedir. Default olarak tanımlanmış Controller kurallarından biri de Controller sınıflarının kurucu metodları (constructor) parametresiz olmasıdır.

Controller
Controller

Bu yazımızda parametresiz constructor metodunu ihlal ettiğimizde karşılaşacağımız sorunlar ve çözümleri üzerinde duracağız.

Parametresiz Constructor Hatası
Parametresiz Constructor Hatası

Parametresiz constructor kuralını ihlal ettiğimizde hemen bir hata ile karşılaşırız. Burada yapmak istediğimiz IoC (Inversion of Control) mantığında Controller sınıfına dışarıdan bir nesne(securityService) enjekte etmektir. Bu işlem için piyasadaki Ioc kütüphanelerini kullanabiliriz. Piyasada şu anda kullanılan kütüphaneler widsor, structuremap, ninject,… şeklinde sıralanabilir. Şu anda konumuz olmasa da IoC kütüphanelerinin yaptığı işten hemen kısaca bahsedelim. IoC kütüphaneleri interface gibi soyut tiplere karşılık olarak belirlediğimiz somut sınıflara ait nesneleri ihtiyaç duyduğumuzda oluşturarak bize sunarlar. Bu sayede “new” anahtar sözcüğü ile Controller içinde nesne oluşturarak somut tiplere bağımlı kalmamış oluruz.

Bu kısa notun ardından kendi tasarladığımız ControllerFactory sınıfımızı oluşturmaya başlayalım.

public class IocControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(

    RequestContext requestContext, Type controllerType)
    {
         return (IController)ObjectFactory.GetInstance(controllerType);
    }
}

DefaultControllerFactory sınıfının GetControllerInstance metodunu ezerek Controller nesnesi oluşturma işlemini StructureMap IoC container kütüphanesine yükledik. StructureMap kütüphanesi, önceden tanımladığımız interface ve sınıf eşleştirmesini yaparak constructor parametresi olarak kullanılan interface tipine karşılık bir somut nesne sunmaktadır.

public static class ContainerBootstrapper
{
     public static void BootstrapStructureMap()
     {
         ObjectFactory.Initialize(x =>
                  x.For<ISecurityService>().Use<SecurityService>());
     }
}

ContainerBootstrapper static sınıfında tanımladığımız BootstrapStructureMap metodu içerisinde interface tipine karşılık bir somut sınıf belirlenmektedir. ISecurityService interface tipi için SecurityService somut tipini kullan demiş olduk.

Hazırladığımız düzeneği çalıştırabilememiz için son olarak Global.asax içerisinde son hamlelerimizi yapmamız gerekiyor.

protected void Application_Start()
{
    .....
    ....

    ContainerBootstrapper.BootstrapStructureMap();

    ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory());

}

Öncelikle ContainerBootstrapper.BootstrapStructureMap(); metodu ile eşleştirme işlemini gerçeklştiriyoruz. Ardından ControllerBuilder sınıfı yardımyla kendi özel conrtoller factory tipimiz olan IocControllerFactory tipini sisteme tanıtıyoruz. Artık DefaultControllerFactory sistemden çıktı ve yeni oluşturduğumuz factory tipi sistemimize dahil oldu.

Parametreli COntroller Constructor
Parametreli COntroller Constructor

Programı çalıştırdığımızda IsecurityService tipine karşılık olarak bir SecurityService nesnesi oluşturulmuştur.

StructureMap IoC container kütüphanesi hakkında detaylı bilgiyi buradan bulabilirsiniz.

Asp.Net MVC 4 ve Jquery Datepicker uygulaması

26 Ara

Asp.Net MVC 4 uygulamalarında tarih biçimli form elemanlarını seçenekli bir şekilde kullanıcıya sunmak için en etkili yöntem JQuery datepicker UI elementini kullanmaktır. JQuery datepicker elementi ile detaylı bilgiye buradan ulaşabilirsiniz. Dil seçeneklerine kadar bir çok özelliği bu siteden bulabilrsiniz.

date1

Asp.net MVC 4 uygulamamızda tarih biçimindeki bir form elemanına nasıl datepicker özelliği eklendiğini incelemeye çalışacağız.

Hemen bir MVC 4 projesi oluşturarak işe başlayabiliriz. Uygulamımızda formu temsil etmek için rezervasyon adında bir Model tanımlıyoruz.


namespace DatepickerJQueryDemo.Models
{
     public class Reservation
     {
       public string Name { get; set; }
       public DateTime Date { get; set; }
     }
}

Modelimizi kullanmak adına ReservationController adında bir controller ekleyerek devam edebiliriz.


public class ReservationController : Controller
{
     public ActionResult Create()
     {
      return View();
     }
}

ReservationController sınıfımınız Create action metodu bir view döndürmektedir. Bu view içerisinde de create formu ve içierisinde de Name ve Date şeklinde iki metin kutusu olacaktır. Bundan sonraki adımınız Date şeklindeki metin kutusuna datepicker özelliğini katmak olacaktır.

editor

Yapacağımız ilk hamle SolutionExplorer penceresindeki projemizin Views dizinindebulunan Shared dizini içerisine EditorTemplates adında bir klasör ekleyip içerisine DateTime adında bir PartialView eklemek olacaktır.

partialview

EditorRemplates ve DisplayTemplates hakkında daha önceden yazılmış makaleleri buradan inceleyebilirsiniz. Bu işlemi yaptığımızda artık bütün view sayfalarındaki DateTime tipinde olan form elemanları (Html.EditorFor extension metodundan) tanımladığımız bu editör template dosyasını kullanır. Burada dikkat edecek olursak “model DateTime?” şeklinde modelin Nullable tipinde olduğunu belirtiyoruz. Bu belirtimi yapmadığımızda karşılaşacağımız hata mesajı şu şeklide olacaktır.

Hata: The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type ‘System.DateTime’.

Bu hatanın sebebi Create action metodunun view sayfası bir reservation modeline bağlı olamsı, ancak create view sayfasına herhangi bir model nesnesi gönderilmediğinden modelin null olmasıdır. Bu sebeple Datetime nesnesi null şeklinde bir hata mesajı karşımıza çıkar.

Bu ince noktayı belirttikten sonra artık ikinci hamleye geçebiliriz. Bu hamlemiz ise formumuzdaki Date tipindeki text kutusuna JQuery datepicker tarafından kullanılacak olan “data-datepicker” adında bir class eklemek olacaktır. JQuery UI scripti bir elementte bu sınıfı gördüğünde, o elemente datepicker özelliğini yapıştırır.

javascript

Bu javascript kodu, input tipinde olan ve “data-datepicker” sınıfını içieren elementlere datepicker özelliğini ekler. Bir önceki adımımızda TextBox tipine “new{data_datepicker=true}” şeklinde sınıf eklemesini yapmıştık.

Bu javascript kodunu bir js dosyasına kaydedip  Create viewe sayfasına refereans olarak gösterebilirsiniz. Ya da direk Create sayfası içerisine yazabilirsiniz.

Son adımda ise Create view sayfasına jquery.ui dosyasını referens olarak vermek gerekmektedir. Bu dosya isteğe göre _Layout.cshtml sayfasına da referans verebilirsiz. Jquery datepicker  elementinin rengi ve şekline bağlı görünüm özellikleri de Content/themes/base/ jquery-ui.css dosyasında bulunmaktadır. Bu dosyayı da refereans olarak eklemeliyiz.

<link href=”~/Content/themes/base/jquery-ui.css” rel=”stylesheet” />

<script src=”~/Scripts/myscripts.js”></script>

<script src=”~/Scripts/jquery-ui-1.8.20.js”></script>

son

Not: Eğer jquery-ui.js refereansını eklemeyi unutursanız aşağıdaki gibi javascript hataları alabilirsiniz.

Hata: 0x800a01b6 – Microsoft JScript çalışma hatası: Nesne, ‘datepicker’ özelliğini veya yöntemini desteklemez.

Çalışan örnek uygulamaya buradan ulaşabilirsiniz.

Bir sonraki yazıda görüşmek dileğiyle.

Proje – Nakliye Noktası ( www.nakliyenoktasi.com)

12 Kas

Nakliye Noktası projesi, yük sahipleri ile nakliyecileri buluşturan bir platformdur. Üye olan kullanıcılar ücretsiz üye olarak yüklerini ve nakliye için bekleyen boş araçlarını bu sitede yayınlayarak daha kolay bir şeklide ihtiyaçlarını karşılayabilmektedirler.

www.nakliyenoktasi.com sitesinde yayınlanan ilanların sahipleri ile iletişim bilgilerine üye olan kullanıcılar ulaşabilmektedir.

Araçlarıyla nakliye işine çıkan kullanıcılar dönüş tarihlerini ilan olarak bıraktıklarında dönüş tarihine kadar nakliyeci arayan kullanıcılar aranarak işlerini garantiye alabilmektedirler.

Tüm nakliyeciler ve yük göndermek isteyen kullanıcıları aramızda görmekten mutluluk duyarız.

Asp.net MVC DisplayTemplates Kullanımı

27 Tem

ASP.NET MVC projelerinde Model tarafından gelen property’ler için özel görünüm şablonları oluşturabiliriz. Bunun için kullanılacak yöntem DisplayTemplates şeklinde şablonlar oluştırmaktır. Display Template oluşturma işlemini gerçekleştirmek için Views/Shared altına DisplayTemplates şeklinde bir dizin oluşturmalıyız. Bu dizin altına şablonlarımızı tanımlayabiliriz.

Display  template içerisinde YesNo.cshtml adında bir partial view oluşturuyoruz. Bu view içerisini bool tipindeki değişkenleri istediğimiz gibi göstermek amacıyla doldurabiliriz. Örneğin kişinin profil tipinin gene veya özel olduğunu gösteren bir şablon oluşturalım. YesNo.cshtml içeriği aşağıdaki gibi olacaktır:

Model içeriğimizde şu şeklide olacaktır:

public class Register

{

[UIHint(“YesNo”)]

[Display(Name=”Profil Türü”)]

public bool Accept { get; set; }

}

Bu durumda view sayfalarında @Html.DisplayFor(m=>m.Accept) şeklindeki render istekleri sonucunda Genel veya özel şeklinde bir format oluşacaktır.

Sonuc: