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.

Reklamlar

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

  1. Zafer dedi ki:

    “Country” controller altındaki “Edit” actionu için “[ValidateAntiForgeryToken]” attribute kullanılmamış ?

  2. Can dedi ki:

    Neden Autofac yerine Ninject kullanmadın? Genelde sanırım IoC için Ninject kullanılıyor. Bu kısmı Ninject ile yazsak nasıl yazarız. Açıklaman mümkün mü? Kolay gelsin.

    • Ninject te kullanılabilirdi ama autofac ta asp.net için yazılmış kullanımı çok basit bir Ioc Containerdır ve de özellikle MVC ile kullanılması çok yaygındır. Tutorial ve examplelar git üzerinde fazlasıyla bulunmaktadır. Castle Widsor, StructureMap, Spring.Net, Autofac, Unity gibi bir çok IOC Container bulunmaktadır Ninject kullanmak zorunda değilsiniz

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s