Asp.Net Core’da NodeJs ile Cross Platform Mvc ve WebAPİ Projeler Yaratma Bölüm1
Selamlar,
Bugünkü makalede, Asp.Net Core 1.1.0 ile Cross Platform bir Mvc projesi oluşturulacak. Projenin Cross Platform olması adına, “Mac Os X” bir işletim sistemi üzerinde ilgili moduleler yazılacaktır. Daha sonra dış bir kaynaktan alınacak datalar NodeJs bir servis ile çekilecektir. Ama bu datalar var olan sisteme uygun olmadığı için araya bir Adaptor yani WebApi servisi yazılıp sisteme uygun hale getirilecektir. Benim de güncel iş hayatımda bolca kullandığım bu seneryoyu, hep beraber bu makale üzerinde tartışacağız.
Öncelikle makinanıza kurmanız gerekenleri, buradaki makalemden ulaşabilirsiniz.
Şimdi ilgili dosyalar kurulduğuna göre:
1-) Yeoman generator kullanılarak, aşağıdaki komut ile yeni bir AspNet projesi oluşturulur.
1 |
yo aspnet |
2-)Bir sonraki adımda, aşağıda görüldüğü gibi yeni bir proje tipinin seçilmesi istenmektedir. Bu projede “Web Application Basic” projesi seçilmiştir.
3-)2. adım olarak projede kullanılacak UI framework’ün seçilmesi istenir. Bu projede Bootstrap seçilmiştir.
4-) Son olarak projenin adı istenir. Bu projenin adı “MyTicket“‘dir.
Aşağıdaki komut yazıldığında ilgili project dosyası bulunamıyor şeklinde bir hata alınabilir.
1 |
dotnet restore |
dotnet Error:
1 |
<span class="str">warn : The folder '/MyTicket' does not contain a project to restore.</span> |
Çözüm : dotnet versiyonu buradan güncellenir.
Yukarıdaki sorunun çözümünden sonra karşılaşabileceğiniz 2. hata:
Mac Security Error: OsX bir işletim sisteminde, bu bilinen bir kaynaktan gelmediği için açılamayan bir dosyadır.
Çözüm: Sağ-click (veya control-click) ile ilgili uygulama açılır. Gelen soruya “Open” cevabı verilir. Ve ilgili paket yüklenir.
Aşağıdaki komutlar ile ilgili proje derlenip, çalıştırılır.
1 2 |
dotnet build dotnet run |
Aşağıdaki bildiri ile ilgili uygulama 5000 portundan yayımlanır.
Şimdi gelin öncelikle dış kaynak olacak NodeJS projesini oluşturalım.
NodeJs Bir Proje Oluşturmak:
Aşağıdaki komutlar ile ilgili nodejs servis modulu’ne ait klasör oluşturulur.
1 2 |
mkdir ticket_node_server cd ticket_node_server |
Aşağıdaki komut ile Npm sayesinde ilgili proje oluşturulur. Proje adı olarak “ticket_node_server” seçilmişitir. Diğer alanlar boş geçilmiştir.
1 |
npm init |
“code .” ile Visual Studio Code açılır ve “server.js” dosyası aşağıdaki gibi oluşturulur.
- Cors işlemleri için header’a “Access-Control-Allow-Origin, Access-Control-Allow-Headers ve Origin,Content-Type,Accept,X-Request-With” yetkileri verilir.
- “req.method.toLowerCase()” methodu ile gelen request’in post veya get olduğu anlaşılır.
- “data” ile örnek dummy bir Ticket listesi json olarak gönderilmektedir. Hemen aşağısında ilgili dummy Ticket Modeli tanımlanmıştır.
- “responseData”‘ya ilgili gönderilecek model string olarak atanır.
- Header’a gönderilecek data tipi json olarak tanımlanıp response tamamlanır.
- Son olarak “1453” portu tanımlanıp, server dinleme(listen) durumuna geçirilir.
NodeJs/Server.js:
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
var http = require('http'); var server = http.createServer(function (req, res) { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Headers", "Origin,Content-Type,Accept,X-Request-With"); console.log(req.method); if (req.method.toLowerCase() == "get") { var data = { "Tickets": [{ "ID":1, "Name": 'Boston Vs Jazz', "Price": '20', "Block": 'A4', "Seat": 17, "Category": 'Mvp', "Status": 'Open' }, { "ID":2, "Name": 'Boston Vs Jazz', "Price": '25', "Block": 'A3', "Seat": 10, "Category": 'Mvp', "Status": 'Open' }, { "ID":3, "Name": 'Orlendo Vs Chicago Bulls', "Price": '30', "Block": 'A2', "Seat": 1, "Category": 'Mvp', "Status": 'Open' }, { "ID":4, "Name": 'New York Knicks Vs Boston Celtics Bulls', "Price": '17', "Block": 'B7', "Seat": 8, "Category": 'Student', "Status": 'Open' }, { "ID":5, "Name": 'Houston Rockets Vs Dallas Mavericks', "Price": '40', "Block": 'E4', "Seat": 30, "Category": 'Private', "Status": 'Open' }, { "ID":6, "Name": 'Phoenix Suns Vs Orlando Magic', "Price": '60', "Block": 'Z2', "Seat": 10, "Category": 'Special', "Status": 'Open' }] } } var responseData = JSON.stringify(data); res.setHeader('Content-Type', 'application/json'); res.end(responseData); console.log('Gönderilen:' + responseData); return; }); var port = 1453; server.listen(port); console.log("Server :" + port + " portundan dinlemeye başlamıştır..."); |
http://localhost:1453: Browserdan çekilen örnek Json data çıktısı aşağıdaki gibidir.
Model /Ticket.cs: İlgili model aşağıdaki gibi tanımlanır.
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 |
using System; public class Ticket { public int ID { get; set; } public string Name { get; set; } public double Price { get; set; } public string Block { get; set; } public int Seat { get; set; } public string Category { get; set; } public string Status { get; set; } public Ticket() { } } |
(WebApi Servisi) TicketServiceController.cs: Amaç NodeJs server’ından ilgili datanın asenkron olarak çekilip, Newtonsoft kütüpahanesi kullanılarak deserialize edilerek alınmasıdır.
Önemli Not:İlgili data NodeJs’den çekilirken “Get()” methodunda “Deserialize” işlemi “List<Ticket>” şeklinde cast edilmeye çalışıldığında uygun bir cast işlemi olmadığı şeklinde bir hata alındı. Bunun için aşağıda görüldüğü gibi “TicketCollection” adında, “IEnumurable<Ticket>” tipinde propertysi olan bir sınıf yaratılıp, çeklen datanın bu sınıf tipine Deserialize işlemi yapılması sağlandı.
- Web servisinin yazılmasında amaç, NodeJs’den çekilen datanın projede kullanılacak sisteme uygun olmaması, ve bu neden ile fiyat bilgisinin Dolar kurundan TL’ye çevrilmesi, ayrıca Category bilgisinin de Türkçeye çevrilmesi gerekmesidir. Bu neden ile projeye Adaptor amaçlı, bu webservisi yazılmıştır.
- “Get()” methodu NodeJS servisinden çekilen tüm Ticket datasını geri dönmektedir.
- “Get(int ID)” methodunda Update sayfasında seçilen bilet bilgilerinin, NodeJS servisinden çekilip ilgili “ID” parametresine göre filitrelenerek geri döndürüldüğü bir Web methoddur.
- “ConvertCategory()” category isimlerinin İngilizceden Türkçeye ve Türkçeden İngilizceye çevrilmesini sağlamaktadır.
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace MyTicket.Controllers { [Route("api/[controller]")] public class TicketServiceController : Controller { // GET api/values [HttpGet] public async Task<List<Ticket>> Get() { using (var client = new HttpClient()) { var response = await client.GetAsync("http://localhost:1453"); var data = JsonConvert.DeserializeObject<TicketCollection>(response.Content.ReadAsStringAsync().Result); List<Ticket> result = new List<Ticket>(); foreach (var ticket in data.Tickets) { ticket.Price *= 3.5; ticket.Category = ConvertCategory(ticket.Category); result.Add(ticket); } return result; } } [HttpGet("{id}")] public async Task<Ticket> Get(int ID) { using (var client = new HttpClient()) { Ticket result = new Ticket(); var response = await client.GetAsync("http://localhost:1453"); var data = JsonConvert.DeserializeObject<TicketCollection>(response.Content.ReadAsStringAsync().Result); result = data.Tickets.Where(Tic => Tic.ID == ID).First(); result.Price *= 3.5; result.Category = ConvertCategory(result.Category); return result; } } public string ConvertCategory(string category) { switch (category) { case "Student": { return "Öğrenci"; } case "Special": { return "Özel"; } case "Mvp": { return "Efsane"; } case "Efsane": { return "Mvp"; } case "Özel": { return "Special"; } case "Öğrenci": { return "Student"; } default: { return "Uzaylı"; } } } } } |
TicketCollection.cs: NodeJs’den gelen datanın deserialize işlemi yapılacağı sınıf tanımlamasıdır.
1 2 3 4 5 |
using System.Collections.Generic; public class TicketCollection { public IEnumerable<Ticket> Tickets { get; set; } } |
HomeController.cs: İlk projeye girildiğinde “Index.cshtml” sayfasına ilgili Ticket bilgileri, WebApi servisinden asenkron olarak çekilip, gönderilmiştir. Ayrıca “Index.cshtml”‘den seçilen Ticket “ID” parametresi ile “Update()” Action’ına gönderilmiş ve ilgili paramtreye göre Ticket bilgisi gene WebApi servisinden çekilip “Update.cshtml” sayfasına iletilmiştir.
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; namespace MyTicket.Controllers { public class HomeController : Controller { public async Task<IActionResult> Index() { using (var client = new HttpClient()) { var response = await client.GetAsync("http://localhost:5000/api/TicketService"); var model = JsonConvert.DeserializeObject<List<Ticket>>( response.Content.ReadAsStringAsync().Result); return View(model); } } public IActionResult Error() { return View(); } public async Task<IActionResult> Update(int ID) { using (var client = new HttpClient()) { var response = await client.GetAsync("http://localhost:5000/api/TicketService/"+ID); var model = JsonConvert.DeserializeObject<Ticket>( response.Content.ReadAsStringAsync().Result); return View(model); } } [HttpPost] public void SaveForm(Ticket ticket) { int i=0; } } } |
Index.cshtml: Model olarak gelen List<Ticket> bootstrap kullanılarak sayfaya basılmıştır. Güncelle butonuna tıklanınca “Update(int ID)” action’ına seçilen ticket ID’yi ile birlikte gidilmektedir.
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 |
@model List<Ticket> @{ ViewData["Title"] = "Maç Listesi"; } <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous"> <body> <div class="container"> <div class="jumbotron"> <h1>Spor Karşılaşması Sonuçları</h1> </div> <table class="table table-responsive"> <thead> <tr> <th class="hBig"></th> <th class="hBig">Ad</th> <th class="hNarrow">Fiyat(₺)</th> <th class="hNarrow">Block</th> <th class="hNarrow">Koltuk</th> <th class="hNarrow">Kategori</th> <th class="hNarrow">Durum</th> </tr> </thead> <tbody> @foreach(var ticket in @Model) { <tr class="table-success"> <td> <a href="/Home/Update/@ticket.ID"><input type="button" value="Güncelle"></a> </td> <td>@ticket.Name</td> <td>@ticket.Price</td> <td>@ticket.Block</td> <td>@ticket.Seat</td> <td>@ticket.Category</td> <td>@ticket.Status</td> </tr> } </tbody> </table> </div> </body> |
Böylece geldik bu makalenin 1. bölümünün sonuna. 2.Bölümde, bu makalede anlatılan data akış transferinin tam ters yönünde bir işlem yapılarak, Web tarafında güncellenen datanın NodeJs servisine gönderilmesi sağlanacaktır. Mvc tarafında güncelleme ekranı oluşturulup, girilen dataların yeni Adaptor şeklinde tanımlanacak WebApi servisine gönderilmesi ve daha sonra, buraya gelen datanın dışarda tanımlanan NodeJs servisine uygun dönüşümü yapılması sağlanacaktır. İlgili data hazırlandıktan sonra, dışarıdan ldinleme dururmunda olan, NodeJs servisine post edilmesi sağlanacaktır.
Bir sonraki makalede görüşmek üzere hoşçakalın.
Source:
2
dotnet build
donet run dotnet olacak hocam eliniz kaymış sanırım :) teşekkürler yazı için
Uyarı için ben teşekkür ederim. Düzelttim :)
merhaba, Asp.Net Core ile gelistirilen uygulama backend de java uygulamasının yerini alabilecek mi acaba? elimizde dll linux ve windows icin var. javadan dolayı linux kullanmak zorunda kaldık. halbuki donanım mac mini. macos yüklü mac miniye Asp.Net Core’da ürünü iki dll den birine gore geliştirip çalıştırsak basarılı sonuc alabilirmiyiz acaba ?
Yani Java uygulamasının yerini Java developerlar için belki almaya bilir. Ama iş performans’a bakar. Ama .Net uygulama geliştiricileri için bulunmaz hint kumaşı:)
Mac için Asp.Net Core kullanır iseniz gayet başarılı sonuçlar alabilirsiniz. Ben alıyorum. Makinam MacBook Pro :) İşletim sistemim Sierra..
İyi çalışmalar.
Merhaba, (WebApi Servisi) TicketServiceController.cs dosyasının 44 ve 45. satırlarındaki ‘ticket’ değişkeni galiba tanımlı değil ve ‘result’ değişkenide ‘Ticket’ sınıfından türetildiği için Add() metodu yok. Bu satırlarda bir hata mı var yoksa ben mi bir yanlışlık yapıyorum?
Selam Ömer,
Söylediğin gibi ilgili satırlardaki hataları düzelttim. Sende hiçbir sorun yok.
Yapıcı yorumun ve desteğin için çok teşekkür ederim.
İyi çalışmalar.
Hocam teşekkürler.Bir sorum olacaktı sizce asp.net core ile proje geliştirmeye başlamalı mıyım stabil mi şuanda sizin tespitleriniz neler yoksa beklemeli miyim
Selam Emre,
Evet stabil. Proje geliştirebilirsin. Bekleyecek birşey yok. En fazla yeni özellikler gelir..
İyi çalışmalar.
Teşekkür Ederim cevabınız için hocam :)
Sizin gibi olmaya çalışıyorum
Selamlar Emre;
Ben teşekkür ederim. Bu ara da estağfurullah..
İyi çalışmalar.
Hocam çok teşekkür ediyorum.Sizin cross çalışmayı yaptığa göre mutlaka bir kullanım alan vardır.Asenkron webapi ile asenkron node.js ile birlikte çalışmasının gerçek hayatta ne gibi faydalar olabilir.
Merhabalar,
Bu yapmış olduğunuz örnek uygulama sanırım, real time değil.
Yani karşılaşma sonuçları webstream şeklinde anlık terminallerde görünmüyor.
Selamlar,
Yok hayır RealTime değil. NodeJs bu projede Web Servisi olarak çalışmaktadır. Bir port dinlense de clientlara realtime push işlemi yapılmamaktadır.
İyi çalışmalar.
Peki yapmanın yolu nedir, böyle bir şey mümkün öyle değil mi ?
Neyi yapmak mümkün mü Kamil?
Merhaba,
Size bir iki sorum olacaktı. Neden ASP.NET Core ile Node.js beraber kullanıyorsunuz? Yani server side tarafında Node.js kullanmanın avantajı nedir? Eğer hız diyorsanız neden ASP.NET Core kullanmadan Node.js ile yapmıyorsunuz. Teşekkür ederim.
Selamlar Erencan,
Valla çok güzel ve haklı bir soru :) Aslında kullan NodeJs ve geç en kısa cevap. Ama bu makalenin esas amacı öğretmek. Okurlarına farklı tecrübeleri deneyimletmek.
İşte tek nedeni bu.
İyi çalışmalar.