2014 yılından itibaren farklı isim ve geliştirme ortamları ile açık kaynak kod ve topluluklar önderliğinde başlayan serüven nihayet son şeklini aldı. K, KRE, DNX, DNVM derken hepsini tek bir çatı altında toplamayı başarıp devasa büyüklükteki ekosistemi bulut ve farklı platformlar ile uyumlu hale getirebilen yeni araç 27 Haziran da RTM olarak sunuldu.

dotnet CLI (.NET Core command-line tools)

Eski olarak dahi nitelemenin güç olduğu araç seti DNX, DNVM ve DNU geçiş sürecini tamamlayarak aynı görevleri yerine getirebilen dotnet cli (Command Line Interface) çatısı altında tekilleştirildi.
Bu sürece şimdiden dahil olanlar önceki adımları keyfe keder araştırabilir, süreci gözlemliyebilmek adına araştırma yapabilir fakat bundan sonra işimiz "dotnet".

Dotnet CLI ile cross-platform .NET uygulamaları geliştirmeye başlayabilmek için basit bir kurulum yöntemi sağlanmış. Go, python ve ruby benzeri çoklu platformları destekleyebilen programlama dillerinin herhangi birisi için geliştirme ortamının elde edilmesi ve çalıştırılması aşağıdakine benzer adımları içerir.

Örneğin:

foo-get install foolang -<version> #apt-get veya nuget
basit bir hello world programı için foo.lg dosyası oluştur
foolang foo #derle ve foo dosyasını çalıştır

İşte tam bu noktada dotnet; benzer bir yapıda .NET Core SDK kurabilmenize, C# veya F# programlama dilleri ile dağıtık konsol uygulamaları, performanslı web projeleri ve taşınabilir kütüphaneler - programlar oluşturmanızı sağlamaktadır.

Dotnet ile bir konsol uygulaması oluşturabilmek için sırasıyla;

  1. Yeni bir klasör oluşturun
  2. Bu klasöre geçin
  3. dotnet new
  4. dotnet restore
  5. dotnet run

komutlarını işletmeniz gerekmektedir. 5 küçük adım ile yeni bir dotnet projesi oluşturmuş olup, dotnet restore komutu ile paket gereksinimlerinin otomatik çözümlenmesini sağlayabilirsiniz. Dizine yakından baktığımızda dotnet tarafından oluşturulan program.cs ve project.json dosyalarını görebiliriz. Program.cs dosyasında belirtilen public Main() isimli, konsol uygulamalarında karşılaştığımız uygulama başlangıç metodu artık tüm ASP.NET Core uygulamaları içinde geçerli!

Oluşturulan program.cs isimli dosyayı herhangi bir editör ile açarak birkaç düzenleme yapıp tekrar çalıştıralım:

Hello World. Time is: 12:34 PM

Dikkat ettiyseniz kodda yaptığımız değişiklikler dotnet run ile otomatik tekrar derlenip çalıştırıldı. Projenizin çalıştırılmadan sadece derlenmesini isterseniz dotnet build komutunu kullanabilirsiniz.

Burada dotnet projesini çalıştırmak için bir exe belirtilmemektedir. Project.json bu noktada uygulama gereksinimleri ve framework bilgisini tutarak çalışma şekline karar verebiliyor. Build süreci tarafından üretilen bin klasörü projenin desteklediği hedef frameworklere ait binary kodlar içermekte olup dotnet run komutu işletildiğinde uygulamanın derlenip derlenmeyeceği veya varolan kütüphanenin çalıştırılmaya hazır olduğuna karar verebilmektedir.

Komut satırı araçları başlangıç için işlemleri kolaylaştırmaktadır. Visual Studio ve kapsamlı tüm bileşenler yerine, bir text editör ve .NET Core SDK yüklemesi yapmanız cross-platfrom .NET Core uygulaması yazabilmeniz için yeterli. Visual Studio yüklemesi ile yaptığınız işlemler aslında bu dotnet cli araçlarını kullanarak projelerinizi derler ve işletir! Özellikle .NET Core ve ASP.NET Core için Visual Studio 2015 e eklenti olarak geliştirilen web araç seti favori geliştirme ortamınızın özelliklerini kullanarak da .NET Core uygulamaları yazmanıza olanak sağlamaktadır.

Özellikle .NET geliştiricilerinin komut satırı işelmlerine çok fazla ihtiyaç duymadıkları bilinmektedir. Son gelişmelere baktığımızda Microsoft, Azure ve .NET Core tarafında komut satırı ile daha fazla etkileşimde olacağımız değerlendirilmektedir. (Bash on Windows!)

Şu ana kadar basitçe yeni konsepti değelerdirmeye çalıştık. Peki ya ASP.NET Core! Aslında yapı çokda farklı değil, aynı altyapı üzerinde bir web uygulaması için program.cs ve project.json dosyalarında şu değişiklikleri yapmamız yeterli olacaktır.

İlk olarak project.json dosyasında web ve hosting araçları için gerekli olan kütüphaneyi global gereksinimler bölümüne ekleleyim:

"dependencies": {
	"Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
}
Namespaces
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
Kod bloğu
public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {            
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                "Hello World. The Time is: " + 
                DateTime.Now.ToString("hh:mm:ss tt")); 
        });
    }
}

dotnet restore ve dotnet run komutları işletildiğinde http://localhost:5000 portundan yayın yapabilen bir web sunucusunun çalıştığı gözlemlenebilir. Burada istenirse program.cs dosyasında belirtilen public Main() metodu startup.cs isimli dosya içerisinde de belirtilebilmektedir. dotnet.exe main metodunun çözümlenmesinde bu dosyayı da kullanabilmektedir!

ASP.NET Core uygulamaları aslında kendi içinde web özellikleri taşıyan bir konsol uygulamasıdır! Kestrel web sunucusu özelliklerini kullanarak host edilmektedir. Böylece uygulamanızın başlangıcından tüm ASP.NET Core Request Pipeline (İstek İşletimi) süreçlerinin kontrolünü sağlayabilirsiniz.

Middleware

Bu kavram bilindik ASP.NET uygulamalarından tecrübe edindiğimiz HttpHandlers ve HttpModules isminde tiplerin isteklere ve cevaplara etki etme özelliğini daha akıcı, yalın, basit ve Dependency Injection (DI) destekli bir yapı ile karşılamaktadır.

Kod örneğinde belirtildiği şekilde App.Run() metodu ile middleware tanımında kullandığımız kurgu sahne almaktadır. Böylece gelen tüm isteklere verilecek cevabı belirtmiş oluruz!

App.Use() metodunu kullanarak varsayılan cevabın değiştirilebildiğini gözlemleyebilirsiniz.

Module: Birincil işleme... 
Handler: Hello World. The Time is: 12:58:38 PM
Module: İşlem sonu...

ASP.NET MVC

App.Run() ve App.Use() metotları alt seviye işlemler için uygun bir yapıya sahip olup ASP.NET MVC framework ü tarafından uygulanmaktadırlar. Böylece bizlere daha hızlı, etkin, HTTP tabanlı, servis ve web uygulamaları yazabilmemiz için bir çok özellik barındıran altyapı oluşmaktadır.

Konsol uygulaması olarak örneklediğimiz projeyi basit bir web uygulamasına çevirmiştik. Şimdi ise ASP.NET MVC framework üne geçişini sağlayabilmek için:

project.json dosyasında global gereksinimlere,

"dependencies": {
	"Microsoft.AspNetCore.Mvc": "1.0.0"
}

paketi eklendikten sonra dotnet restore komutunu çalıştırdığımızda MVC için gerekli kütüphaneler nuget tarafından alt gereksinimleri ile birlikte çözümlenip, yüklenecektir.

program.cs dosyasını güncellediğimizde çıkan sonuç aşağıdaki şekilde olmalıdır.

Tek bir dosyada MVC, Middleware ve DI (Dependency Injection) kullanım şeklini hızlıca belirtip bir web uygulamasını ConfigureServices() ve Configure() metotları sırasıyla çağrılmak suretiyle aktif etmiş oluyoruz! Bu adımdan itibaren uygulamada kullanacağımız ekranları, metotları (Actions) ve bağlantıları (Routes) daha basit bir şekilde oluşturabiliriz.

Gerekli ayarları tamamladıktan sonra basit bir Echo API - Controller u yazabiliriz:

public class EchoController
{
    [HttpGet("api/echo")]
    public object Echo()
    {
        return new
        {
            message = "Hello World",
            time = DateTime.Now
        };
    }
}

program.cs dosyası içerisinde belirttiğimiz bu tip, Controller son ekiyle biten bir ifade uyguladığından otomatik olarak çözümlenip MVC tarafından işlenebilmektedir. Böylece Controller tipinden türemek zorunda olmayan POCO Controller ismiyle anılan bir tip oluşturmuş oluyoruz.

dotnet run komutu ile http://localhost:5000/api/echo adresine gittiğimizde şu şekilde bir JSON çıktısı elde etmemiz gerekmektedir.

{
	message: "Hello World",
	time: "2016-07-07T13:28:15.34107+03:00"
}

ASP.NET Core MVC isteği yapan istemcinin talep ettiği dönüş tipine göre cevabı belirler, aksi belirtilmedikçe cevap tipi JSON olarak ve küçük harfli key-value şeklinde çözümlenir!

MVC ve Razor

HTML ve Razor ikilisinin sunucu taraflı işletilip oluşan ekranlarımızı istemciye dönmesini sağlayabilmek için projede bir kaç değişiklik daha yapalım.

project.json dosyasında yine global gereksinimler bölümünde:

"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0"

paketini seçip dotnet restore komutu ile gerekli paketleri yükleyebiliriz. buildOptions bölümünde ise

"preserveCompilationContext": true

değerini set ederek ekranlar için dinamik derleme özelliğini aktif etmiş oluyoruz.

Main() metodunda hosting için belirlediğimiz ayarlara ek olarak UseContentRoot() metodu ile uygulamanın baz alacağı root klasörü belirlememiz gerekmektedir.

var host = new WebHostBuilder()
            .UseContentRoot(Directory.GetCurrentDirectory())
            ...

ASP.NET Core MVC iki tip temel sınıf sunmaktadır. Controller ve ControllerBase. MVC özelliklerini kullanabilmek için EchoController isimli POCO Controller sınıfımızın Controller tipinden türetilmesi gerekmektedir. ControllerBase ise View özelliklerinden arındırılmış Web API için daha sade hale getirilmiş varlıkları içermektedir.

public class EchoController : Controller
{
    [HttpGet("echoview")]
    public ActionResult EchoViewResult()
    {
        ViewBag.Message = "Hello world!";
        ViewBag.Time = DateTime.Now;

        return View("echoview.cshtml");
    }
}

ASP.NET Core MVC, ekranları varsayılan olarak Views klasörü altında ilişkili controller ismiyle eşleştirerek arama yapar! Biz burada root dizini kullanarak ve ekran ismini açıkca belirtirek basit bir şekilde bu metot için öngördüğümüz çıktının üretilmesini sağlayabiliyoruz. EchoView.cshtml içeriği:

<label>Message:</label>
@ViewBag.Message

<hr/>

<label>Time:</label>
@ViewBag.Time

http://localhost:5000/echoview bağlantısına gittiğimizde sonucun bu bağlantı için belirlediğimiz controller ile değişkenlerin ekran çıktısına işlendiğini görebilirsiniz.

Buraya kadar sıfırdan bir konsol uygulamasının çeşitli evrelerden geçerek bir web uygulamasına dönüştürülmesini sağladık!

IIS ve Reverse Proxy

ASP.NET Core uygulamalarının kestrel web sunucusu sayesinde kendi içinde çalışan (self-hosted) bir yapıda olduğunu belirtmiştik. Bu sayede bu tip uygulamalar IIS, nginx veya apache gibi web sunucularına ihtiyaç duymadan çalışabileceği sonucu çıkarılabilir. Bu pek de önerilen bir yöntem değildir. Front-End Reverse Proxy sayesinde uygulamanızı bir IIS veya nginx arkasında farklı portlar veya yük dengeliyiciler ile uyumlu hale getirebilirsiniz.

Burada IIS bir proxy olarak davranır ve istekleri direk olarak sizin uygulamanıza yönlendirir! Ayrıca IIS tarafından sunulan bir çok özelliğide (tracing, logging, application pool) beraberinde kullanabilirsiniz.

Sunucunuzda ASP.NET Core uygulamasının IIS ile entegre olabilmesini sağlamak amacıyla geliştirilen ve IIS süreçlerini native, performansa dayalı bir şekilde uygulamanıza geçmesini sağlayan AspNetCoreModule kullanılmalıdır.

Uygulamamızın çoklu platform desteğini test edebilmek için bir Mac veya Linux makinada şu adımları izleyebiliriz:

git clone https://github.com/gencebay/NetCoreSamples.git
dotnet restore
dotnet run

Elbette basit, çok fazla efor harcamadan yazdığımız bu uygulama örneği, sadece yeni .NET Core, ASP.NET Core ve MVC 6 prensiplerine vurgu yapmaktadır. Bundan sonraki süreçte bu yapının bir çok yeni özellik ve fırsat ile geliştiricilere kolaylıklar sağlayacağı değerlendirilmektedir.

Yararlı olması dileğiyle!

Kaynaklar:
  1. .NET Core
  2. .NET Core Visual Studio 2015 Web Tools
  3. .NET Documentation
  4. Kestrel Http Web Server