https://www.buraksenyurt.com/Burak Selim Şenyurt - Asp.Net 4.52016-08-08T07:27:38+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/TFI-109-IIS-Uzerindeki-Uygulamalarc4b1-Kod-Yoluyla-OgrenmekTFİ 109 - IIS Üzerindeki Uygulamaları Kod Yoluyla Öğrenmek2014-08-27T13:52:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p>Diyelim ki sunucudaki <strong>IIS </strong>üzerinde konuşlandırdığınız Web uygulamalarının bir listesini almak istiyorsunuz. Bunun elbette pek çok yolu olduğunu biliyorsunuz. Bir Powershell script' i belki de işinizi görür. Ancak belki de siz bunu kendi geliştireceğiniz windows forms uygulamasında bu listeyi kullanmak istiyorsunuz. Ne yaparsınız? Kod yardımıyla <strong>IIS </strong>üzerindeki <strong>Application</strong>' ları, <strong>Site</strong>' ları öğrenebilir misiniz?</p>
<p>Aslında hep elinizin altında olan<em> (Windows\System32\inetsrv\Microsoft.Web.Administration.dll)</em> ve hatta isterseniz <strong>NuGet Package Manager </strong>ile de indirebileceğiniz <strong>Microsoft.Web.Administration</strong> kütüphanesini kullanarak bu işi gerçekleştirmeniz oldukça kolay. Nasıl mı? İşte böyle.</p>
<p><img src="http://www.buraksenyurt.com/pics/2014%2f8%2ftfi109.png" alt="" /></p>
<p>Başka neler mi yapabilirsiniz? Örneğin bir Application Pool' u Recylce edebilirsiniz. Ya da bir Web Site' ı Stop-Start. Hatta yeni bir Web Site bile açabilirsiniz. Araştırmaya değer değil mi?</p>
<p>Başka bir ipucunda görüşmek dileğiyle.</p>2014-08-27T13:52:00+00:00bsenyurthttps://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=b0a0f719-7be3-43f8-96a5-6635b286bc471https://www.buraksenyurt.com/trackback.axd?id=b0a0f719-7be3-43f8-96a5-6635b286bc47https://www.buraksenyurt.com/post/TFI-109-IIS-Uzerindeki-Uygulamalarc4b1-Kod-Yoluyla-Ogrenmek#commenthttps://www.buraksenyurt.com/syndication.axd?post=b0a0f719-7be3-43f8-96a5-6635b286bc47https://www.buraksenyurt.com/post/AspNete28093Farklc4b1-Ortam-Farklc4b1-Config-Farklc4b1-DeployAsp.Net–Farklı Ortam, Farklı Config, Farklı Deploy2014-07-07T12:04:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p>Bazen geliştirdiğimiz web uygulamaları farklı ortamlar için farklı parametrik değerler kullanır. Bu parametre değerleri çoğunlukla <strong>web.config </strong>dosyası içerisinde yer alır. Böyle bir durumda ortamlara göre <strong>Deployment</strong> yapmak zahmetli bir hal alabilir. Nitekim yaygın olarak kullanılan dört farklı ortam söz konusudur. <strong>Development</strong>, <strong>Test</strong>, <strong>PreProd</strong> ve <strong>Prod</strong>. Her bir ortam için parametreler farklı değerlere sahip olabilir/olması gerekir. Bu yüzden Publish adımlarında, ortamlara göre <strong>Profile</strong> hazırlanması tercih edilir. Peki bu farklı profiller, <strong>config</strong> dosyaları içerisindeki çeşitli değerleri <em>(veritabanı bağlantıları, proxy veya servis adresleri, fiziki path bildirimleri vb)</em> ortamlara göre nasıl değiştirebilir? İşte bu görsel dersimizde bu soruya cevap bulmaya çalışıyoruz.</p>
<p>
<object width="640" height="360">
<param name="movie" value="//www.youtube.com/v/fulrSt5rwk4?version=3&hl=tr_TR" />
<param name="allowFullScreen" value="true" />
<param name="allowscriptaccess" value="always" /><embed type="application/x-shockwave-flash" width="640" height="360" src="//www.youtube.com/v/fulrSt5rwk4?version=3&hl=tr_TR" allowfullscreen="true" allowscriptaccess="always"></embed>
</object>
</p>
<p>Bir başka görsel dersimizde görüşünceye dek hepinize mutlu günler dilerim.</p>2014-07-07T12:04:00+00:00bsenyurthttps://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=7d2e139a-5ebf-4380-afb6-ec45fd04950c8https://www.buraksenyurt.com/trackback.axd?id=7d2e139a-5ebf-4380-afb6-ec45fd04950chttps://www.buraksenyurt.com/post/AspNete28093Farklc4b1-Ortam-Farklc4b1-Config-Farklc4b1-Deploy#commenthttps://www.buraksenyurt.com/syndication.axd?post=7d2e139a-5ebf-4380-afb6-ec45fd04950chttps://www.buraksenyurt.com/post/AspNete28093Dogru-async-await-Kullanc4b1mc4b1Asp.Net–Doğru async, await Kullanımı2014-06-27T04:00:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p>Bazen web sayfalarının yüklenmesi sırasında senkron olarak çalışan ve uzun süren işlemler gerçekleştiririz<em>(ki aslında Web uygulamalarında bu tip yaklaşımları pek tercih etmeyiz)</em> Sayfada ki kontrollerde gösterilmek üzere çeşitli kaynaklardan veri çekilmesi buna örnek olarak verilebilir. Bu tip veri yükleme işlemleri ağırlıklı olarak <strong>Page_Load</strong> olay metodu içerisinde gerçekleştirilir. Uzun süren işlemlerin kısa sürede tamamlanabilmesi için farklı teknikler mevcuttur. Bir tanesi de asenkron olarak çalışabilmelerini sağlamaktır<em>(Örneğin zaman kaybettiren servis çağrılarının, veri çekme işlemlerinin eş zamanlı hale getirilmesi)</em></p>
<p><strong>.Net</strong> dünyasında bu tip asenkron işleri kolaylaştıran <strong>async</strong>, <strong>await</strong> keyword’ leri artık yaygın olarak kullanılmakta. Lakin Web dünyasında biraz daha dikkatli olmak gerekir. Nitekim bir web sayfasının yaşam döngüsü<strong><em>(Page Life-Cycle)</em>,</strong> <strong>async </strong>geri bildirimlerini sorunsuz şekilde ele alan <strong>Windows UI Thread</strong>’ lerinden biraz daha farklı çalışmaktadır. Güvenilir ve stabil bir ortam söz konusu değildir. Dahası <strong>HTTP 503</strong> hatasının alınmasına neden olabilecek vakalar vardır. İşte bu görsel dersimizde bir sayfanın yüklenmesi esnasında asenkron hale getirilmesi istenen işlemlerde uygulanabilecek doğru ve tavsiye edilen bir pratiği incelemeye çalışacağız.</p>
<p>
<object width="640" height="360">
<param name="movie" value="//www.youtube.com/v/palXWq8li-8?version=3&hl=en_US" />
<param name="allowFullScreen" value="true" />
<param name="allowscriptaccess" value="always" /><embed type="application/x-shockwave-flash" width="640" height="360" src="//www.youtube.com/v/palXWq8li-8?version=3&hl=en_US" allowfullscreen="true" allowscriptaccess="always"></embed>
</object>
</p>
<p>Bir başka görsel dersimizde görüşmek dileğiyle.</p>2014-06-27T04:00:00+00:00bsenyurthttps://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=f0e659dd-ec81-4e25-8414-a19d3ef4e9049https://www.buraksenyurt.com/trackback.axd?id=f0e659dd-ec81-4e25-8414-a19d3ef4e904https://www.buraksenyurt.com/post/AspNete28093Dogru-async-await-Kullanc4b1mc4b1#commenthttps://www.buraksenyurt.com/syndication.axd?post=f0e659dd-ec81-4e25-8414-a19d3ef4e904https://www.buraksenyurt.com/post/AspNet-4-5-Asenkron-HTTP-Module-GelistirmekAsp.Net 4.5–Asenkron HTTP Module Geliştirmek2013-10-13T11:00:00+00:00bsenyurt<p><a href="https://www.buraksenyurt.com/pics/Pioneer%20Stereo%20Ad%201974.jpg"><img style="float: right; margin: 4px 0px; display: inline;" title="Pioneer Stereo Ad 1974" src="/pics/Pioneer%20Stereo%20Ad%201974_thumb.jpg" alt="Pioneer Stereo Ad 1974" width="240" height="313" align="right" /></a>Merhaba Arkadaşlar,</p>
<p>Bir çoğunuz gibi ben de düzenli olarak bazı dergilerin abonesiyim ve her ay onları alıp biraz karıştırdıktan sonra arşive<em>(yani çalışma odasındaki kütüphaneye)</em> kaldırmaktayım.</p>
<p>Tabi gün oluyor pek çoğuna dönüp bakmıyorum bile. Hatta kimisinin rengi sararıp soluyor bir köşede mazlum mazlum kalıyor. Ama eminim ki geride kalanlar için bazıları güncel içeriklere sahip iken, bazıları da tam anlamıyla bir Retro havası veriyor. Ve hatta çoğu, yıllar geçtikçe daha fazla değer kazanıyor.</p>
<p>Söz gelimi yandaki basılı medya görselinde 1974 model bir Pioneer ses sisteminin reklamı yer almakta. Bu pek çoğumuzun daha henüz hayatta bile olmadığı, olsa da pek hatırlamadığı bir yıl belki de? Sanıyorum blog tutan bizlerin yazıları da, zaman içerisinde bu şekilde eskiyor. Hele de yazılım teknolojileri gibi çok çabuk gelişen konular ele alınıyorsa.</p>
<p>Ben bazen geçmişte yazmış olduğum yazılara bakıyorum ve ne kadar da çabuk eskidiklerini görüyorum. Ancak bir yandan da, “acaba yeni sürümde bu konuda neler yapılmış?” sorusunun cevabını da kurcalamaya çalışıyorum.</p>
<blockquote>
<p>Nostalji : <a href="https://www.buraksenyurt.com/post/HTTPHandler-ve-HttpModule-Kavramlarc4b1-bsenyurt-com-dan" target="_blank">2006 dan</a> bir makale. O zamanlar Asp.Net Pipeline’ ın önemli parçaları olan HttpModule ve HttpHandler kavramlarını incelemeye çalışmıştım.</p>
</blockquote>
<p>İşte bu günkü konumuzda <strong>HttpModule</strong> tipleri içerisindeki işlemleri asenkron olarak nasıl yaptırabileceğimizi incelemeye çalışıyor olacağız. Bildiğiniz üzere <strong>.Net Framework 4.0</strong> ile hayatımıza giren <strong>Task</strong> ve doğal olarak <strong>Task Parallel Library</strong> kavramı, <strong>4.5</strong> sürümünde gelen <strong>async</strong> ve <strong>await</strong> anahtar kelimeleri ile birlikte alt yapının pek çok noktasında daha sık görülmeye başladı. Bu açıdan bakıldığında<strong> Asp.Net 4.5</strong> tarafında da ilgili anahtar kelime ve <strong>Task</strong> tiplerini kullanarak bazı senkronize edilmiş işlemlerin asenkron hale getirilmesi sağlanabilmekte.</p>
<blockquote>
<p><strong>Asp.Net</strong> ve asenkron çalışma diyince bir duraksayıp düşünmek gerekir.</p>
<p>Asp.Net aslında client-server modelini baz alarak çalışır ve stateless bir ortam sunar. Bu yüzden istemciden gelen her talep(Request) sonrası, uygulama ve talep gören sayfanın Lifecycle’ ının tekrar işletilmesi gerekir. Web tarafında asenkronluk diyince bunu belki de iki taraflı olarak düşünmek gerekebilir. Sunucu tarafında çalışan asenkron işlemler ve istemcinin kendi açısından asenkron olarak başlatıp, Response’ u beklemeye gerek kalmadan başka talepleri de gönderebildiği işlemler<em>(Genelde AJAX tarzı çağrılar ile hallettiğimiz çalışma şekli)</em> </p>
<p>Module ve Handler gibi tipler sunucu tarafında çalışan yapılar olduklarından, yazıda bahsedeceğimiz asenkron çalışma aslında, sunucu üzerinde söz konusu olan ve LifeCycle yaşamı boyunca ele alınan yapılar olarak düşünülmelidirler.</p>
</blockquote>
<p>Bu işten nasibini alan kısımlardan ikisi de <strong>Asp.Net</strong> uygulamalarının yaşam döngüsünde önemli yere sahip olan <strong>Module</strong> ve <strong>Handler’</strong> lardır. Aslında bir Web sayfasını talep ettiğimizde, sunucu tarafında gerçekleşen bir dizi işlem söz konusudur. Ayrıca yaşam döngüsüne ait süreçte devreye giren bir kanal yapısı mevcuttur. Bu kanal yapısına göre istemciden gelen <strong>Request’</strong> in önce <strong>Http</strong> bazlı <strong>Module’</strong> lerden geçmesi ve ardından da <strong>Handler’</strong> lar tarafından değerlendirilmesi söz konusudur. Klasik çalışma modeline baktığımızda aşağıdaki grafikte yer alan ve özetle ifade edilmeye çalışılan işleyişin gerçekleştiğini söyleyebiliriz.</p>
<h1><strong>Klasik Senkron Çalışma Modeli</strong></h1>
<p><a href="https://www.buraksenyurt.com/pics/ahm_1.png"><img style="margin: 4px 0px; display: inline;" title="ahm_1" src="/pics/ahm_1_thumb.png" alt="ahm_1" width="611" height="252" /></a></p>
<p>Görüldüğü gibi gelen talep, <strong>Built-In</strong> bazı <strong>Http</strong> <strong>Module’</strong> lerinden geçmekte ve <strong>Handler</strong> seviyesinde de değerlendirildikten sonra geriye döndürülmektedir. <em>(Bu çizelgede talep edilen içeriğe ait sayfa veya user control’ un iç çalışma şekli göz ardı edilmiştir)</em> Dikkat edilmesi gereken husus, <strong>Module</strong> ve <strong>Handler’</strong> lardan oluşan bu kanal yapısının <strong>Thread</strong> havuzundan çekilen tek bir <strong>Thread</strong> içerisinde uçtan uca çalışıyor olmasıdır. Dolayısıyla bir <strong>module’</strong> den diğerine olan geçiş sırasında, işlemekte olan module’ ün işini <span style="text-decoration: underline;">tamamlamış</span> olması gerekmektedir. Aynı durum doğal olarak <strong>Handler’</strong> lar için de geçerlidir.</p>
<h1>Asenkron Çalışma Modeli</h1>
<p>Asenkron çalışma modeline göre ise, bir <strong>Module</strong> veya <strong>Handler’</strong> ın kendi çalışmasını farklı bir <strong>Thread’</strong> e yıkması ve daha sonra ana <strong>Thread’</strong> e sonuç dönerek işleyişi uzun süre <span style="text-decoration: underline;">duraksatmaması</span> hedeflenmektedir. Bu, özellikle geliştirici tarafından yazılan <strong>Module</strong> veya <strong>Handler</strong> tipleri için kullanılabilecek bir stratejidir. Aşağıdaki grafikte bu yaklaşım modeli özetlenmeye çalışılmıştır.</p>
<p><a href="https://www.buraksenyurt.com/pics/ahm_2.png"><img style="margin: 4px 0px; display: inline;" title="ahm_2" src="/pics/ahm_2_thumb.png" alt="ahm_2" width="611" height="310" /></a></p>
<p>Dikkat edileceği üzere <strong>X Module</strong> tipi kendi işleyişini farklı bir <strong>Thread</strong> altında yapmaktadır. Dolayısıyla işlenmekte olan talebin akışı sırasında <strong>X</strong> modülüne gelindikten sonra, sıradaki <strong>Module</strong> veya takip eden <strong>Handler’</strong> lara geçilmesi için bir duraksama söz konusu değildir. İlgili <strong>Module</strong> çalışmasını tamamladığında, kanal içerisindeki işleyişe otomatikman dahil olacaktır.</p>
<h1>Asp.Net 4.5 için Örnek Uygulama</h1>
<p>Peki bu modeli <strong>Asp.Net 4.5</strong> içerisinde nasıl gerçekleştirebiliriz? Gelin basit ve klasik bir örnek üzerinden ilerleyelim. Bu amaçla <strong>Visual Studio 2012</strong> ortamında <strong>Asp.Net Empty Web Application</strong> tipinden bir proje açalım. Bir <strong>Web</strong> uygulamasında veya bir <strong>Application Pool</strong> içerisinde kendi <strong>Http</strong> <strong>Module’</strong> lerimizi kullanabilmenin yolu <strong>IHttpModule</strong> arayüzünden türeyen sınıflar geliştirmekten geçmektedir.</p>
<p><strong>IHttpModule</strong> kendi içerisinde <strong>Asenkron</strong> kullanım için doğal bir metod içermemektedir. Bunun yerine ezilmesi gereken <strong>Init</strong> ve <strong>Dispose</strong> metodlarını sunmaktadır. <strong>Init</strong> fonksiyonu tahmin edileceği üzere <strong>Module </strong>devreye girdiğinde yapılacak işlemleri içermekte ve icra ettirmektedir. Biz burada asenkron işleyişlere yer verebiliriz. Nasıl mı? İşte uygulama içerisindeki sınıf çizelgesi ve kod yapısı.</p>
<p><a href="https://www.buraksenyurt.com/pics/ahm_3.png"><img style="margin: 4px 0px; display: inline;" title="ahm_3" src="/pics/ahm_3_thumb.png" alt="ahm_3" width="360" height="521" /></a></p>
<p><strong>RequestLogInfo POCO tipinin içeriği;</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace HowTo_AsyncModules
{
public class RequestLogInfo
{
public string IpAddress { get; set; }
public DateTime Time { get; set; }
public bool IsAuthenticated { get; set; }
public string User { get; set; }
public string RequestType { get; set; }
public Uri Url { get; set; }
public override string ToString()
{
return string.Format("{0}|{1}|{2}|{3}|{4}|{5}"
,Time.ToLongTimeString()
,IpAddress
,IsAuthenticated.ToString()
,User
,RequestType
,Url.ToString()
);
}
}
}</pre>
<p><strong>RequestLogInfo</strong> örnek senaryoda kullanacağımız ve içerisinde istemciden gelen <strong>talep<em>(Request)</em></strong> ile ilişkili bir kaç basit bilgiyi içeren <strong>POCO<em>(Plain Old CLR Object)</em></strong> sınıfımızdır. Gelelim <strong>AsyncHttpLogModule</strong> sınıfının içeriğine.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Configuration;
using System.IO;
using System.Threading.Tasks;
using System.Web;
namespace HowTo_AsyncModules
{
public class AsyncHttpLogModule
:IHttpModule
{
public void Dispose()
{
// Do Something
}
public void Init(HttpApplication context)
{
EventHandlerTaskAsyncHelper eventHandler =new EventHandlerTaskAsyncHelper(WriteLogToTextFile);
context.AddOnPostAuthorizeRequestAsync(
eventHandler.BeginEventHandler
, eventHandler.EndEventHandler
);
}
private async Task WriteLogToTextFile(object sender, EventArgs e)
{
var context = HttpContext.Current;
string filePath = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["LogFileAddress"]);
RequestLogInfo requestLog = new RequestLogInfo()
{
Time = DateTime.Now,
IpAddress = context.Request["REMOTE_ADDR"],
User = context.User.Identity.Name,
IsAuthenticated = context.User.Identity.IsAuthenticated,
RequestType = context.Request.RequestType,
Url = context.Request.Url
};
using (StreamWriter streamWriter = File.AppendText(filePath))
{
await streamWriter.WriteLineAsync(requestLog.ToString());
}
}
}
}</pre>
<p>Örnek kod parçasında dikkat edileceği üzere <strong>Init</strong> metodu içerisinde gerçekleştirilen olay bazlı bir asenkron çalıştırma kayıt bildirimi söz konusudur. <strong>Init</strong> metodu içerisinde kullanılan <strong>EventHandlerTaskAsyncHelper </strong>sınıfı, <strong>TaskEventHandler</strong> <strong>temsilci(delegate)</strong> tipinden bir parametre almaktadır.</p>
<p>Aslında bu temsilci geriye <strong>Task</strong> örneği döndüren ve <strong>object</strong> ile <strong>EventArgs</strong> tipinden parametre alan metodları işaret edebilir ki örneğimizde bu fonksiyon <strong>WriteLogToTextFile</strong>’ dır. Bu metod <strong>async</strong> anahtar kelimesi ile işaretlendiğinden kendi içerisinde <strong>awaitable</strong> operasyonları da içerebilmektedir. Örnekte bunu sembolize etmek için <strong>StreamWriter</strong> tipinin asenkron çalışabilen <strong>WriteLineAsync</strong> metodu kullanılmıştır.</p>
<blockquote>
<p>Çok doğal olarak bir Module her zaman asenkron çalışacak şekilde <span style="text-decoration: underline;">tasarlanmamalıdır</span>. Nitekim içerisindeki işlemlerin sonucuna göre sonraki Module’ lere bilgi taşınması veya çalışmanın kesilerek anında bir Exception döndürülmesi vb durumlar söz konusu olabilir.</p>
</blockquote>
<p>İlgili asenkron işleyişlerde <strong>text</strong> tabanlı olarak fiziki bir dosyaya <strong>log</strong> atma işlemi sembolize edilmiştir. Pek tabi bunun yerine <strong>log</strong> içeriğinin veritabanına aktarılması, bir servise çağrıda bulunulması, harici 3ncü parti bir arayüz ile konuşulması<em>(Örneğin bir Bussines Process Management sistemine mesaj gönderilmesi)</em> ve benzeri zaman alabilecek ve dolayısıyla asenkron hale getirilebilecek işlemler ele alınabilir. Uygulamayı teste tabi tutmadan önce <strong>Web.config</strong> dosyası içerisinde, tasarlanmış olan yeni <strong>HttpModule</strong> tipine ait bildirimin de yapılması gerekmektedir ki çalışma zamanı var olan <strong>Module’</strong> lere ek olarak <strong>AsyncHttpLogModule </strong>örneğini de devreye alabilsin. Bunun için <strong>system.webServer</strong> elementi içerisinde aşağıdaki <strong>module</strong> tanımlaması yapılmalıdır.</p>
<h1>Config Ayarlarmaları</h1>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules>
<add name="AsyncLogModule" type="HowTo_AsyncModules.AsyncHttpLogModule,HowTo_AsyncModules"/>
</modules>
</system.webServer>
<appSettings>
<add key="LogFileAddress" value="~/App_Data/Logs.txt"/>
</appSettings>
</configuration></pre>
<p><strong>modules</strong> elementi içerisinde dikkat edilmesi gereken nokta <strong>type</strong> niteliğine atanan değerdir. Burada <strong>[Namespace Adı].[Module Tip Ad],[Assembly Adı]</strong> notasyonundan yararlanılmıştır. Bu, özellikle ilgili <strong>Module</strong> tipinin harici bir <strong>Class Library</strong> içerisinde olduğu durumlarda ön plana çıkan önemli kurallardan birisidir.</p>
<h1>Test</h1>
<p><strong>Test</strong> için dilerseniz çok basit bir de <strong>aspx</strong> sayfası hazırlayalım. Böylece basit anlamda <strong>Get</strong>, <strong>Post</strong> gibi aksiyonları simüle ettirmiş oluruz.</p>
<p><strong>Örnek aspx içeriği;</strong></p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HowTo_AsyncModules.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
Mesajınız : <asp:TextBox ID="txtMessage" runat="server" /><br />
<asp:Button ID="btnSendMessage" runat="server" Text="Send My Message" OnClick="btnSendMessage_Click"/>
</div>
</form>
</body>
</html></pre>
<p><strong>WebForm</strong> içerisinde bir <strong>TextBox</strong> ve <strong>Button</strong> kontrolü bulunmaktadır. Kullanıcı sayfayı ilk kez talep ettiğinde <strong>HTTP</strong> <strong>Get</strong> ve <strong>Button’</strong> a her bastığında da <strong>HTTP</strong> <strong>Post</strong> tipinden talepler üretilmesine neden olmaktadır. Çalışma zamanında yapılan çeşitli aksiyonlar sonrası oluşan örnek bir <strong>log</strong> içeriği ise aşağıda görüldüğü gibidir.</p>
<p><a href="https://www.buraksenyurt.com/pics/ahm_4.png"><img style="margin: 4px 0px; display: inline;" title="ahm_4" src="/pics/ahm_4_thumb.png" alt="ahm_4" width="579" height="345" /></a></p>
<p>Dikkat edileceği üzere geliştirici tanımlı bir <strong>HttpModule</strong> tipinin işleyişinin asenkron hale getirilmesi mümkündür. Aynı prensiplerden yola çıkarak bir <strong>HttpHandler</strong> tipinin de asenkron çalışacak hale getirilmesi söz konusu olabilir elbette. Lakin <strong>Asp.Net 4.5,</strong> <strong>HttpHandler</strong> tiplerinin asenkron yazılabilmesi için daha güçlü bir yol sunmaktadır. Bu yolun başında <strong>HttpTaskAsyncHandler</strong> isimli <strong>soyut sınıf<em>(Abstract Class)</em></strong> yer almaktadır. Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2012%2f9%2fHowTo_AsyncModules.zip">HowTo_AsyncModules.zip (25,83 kb)</a></p>2013-10-13T11:00:00+00:00asp.net 4.5asp.nethttp handlerasyncawaithttp moduleasynchttpmodulemoduleasp.net pipelineasp.net runtimebsenyurtİşte bu günkü konumuzda HttpModule tipleri içerisindeki işlemleri asenkron olarak nasıl yaptırabileceğimizi incelemeye çalışıyor olacağız. Bildiğiniz üzere .Net Framework 4.0 ile hayatımıza giren Task ve doğal olarak Task Parallel Library kavramı, 4.5 sürümünde gelen async ve await anahtar kelimeleri ile birlikte alt yapının pek çok noktasında daha sık görülmeye başladı. Bu açıdan bakıldığında Asp.Net 4.5 tarafında da ilgili anahtar kelime ve Task tiplerini kullanarak bazı senkronize edilmiş işlemlerin asenkron hale getirilmesi sağlanabilmekte.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=e9c952b8-2688-4081-967b-1e08021ba8962https://www.buraksenyurt.com/trackback.axd?id=e9c952b8-2688-4081-967b-1e08021ba896https://www.buraksenyurt.com/post/AspNet-4-5-Asenkron-HTTP-Module-Gelistirmek#commenthttps://www.buraksenyurt.com/syndication.axd?post=e9c952b8-2688-4081-967b-1e08021ba896https://www.buraksenyurt.com/post/AspNet-Routing-HatirlamakAsp.Net Routing – Hatırlamak2013-06-20T05:07:00+00:00bsenyurt<p><a href="https://www.buraksenyurt.com/pics/oblivious.jpg"><img style="margin: 4px 0px; display: inline; float: right;" title="oblivious" src="/pics/oblivious_thumb.jpg" alt="oblivious" width="320" height="207" align="right" /></a>Merhaba Arkadaşlar,</p>
<p>Geçtiğimiz günlerde şirkette çok küçük bir web uygulamasına ihtiyaç duyuldu. Neredeyse bir günlük geliştirme maliyeti olan, küçük bir departmanın önemli bir gereksinimi karşılayacaktı. Tabi insan uzun zaman kodlama yapmayınca veya kodlamaya ara verince bazı temel bilgileri de unutabiliyor.</p>
<p>Ben de kafayı <strong>Team Foundation Server</strong> entegrasyonu, <strong>SOA </strong>mimarisi ve <strong>Scrum</strong> gibi metodolojiler ile bozunca, zihinsel diskimdeki ana <strong>partition</strong>’ a yeni bilgilerin yazıldığına ve eskilerinin yerinde yeller estiğine şahit oldum. Ama malum, günümüz teknolojilerinde bilginin tamamını ezberlemeye çalışmak yerine, en doğrusuna en hızlı şekilde nasıl ulaşabileceğimizi bilmek daha önemli. İşte bu felsefeden yola çıkıp dedim ki, şu <strong>Asp.Net Routing</strong> konusunu bir hatırlayayım ve hatta kayıt altına alayım. İşte hikayemiz böyle başladı <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_96.png" alt="Smile" /></p>
<p>Asp.Net MVC’ nin en cazip yanlarından birisi sanırım sağladığı <strong>URL</strong> eşleştirme<em>(Routing)</em> sistemidir. Özellikle <strong>Search Engine Optimization<em>(SEO)</em></strong> kriterleri göz önüne alındığında, <strong>orders.aspx?categoryName=Beverages&shipCity=istanbul&orderNumber=12903 </strong>gibi bir ifade yerine, <strong>orders/beverages/istanbul/12903 </strong>şeklinde bir <strong>URL</strong> çok daha değerlidir.</p>
<p>Bilindiği üzere <strong>Asp.Net 4.0</strong> sürümü ile birlikte, <strong>URL</strong> ve asıl kaynak<em>(aslında yönlendirme sonucu gidilmesi gereken bir aspx sayfa kodu düşünebiliriz)</em> eşleştirmelerinde kullanılan yönlendirme işlemleri oldukça kolaylaştırılmıştır. İşte bu yazımızda, biraz temelleri hatırlamaya çalışacak ve <strong>SEO</strong>’cu arama motorlarının olmassa olmaz isterlerinden birisi olan <strong>Routing</strong> konusunu dört basit örnek üzerinden inceleyeceğiz. İlk olarak senaryomuza bir göz atalım.</p>
<h1>Senaryo</h1>
<p>Senaryomuzda veri kaynağı olarak emektar <strong>Northwind</strong> veritabanını kullanacağız. Örneklerimizde hem <strong>Entity Framework</strong> kullanacağımız hem de doğrudan <strong>SQL</strong> sorgusu çalıştıracağımız bir vakamız yer alacak. Temel olarak amacımız aşağıdaki ekran görüntüsünde yer alan <strong>URL</strong> eşleştirmelerini web uygulaması üzerinden işlettirmek.</p>
<p><a href="https://www.buraksenyurt.com/pics/route_2.png"><img style="margin: 4px 0px; display: inline;" title="route_2" src="/pics/route_2_thumb.png" alt="route_2" width="624" height="258" /></a></p>
<p>Dikkat edileceği üzere <strong>URL</strong> satırından girilecek olan anlamlı ifadeler, aslında arka planda bir eşleştirme tablosuna uygun olacak şekilde ilgili kaynaklara yönlendirilmekteler. Örneğin <strong>beverages</strong> isimli kategoride yer alan ürünlerin listelenmesi için yazılan <strong>urunler/beverages</strong> sorgusu, sisteme daha önceden öğretilen <strong>Urunler/{CategoryName}</strong> üzerinden geçerek <strong>urun.aspx</strong> sayfasına yönlendiriliyor. Çok doğal olarak ilgili sayfa içerisinde, <strong>CategoryName</strong> değerine bakılarak bir sonuç kümesinin sunulması gerekiyor.</p>
<h1>Route Eşleştirmelerinin Ayarlanması</h1>
<p>Bu işlem için <strong>global.asax.cs</strong> dosyasında aşağıdaki kodlamaları yapmamız gerekmektedir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Web;
using System.Web.Routing;
namespace HowTo_EasyRouting
{
public class Global
: HttpApplication
{
private void SetRouteMaps()
{
RouteTable.Routes.MapPageRoute("Varsayilan", "", "~/kategori.aspx");
RouteTable.Routes.MapPageRoute("Kategoriler", "kategoriler", "~/kategori.aspx");
RouteTable.Routes.MapPageRoute("KategoriBazliUrunler","urunler/{CategoryName}","~/urun.aspx");
RouteTable.Routes.MapPageRoute("SehirBazliSiraliMusteriler", "musteriler/{City}$orderby={FieldName}", "~/musteri.aspx");
RouteTable.Routes.MapPageRoute("SehirBazliSiparisler", "siparisler/{ShipCity}", "~/siparis.aspx");
}
protected void Application_Start(object sender, EventArgs e)
{
SetRouteMaps();
}
}
}</pre>
<p><strong>Application_Start</strong> olay metodu bilindiği üzere, Web uygulaması ayağa kalktığında devreye girmektedir. Dolayısıyla uygulamanın başladığı bir yerde, <strong>URL</strong> eşleştirme tanımlamalarını yapmak son derece mantıklıdır. Olayın ana kahramanı <strong>RouteTable</strong> sınıfıdır. Söz konusu tipin <strong>static</strong> olarak erişilebilen <strong>Routes</strong> özelliği bir <strong>RouteCollection</strong> referansını işaret etmektedir. Bu koleksiyon tahmin edileceği üzere <strong>URL</strong> ile asıl kaynak eşleştirmelerini taşımaktadır. Bu nedenle <strong>MapPageRoute</strong> metodundan da yararlanılarak gerekli eşleştirme bilgileri koleksiyona eklenir.</p>
<p>İlk satır ile <strong>Root URL</strong> adresine gelen bir talebin doğrudan <strong>kategori.aspx</strong> sayfasına yönlendirilmesi gerektiği ifade edilmektedir. İkinci satırda ise web kök adresini takiben kategoriler şeklinde gelen bir ifadenin gelmesi halinde yine, kategori.aspx sayfasına gidilmesi gerektiği belirtilmektedir.</p>
<p><strong>KategoriBazliUrunler</strong> ismi ile tanımlanmış eşleştirmeye göre, <strong>urunler/{CategoryName}</strong> şeklinde gelen talepler <strong>urun.aspx</strong> sayfasına yönlendirilmektedir. İlginç kullanımlardan birisi de <strong>SehirBazliSiraliMusteriler</strong> isimli eşleştirmedir. Burada <strong>City</strong> ve <strong>FieldName</strong> isimli iki <strong>Route</strong> parametresi söz konusudur. İfade ise size sanıyorum tanıdık gelecektir. Neredeyse bir <strong>REST</strong> servis sorgusuna<em>(örneğin <strong>OData</strong> sorgusuna)</em> oldukça yakın değil mi? <img class="wlEmoticon wlEmoticon-nerdsmile" style="border-style: none;" src="/pics/wlEmoticon-nerdsmile_1.png" alt="Nerd smile" /></p>
<p>Şimdi bu durumları kod tarafında nasıl karşılayacağımızı örnek bir Asp.Net uygulaması üzerinden incelemeye çalışalım.</p>
<h1>Birinci Durum</h1>
<p>İlk olarak <strong>kategori.aspx</strong> sayfasına doğru yapılacak yönlendirmeleri ele almaya çalışacağız. Bunun için web uygulamamıza <strong>kategori.aspx</strong> isimli bir sayfa ekleyip içeriği ile kod tarafını aşağıdaki gibi geliştirelim.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Kategori.aspx.cs" Inherits="HowTo_EasyRouting.Kategori" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div id="divCategories" runat="server" style="background-color:lightcyan">
</div>
</form>
</body>
</html></pre>
<p>kod tarafı</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace HowTo_EasyRouting
{
public partial class Kategori
: Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
using (NorthwindEntities context = new NorthwindEntities())
{
var categories = from c in context.Categories
orderby c.CategoryName
select new
{
c.CategoryID,
c.CategoryName
};
foreach (var category in categories)
{
HyperLink categoryLink = new HyperLink();
categoryLink.NavigateUrl = GetRouteUrl("KategoriBazliUrunler", new { CategoryName = category.CategoryName });
categoryLink.Text = string.Format("[{0}]-{1}<br/>", category.CategoryID.ToString(), category.CategoryName);
divCategories.Controls.Add(categoryLink);
}
}
}
}
}
}</pre>
<p>Aslında <strong>kategori.aspx</strong> sayfasında tipik olarak <strong>Entity Framework</strong> odaklı bir sorgulama gerçekleştirilmekte ve kategori adları birer <strong>HyperLink</strong> bileşeni olarak <strong>div</strong> içerisine eklenmektedir. Konu itibariyle işin önemli olan kısmı ise <strong>HyperLink</strong> bileşeninin <strong>NavigateUrl</strong> özelliğine <strong>GetRouteUrl</strong> metodu sonucunun atanmasıdır.</p>
<p><strong>GetRouteUrl</strong> metodu dikkat edileceği üzere iki parametre alır. İlk parametre <strong>route</strong> adıdır. Yazdığımız değere göre <strong>urunler/{CategoryName}</strong> şeklindeki atama değerlendirilir. İkinci parametre ise bu <strong>Route</strong> içerisinden kullanılmak istenen değişken adı ve değerini içeren nesnenin örneklendiği kısımdır. <strong>CategoryName</strong> tahmin edileceği üzere <strong>Route</strong> tanımı içerisindeki parametre adıdır. Değeri ise zaten <strong>LINQ<em>(Language INtegrated Query)</em></strong> sorgusu içerisinden elde edilmektedir. İkinci parametre <strong>object</strong> tipinden olduğundan <strong>bir isimsiz tip<em>(anonymous type)</em></strong> ataması yapılabilmiştir. Bu nedenle <strong>Route</strong> içerisinde birden fazla parametre olması halinde, isimsiz tipin de birden fazla özellik içermesi gerektiğini ifade edebiliriz.</p>
<p>İlk durumda herhangibir sayfa talep edilmediğinde veya kök web adresi ardından <strong>/kategoriler</strong> şeklinde bir <strong>URL</strong> ifadesi kullanıldığında, aşağıdaki ekran görüntüsünde yer alan sonuçlar ile karşılaşırız.</p>
<p><a href="https://www.buraksenyurt.com/pics/route_3.png"><img style="margin: 4px 0px; display: inline;" title="route_3" src="/pics/route_3_thumb.png" alt="route_3" width="369" height="331" /></a></p>
<p>Dikkat edilmesi gereken en önemli nokta, her hangi bir bağlantı üstüne gelindiğinde oluşan sorgu adresidir. Örneğin <strong>Condiments</strong> için <strong>http://localhost:54605/urunler/condiments</strong> şeklinde bir <strong>URL</strong> tanımı oluşmuştur. Peki bu bağlantıya tıklanırsak ne olur? <img class="wlEmoticon wlEmoticon-whome" style="border-style: none;" src="/pics/wlEmoticon-whome_10.png" alt="Who me?" /></p>
<h1>İkinci Durum</h1>
<p><strong>kategori.aspx</strong> sayfasında bir bağlantıya tıklandığında, <strong>HyperLink</strong> bileşeninin <strong>NavigateUrl</strong> özelliğinin sahip olduğu değerin <strong>Route</strong> tablosundaki eşleniğine bakılmalıdır. Yaptığımız tanımlamalara göre <strong>urun.aspx</strong> sayfasına gidilmesi beklenmelidir<em>(KategoriBazliUrunler isimli Route tanımına dikkat edin)</em> Buna göre <strong>urun.aspx</strong> sayfasının içeriğini aşağıdaki gibi düzenleyebiliriz.</p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Urun.aspx.cs" Inherits="HowTo_EasyRouting.Urun" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1 style="color:purple">
<asp:Label ID="lblCategoryName" runat="server" /></h1>
<br />
<asp:GridView ID="grdUrunler" runat="server" />
</div>
</form>
</body>
</html></pre>
<p>kod tarafı</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Linq;
using System.Web.UI;
namespace HowTo_EasyRouting
{
public partial class Urun
: Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (RouteData.Values["CategoryName"] != null)
{
string categoryName = RouteData.Values["CategoryName"].ToString();
using (NorthwindEntities context = new NorthwindEntities())
{
var products = from p in context.Products.Include("Product")
where p.Category.CategoryName == categoryName
orderby p.ProductName
select new
{
p.ProductID,
p.ProductName,
p.UnitPrice
};
grdUrunler.DataSource = products.ToList();
grdUrunler.DataBind();
}
}
else
Response.Redirect(GetRouteUrl("Kategoriler", null));
}
}
}</pre>
<p>Tabi bu sayfaya gelindiğinde aslında <strong>Route</strong> tanımlaması içerisinde yer alan parametre değerinin okunması gerekmektedir. Bu sebepten sayfanın <strong>RouteData</strong> özelliğinden hareket edilerek <strong>RouteValueDictionary</strong> tipinden olan <strong>Values</strong> özelliğine gidilir ve indeksleyiciye verilen <strong>CategoryName</strong> alanının var olup olmadığına bakılır. Malum urun.aspx sayfasına farklı bir şekilde erişilmek istenebilir ve <strong>CategoryName</strong> değeri null olarak gelebilir. Bu nedenle bir <strong>null</strong> değer kontrolü ardından <strong>Entity</strong> sorgulama işlemi yapılmıştır. <strong>RouteData.Values[“CategoryName”] </strong>ile <strong>URL</strong> satırındaki kategori adı bilgisi alındıktan sonra standart olarak bir <strong>Entity</strong> sorgusu icra edilmektedir. Eğer kategori adı <strong>null </strong>olarak gelirse bu durumda varsayılan <strong>URL</strong> eşleştirilmesi nedeniyle kategorilerin gösterildiği sayfaya gidilir.</p>
<p><a href="https://www.buraksenyurt.com/pics/route_4.png"><img style="margin: 4px 0px; display: inline;" title="route_4" src="/pics/route_4_thumb.png" alt="route_4" width="399" height="421" /></a></p>
<h1>Üçüncü Durum</h1>
<p><strong>URL</strong> eşleştirmelerinden <strong>SehirBazliSiraliMusteriler</strong> isimli olanı, iki adet <strong>route</strong> parametresi içermektedir. Burada başta da belirttiğimiz üzere <strong>OData</strong> sorgularına benzer bir ifade tanımlanmıştır. Eşleştirme bilgisine göre <strong>musteri.aspx</strong> sayfasına doğru bir yönlendirme söz konusudur. <strong>musteri.aspx</strong> içeriğini aşağıdaki gibi geliştirdiğimizi düşünelim.</p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Musteri.aspx.cs" Inherits="HowTo_EasyRouting.Musteri" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1 style="color:purple">Customers</h1>
<asp:GridView ID="grdCustomer" runat="server" />
</div>
</form>
</body>
</html></pre>
<p>kod tarafı</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Linq;
using System.Reflection;
using System.Web.Routing;
namespace HowTo_EasyRouting
{
public partial class Musteri : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(RouteData.Values["City"]!=null
|| RouteData.Values["FieldName"]!=null)
{
string cityName=RouteData.Values["City"].ToString();
string fieldName=RouteData.Values["FieldName"].ToString();
using(NorthwindEntities context=new NorthwindEntities())
{
var customers = context
.Customers
.Where(c => c.City == cityName)
.OrderBy(GetField<Customer>(fieldName))
.Select(c => new
{
ID=c.CustomerID,
Title=c.ContactTitle,
Contact=c.ContactName,
Company=c.CompanyName,
c.City
});
grdCustomer.DataSource = customers.ToList();
grdCustomer.DataBind();
}
}
}
public static Func<T, string> GetField<T>(string fieldName)
{
PropertyInfo pInfo=typeof(T).GetProperty(fieldName);
if (pInfo == null)
pInfo = typeof(T).GetProperty("CustomerID");
return o => Convert.ToString(pInfo.GetValue(o, null));
}
}
}</pre>
<p><strong>RouteData.Values</strong> özelliğinden yararlanılarak <strong>CityName</strong> ve <strong>FieldName</strong> değerlerinin <strong>null</strong> olup olmamasına göre bir kod parçası çalıştırılmaktadır. Bir önceki örnekten farklı bir durum olmasa da <strong>Entity</strong> sorgusunda <strong>OrderBy</strong> <strong>extension</strong> metodunu nasıl kullandığımıza dikkat etmenizi rica ederim. İşte bu vakaya ait örnek ekran çıktıları.</p>
<p><em>Londra’ daki müşterilerin CustomerId bilgilerini göre sıralı olarak çekilmesi</em></p>
<p><a href="https://www.buraksenyurt.com/pics/route_5.png"><img style="margin: 4px 0px; display: inline;" title="route_5" src="/pics/route_5_thumb.png" alt="route_5" width="576" height="322" /></a></p>
<p><em>Londra’ daki müşterilerin ContactName bilgisine göre sıralı olarak çekilmesi</em></p>
<p><a href="https://www.buraksenyurt.com/pics/route_6.png"><img style="margin: 4px 0px; display: inline;" title="route_6" src="/pics/route_6_thumb.png" alt="route_6" width="581" height="333" /></a></p>
<h1>Dördüncü Durum</h1>
<p>Son vakada bir <strong>Route</strong> parametrenin her hangi bir veri bağlı kontrol ile nasıl ilişkilendirilebileceğini görmeye çalışacağız. Örneğin bir <strong>SqlDataSource</strong> bileşenindeki <strong>Select</strong> sorgusuna ait <strong>Where</strong> koşullarını <strong>Route</strong> parametreler ile ilişkilendirebiliriz. Bu durumu <strong>siparis.aspx</strong> sayfası içerisinde ele almaya çalışalım. <strong>Siparis</strong> sayfasına gelinebilmesi için <strong>Route</strong> tablo tanımlamalarına göre <strong>/siparisler/{ShipCity}</strong> şeklinde bir <strong>URL</strong> talebinin gönderilmesi gerekmektedir.</p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Siparis.aspx.cs" Inherits="HowTo_EasyRouting.Siparis" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1 style="color:purple">Siparişler</h1>
<asp:GridView ID="grdOrders" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataKeyNames="OrderID" DataSourceID="SqlDataSource1" >
<Columns>
<asp:BoundField DataField="OrderID" HeaderText="OrderID" InsertVisible="False" ReadOnly="True" SortExpression="OrderID" />
<asp:BoundField DataField="CustomerID" HeaderText="CustomerID" SortExpression="CustomerID" />
<asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" SortExpression="EmployeeID" />
<asp:BoundField DataField="ShippedDate" HeaderText="ShippedDate" SortExpression="ShippedDate" />
<asp:BoundField DataField="ShipCity" HeaderText="ShipCity" SortExpression="ShipCity" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [OrderID], [CustomerID], [EmployeeID], [ShippedDate], [ShipCity] FROM [Orders] WHERE ([ShipCity] = @ShipCity)">
<SelectParameters>
<asp:RouteParameter DefaultValue="" Name="ShipCity" RouteKey="ShipCity" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html></pre>
<p>Önemli olan, <strong>SqlDataSource</strong> bileşenine ait <strong>SelectCommand</strong> ifadesindeki <strong>where</strong> koşulunda yer alan <strong>ShipCity</strong> isimli parametrenin bir <strong>RouteParameter</strong> ile ilişkilendirilmiş olmasıdır. <strong>RouteParameter</strong> bileşenine ait <strong>RouteKey</strong> özelliği, <strong>Route Table</strong>’ daki ile aynı olmalıdır. Çok doğal olarak <strong>aspx</strong> kaynak tarafında yapılabilen bu eşleştirme, <strong>Wizard</strong> üzerinden de kolayca belirlenebilir. Aynen aşağıdaki ekran görüntüsünde olduğu gibi <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_198.png" alt="Winking smile" /></p>
<p><a href="https://www.buraksenyurt.com/pics/route_1.png"><img style="margin: 4px 0px; display: inline;" title="route_1" src="/pics/route_1_thumb.png" alt="route_1" width="574" height="760" /></a></p>
<p>Buna göre örneğin Stuttgart’ a yapılan sevkiyatları aşağıdaki gibi elde edebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/route_7.png"><img style="margin: 4px 0px; display: inline;" title="route_7" src="/pics/route_7_thumb.png" alt="route_7" width="513" height="403" /></a></p>
<h1>Sonuç</h1>
<p>Görüldüğü üzere <strong>URL</strong> eşleştirme işlemleri klasik sunucu tabanlı <strong>Asp.Net </strong>uygulamalarında da etkili bir şekilde kullanılabilir. Hatta bu felsefeden yola çıkarak <strong>OData</strong> sorgularının daha fazla gelişmişlerini destekleyecek web uygulamaları yazılması da pekala olasıdır. Yazımıza konu olan basit örneklerimizde ki anahtar noktalar, <strong>RouteTable</strong> sınıfı, <strong>RouteData.Values</strong> özelliği ve <strong>GetRouteUrl</strong> metodudur. Örneği geliştirmek tamamen sizin elinizde. İşe <strong>/siparisler/stuttgart/10301/</strong> şeklinde bir sorguyu ele alıp, <strong>10301</strong> numaralı siparişe ait detay bilgileri göstereceğiniz bir sayfayı üretmeyi deneyerek başlayabilirsiniz. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2013%2f3%2fHowTo_EasyRouting.zip">HowTo_EasyRouting.zip (605,23 kb)</a></p>2013-06-20T05:07:00+00:00asp.netroutingroute tablemvcmodel view controllerurlurl mappingbsenyurtAsp.Net MVC’ nin en cazip yanlarından birisi sanırım sağladığı URL eşleştirme(Routing) sistemidir. Özellikle Search Engine Optimization(SEO) kriterleri göz önüne alındığında, orders.aspx?categoryName=Beverages&shipCity=istanbul&orderNumber=12903 gibi bir ifade yerine, orders/beverages/istanbul/12903 şeklinde bir URL çok daha değerlidir.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=9ea12f5b-1b7a-4f4a-8f26-90f8c860e6284https://www.buraksenyurt.com/trackback.axd?id=9ea12f5b-1b7a-4f4a-8f26-90f8c860e628https://www.buraksenyurt.com/post/AspNet-Routing-Hatirlamak#commenthttps://www.buraksenyurt.com/syndication.axd?post=9ea12f5b-1b7a-4f4a-8f26-90f8c860e628