#

TECRÜBEMİZİ YAZILIMCILARLA 

PAYLAŞIYORUZ. 

BİLGİ PAYLAŞTIKÇA ÇOĞALIR

BLOG

ASP.NET MVC & AngularJS ile Alışveriş Sepeti Uygulaması - 1

ASP.NET MVC & AngularJS ile Alışveriş Sepeti Uygulaması - 1

Herkese merhaba,

ASP.NET MVC & AngularJS kullanarak en basit haliyle nasıl alışveriş sepeti yapabiliriz bunu öğreneceğiz. Peki başka neler öğreneceksiniz
- C# Session yönetimi, C# Casting,
- C# Dictionary yapısı
- AngularJS ile .NET'e veri göndermek, veri almak
- AngularJS ile html/cshtml'de listeleme işlemleri
-AngularJS ile broadcast yayını
Hiç vakit kaybetmeden dersimize geçelim. Öncelikle Visual Studio'da ASP.NET MVC Web projesi oluşturuyoruz.


CSS framework'ü olarak bootstrap kullanacağız. Aşağıdaki bağlantıdan bootstrap'in son sürümünü indirebilirsiniz.

https://getbootstrap.com/docs/4.1/getting-started/download/

İkonlar için font-awesome kullanabilirsiniz.

https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css


AngularJS'i ise https://angularjs.org/ buradan indirebilirsiniz. Ben CDN kullanacağım.
JS, CSS ve resimlerimizi tutmak için ana dizinde Assets adında klasör oluşturup aşağıdaki gibi klasör ve dosya(lar) oluşturuyoruz.


Burada bulunan app.js isimli dosya'da AngularJS'i kullanabilmek için aşağıdaki şekilde modül'ü aktif edeceğiz.


ProductCtrl.js dosyasında ise daha sonra kullanılmak üzere ürünlerimizin sepete eklenmesi ve çıkartılması gibi işlemler yapacağız.
CSS dosyası içerisindeki kodlarımız ise şöyle;

body {

   background: #f3f3f3 !important;

}

.shopping-cart {

   font-size: 25px;

   color: black;

}

.shopping-cart-count {

   position: relative;

   top: -12px;

   font-size: 10px !important;

}

.mt-20 {margin-top: 20px}

Views klasörü altında _ViewStart.cshtml dosyası oluşturup Layout belirtiyoruz.
 

Views klasörü altındaki _Layout.cshtml dosyası aşağıdaki gibi olmalı

<!DOCTYPE html>

<html ng-app="shopping" ng-controller="ProductCtrl">

<head>

   <meta charset="UTF-8">

   <title>ASP.NET MVC & AngularJS ile Alışveriş Sepeti Uygulaması</title>

   <!-- styles -->

   <link href="~/Assets/css/custom.css" rel="stylesheet" />

   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

   <link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

</head>

<body>

   <nav class="navbar navbar-expand-lg navbar-light bg-light">

       <a class="navbar-brand" href="@(Url.Action("Index","Home"))">MANTA</a>

       <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">

           <span class="navbar-toggler-icon"></span>

       </button>

       <div class="collapse navbar-collapse" id="navbarSupportedContent">

           <ul class="navbar-nav mr-auto">

               <li class="nav-item active">

                   <a class="nav-link" href="@(Url.Action("Index","Product"))">Ürünler <span class="sr-only">(current)</span></a>

               </li>

           </ul>

           <a href="@Url.Action("Basket","Product")" class="shopping-cart">

               <span class="fa fa-shopping-cart"></span>

           </a>

           <span class="badge badge-danger shopping-cart-count">7</span>

       </div>

   </nav>

   <div class="container mt-20">

       @(RenderBody())

   </div>

   <!-- scripts -->

   <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

   <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>


   <!-- AngularJS -->

   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>

   <script src="~/Assets/angularjs/app.js"></script>

   <script src="~/Assets/angularjs/ProductCtrl.js"></script>


</body>

</html>

.NET tarafında Home adında Controller oluşturup geriye ürünlerimizin gösterimini sağlaması için Index adında ActionResult oluşturuyoruz. Index.cshtml ise şu şekilde;

<div class="row">

   <div class="col-md-3">

       <div class="card">

           <img class="card-img-top" src="~/Assets/img/iphonex.jpg" alt="Card image cap">

           <div class="card-body">

               <h5 class="card-title">iPhone X</h5>

               <p class="card-text">Apple iPhone X 64 GB (Apple Türkiye Garantili)</p>

<p class="card-text badge">7.499,00 ₺</p>

               <button type="button" class="btn btn-primary pull-right">

                   <span class="fa fa-shopping-cart"></span> SEPETE EKLE

               </button>

           </div>

       </div>

   </div>

</div>

Her şey tamamsa projemiz aşağıdaki şekilde gözükecek.


.NET tarafında Models klasörü altında Product isimli class oluşturuyoruz. Ürünlerimizi bu class'ta tutacağız.

namespace ShoppingCart.Models

{

   public class Product

   {

       public Guid ID { get; set; }

       public string Title { get; set; }

       public string Image { get; set; }

       public string Description { get; set; }

       public decimal Price { get; set; }

   }

}

public static List<Product> products = new List<Product>();

Statik kullanmamızın sebebi sayfa yenilendiğinde ürünlerin ID'lerinde herhangi bir değişiklik olmaması. DB bağlantısı vs. yapmadığımız için bu yolu seçtik. Ve controller constructor'ında ilgili listeye 4 adet ürün ekleyelim.


products.Add(new Product()

               {

                   ID = Guid.NewGuid(),

                   Title = "iPhone X",

                   Description = "Apple iPhone X 64 GB (Apple Türkiye Garantili)",

                   Image = "iphonex.jpg",

                   Price = 7499.00M

               });

               products.Add(new Product()

               {

                   ID = Guid.NewGuid(),

                   Title = "OnePlus 6",

                   Description = "OnePlus 6 64 GB (İthalatçı Garantili)",

                   Image = "oneplus.jpg",

                   Price = 4000.00M

               });

               (gibi . . .)

HomeController / Index ActionResult'ında ise View dönerken içerisinde products listesini model olarak dönelim.

public ActionResult Index()

       {

           return View(products);

       }

İçeriği ise şu şekilde olacak;

@model List<ShoppingCart.Models.Product>

<div class="row">

   @foreach (var product in Model)

   {

       <div class="col-md-3">

           <div class="card">

               <img class="card-img-top"

                    src="~/Assets/img/@(product.Image)" alt="@(product.Title)" />

               <div class="card-body">

                   <h5 class="card-title">@(product.Title)</h5>

                   <p class="card-text">@(product.Description)</p>

                   <p class="card-text badge">@(product.Price)</p>

                   <button type="button"

                           ng-click="addToBasket('@(product.ID)')"

                           class="btn btn-primary pull-right">

                       <span class="fa fa-shopping-cart"></span> SEPETE EKLE

                   </button>

               </div>

           </div>

       </div>

   }

</div>

JSON ile çalışacağımız için Nuget Package Manager'dan Newtonsoft.JSON kütüphanesini projemize dahil ediyoruz. Ürünlerimizi sepete eklediğimizde veya sepetten çıkardığımızda sepet listesini görebilmek için Basket adında model oluşturuyoruz.

public class Basket

   {

       public Guid ID { get; set; }

       public string Title { get; set; }

       public string Image { get; set; }

       public decimal Price { get; set; }

       public int Total { get; set; }

   }

Sepetteki ürünler için Dictionary yapısı kullanacağız. Dictionary TKey (anahtar değer) ve TValue (değer) şeklinde işler. Örneğin basket adında Dictionary'miz olsun. Key => Guid, Value => Basket modelini baz alsın. İlgili dictionary'e ürün eklerken basket.Add(Key, new Basket()); şeklinde ekleriz. Güncelleme işlemi yaparken ise basket[Key].Property = value; şeklinde işlem yaparız.

Sistemde kullanacağımız Dictionary'miz şu şekilde olacak;

public Dictionary<Guid, Basket> basket = new Dictionary<Guid, Basket>();

Gelelim sepete ekle butonunun işlevlerine. HomeController içerisine AddToBasket adında HttpPost niteliğinde bir ActionResult ekleyelim. Guid tipinde ID parametresi alacak. Sepete ekle butonuna tıklandığında AngularJS ile, ilgili action'ı tetikleterek sepete ürün ekleyeceğiz. Kod içerisinde gerekli açıklamaları yaptım.

[HttpPost]

       public ActionResult AddToBasket(Guid ID)

       {

           //Ürün yoksa uyarı ver

           if (!products.Any(c => c.ID != ID))

           {

               return Json(new { Status = false, Msg = "Ürün bulunamadı" }, JsonRequestBehavior.AllowGet);

           }

           else

           {

               Product product = products.Where(c => c.ID == ID).FirstOrDefault();

               //session boş ise sepette ürün yok demektir. Sepete yeni ürün olarak ekle

               if (Session["Basket"] == null)

               {

                   basket.Add(ID, new Basket()

                   {

                       ID = product.ID,

                       Title = product.Title,

                       Image = product.Image,

                       Price = product.Price,

                       Total = 1

                   });

                   Session["Basket"] = basket;

               }

               else

               {

                   basket = (Dictionary<Guid, Basket>)Session["Basket"]; //session içerisindeki (sepetteki ürünleri) Dictionary<Guid, Basket> şeklinde cast edip statik basket dictionary'sine set et.


                   //Ürün sepette var. Adet artır ve fiyat güncelle

                   Basket _basket = basket.Where(c => c.Key == ID).Select(c => c.Value)

                       .FirstOrDefault();

                   if (_basket != null)

                   {

                       basket[ID].Total++;

                       basket[ID].Price = basket[ID].Total * basket[ID].Price;

                   }

                   else //Ürün sepette yok. Yeni ürün olarak ekle

                   {

                       basket.Add(ID, new Basket()

                       {

                           ID = product.ID,

                           Title = product.Title,

                           Image = product.Image,

                           Price = product.Price,

                           Total = 1

                       });

                   }

                   Session["Basket"] = basket;

               }

               return Json(new { Status = true, Msg = "Ürün sepete eklendi", Data = basket.Values }, JsonRequestBehavior.AllowGet);

           }

       }

AngularJS tarafında ProductCtrl.js aşağıdaki şekilde olacak.

app.controller("ProductCtrl", ProductCtrl); //app.js içerisinde modüle controller ekle

function ProductCtrl($scope, $http) {

   $scope.total = total; //navbar'da bulunan sepetteki toplam ürün sayısı

   $scope.addToBasket = (id) => { //id parametresi alacak

       $http.post("/Home/AddToBasket", { ID: id }).then(resp => {

           var data = resp.data;

           if (data.Status && data.Data && data.Data.length > 0) {

               $scope.total = 0;

               data.Data.forEach(d => {

                   $scope.total += d.Total;

               });

           }

           alert(data.Msg); //Ürün sepete eklendi mi/eklenmedi mi mesajı

       });

   };

}

Sayfa yenilendiğinde sağ tarafta bulunan sepetteki ürün sayısını çekmek için _Layout.cshtml'de class'ı shopping-cart-count olan satırı şu şekilde güncelleyelim.

<span class="badge badge-danger shopping-cart-count">{{ total }}</span>

Yine _Layout.cshtml'de en alt satıra gelip şu kodları ekleyelim

@{

       int total = 0; //Sepetteki ürün sayısını dönecek. Başlangıç değeri 0 olacak.

       if (Session["Basket"] == null) //Session boş ise sepette ürün yok demektir.

       {

           total = 0;

       }

       else

       {

           //Session dolu ise veriyi çek. Ve foreach ile dönerek Basket modelindeki Total property'sini total değişkenine set et.

           var _basket = (Dictionary<Guid, ShoppingCart.Models.Basket>)Session["Basket"];

           foreach (var b in _basket)

           {

               total += b.Value.Total;

           }

       }

   }

   <script>

       var total = @(total); //.NET'ten gelen veriyi js ile değişkene atayıp AngularJS tarafında değeri alabiliyoruz

   </script>

Dersimizi burada sonlandıralım. 2.derste sepeti görüntüleme, sepet güncelleme ve sepetten silme işlemlerini yapacağız.


Video(lar) / GIF