in

Chennai .Net User Group

A platform that enables you to Learn, Share & Grow (India's first .Net user group)

Shiju Varghese's Blog

April 2010 - Posts

  • Dependency Injection in ASP.NET MVC NerdDinner App using Ninject

    In this post, I am applying Dependency Injection to the NerdDinner application using Ninject. The controllers of NerdDinner application have Dependency Injection enabled constructors. So we can apply Dependency Injection through constructor without change any existing code. A Dependency Injection framework injects the dependencies into a class when the dependencies are needed. Dependency Injection enables looser coupling between classes and their dependencies and provides better testability of an application and it removes the need for clients to know about their dependencies and how to create them. If you are not familiar with Dependency Injection and Inversion of Control (IoC), read Martin Fowler’s article Inversion of Control Containers and the Dependency Injection pattern.

    The Open Source Project NerDinner is a great resource for learning ASP.NET MVC.  A free eBook provides an end-to-end walkthrough of building NerdDinner.com application. The free eBook and the Open Source Nerddinner application are extremely useful if anyone is trying to lean ASP.NET MVC. The first release of  Nerddinner was as a sample for the first chapter of Professional ASP.NET MVC 1.0. Currently the application is updating to ASP.NET MVC 2 and you can get the latest source from the source code tab of Nerddinner at http://nerddinner.codeplex.com/SourceControl/list/changesets. I have taken the latest ASP.NET MVC 2 source code of the application and applied  Dependency Injection using Ninject and Ninject extension Ninject.Web.Mvc.

    Ninject &  Ninject.Web.Mvc

    Ninject is available at http://github.com/enkari/ninject and Ninject.Web.Mvc is available at http://github.com/enkari/ninject.web.mvc
    Ninject is a lightweight and a great dependency injection framework for .NET.  Ninject is a great choice of dependency injection framework when building ASP.NET MVC applications. Ninject.Web.Mvc is an extension for ninject which providing integration with ASP.NET MVC.


    Controller constructors and dependencies of NerdDinner application

    Listing 1 – Constructor of DinnersController

     

    public DinnersController(IDinnerRepository repository) {

        dinnerRepository = repository;

    }

     

    Listing 2 – Constrcutor of AccountController

    public AccountController(IFormsAuthentication formsAuth, IMembershipService service) {

        FormsAuth = formsAuth ?? new FormsAuthenticationService();

        MembershipService = service ?? new AccountMembershipService();

    }



     Listing 3 – Constructor of AccountMembership – Concrete class of IMembershipService

    public AccountMembershipService(MembershipProvider provider) {

        _provider = provider ?? Membership.Provider;

    }


       
    Dependencies of NerdDinner

    DinnersController, RSVPController SearchController and ServicesController have a dependency with IDinnerRepositiry. The concrete implementation of IDinnerRepositiry is DinnerRepositiry. AccountController has dependencies with IFormsAuthentication and IMembershipService. The concrete implementation of IFormsAuthentication is FormsAuthenticationService and the concrete implementation of IMembershipService is AccountMembershipService. The AccountMembershipService has a dependency with ASP.NET Membership Provider.

     Dependency Injection in NerdDinner using Ninject

    The below steps will configure Ninject to apply controller injection in NerdDinner application.

    Step 1 – Add reference for Ninject

    Open the  NerdDinner application and add  reference to Ninject.dll and Ninject.Web.Mvc.dll. Both are available from http://github.com/enkari/ninject and http://github.com/enkari/ninject.web.mvc

    Step 2 – Extend HttpApplication with NinjectHttpApplication

    Ninject.Web.Mvc extension allows integration between the Ninject and ASP.NET MVC. For this, you have to extend your HttpApplication with NinjectHttpApplication. Open the Global.asax.cs and inherit your MVC application from  NinjectHttpApplication instead of HttpApplication.

     

    public class MvcApplication : NinjectHttpApplication


    Then the Application_Start method should be replace with OnApplicationStarted method. Inside the OnApplicationStarted method, call the RegisterAllControllersIn() method.

     

    protected override void OnApplicationStarted()

    {

        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        ViewEngines.Engines.Clear();

        ViewEngines.Engines.Add(new MobileCapableWebFormViewEngine());

        RegisterAllControllersIn(Assembly.GetExecutingAssembly());

    }

     The RegisterAllControllersIn method will enables to activating all controllers through Ninject in the assembly you have supplied .We are passing the current assembly as parameter for RegisterAllControllersIn() method. Now we can expose dependencies of controller constructors and properties to request injections

    Step 3 – Create Ninject Modules

    We can configure your dependency injection mapping information using Ninject Modules.Modules just need to implement the INinjectModule interface, but most should extend the NinjectModule class for simplicity.

    internal class ServiceModule : NinjectModule

    {

        public override void Load()

        {           

            Bind<IFormsAuthentication>().To<FormsAuthenticationService>();

            Bind<IMembershipService>().To<AccountMembershipService>();         

            Bind<MembershipProvider>().ToConstant(Membership.Provider);

            Bind<IDinnerRepository>().To<DinnerRepository>();

        }

    }



    The above Binding inforamtion specified in the Load method tells the Ninject container that, to inject instance of DinnerRepositiry when there is a request for IDinnerRepositiry and  inject instance of FormsAuthenticationService when there is a request for IFormsAuthentication and inject instance of AccountMembershipService when there is a request for IMembershipService. The AccountMembershipService class has a dependency with ASP.NET Membership provider. So we configure that inject the instance of Membership Provider. When configuring the binding information, you can specify the object scope in you application.


    There are four built-in scopes available in Ninject:

    1. Transient  -  A new instance of the type will be created each time one is requested. (This is the default scope). Binding method is .InTransientScope()  
    2. Singleton - Only a single instance of the type will be created, and the same instance will be returned for each subsequent request. Binding method is .InSingletonScope()
    3. Thread -  One instance of the type will be created per thread. Binding method is .InThreadScope()
    4. Request -  One instance of the type will be created per web request, and will be destroyed when the request ends. Binding method is .InRequestScope()


    Step 4 – Configure the Ninject Kernel

    Once you create NinjectModule, you load them into a container called the kernel. To request an instance of a type from Ninject, you call the Get() extension method. We can configure the kernel, through the CreateKernel method in the Global.asax.cs.

    protected override IKernel CreateKernel()

    {

        var modules = new INinjectModule[]

        {

            new ServiceModule()

        };

     

        return new StandardKernel(modules);

    }



    Here we are loading the Ninject Module (ServiceModule created in the step 3)  onto the container called the kernel for performing dependency injection.



    Source Code

    You can download the source code from http://nerddinneraddons.codeplex.com. I just put the modified source code onto CodePlex repository. The repository will update with more add-ons for the NerdDinner application.

  • ASP.NET MVC ModelCopier

     In my earlier post ViewModel patten and AutoMapper in ASP.NET MVC application, We have discussed the need for  View Model objects and how to map values between View Model objects and Domain model objects using AutoMapper. ASP.NET MVC futures assembly provides a static class ModelCopier that can also use for copying values between View Model objects and Domain model objects. ModelCopier class has two static methods - CopyCollection and CopyModel.CopyCollection method would copy values between two collection objects and CopyModel would copy values between two model objects. 

    var expense=new Expense();

    ModelCopier.CopyModel(expenseViewModel, expense);


    The above code copying values from expenseViewModel object to  expense object.
                    
    For simple mapping between model objects, you can use ModelCopier but for complex scenarios, I highly recommending to using AutoMapper for mapping between model objects.

  • NoSQL with MongoDB, NoRM and ASP.NET MVC - Part 2

     
    In my last post, I have given an introduction to MongoDB and NoRM using an ASP.NET MVC demo app. I have updated the demo ASP.NET MVC app and a created a new drop at codeplex. You can download the demo at http://mongomvc.codeplex.com/

    In my last post, we have discussed to doing basic CRUD operations against a simple domain entity. In this post, let’s discuss on domain entity with deep object graph.

    The below is our domain entities

     

    public class Category

    {

     

        [MongoIdentifier]

        public ObjectId Id { get; set; }

     

        [Required(ErrorMessage = "Name Required")]

        [StringLength(25, ErrorMessage = "Must be less than 25 characters")]

        public string Name { get; set;}

        public string Description { get; set; }

        public List<Expense> Expenses { get; set; }

     

        public Category()

        {

            Expenses = new List<Expense>();

        }

    }

     

     

    public class Expense

    {

        [MongoIdentifier]

        public ObjectId Id { get; set; }

        public Category Category { get; set; }

        public string  Transaction { get; set; }

        public DateTime Date { get; set; }

        public double Amount { get; set; }

     

    }

     

     We have two domain entities - Category and Expense. A single category contains a list of expense transactions and every expense transaction should have a Category.

     

    The MongoSession class

     

    internal class MongoSession : IDisposable

    {

        private readonly MongoQueryProvider provider;

     

        public MongoSession()

        {

            this.provider = new MongoQueryProvider("Expense");

        }

     

        public IQueryable<Category> Categories

        {

            get { return new MongoQuery<Category>(this.provider); }

        }

        public IQueryable<Expense> Expenses

        {

            get { return new MongoQuery<Expense>(this.provider); }

        }

        public MongoQueryProvider Provider

        {

            get { return this.provider; }

        }

     

        public void Add<T>(T item) where T : class, new()

        {

            this.provider.DB.GetCollection<T>().Insert(item);

        }

     

        public void Dispose()

        {

            this.provider.Server.Dispose();

        }

        public void Delete<T>(T item) where T : class, new()

        {

            this.provider.DB.GetCollection<T>().Delete(item);

        }

     

        public void Drop<T>()

        {

            this.provider.DB.DropCollection(typeof(T).Name);

        }

     

        public void Save<T>(T item) where T : class,new()

        {

            this.provider.DB.GetCollection<T>().Save(item);           

        }

     

     

    }   

     

    ASP.NET MVC view model  for Expense transaction

     

    public class ExpenseViewModel

    {

        public ObjectId Id { get; set; }

     

        public ObjectId CategoryId { get; set; }

     

        [Required(ErrorMessage = "Transaction Required")]       

        public string Transaction { get; set; }

     

        [Required(ErrorMessage = "Date Required")]       

        public DateTime Date { get; set; }

     

        [Required(ErrorMessage = "Amount Required")]   

        public double Amount { get; set; }

     

        public IEnumerable<SelectListItem> Category { get; set; }

    }

     

    Let's create an action method for Insert and Update a expense transaction

     

    [HttpPost]

    public ActionResult Save(ExpenseViewModel expenseViewModel)

    {

        try

        {

            if (!ModelState.IsValid)

            {

                using (var session = new MongoSession())

                {

                    var categories = session.Categories.AsEnumerable<Category>();

                    expenseViewModel.Category = categories.ToSelectListItems(expenseViewModel.CategoryId);   

                }

                return View("Save", expenseViewModel);

            }

     

            var expense=new Expense();

            ModelCopier.CopyModel(expenseViewModel, expense);

     

            using (var session = new MongoSession())

            {

                ObjectId Id = expenseViewModel.CategoryId;

                var category = session.Categories

                    .Where(c => c.Id ==Id  )

                    .FirstOrDefault();

                expense.Category = category;

                session.Save(expense);

            }

            return RedirectToAction("Index");

        }

        catch

        {

            return View();

        }

    }

     

    To save a expense transaction is very easy. You just need to create a Expense object and set the Category object for Category property. The session.Save method will do the all magic for you. If it is a new Expense traction, it will create a new record to MongoDB with associated Category object and update the Expense if it is existing Expense record.

     

    Query with Expenses

    using (var session = new MongoSession())

    {

        var expenses = session.Expenses.

            Where(exp => exp.Date >= StartDate && exp.Date <= EndDate)

            .AsEnumerable<Expense>();

    }

     

    We are doing a LINQ query expression with a Date filter. We can easily work with MongoDB using NoRM driver and managing object graph of domain entities are pretty easy.


     Download the Source - You can download the source code form http://mongomvc.codeplex.com

  • NoSQL with MongoDB, NoRM and ASP.NET MVC

     

    In this post, I will give an introduction to how to work on NoSQL and document database with MongoDB , NoRM and ASP.Net MVC 2.


    NoSQL and Document Database


    The NoSQL movement is getting big attention in this year and people are widely talking about document databases and NoSQL along with web application scalability. According to Wikipedia, "NoSQL is a movement promoting a loosely defined class of non-relational data stores that break with a long history of relational databases. These data stores may not require fixed table schemas, usually avoid join operations and typically scale horizontally. Academics and papers typically refer to these databases as structured storage".


    Document databases are schema free so that you can focus on the problem domain and don't have to worry about updating the schema when your domain is evolving. This enables truly a domain driven development. One key pain point of relational database is the synchronization of database schema with your domain entities when your domain is evolving.There are lots of NoSQL implementations are available and both CouchDB and MongoDB got my attention. While evaluating both CouchDB and MongoDB, I found that CouchDB can’t perform dynamic queries and later I picked MongoDB over CouchDB. There are many .Net drivers available for MongoDB document database.


    MongoDB


    MongoDB is an open source, scalable, high-performance, schema-free, document-oriented database written in the C++ programming language. It has been developed since October 2007 by 10gen. MongoDB stores your data as binary JSON (BSON) format . MongoDB has been getting a lot of attention and you can see the the list of production deployments from here


    NoRM – C# driver for MongoDB


    NoRM is a C# driver for MongoDB with LINQ support. NoRM project is available on Github at http://github.com/atheken/NoRM.

    Demo with ASP.NET MVC

    I will show a simple demo with MongoDB, NoRM and ASP.NET MVC. To work with MongoDB and  NoRM, do the following steps

    1. Download the MongoDB databse For Windows 32 bit, download from http://downloads.mongodb.org/win32/mongodb-win32-i386-1.4.1.zip  and for Windows 64 bit, download  from http://downloads.mongodb.org/win32/mongodb-win32-x86_64-1.4.1.zip . The zip contains the mongod.exe for run the server and mongo.exe for the client
    2. Download the NorM driver for MongoDB at http://github.com/atheken/NoRM
    3. Create a directory call C:\data\db. This is the default location of MongoDB database. You can override the behavior.
    4. Run C:\Mongo\bin\mongod.exe. This will start the MongoDb server

    Now I am going to demonstrate how to program with MongoDb and NoRM in an ASP.NET MVC application.

    Let’s write a domain class

     

    public class Category

    {           

    [MongoIdentifier]

    public ObjectId Id { get; set; }

    [Required(ErrorMessage = "Name Required")]

    [StringLength(25, ErrorMessage = "Must be less than 25 characters")]

    public string Name { get; set;}

    public string Description { get; set; }

    }

     

    ObjectId is a NoRM type that represents a MongoDB ObjectId. NoRM will automatically update the Id becasue it is decorated by the MongoIdentifier attribute. The next step is to create a mongosession class. This will do the all interactions to the MongoDB.

     

    internal class MongoSession<TEntity> : IDisposable

    {

        private readonly MongoQueryProvider provider;

     

        public MongoSession()

        {

            this.provider = new MongoQueryProvider("Expense");

        }

     

        public IQueryable<TEntity> Queryable

        {

            get { return new MongoQuery<TEntity>(this.provider); }

        }

     

        public MongoQueryProvider Provider

        {

            get { return this.provider; }

        }

     

        public void Add<T>(T item) where T : class, new()

        {

            this.provider.DB.GetCollection<T>().Insert(item);

        }

     

        public void Dispose()

        {

            this.provider.Server.Dispose();

        }

        public void Delete<T>(T item) where T : class, new()

        {

            this.provider.DB.GetCollection<T>().Delete(item);

        }

     

        public void Drop<T>()

        {

            this.provider.DB.DropCollection(typeof(T).Name);

        }

     

        public void Save<T>(T item) where T : class,new()

        {

            this.provider.DB.GetCollection<T>().Save(item);           

        }

     

     

    }   

    The MongoSession constrcutor will create an instance of MongoQueryProvider that supports the LINQ expression and also create a database with name "Expense". If database is exists, it will use existing database, otherwise it will create a new databse with name  "Expense". The Save method can be used for both Insert and Update operations. If the object is new one, it will create a new record and otherwise it will update the document with given ObjectId.

     Let’s create ASP.NET MVC controller and controller actions for handling CRUD operations for the domain class Category

     

    public class CategoryController : Controller

    {

     

    //Index - Get the category list

    public ActionResult Index()

    {

        using (var session = new MongoSession<Category>())

        {

            var categories = session.Queryable.AsEnumerable<Category>();

            return View(categories);

        }

    }

     

    //edit a single category

    [HttpGet]

    public ActionResult Edit(ObjectId id)

    {

     

        using (var session = new MongoSession<Category>())

        {

            var category = session.Queryable

                  .Where(c => c.Id == id)

                  .FirstOrDefault();

     

            return View("Save",category);

        }

     

    }

    // GET: /Category/Create

    [HttpGet]

    public ActionResult Create()

    {

        var category = new Category();

        return View("Save", category);

    }

    //insert or update a category

    [HttpPost]

    public ActionResult Save(Category category)

    {

        if (!ModelState.IsValid)

        {

            return View("Save", category);

        }

        using (var session = new MongoSession<Category>())

        {

            session.Save(category);

            return RedirectToAction("Index");

        }

     

    }

    //Delete category

    [HttpPost]

    public ActionResult Delete(ObjectId Id)

    {

        using (var session = new MongoSession<Category>())

        {

            var category = session.Queryable

                  .Where(c => c.Id == Id)

                  .FirstOrDefault();

            session.Delete(category);

            var categories = session.Queryable.AsEnumerable<Category>();

            return PartialView("CategoryList", categories);

        }

     

    }       

    }

    You can easily work on MongoDB with NoRM and can use with ASP.NET MVC applications. I have created a repository on CodePlex at http://mongomvc.codeplex.com  and you can download source code of the ASP.NET MVC application from here

     

Copyright © 2002-2008 Chennai .Net User Group. All Rights Reserved. Microsoft and Microsoft logo's are trademarks of Microsoft Corporation