AngularJ2 Data Binding ve Data Display

Merhaba, bir önceki makalemde nasıl yeni bir angularJs2 projesi oluşturacağımdan bahsetmiştim. Bu makalemde ise angularjs2’de data binding ve data display’den bahsedeceğim.

Önceki makalemde oluşturduğum app klasörünün altına data_binding_main.ts doyasını ekliyorum.


import {bootstrap} from 'angular2/platform/browser';           //importing bootstrap function
import {AppComponent} from "./data_binding_app.component";     //importing component function

bootstrap(AppComponent);

Şimdi de data_binding_app.component.ts isminde içinde component barındıran bir TypeScript dosyası ekleyelim


import {Component, View} from "angular2/core";

@Component({
   selector: 'my-app'
})

@View({
  template: `


<h3>İsim : {{name}}</h3>



<h3>Soyisim : {{surname}}</h3>



<h3>Şehir : {{City}}</h3>



<h2>Showing data using array property with NgFor</h2>



<h3>My favorite is: {{myfavorite}}</h3>


List of Favorites:


<ul>


<li *ngFor="#favorite of favorites" (click)="onItemClicked(favorite)">
          {{ favorite }}
       </li>

    </ul>

    <input type="text" [(ngModel)]="clickedItem">
    `
})

export class AppComponent {
   name: 'Mustafa';
   surname:'Alkan';

City: string;
constructor() {
   this.City = 'İzmir';
}

favorites = ['Sport', 'Music', 'Sinema', 'Swimming'];
   myfavorite = this.favorites[1];

   public clickedItem = "";
     onItemClicked(Item) {
        this.clickedItem = Item;
     }
}

Yukarıda yaptığımız işleri kısaca özetlemek istersek, AppComponent ismiyle yarattığımız component içerisinde name, surname ve City olarak 3 değişken oluşturup, bunlara değer atadık. Önceki makalemde anlattığım üzere, AngularJS2’de scopelar kaldırılmıştı ve artık bu gibi değişkenleri componentler içerisinde tanımladığımızı söylemiştik. Böylece component içerisinde oluşturduğumuz dataları son kullanıcıya view içinde göstermiş olduk.

Favorites isminde bir array nesnesi oluşturduk ve array içerisindeki her bir itemi view içerisindeki templatede *ng-for directive ile bind ettik. Listemizdeki herhangi bir nesneye tıkladığımızda, gidip aşağıdaki text inputta görünmesini istiyorsak bunu da aşağıda gördüğümüz click eventi ile gerçekleştirebiliriz.

(click)="onItemClicked(favorite)"

onItemClicked fonksiyonu ise, AppComponent içerisinde tanımlanmış bir fonksiyondur ve görevi clickedItem değişkenine, fonksiyon içerisinde gelen parametreyi set etmektir.

public clickedItem = "";
     onItemClicked(Item) {
        this.clickedItem = Item;
     }
<input type="text" [(ngModel)]="clickedItem">

Şimdi databinding.html dosyasımızı oluşturalım.


<html>
   <head>
      <title>Data Binding</title>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.33.3/es6-shim.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>
      <script src="https://code.angularjs.org/2.0.0-beta.6/angular2-polyfills.js"></script>
      <script src="https://code.angularjs.org/tools/system.js"></script>
      <script src="https://code.angularjs.org/tools/typescript.js"></script>
      <script src="https://code.angularjs.org/2.0.0-beta.6/Rx.js"></script>
      <script src="https://code.angularjs.org/2.0.0-beta.6/angular2.dev.js"></script>
      <script>
         System.config({
           transpiler: 'typescript',
           typescriptOptions: { emitDecoratorMetadata: true },
           packages: {'app': {defaultExtension: 'ts'}},
           map: { 'app': './app' }
         });
         System.import('app/data_binding_main')
               .then(null, console.error.bind(console));
      </script>
   </head>
   <body>
      <my-app>Loading...</my-app>
   </body>
</html>

NodeJS command promptan databinding.html dosyasını içeren klasöre gidelim ve projemizi npm start komutuyla çalıştıralım.

1

Reklamlar

AngularJS 2 İlk Bakış ve İlk Proje

Bu yazımda Angular-2 de angular2’in yeni özelliklerinden, avantajlarından ve angular2 ile bir uygulamanın nasıl build edileceğinden bahsedeceğim.

Öncelikle, Angular2’den kısaca bahsedeyim. Günümüzde AngularJs, çok kullanılan ve ünlü bir JavaScript framework. Single Page Application ve web application geliştiriciler için çok popüler olan js framework. Google, AngularJS’in final versiyonu olan AngularJS2’yi yeni özellikleriyle bizlere sundu.

AngularJS Nedir?

Genel olarak özetlersek AngularJS:

  • MVC Yapısında bir frameworktur.
  • Single Page Application frameworkudur
  • Client Side Template oluşturmaya uygundur.
  • TDD (Test Driven Development)’a uygundur ve yazdığımız kodları kolayca unit test yapabiliriz.
  • Custom olarak Html taglerinde attribute tanıtmaya ve oluşturmaya imkan sağlar (Directives)
  • Dependency Injectionı destekler

Neden AngularJS2’yi Kullanmalıyız ?

  • Performans açısından Angular1’den daha hızlıdır.
  • Angular2 Mobil app development aşamasında daha güçlüdür. Angular2 tamamen mobil geliştirme odaklı olarak geliştirilmiştir.
  • Cross-platform bir frameworktur.
  • Browserların son versiyonlarına destek vermektedir. Ayrıca IE9+ ve Android 4.1+ gibi eksi browser versiyonlarına da destek vermektedir.
  • Angular2 component bazlı bir frameworktur. Angular2de scopelar ve controllerlar kaldırılıp, componentler ve directivelere yerleştirilmiştir.
  • Typescript kullanımını destekler.
  • Mobilde viewları daha hızlı render etmek için server side rendering kullanır.

AngularJS2 ile Proje Oluşturma

Öncelikle bir klasör oluşturalım ve ismini angular2-demo olarak verelim. Örneğin C: sürücüsüne gidip, klasörü oluşturup içine gidelim:

mkdir angular2-demo
cd angular2-demo

Burada visual studio code kullanacağım. Dilerseniz bu adresten Visual Studio Code’u indirebilirsiniz : Link

Klasörü visual studio code üzerinde açıyorum:

1

İlk olarak tsconfig.json typescript config dosyasını ekleyelim.

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

Şimdi ise typings.json dosyasını ekleyelim. Typings.json dosyası angular2 applicationınızdaki TypeScript değişkenlerini tanımlamak için kullanılır.

{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160602141332",
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
    "node": "registry:dt/node#6.0.0+20160621231320"
  }
}

Sonraki adımda da package.json dosyasını oluşturalım. Package json dosyası gereksinimiz olan packageların tanımladığı config dosyasıdır. Bu packagelar npm (Node Package Manager) ile yüklenecektir. Bunun için package.json dosyasını oluşturduktan sonra npm install komutu çalıştırılmalıdır. Package.json dosyası aşağıdaki gibidir.

{
  "name": "angular2-demo",
  "version": "1.0.0",
  "scripts": {
    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "typings": "typings",
    "postinstall": "typings install"
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.7",
    "systemjs": "0.19.22",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.5.15"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.1.0",
    "typescript": "^1.7.5",
    "typings":"^0.6.8"
  }
}

Package.json dosyasını oluşturduktan sonra Node.js command prompta gidip package.json dosyasının bulunduğu klasöre gidip npm install etmemiz gerekmektedir.

npm install

Npm ile packageları install ettikten sonra visual studio codeda node_modules klasörünün geldiğini göreceğiz.

1

Bundan sonraki adımda ise oluşturacağımız app componentlerin tutulduğu app isminde bir klasör oluşturalım. Aşağıdaki komutları kullanabiliriz:

mkdir app
cd app

Şimdi ise oluşturduğumuz app klasörünün altında .ts uzantılı bir typescript dosyası ekleyelim. Oluşturacağımız dosyanın adı app.component.ts olsun.

import {Component, View} from "angular2/core";

@Component({
   selector: 'my-app'
})

@View({
  template: '


<h2>My First Angular 2 App</h2>



'
})

export class AppComponent {

}
  • Yukarıdaki kod blogu, angular2/core modülü, Component ve View packagelarını import eder.
  • @Component, component classı ile metadatayı ilişkilendiren bir decorator görevini görür
  • my-app html taglerin component olarak kullanılabilmesini sağlar.
  • @View, angular’ın templatei nasıl render edeceğini belirler.

Sıradaki işlem olarak, main.ts dosyasını oluşturalım.

import {bootstrap} from "angular2/platform/browser"
import {AppComponent} from "./app.component"

bootstrap(AppComponent);
  • main.ts dosyası Angulara componentin yüklenmesini söyler.
  • Projeyi başlatmak için boostrap fonksiyonuna ihtiyacımız var. Componenti yüklemek ve oluşturduğumuz app’ı çalıştırmak için yukarıda oluşturduğumuz app.component.ts dosyasını import edip, bu dosyadaki AppComponent‘i boostrap fonksiyonu ile initialize etmemiz gerekmektedir.

Şimdi ise angular2-demo/ klasörünün altına index.html ekleyelim.

<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fes6-shim%2F0.33.3%2Fes6-shim.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fsystemjs%2F0.19.20%2Fsystem-polyfills.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcode.angularjs.org%2F2.0.0-beta.6%2Fangular2-polyfills.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcode.angularjs.org%2Ftools%2Fsystem.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcode.angularjs.org%2Ftools%2Ftypescript.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcode.angularjs.org%2F2.0.0-beta.6%2FRx.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcode.angularjs.org%2F2.0.0-beta.6%2Fangular2.dev.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%20%20%20%20%20%20System.config(%7B%0A%20%20%20%20%20%20%20%20transpiler%3A%20'typescript'%2C%0A%20%20%20%20%20%20%20%20typescriptOptions%3A%20%7B%20emitDecoratorMetadata%3A%20true%20%7D%2C%0A%20%20%20%20%20%20%20%20packages%3A%20%7B'app'%3A%20%7BdefaultExtension%3A%20'ts'%7D%7D%2C%0A%20%20%20%20%20%20%20%20map%3A%20%7B%20'app'%3A%20'.%2Fapp'%20%7D%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20System.import('app%2Fmain')%0A%20%20%20%20%20%20%20%20%20%20%20%20.then(null%2C%20console.error.bind(console))%3B%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
  </head>
<body>
   <my-app>Loading...</my-app>
</body>
</html>

Son olarak projemizi compile ve run etmek için aşağıdaki komutu command promptan çalıştırıyoruz.

npm start

Komutu çalıştırdıktan sonra karşımıza aşağıdaki ekran gelecektir:

1

Visual studio codedaki projemizin son hali şu şekilde olacaktır:

1

AngularJS, Asp.net Mvc 5 ve Web Api ile Crud İşlemlerinin Gerçekleştirilmesi

  • Visual studiomuzu başlatıyoruz.
  • Create a new project.
  • Web template seçiyoruz ve ardından ASP.NET Web Application seçiyoruz.
  • Projeye isim verip, projenin oluşturalacağı dizini seçiyoruz.
  • Next tıklıyoruz.
  • MVC seçiyoruz ve code referanslardan Web Apiyi seçip projemize dahil ediyoruz.

MVC template

Kolay bir örnek olması açısından education adında bir entity type oluşturuyorum.

public partial class Education
    {
        public Education()
        {
            this.Members = new List<Member>();
        }

        public int ID { get; set; }
        public string Education1 { get; set; }
        public virtual ICollection<Member> Members { get; set; }
    }

Yeni bir context class oluşturalım.

public class EducationContext : DbContext
{
     public EducationContext()
         : base("name=DefaultConnection")
     {
         base.Configuration.ProxyCreationEnabled = false;
     }
     public DbSet<Education> Education{ get; set; }
     public DbSet<Member> Member{ get; set; }
}

Şimdi ise tüm entity classlar için tek tek repository oluşturmaktansa Generic Repository oluşturacağız ve her bir poco classlar için tek bir repository yeterli olacak.

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
    {
        private readonly EducationContext _context;
        private readonly DbSet<TEntity> _dbSet;

        public GenericRepository(EducationContext context)
        {
            _context = context;
            _dbSet = context.Set<TEntity>();
        }

        /// <summary>
        /// Tüm kayıtlar.
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<TEntity> GetAll()
        {
            return _dbSet;
        }

        /// <summary>
        /// Kayıt bul.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual TEntity Find(int id)
        {
            return _dbSet.Find(id);
        }

        /// <summary>
        /// Kayıt ekle.
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Insert(TEntity entity)
        {
            _dbSet.Add(entity);
            _context.SaveChanges();
        }

        /// <summary>
        /// Kayıt güncelle.
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Update(TEntity entity)
        {
            _dbSet.Attach(entity);
            _context.Entry(entity).State = EntityState.Modified;
            _context.SaveChanges();
        }

        /// <summary>
        /// Kayıt sil.
        /// </summary>
        /// <param name="entity">Kayıt</param>
        public virtual void Delete(TEntity entity)
        {
            if (_context.Entry(entity).State == EntityState.Detached)
            {
                _dbSet.Attach(entity);
            }
            _dbSet.Remove(entity);
            _context.SaveChanges();
        }
    }

Generic Repository’i türettiğimiz IGenericRepository interfacesini oluşturalım.

public interface IGenericRepository where TEntity : class
{
/// Tüm kayıtlar.
IQueryable GetAll(); ///
/// Kayıt bul. ///
TEntity Find(int id); ///
/// Kayıt ekle. ///
void Insert(TEntity entity); ///
/// Kayıt güncelle. ///
void Update(TEntity entityToUpdate); ///
/// Kayıt sil. ///
void Delete(TEntity entityToDelete);
}

Web api controller oluşturmadan önce education bilgileriyle işlem yapabilmek için service oluşturalım.

public class EducationService : IEducationService
    {
        private readonly IGenericRepository<Education> _educationRepository;

        public EducationService(IGenericRepository<Education> educationRepository)
        {
            _educationRepository = educationRepository;
        }
        public IQueryable<Education> GetAll()
        {
            var educations = _educationRepository.GetAll();
            return educations;
        }
        public Education Find(int id)
        {
            var educations = _educationRepository.GetAll().FirstOrDefault(a => a.ID == id);
            return educations;
        }

        public void Insert(Education education)
        {
            _educationRepository.Insert(education);
        }

        public void Update(Education education)
        {
            _educationRepository.Update(education);
        }

        public void Delete(Education education)
        {
            _educationRepository.Delete(education);
        }
    }

Şimdi ise servisimizin türetildiği IEducationService interfacesini oluşturalım

public interface IEducationService
{
IQueryable GetAll(); ///
Education Find(int id); ///
void Insert(Education education);
void Update(Education education);
void Delete(Education education); 

}

Şimdi sıra geldi web apiyi oluşturmaya. Web api controllerin içerisinde tüm transactionları gerçekleştirmek için tüm http methodları kullanacağız. Bunlar: GET, POST, PUT, DELETE methodlarıdır.

public class EducationApiController : ApiController
    {
        private readonly IEducationService service =  ServiceFactory.Get<IEducationService>();

        [HttpGet()]
        //[Route("api/educations")]
        public IEnumerable<Education> Get()
        {
                var list = service.GetAll().ToList().AsEnumerable();
                return list;
            
        }
        //[Route("api/education/{id}")]
        public Education Get(int id)
        {
            try
            {
                var education = service.GetAll().FirstOrDefault(p => p.ID == id);
                if(education == null)
                {
                    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
                }
                return education;
            }
            catch(Exception ex)
            {
                return null;
            }
        }

        public HttpResponseMessage Post(Education education)
        {

                try
                {
                    var education1 = new Education();
                    service.Insert(education);

                    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, education1);
                    response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = education1.ID }));
                    return response;
                }
                catch(Exception ex)
                {
                    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
                    //unitofwork.Rollback();
                }
                
        }

        public HttpResponseMessage Put(Education education)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            try
            {
                service.Update(education);
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        public HttpResponseMessage Delete(int id)
        {
            var education1 = new Education();
            education1 = service.Find(id);
            if (education1 == null)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            try
            {
                service.Delete(education1);
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }
            return Request.CreateResponse(HttpStatusCode.OK, education1);
        }


    }

Web api controllerda dependency injection kullanamadığımız için Service Factory adında generic bir helper ekleyeceğiz ve bu helper web api controllera Education Servicein enjekte edilmesini sağlayacak.

public static class ServiceFactory
    {
        public static THelper Get<THelper>()
        {
            if (HttpContext.Current != null)
            {
                var key = string.Concat("factory-", typeof(THelper).Name);
                if (!HttpContext.Current.Items.Contains(key))
                {
                    var resolvedService = DependencyResolver.Current.GetService<THelper>();
                    HttpContext.Current.Items.Add(key, resolvedService);
                }
                return (THelper)HttpContext.Current.Items[key];
            }
            return DependencyResolver.Current.GetService<THelper>();
        }
    }

Şimdi ise Manage Nuget Package Manager kullanarak Angular JS kütüphanelerini solutiona ekleyelim.

search AngularJS

Şimdi yeni bir javascript dosyası oluşturalım ve angular functionları ekleyelim. Bu angular controllerının adına educationController koyduk. İlerde oluşturacağımız view sayfasında controllerı bu isimle çağıracağız.

var myApp = angular.module('myApp', []).controller('educationController',
['$scope', '$http', function ($scope, $http) {
    $scope.loading = true;
    $scope.addMode = false;

    function GetEducations()
    {
        $http.get('/api/EducationApi/').success(function (data) {
            $scope.educations = data;
            $scope.loading = false;
        })
            .error(function () {
                $scope.error = "An Error has occured while loading posts!";
                $scope.loading = false;
            });
    }
    //Used to display the data
    GetEducations();

    $scope.toggleEdit = function () {
        this.education.editMode = !this.education.editMode;
    };
    $scope.toggleAdd = function () {
        $scope.addMode = !$scope.addMode;
    };

    //Used to save a record after edit
    $scope.save = function () {
        $scope.loading = true;
        var educate = this.education;
        $http.put('/api/EducationApi/put',  educate).success(function (data) {
            alert("Saved Successfully!!");
            educate.editMode = false;
            $scope.loading = false;
            GetEducations();
        }).error(function (data) {
            $scope.error = "An Error has occured while Saving Friend! " + data;
            $scope.loading = false;

        });
    };

    //Used to add a new record
    $scope.add = function () {
        $scope.loading = true;
        $http.post('/api/EducationApi/post', this.neweducation).success(function (data) {
            alert("Added Successfully!!");
            $scope.addMode = false;
            $scope.educations.push(data);
            $scope.loading = false;
            GetEducations();
        }).error(function (data) {
            $scope.error = "An Error has occured while Adding Friend! " + data;
            $scope.loading = false;

        });
    };

    //Used to edit a record
    $scope.deleteeducation = function () {
        $scope.loading = true;
        var educationid = this.education.id;
        $http.delete('/api/EducationApi/delete' + educationid).success(function (data) {
            alert("Deleted Successfully!!");
            $.each($scope.educations, function (i) {
                if ($scope.educations[i].ID === educationid) {
                    $scope.educations.splice(i, 1);
                    return false;
                }
            });
            $scope.loading = false;
            GetEducations();
        }).error(function (data) {
            $scope.error = "An Error has occured while Saving Friend! " + data;
            $scope.loading = false;

        });
    };

}]);

Shared klasörü altındaki _Layout.cshtml sayfasını açıp 2 farklı scripti render etmemiz gerekiyor.

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/angularjs")
    @Scripts.Render("~/bundles/education")

Sıradaki işlemimiz view oluşturup bunun üzerinde çalışmak.



@{
    ViewBag.Title = "EducationIndex";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Education </h2>
<style>
    #mydiv {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 1000;
        background-color: grey;
        opacity: .8;
    }

    .ajax-loader {
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -32px; /* -1 * image width / 2 */
        margin-top: -32px; /* -1 * image height / 2 */
        display: block;
    }
</style>
@*<script src="~/Scripts/EducationController.js"></script>*@
<div data-ng-app="myApp">
<div data-ng-controller="educationController" class="container">
    <strong class="error">{{ error }}</strong>
    <div id="mydiv" data-ng-show="loading">
        <img src="~/Images/ajax-loader.gif" class="ajax-loader" />
    </div>
    <p data-ng-hide="addMode"><a data-ng-click="toggleAdd()" href="javascript:;" class="btn btn-primary">Add New</a></p>
    <form name="addEducation" data-ng-show="addMode" style="width:600px;margin:0px auto;">
        <label>Education:</label><input type="text" data-ng-model="neweducation.Education1" required />

        <br />
        <br />
        <input type="submit" value="Add" data-ng-click="add()" data-ng-disabled="!addEducation.$valid" class="btn btn-primary" />
        <input type="button" value="Cancel" data-ng-click="toggleAdd()" class="btn btn-primary" />
        <br /><br />
    </form>
    <table class="table table-bordered table-hover" style="width:800px">
        <tr>
            <th>#</th>
            <td>Education</td>

        </tr>

        <tr data-ng-repeat="education in educations track by $index">
            <td><strong data-ng-hide="education.editMode">{{ education.id }}</strong></td>
            <td>
                <p data-ng-hide="education.editMode">{{ education.education1 }}</p>
                <input data-ng-show="education.editMode" type="text" data-ng-model="education.education1" />
            </td>
            <td>
                <p data-ng-hide="education.editMode"><a data-ng-click="toggleEdit(education)" href="javascript:;">Edit</a> | <a data-ng-click="deleteeducation(education)" href="javascript:;">Delete</a></p>
                <p data-ng-show="education.editMode"><a data-ng-click="save(education)" href="javascript:;">Save</a> | <a data-ng-click="toggleEdit(education)" href="javascript:;">Cancel</a></p>
            </td>
        </tr>
    </table>
    <hr />


</div>
</div>

Şimdi uygulamamızı çalıştıralım.

Ekran Alıntısı1

Ekran Alıntısı2

Ekran Alıntısı3

Ekran Alıntısı4

Bu makalede MVC 5 ile AngularJS ve Web Api ile CRUD işlemleri nasıl yapılır onu öğrendik. Bir dahaki makalede görüşmek dileğiyle..

Asp.net Cookie Encyript ve Decrypt

Bu makalemde asp.net projesi içerisindeki cookieleri nasıl encyript ve decrypt yapıcağımızı göstereceğim. Bunun için ise “MachineKey.Protect” and “MachineKey.Unrotect” methodlarını kullanacağız.

Encrypt Cookies:
//using System.Text;
//using System.Web.Security;

var cookieText = Encoding.UTF8.GetBytes("Text for Cookie");
var encryptedValue = Convert.ToBase64String(MachineKey.Protect(cookieText, "ProtectCookie"));

//--- Create cookie object and pass name of the cookie and value to be stored.
HttpCookie cookieObject = new HttpCookie("NameOfCookie", encryptedValue);

//---- Set expiry time of cookie.
cookieObject.Expires.AddDays(5);

//---- Add cookie to cookie collection.
Response.Cookies.Add(cookieObject);
Decrypt Cookies:
 
var bytes = Convert.FromBase64String(Request.Cookies["NameOfCookie"].Value);
var output = MachineKey.Unprotect(bytes, "ProtectCookie");
string result = Encoding.UTF8.GetString(output);

Asp.net Mvc Bir Sayfada Partial View Render Etme

Merhabalar. Bu yazımda mvc projemizde herhangi bir cshtml view sayfamızdan partial view çağırmayı ve bu sayfada nasıl render edildiğini anlatacağım.

Görüntülemek istediğimiz bir view sayfasında partial viewlar kullanmak isteyebiliriz. Sayfada görüntülemek istediğimiz her şeyi tek bir controller actionda yüklemek yerine küçük partial sayfalara ayırmak işimizi daha kolaylaştırır ve de daha sadeleştirip, okunurluğu artırabiliriz. Bunun için bir PartialViewResult methodu oluşturalım.

public PartialViewResult Partial()
{
    return PartialView("Partial");
}

Daha sonra bu methodumuzun üzerine gelip sağ tıklayıp Add View ekranında viewa bir isim verdikten sonra View Options kısmında Create as a partial view seçip bir view ekleyelim. Eğer methodumuzun return olan PartialView() methodu içerisinde bir Partial view ismi yazıyorsa, o viewi yükler. Eğer return olan partialview() methodunun içerisi boş ise, yani hiç bir view sayfasını yüklemek istemiyorsak yukarıdaki oluşturduğumuz ve kendi belirlediğimiz isimdeki partial view’i yükler.

Şimdi ise sırada herhangi bir view sayfasının içerisinden yukarıda oluşturduğumuz Partial isimli methodu çağırma işlemi var. Bu methodu çağırdığımızda partial view render edilmiş olacak.

@Html.Action("Partial", "Home")

Böylece Html helper yardımı ile sayfamızda partial view render etmiş olduk.

Generic Repository ve Unit of Work Pattern, Entity Framework, Unit Testing, Autofac IoC Container ve ASP.NET MVC [Part 3]

Son 2 makalemdeki yaptığımız şeylere göz gezdirelim:

Entity Framework ile Generic Repository ve Unit Of Work İmplementasyonu

Autofac ve CRUD İşlemleri ile MVC Dependency Injection

Unit Testing:

SampleArch.Test projesini oluşturmuştuk. Şimdi mocking işlemleri için Moq kütüphanesini kullanacağız. Moq kullanmak için Package Manager Console ekranına Install-Package Moq satırını ekleyin ve çalıştırın. Bunu diğer tüm projelere referans olarak ekleyin.

Controller Test:

Controller test için Mock servis objesi ve controller methodları oluşturacağız. Basit bir örnek olması için CountryController test edeceğiz.

[TestClass]
  public class CountryControllerTest
  {
      private Mock<ICountryService> _countryServiceMock;
      CountryController objController;
      List<Country> listCountry;
      [TestInitialize]
      public void Initialize()
      {
          _countryServiceMock = new Mock<ICountryService>();
          objController = new CountryController(_countryServiceMock.Object);
          listCountry = new List<Country>() {
           new Country() { Id = 1, Name = "US" },
           new Country() { Id = 2, Name = "India" },
           new Country() { Id = 3, Name = "Russia" }
          };
      }
      [TestMethod]
      public void Country_Get_All()
      {
          //Arrange
          _countryServiceMock.Setup(x => x.GetAll()).Returns(listCountry);
          //Act
          var result = ((objController.Index() as ViewResult).Model) as List<Country>;
          //Assert
          Assert.AreEqual(result.Count, 3);
          Assert.AreEqual("US", result[0].Name);
          Assert.AreEqual("India", result[1].Name);
          Assert.AreEqual("Russia", result[2].Name);
      }
      [TestMethod]
      public void Valid_Country_Create()
      {
          //Arrange
          Country c = new Country() { Name = "test1"};
          //Act
          var result = (RedirectToRouteResult)objController.Create(c);
          //Assert
          _countryServiceMock.Verify(m => m.Create(c), Times.Once);
          Assert.AreEqual("Index", result.RouteValues["action"]);
         
      }
      [TestMethod]
      public void Invalid_Country_Create()
      {
          // Arrange
          Country c = new Country() { Name = ""};
          objController.ModelState.AddModelError("Error", "Something went wrong");
          //Act
          var result = (ViewResult)objController.Create(c);
          //Assert
          _countryServiceMock.Verify(m => m.Create(c), Times.Never);
          Assert.AreEqual("", result.ViewName);
      }
  }

Initialize: Mock servis objesi, controller ve diğer objeleri initialize eder.
Country_Get_All: Test controllerın index methodu.
Valid_Country_Create: Create actionunun Modelstate’i valid olduğu andaki test methodu.
Invalid_Country_Create: Create actionunun Modelstate’i invalid olduğu andaki yani hata fırlattığı andaki test methodu.

Service Testing:

Bunun için Mock repository ve diğer servis methodlarını kullanan objeleri oluşturacağız.

[TestClass]
  public class CountryServiceTest
  {
      private Mock<ICountryRepository> _mockRepository;
      private ICountryService _service;
      Mock<IUnitOfWork> _mockUnitWork;
      List<Country> listCountry;
      [TestInitialize]
      public void Initialize()
      {
          _mockRepository = new Mock<ICountryRepository>();
          _mockUnitWork = new Mock<IUnitOfWork>();
          _service = new CountryService(_mockUnitWork.Object, _mockRepository.Object);
          listCountry = new List<Country>() {
           new Country() { Id = 1, Name = "US" },
           new Country() { Id = 2, Name = "India" },
           new Country() { Id = 3, Name = "Russia" }
          };
      }
      [TestMethod]
      public void Country_Get_All()
      {
          //Arrange
          _mockRepository.Setup(x => x.GetAll()).Returns(listCountry);
          //Act
          List<Country> results = _service.GetAll() as List<Country>;
          //Assert
          Assert.IsNotNull(results);
          Assert.AreEqual(3, results.Count);
      }
      [TestMethod]
      public void Can_Add_Country()
      {
          //Arrange
          int Id = 1;
          Country emp = new Country() { Name = "UK" };
          _mockRepository.Setup(m => m.Add(emp)).Returns((Country e) =>
          {
              e.Id = Id;
              return e;
          });
         
          //Act
          _service.Create(emp);
          //Assert
          Assert.AreEqual(Id, emp.Id);
          _mockUnitWork.Verify(m => m.Commit(), Times.Once);
      }
  }

Initialize: Mock repository, mock unit of work ve servis objelerini initalize eder.
Country_Get_All:  GetAll methodunu test eder.
Can_Add_Country:  Create methodunu test eder.

Repository Testing:

It is less required to test repository because EF is already well tested.

Teste başlamadan önce testcontext oluşturalım ve şu classları ve kod satırlarını ekleyelim: TestContext.cs

public class TestContext : DbContext
  {
      public TestContext()
          : base("Name=TestContext")
      {
      }
      public TestContext(bool enableLazyLoading, bool enableProxyCreation)
          : base("Name=TestContext")
      {
          Configuration.ProxyCreationEnabled = enableProxyCreation;
          Configuration.LazyLoadingEnabled = enableLazyLoading;
      }
      public TestContext(DbConnection connection)
          : base(connection, true)
      {
          Configuration.LazyLoadingEnabled = false;
      }
      public DbSet<Person> Persons { get; set; }
      public DbSet<Country> Countries { get; set; }
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          // Suppress code first model migration check         
          Database.SetInitializer<TestContext>(new AlwaysCreateInitializer());
          modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
          modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
          modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
          base.OnModelCreating(modelBuilder);
      }
      public void Seed(TestContext Context)
      {
          var listCountry = new List<Country>() {
           new Country() { Id = 1, Name = "US" },
           new Country() { Id = 2, Name = "India" },
           new Country() { Id = 3, Name = "Russia" }
          };
          Context.Countries.AddRange(listCountry);
          Context.SaveChanges();
      }
      public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<TestContext>
      {
          protected override void Seed(TestContext context)
          {
              context.Seed(context);
              base.Seed(context);
          }
      }
      public class CreateInitializer : CreateDatabaseIfNotExists<TestContext>
      {
          protected override void Seed(TestContext context)
          {
              context.Seed(context);
              base.Seed(context);
          }
      }
      public class AlwaysCreateInitializer : DropCreateDatabaseAlways<TestContext>
      {
          protected override void Seed(TestContext context)
          {
              context.Seed(context);
              base.Seed(context);
          }
      }
  }

1. Burada iki tip constructor bulunmakta. Bunlardan bir tanesi connectionstring kullanırken bir tanesi de DBConnection  nesnesini kullanıyor. Biz bu iki tipi de kullanacağız.
2. Datasource tekrardan oluşturulduğunda, recreate edildiğinde her defasında tekrardan initialize etmesi için AlwaysCreateInitializer Initializer nesneni kullanılıyorum.

1
Database.SetInitializer<TestContext>(new AlwaysCreateInitializer());

İhtiyacınıza göre DropCreateIfChangeInitializer,CreateInitializer initializer nesnelerini de kullanabilirsiniz.

Test için 2 yol daha var bunlar :
1. Memory database içinde kullanma
2. Diğer bir database’i kullanarak test etmek.

Biz iki yolu da kullanacağız.

1. Memory database İçinde Kullanma

Bunun için Effort kütüphanesini kullanacağız. EF6 için Effort kütüphanesini install etmek için Package Manager Console ekranına :

Install-Package Effort.EF6

kod satırını ekleyip çalıştırmamız yeterlidir.

[TestClass]
  public class CountryRepositoryTest
  {
      DbConnection connection;
      TestContext databaseContext;
      CountryRepository objRepo;
      [TestInitialize]
      public void Initialize()
      {
          connection = Effort.DbConnectionFactory.CreateTransient();
          databaseContext = new TestContext(connection);
          objRepo = new CountryRepository(databaseContext);
         
      }
      [TestMethod]
      public void Country_Repository_Get_ALL()
      {
          //Act
          var result = objRepo.GetAll().ToList();
          //Assert
          Assert.IsNotNull(result);
          Assert.AreEqual(3, result.Count);
          Assert.AreEqual("US", result[0].Name);
          Assert.AreEqual("India", result[1].Name);
          Assert.AreEqual("Russia", result[2].Name);
      }
      [TestMethod]
      public void Country_Repository_Create()
      {
          //Arrange
          Country c = new Country() {Name  = "UK" };
          //Act
          var result = objRepo.Add(c);
          databaseContext.SaveChanges();
          var lst = objRepo.GetAll().ToList();
          //Assert
          Assert.AreEqual(4, lst.Count);
          Assert.AreEqual("UK", lst.Last().Name);
      }
  }

Initialize: Effort, context ve repository nesnesini initialize etmek için.
Country_Repository_Get_ALL: Repositorynin GetAll methodunu check etmek için kullanılır.
Country_Repository_Create: Repositorynin Add methodunu check etmek için kullanılır.

2. Use another database for testing

Appconfig içerisine connectionstring ekleyelim.

1
2
3
<connectionStrings>
    <add name="TestContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=SampleArchTest;Integrated Security=SSPI;AttachDBFilename=E:\Project SA\Arch\SampleArch\SampleArch\SampleArch.Test\DB\SampleArchTest.mdf" providerName="System.Data.SqlClient"/>
  </connectionStrings>
[TestClass]
   public class CountryRepositoryTestWithDB
   {
    
       TestContext databaseContext;
       CountryRepository objRepo;
       [TestInitialize]
       public void Initialize()
       {
         
           databaseContext = new TestContext();
           objRepo = new CountryRepository(databaseContext);
          
       }
       [TestMethod]
       public void Country_Repository_Get_ALL()
       {
           //Act
           var result = objRepo.GetAll().ToList();
           //Assert
           Assert.IsNotNull(result);
           Assert.AreEqual(3, result.Count);
           Assert.AreEqual("US", result[0].Name);
           Assert.AreEqual("India", result[1].Name);
           Assert.AreEqual("Russia", result[2].Name);
       }
       [TestMethod]
       public void Country_Repository_Create()
       {
           //Arrange
           Country c = new Country() {Name  = "UK" };
           //Act
           var result = objRepo.Add(c);
           databaseContext.SaveChanges();
           var lst = objRepo.GetAll().ToList();
           //Assert
           Assert.AreEqual(4, lst.Count);
           Assert.AreEqual("UK", lst.Last().Name);
       }
   }

Burada kendi regular provider’ımız kullanıyoruz ve her defasında databasei tekrardan oluşturuyoruz.

unit-test

 

ÖZET:

Bu makalede uygulamamızın kodlarına dokunmadan farklı katmanlarının nasıl test edildiğini görmüş olduk.

İyi Çalışmalar.

Generic Repository ve Unit of Work Pattern, Entity Framework, Unit Testing, Autofac IoC Container ve ASP.NET MVC [Part 2]

Bir önceki makalemde model, servis ve repository katmanları oluşturdum. Bu makalemde ise oluşturduğum katmanlarla CRUD işlemlerini yapacağız ve Autofac IoC Container kuracağım.

Setup AutoFac:

Mvc projesi içinde Package Manager Console ekranındaki command satırına şu komutu yazın:

Install-Package Autofac.Mvc5

Ayrıca bu komut Autofac’ı da install edecektir.

Autofac kurulumu ile classlarımızı da register etmeye başlayabiliriz. Modules adında bir folder oluşturalım ve içine şu dosyaları alsın:

RepositoryModule.cs

public class RepositoryModule : Autofac.Module
   {
       protected override void Load(ContainerBuilder builder)
       {
           builder.RegisterAssemblyTypes(Assembly.Load("SampleArch.Repository"))
                  .Where(t => t.Name.EndsWith("Repository"))
                  .AsImplementedInterfaces()
                 .InstancePerLifetimeScope();
       }
   }

Bu işlem Autofac içindeki bütün classların sonuna “Repository” getirerek classları register edecektir.ServiceModule.cs

public class ServiceModule : Autofac.Module
  {
      protected override void Load(ContainerBuilder builder)
      {
          builder.RegisterAssemblyTypes(Assembly.Load("SampleArch.Service"))
                    .Where(t => t.Name.EndsWith("Service"))
                    .AsImplementedInterfaces()
                    .InstancePerLifetimeScope();
      }
  }

Bu işlem Autofac içindeki bütün classların sonuna “Service” getirerek classları register edecektir.

EFModule.cs

public class EFModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterModule(new RepositoryModule());
            builder.RegisterType(typeof(SampleArchContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
            builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerRequest();        
        }
    }

Global.asax dosyası içindeki Application_Start methodu içerisine bazı satırlar ekleyelim:

//Autofac Configuration
          var builder = new Autofac.ContainerBuilder();
          builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
          builder.RegisterModule(new RepositoryModule());
          builder.RegisterModule(new ServiceModule());
          builder.RegisterModule(new EFModule());
          var container = builder.Build();
          DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Ayrıca şu namespaceleri de eklememiz gerekmektedir.

using Autofac.Integration.Mvc;
using Autofac;

Artık service objesini controller classları içerisine enjekte edebiliriz.

Country CRUD Implementasyonu:

Mvc projesinin içerisine Model ve Servis projelerinin referanslarını ekleyelim. Yeni bir controller ekleyip optionunu “MVC 5 Controller with Views using Entity Framework” seçelim. Name : CountryController,  Select Model : “Country“, DataContext:SampleArchContext, Set “Generate Views” true, Click Add deyip controller ekleme işini tamamlayalım. Böylece EF kullanarak action ve viewları implement etmiş olduk. Şimdi controllerımızı service katmanına göre modifiye edelim:

public class CountryController : Controller
   {
       //initialize service object
       ICountryService _CountryService;
       public CountryController(ICountryService CountryService)
       {
           _CountryService = CountryService;
       }
       //
       // GET: /Country/
       public ActionResult Index()
       {
           return View(_CountryService.GetAll());
       }      
       //
       // GET: /Country/Create
       public ActionResult Create()
       {
           return View();
       }
       //
       // POST: /Country/Create
       [HttpPost]
       [ValidateAntiForgeryToken]
       public ActionResult Create(Country country)
       {
           // TODO: Add insert logic here
           if (ModelState.IsValid)
           {
               _CountryService.Create(country);
               return RedirectToAction("Index");
           }
           return View(country);
       }
       //
       // GET: /Country/Edit/5
       public ActionResult Edit(int id)
       {           
           Country country = _CountryService.GetById(id);
           if (country == null)
           {
               return HttpNotFound();
           }
           return View(country);
       }
       //
       // POST: /Country/Edit
       [HttpPost]
       public ActionResult Edit(Country country)
       {
           if (ModelState.IsValid)
           {
               _CountryService.Update(country);
               return RedirectToAction("Index");
           }
           return View(country);
       }
       //
       // GET: /Country/Delete/5
       public ActionResult Delete(int id)
       {
           Country country = _CountryService.GetById(id);
           if (country == null)
           {
               return HttpNotFound();
           }
           return View(country);
       }
       //
       // POST: /Country/Delete/5
       [HttpPost, ActionName("Delete")]
       [ValidateAntiForgeryToken]
       public ActionResult Delete(int id, FormCollection data)
       {
           Country country = _CountryService.GetById(id);
           _CountryService.Delete(country);
           return RedirectToAction("Index");
       }
   }

Yukarıda gördüğünüz gibi Controller classımızın constructoruna servis katmanından gelen ICountryService objesini enjekte ettik. Constructor Dependency injection controller classımız teste uygun hale getirir.

Şimdi relationship içeren diğer CRUD işlemlerinin gözden geçirelim :

Person CRUD Implementasyonu :

CountryControllara benzer bir şekilde PersonController ekliyoruz. Aşağıda Entity Framework yapısı kullanarak Country dropdownList oluşturacağız. CountryController’da olduğu gibi servis katmanı ile PersonController classını da modifiye edelim.

public class PersonController : Controller
  {
      IPersonService _PersonService;
      ICountryService _CountryService;
      public PersonController(IPersonService PersonService, ICountryService CountryService)
      {
          _PersonService = PersonService;
          _CountryService = CountryService;
      }
      // GET: /Person/
      public ActionResult Index()
      {
          return View(_PersonService.GetAll());
      }
      // GET: /Person/Details/5
      public ActionResult Details(long? id)
      {
          if (id == null)
          {
              return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
          }
          Person person = _PersonService.GetById(id.Value);
          if (person == null)
          {
              return HttpNotFound();
          }
          return View(person);
      }
      // GET: /Person/Create
      public ActionResult Create()
      {
          ViewBag.CountryId = new SelectList(_CountryService.GetAll(), "Id", "Name");
          return View();
      }
      // POST: /Person/Create
      // To protect from overposting attacks, please enable the specific properties you want to bind to, for
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Create([Bind(Include = "Id,Name,Phone,Address,State,CountryId")] Person person)
      {
          if (ModelState.IsValid)
          {
              _PersonService.Create(person);
              return RedirectToAction("Index");
          }
          ViewBag.CountryId = new SelectList(_CountryService.GetAll(), "Id", "Name", person.CountryId);
          return View(person);
      }
      // GET: /Person/Edit/5
      public ActionResult Edit(long? id)
      {
          if (id == null)
          {
              return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
          }
          Person person = _PersonService.GetById(id.Value);
          if (person == null)
          {
              return HttpNotFound();
          }
          ViewBag.CountryId = new SelectList(_CountryService.GetAll(), "Id", "Name", person.CountryId);
          return View(person);
      }
      // POST: /Person/Edit/5
      // To protect from overposting attacks, please enable the specific properties you want to bind to, for
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Edit([Bind(Include = "Id,Name,Phone,Address,State,CountryId")] Person person)
      {
          if (ModelState.IsValid)
          {
              _PersonService.Update(person);
              return RedirectToAction("Index");
          }
          ViewBag.CountryId = new SelectList(_CountryService.GetAll(), "Id", "Name", person.CountryId);
          return View(person);
      }
      // GET: /Person/Delete/5
      public ActionResult Delete(long? id)
      {
          if (id == null)
          {
              return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
          }
          Person person = _PersonService.GetById(id.Value);
          if (person == null)
          {
              return HttpNotFound();
          }
          return View(person);
      }
      // POST: /Person/Delete/5
      [HttpPost, ActionName("Delete")]
      [ValidateAntiForgeryToken]
      public ActionResult DeleteConfirmed(long id)
      {
          Person person = _PersonService.GetById(id);
          _PersonService.Delete(person);
          return RedirectToAction("Index");
      }
  }

Yukarda da gördüğümüz bu controllerımızın constructoruna üzere hem CountryService , hem de PersonService nesnesini enjekte ettik. Çünkü controllerımızda her iki servisimize de erişmemiz gerekti. CountryService, ülkelerin dropdown seçimi için, PersonService ise CRUD işlemleri için gerekliydi.

Sonuç olarak view ekranımız şu şekilde olacaktır:

crud-autofac

ÖZET:

Bu makalemde Autofac kurulumunu ve Entity Framework ve Service Katmanları ile Generic Repository ve Unit of Work Pattern üzerinden base alarak CRUD işlemlerinin nasıl yapıldığını öğrendik. Diğer makalemde farklı katmanların Unit Test implementasyonunu anlatacağım.

İyi Çalışmalar.