Sayfalar

19 Kasım 2013 Salı

ASP.NET MVC - KOMPLE BİR PROJE YAPISI OLUŞTURMAK - 3

Önceki yazılarda, projemizin altyapısını nasıl oluşturacağımıza bakmıştık. Proje artık veritabanı ile ileşime geçmiş haldedir. Bu yazıdada, uygulama tarafının iskeletini oluşturacağız.

Öncelikle, BaseController diye bir controller sınıfı oluşturalım. Diğer tüm controller sınıfları bu sınıftan kalıtım alacak. Bu controller sınıfının amacı, tüm controller sınıfları için ortak bir veri iletişimi sağlamak. Bu sınıfın ne iş yaptığını, kullanınca daha iyi anlayacaksınız. Base controller sınıfımız aşağıdaki gibidir.

BaseController.cs
using System.Web.Mvc;
using MvcProject.Data.UnitOfWork;
 
namespace MvcProject.Web.Controllers
{
    public class BaseController : Controller
    {
        protected readonly IUnitOfWork _uow;
 
        public BaseController(IUnitOfWork uow)
        {
            _uow = uow;
        }
 
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
        }
    }
}

UnitOfWork sınıfı her controller için ortaktır. Çünkü, DbContext içerisinde yaptığımız her değişikliğin, veritabanına yansıması için, bu sınıf içerisindeki saveChanges metodunu kullanıyoruz. Şimdi artık tüm controller sınıfları bu sınıftan kalıtım alacak. Örneğin, HomeController sınıfını ekleyelim.

HomeController.cs
using System.Web.Mvc;
using MvcProject.Data.UnitOfWork;
 
namespace MvcProject.Web.Controllers
{
    public class HomeController : BaseController
    {
        public HomeController(IUnitOfWork uow)
            : base(uow)
        {
 
        }
 
        public ActionResult Index()
        {
            return View();
        }
 
    }
}

Index metodu için bir View oluşturalım ve projeyi çalıştıralım. Projeyi çalıştırdığımız zaman aşağıdaki gibi bir hata alacağız:

MVC controller lar için parametreli bir yapıcı metodu yok. Bundan dolayı controller ların yapıcı metodlarına, parametre gondermek için, bir IOC projesi kullanacağız. Öncelikler IOC projesinde ayarlamalar, daha sonra web projesinde ayarlamalar yaparak, projemizi dependency injection (DI) için uygun hale getireceğiz.

DI için yapılması gerekenler sırasıyla;

  1. Solution a IOC adında bir Class Library projesi ekliyoruz.
  2. Bu projeye Refrences/Manage Nuget Pack... ile acılan sayfada unity.mvc4 ü aratıp kuruyoruz.
  3. Projeye, Bootsrapper.cs adında bir sınıf ekleniyor. Bu sınıfı aşağıdaki gibi değiştiriyoruz.
  4. IOC içerisine service, core ve data projelerimizi referans etmeliyiz.
  5. IOC projesini de web projesi içerisinde referans ediyoruz.
  6. Ayrıca web projesine, IOC/bin klasorundeki Unity.Mvc4.dll, Microsoft.Practices.Unity.dll ve Microsoft.Practices.Unity.Configuration.dll dosyalarını referans ediyoruz.
  7. Global.asax içerisinde Bootstrapper.Initialise(); komutu ile unity i ilkleme yapıyoruz.     
Bootstrapper.cs
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using MvcProject.Core.Domain.Entity;
using MvcProject.Data.Repository;
using MvcProject.Data.UnitOfWork;
using MvcProject.Service.Roles;
using MvcProject.Service.Users;
using Unity.Mvc4;
 
namespace MvcProject.IOC
{
    /// <summary>
    /// Bind the given interface in request scope
    /// </summary>
    public static class IOCExtensions
    {
        public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
        {
            container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
        }
 
        public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
        {
            container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
        }
    }
 
    public static class Bootstrapper
    {
        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();
 
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
            return container;
        }
 
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
 
            // register all your components with the container here
            // it is NOT necessary to register your controllers
 
            // e.g. container.RegisterType<ITestService, TestService>();    
            RegisterTypes(container);
 
            return container;
        }
 
        public static void RegisterTypes(IUnityContainer container)
        {
            container.BindInRequestScope<IGenericRepository<User>, GenericRepository<User>>();
            container.BindInRequestScope<IGenericRepository<Role>, GenericRepository<Role>>();
 
            container.BindInRequestScope<IUnitOfWorkUnitOfWork>();
 
            container.BindInRequestScope<IUserServiceUserService>();
            container.BindInRequestScope<IRoleServiceRoleService>();
        }
    }
}

Global.asax
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcProject.IOC;
 
namespace MvcProject.Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801
 
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
 
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
 
            Bootstrapper.Initialise();
        }
    }
}

Tüm bu ayarlardan sonra projeyi çalıştırdığımızda, bir hata almadan, proje DI na uygun bir yapıda çalışacaktır. Son olarak, twitter bootstrap içinde js ve css lerimizi eklersek, _Layout.cshtml sayfasının kodları aşağıdaki gibi olacaktır.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/modernizr")
    @RenderSection("scripts", required: false)
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>
</head>
<body class="container">
    <div class="header">
        <div id="main_menu">
            <nav class="navbar navbar-default" role="navigation">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Anasayfa</a>
                </div>
 
                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="navbar-collapse">
                    <ul class="nav navbar-nav">
                        <li><a href="#">Hakkımızda</a></li>
                        <li><a href="#">İletişim</a></li>
                    </ul>
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">Kullanıcı adı</a></li>
                        <li><a href="#">Giriş</a></li>
                    </ul>
                </div>
                <!-- /.navbar-collapse -->
            </nav>
        </div>
    </div>
    <div id="body">
        @RenderBody()
    </div>
    <div id="footer">
    </div>
</body>
</html>

Bu sayfa, web arayüzümüzün iskeleti olacaktır. Tabi burada, index sayfası nasıl eklenir, layout nedir, nasıl eklenir falan bu kısımları geciyorum. Bir sonraki makalede üyelik işlemlerini yapacağız.

21 yorum:

  1. eline sağlık hacı gene güzel bi makale olmuş her zaman ki gibi

    YanıtlaSil
  2. makale için teşekkürler.Bu servislerin controller ve view içinde nasıl kullanıldığına örnek gösterebilirmisiniz. Kullanıcılar Actionı içinde userService.GetAll() ve Viewda gösterilmesi gibi.

    YanıtlaSil
    Yanıtlar
    1. Şu an 4. makaleyi yazıyorum. Uyelik işlelerini anlattıgım. Bu makalede anlatacagım...

      Sil
  3. 4. makale ne zaman cikar

    YanıtlaSil
  4. Hocam elinize saglik cok guzel gidiyorsunuz devami bekliyoruz heyecanla.
    Benim merak ettigim bir sey var yalniz :) bu proje yapisini bu kadar dallandirdigimiz zaman bize neler kazandiriyor, neden bu kadar parcali yapi kuruyoruz?

    YanıtlaSil
    Yanıtlar
    1. Yapısal olarak, işleri birbirinden ayırmak için bu kadar katmana ayırıyoruz. Herkes kendi işini yapıyor. Repository, sadece veritabanına baglanıyor. Service repository den gelen verileri uygulama katmanına servis ediyor. Yazılım tasarımları, mimarileri, yazılımın bakımını geliştirilmesini kolaylaştırır. Yazılım tasarımları konusunda biraz araştırma yaparak, aslında ne demek istedigimi anlarsınız.

      Sil
    2. Tesekkurler hocam dun yazdiktan sonra baya bir arastirdim suan hepsi kafama yatti :).

      4. yazi ne zaman gelir kabaca bir tahmin yapilir mi?

      Sil
    3. Hocam ne zaman cikacak ya artik ciksin :D

      Sil
  5. Hocam en uzun zamana yayılan makale rekoru kırılmak üzere :)

    YanıtlaSil
  6. inşallah bekliyoruz günde 10 kere bakar oldum :)

    YanıtlaSil
  7. Merhaba,
    Aşağıdaki hatayı alıyorum. Yardımcı olursanız sevinirim.


    The type IUnitOfWork does not have an accessible constructor.

    Açıklama: Geçerli web isteği yürütülürken işlenmemiş özel durum oluştu. Lütfen hata ve kod içinde kaynaklandığı yer hakkında daha fazla bilgi almak için yığın izlemesini gözden geçirin.

    Özel Durum Ayrıntıları: System.InvalidOperationException: The type IUnitOfWork does not have an accessible constructor.

    YanıtlaSil
    Yanıtlar
    1. IUnitOfWork sınıflarını IOC projesine eklememişsiniz. Yada IOC projesini Web projesinde referans etmemişsiniz.

      Sil
    2. Aynı hata ile bende karşı karşıyayım :)

      "IUnitOfWork sınıflarını IOC projesine eklememişsiniz."

      derken neyi kast ettiğinizi anlamadım hocam?

      Sil
    3. Merhaba Alirıza bey;
      Aynı hatayla bende karşılaşmaktayım. hangi projeye hangi sınıfların ekleneceğini yazmanız mumkunmudur.
      Ben herbirini denedim ama bir yerde bir hatam var. ve hatayı maalesef bulamadım.

      Sil
  8. 6. maddedeki dll'leri aşşağıdaki dizinde bulabilirsiniz.Tabi projesinizi varsayılan dizinde oluşturmadıysanız.
    C:\Users\user\Documents\Visual Studio 2012\Projects\MvcProject\packages

    YanıtlaSil
  9. Merhaba blog'la ilgilenmiyorsunuz sanırım ama işin içinden çıkamadım ve şu şekilde bir hata alıyorum."Error2 The type 'Microsoft.Practices.Unity.IUnityContainer' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.Practices.Unity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    " yardımcı olur musunuz?

    YanıtlaSil
  10. Bu yorum yazar tarafından silindi.

    YanıtlaSil
  11. Makale için teşekkürler. Çok faydalı olmuş. Anlattıklarınızı adım adım projemde uyguluyorum. Projenin kaynak kodlarını yayınlamanız mümkün müdür? Teşekkür ederim.

    YanıtlaSil