Tuesday, 4 April 2017

Setup Windows File Server Cluster using Failover Clustering in Azure

Azure does not directly support failover clustering. This is due to the fact that Azure does not support shared storage. Since this is the case one of the options is to use some 3rd party software called SIOS Datakeeper cluster edition to create an Azure only failover cluster. In this guide we will go through creating the failover cluster in Server 2008 R2. Although this guide is made for 2008 the principles can be applied to 2012. This guide is for creating a file server cluster in Azure Classic, however it can be used for RM with the only difference being the PowerShell commands to create the load balancer.
Before you start creating the cluster nodes you need to have a working domain in place. Once you have one, we can start creating the cluster nodes. I would recommend creating the 2 cluster nodes with 2 Network cards. One for the LAN traffic and one for the replication. Ideally these should be on separate subnets. In my build I have assumed they are on separate subnets. The following prerequisites are needed.
  • Separate Cloud Service for the cluster nodes
  • Storage Account for each of the 2 Cluster Nodes
  • Virtual Network with 2 subnets (Live and replication)
Once all the above is in place you can create the 2 Cluster nodes. Since they each need 2 Network cards, you have to create them using PowerShell. You cannot create a VM with 2 networks card in the GUI. You also cannot add a NIC to a VM once its built.
I have previously detailed how to build a 2 NIC VM. You can find this guide at the link below. Once you have the 2 nodes created come back to this guide.
Once the VMs are booted and available, the first thing I do is rename the NICs in Network connections to Live and Replication on each node. This enables you to clearly see what the role of each NIC does. Right click on each network card and click rename.

Rename1

If you have a keen eye you will have noticed that also only 1 NIC has internet access. This will always be NIC 1. You are unable to have 2 NIC’s going out to the internet in Azure. All renamed below. Nice and tidy.

Rename2

Now we need to turn off DNS registration on the Replication NIC. This ensures that when one tries to communicate with the server it only goes through the Live NIC. Right click on the Replication network connection, properties. Now double click on TCP/IP v4 and then into advanced. Under the DNS tab untick the DNS registration box.
Right click on the Replication NIC and click on properties.

dnsregis

Double Click on Internet Protocol Version 4 (TCP/IP v4)

dnsregis2

Click on the advanced button down the bottom right.

dnsregis3

Click on the DNS tab along the top and then untick Register this connection’s addresses in DNS.

dnsregis4

Once done save all the settings, click ok until your back at network connections.
We also need to check to ensure the Live network card is used first. This is done under advanced settings in Network connections. Ensure that the Live NIC is at the top and first priority. When back in Network Connections press the Alt key to show the title menu. Then select advanced and then advanced settings.

advanced

Move the Live network connection to the top. Do this by highlighting Live and clicking the up arrow on the right. Also untick Internet Protocol Version 6 on each adapter and protocol. Once done click ok.

advanced2

Now we need to install the roles that we require to build our cluster on each of the nodes. We also need to install .net 3.5 as this is needed by the SIOS cluster software. Open an elevated PowerShell window and run the command below to install the roles needed.
Import-Module ServerManager
Add-WindowsFeature as-net-framework
Add-WindowsFeature File-Services
Add-WindowsFeature -Name Failover-Clustering
You will need to reboot each of the nodes. Then install the 2 following Microsoft hotfixes.

You should now add each of the nodes to your existing active directory domain. Once joined to the domain check to ensure DNS resolution is working as intended. Then go into the firewall settings on each node and disable the windows firewall. You can if you wish allow certain ports through to allow the cluster to work. However, this is out of scope of this guide and for simplicity we will disable it.
We will now focus on configuring the cluster. This can all be done from 1 of the cluster nodes. Open failover cluster manager and right click Failover Cluster Manager. Click create a cluster.

createcluster

Azure assigns all addresses using Azure DHCP. Since we do not want this, we will have to change the cluster IP later. For now only add the one node. We will add the 2nd later on. Click next.

createcluster2

Dont worry about validating the cluster for now. Select no and then click next.

createcluster3

Give the cluster a name. We will not be referencing the cluster with this name so it doesn’t really matter. For my example I have called it “cluster”. Click next once you have entered a name.

createcluster4

Confirm all the details are correct and click Next.

createcluster5

It will now create the cluster. Once finished click Finish.

createcluster6

We now need to change the IP of the cluster. This is where the GUI is really misleading. Hightlight the cluster name and then click properties under the cluster name on the right. Its the one circled, not the one above.

createcluster7

Click on the IP address and then click edit.

Editcluster

Type in the IP address that you want to use. It must not be in use obviously. In my example I have used .100 as I know its not in use. Once happy click ok.

editcluster2

You will now notice the IP has changed to the one entered. Click ok.

editcluster3

It will take a few seconds. Once done you will be back at the failover manager window. We can now add the 2nd node. Right click on the cluster and then click add node.

addnode

Browse and Add the 2nd node. Cluster02 in my example. Then click next. Then click next on the confirmation screen.

addnode4

Once the cluster node has been added you might have a warning come up about Quorum and node settings. This is expected. We will configure this next.
Now we have the cluster in place we now need to create our cluster quorum. Create a file share on a server in Azure somewhere. Give everyone full read / write, also add the name of the cluster computer account and give it full permission. Also give it full NTFS permission. In the real world you can lock these permissions down further. In my example I am going to create a file share on my DC called DC01. The quorum should be located on a highly available machine, but this is a lab after all…
Create a folder on your server called Quorum. Right click on the folder and click properties. Go into the sharing tab and then click advanced sharing

Quorum1

Tick the share this folder box and then click the permissions button.

Quorum2

Change the permissions for everyone to full control and then click the add button. We now need to add the cluster name.

Quorum3

By default the permissions screen does not search for computer accounts. We need to change the search criteria. Click Object types in the top right.

Quorum4

Tick computers and then click ok

Quorum5

Type in the name of the new cluster we created and click check names. If you called your cluster name something obscure it will underline. If not it will ask to check which one is your cluster name.

Quorum6

In my example I doubled click on cluster.

Quorum7

Click ok back to the permissions screen. Change the permissions for the computer account to full control.

Quorum8

We have now created our quorum folder. Lets pop back over to failover cluster manager. Right click on the cluster and then click more actions, followed by Configure Cluster quorum settings.

createquorum

Select node and file share majority. Click next

createquorum2

Enter the path of the newly created quorum share. Click next.

createquorum3

Click next. Once created click finish.

createquorum4

Our cluster is now complete. You can now bring the resource online down the bottom right corner of the Failover cluster manager window.

clusteronline

Before we can create our clustered file server role, we need to present some storage to failover cluster manager. We now need to install the SIOS software. I have detailed how to install it and present the storage in the guide at the link below :
We now have some storage available in failover cluster manager. We can now go ahead and create our File Server Cluster Resource.
Right click on Services and application and then click on “Configure a service or application”

configservice

Select File Server. It will check to ensure you have the file server role installed so will take a few minutes. Once its happy click next.

configservice2

Choose the name of your file server cluster. I have called mine ClusterFS. You might want to give it a better name. Click next.

configservice3

Choose the storage we added earlier and click next.

configservice4

Confirm everything is ok and click Next.

configservice5

It will then configure it all. Click Finish.

configservice6

By default the cluster resource is brought online with an Azure DHCP address. We need to change this to a static address. Click on new cluster name as circled below and then on the right down the bottom click properties.

configservice7

When the properties box comes up click on the IP addresses assigned and then click edit.

clusternet3

Enter our chosen IP followed by ok.

configservice8

I would now reboot both cluster nodes so that they can come back up cleanly. You cluster resource should now come online. Noone will be able to access the resource as we need to use a load balancer in Azure to provide access for users.
We now need to run command in order to create the endpoints needed for the cluster. We need to find out some information first to build up the command. Open an elevated powershell window and run the following command on one of the cluster nodes.
Import-Module FailoverClusters
Get-ClusterNetwork
This will list our cluster networks. We will want to run the script on the one that is connected to Live / LAN. In my instance its still the default name so “Cluster Network 1”.

clusternet

We now run another powershell command
get-clusterresource
We want to select the one which has the IP resource of our new file server cluster. So in my example “IP Address 10.0.1.0”

clusternet2

We can now build the final command up we want to run. The $ILBIP is the IP of the cluster we just created.
$ClusterNetworkName = "Cluster Network 1"
$IPResourceName = "IP Address 10.0.1.0"
$ILBIP = "10.0.1.200"
cluster res $IPResourceName /priv enabledhcp=0 overrideaddressmatch=1 address=$ILBIP probeport=59999 subnetmask=255.255.255.255

clusternet4

We are now done on the cluster nodes, do one last reboot on them. We now need to create the Azure load balancer. Connect to Azure using PowerShell. If you need to know how to do this use the guide below :-
Run the script below but change the variables to your config.
# Cloud Service where the load balancer needs to sit.
$ServiceName = "clusterservices"
# newly chosen name for the new ILB
$ILBName = "FileServerILB"
# subnet name that the VMs use in the VNet
$SubnetName = "Live"
# static IP address for the ILB in the subnet
$ILBStaticIP = "10.0.1.200"
# Add Azure ILB using the above variables.
Add-AzureInternalLoadBalancer -InternalLoadBalancerName $ILBName -SubnetName $SubnetName -ServiceName $ServiceName -StaticVNetIPAddress $ILBStaticIP
It should come back with succeeded

createload

We now want to add the endpoints to each of the cluster VMs
# cluster nodes’ names, separated by commas. Your nodes’ names will be different.
$VMNodes = "cluster01", "cluster02"
# newly chosen name of the endpoint
$EndpointName = "SMB"
# public port to use for the endpoint for SMB file sharing. If the cluster is used for other purpose, i.e., HTTP, the port number needs change to 80.
$EndpointPort = "445"
# Add endpoint with port 445 and probe port 59999 to each node. It will take a few minutes to complete. Please pay attention to ProbeIntervalInSeconds parameter. This tells how often the probe port detects which node is active.
ForEach ($node in $VMNodes)
{
Get-AzureVM -ServiceName $ServiceName -Name $node | Add-AzureEndpoint -Name $EndpointName -LBSetName "$EndpointName-LB" -Protocol tcp -LocalPort $EndpointPort -PublicPort $EndpointPort -ProbePort 59999 -ProbeProtocol tcp -ProbeIntervalInSeconds 10 -InternalLoadBalancerName $ILBName -DirectServerReturn $true | Update-AzureVM
}
It will say its succeeded.


createload2

You can check it has run ok by running the following command
ForEach ($node in $VMNodes)
{
Get-AzureVM –ServiceName $ServiceName –Name $node | Get-AzureEndpoint | where-object {$_.name -eq "smb"}
}
We should now have a fully working file server cluster. Log back into the cluster node which is active. Then on the right, click on Add a shared folder.

addshare

Add one from the F drive and it should now work on the UNC path \\clusterfs\ShareName
One thing to note is that you will NOT be able to ever ping the cluster IP. So dont worry if you get no reply!! Also if you move the cluster over to the other node, you will lose connectivity to the share for up to 10 seconds. This is due to the load balancer polling every 10 seconds. Enjoy ðŸ™‚

Monday, 20 February 2017

How to Implement the Repository Pattern in ASP.NET MVC Application

The Repository Pattern is one of the most popular patterns to create an enterprise level application. It restricts us to work directly with the data in the application and creates new layers for database operations, business logic and the application’s UI. If an application does not follow the Repository Pattern, it may have the following problems:
  • Duplicate database operations codes
  • Need of UI to unit test database operations and business logic
  • Need of External dependencies to unit test business logic
  • Difficult to implement database caching, etc.
Using the Repository Pattern has many advantages:
  • Your business logic can be unit tested without data access logic;
  • The database access code can be reused;
  • Your database access code is centrally managed so easy to implement any database access policies, like caching;
  • It’s easy to implement domain logics;
  • Your domain entities or business entities are strongly typed with annotations; and more.
On the internet, there are millions of articles written around Repository Pattern, but in this one we’re going to focus on how to implement it in an ASP.NET MVC Application. So let’s get started!
Project Structure
Let us start with creating the Project structure for the application. We are going to create four projects:
  1. Core Project
  2. Infrastructure Project
  3. Test Project
  4. MVC Project
Each project has its own purpose. You can probably guess by the projects’ names what they’ll contain: Core and Infrastructure projects are Class Libraries, Web project is a MVC project, and Test project is a Unit Test project. Eventually, the projects in the solution explorer will look as shown in the image below:
As we progress in this post, we will learn in detail about the purpose of each project, however, to start we can summarize the main objective of each project as the following:
So far our understanding for different projects is clear. Now let us go ahead and implement each project one by one. During the implementations, we will explore the responsibilities of each project in detail.

Core Project
In the core project, we keep the entities and the repository interfaces or the database operation interfaces. The core project contains information about the domain entities and the database operations required on the domain entities. In an ideal scenario, the core project should not have any dependencies on external libraries. It must not have any business logic, database operation codes etc.
In short, the core project should contain:
  • Domain entities
  • Repository interfaces or database operations interfaces on domain entities
  • Domain specific data annotations
The core project can NOT contain:
  • Any external libraries for database operations
  • Business logic
  • Database operations code
While creating the domain entities, we also need to make a decision on the restrictions on the domain entities properties, for example:
  • Whether a particular property is required or not. For instance, for a Product entity, the name of the product should be required property.
  • Whether a value of a particular property is in given range or not. For instance, for a Product entity, the price property should be in given range.
  • Whether the maximum length of a particular property should not be given value. For instance, for a Product entity, the name property value should be less than the maximum length.
There could be many such data annotations on the domain entities properties. There are two ways we can think about these data annotations:
  1. As part of the domain entities
  2. As part of the database operations logic
It is purely up to us how we see data annotations. If we consider them part of database operation then we can apply restrictions using database operation libraries API. We are going to use the Entity Framework for database operations in the Infrastructure project, so we can use Entity Framework Fluent API to annotate data.
If we consider them part of domain, then we can use System.ComponentModel.DataAnnotations library to annotate the data. To use this, right click on the Core project’s Reference folder and click on Add Reference. From the Framework tab, select System.ComponentModel.DataAnnotations and add to the project.
We are creating a ProductApp, so let us start with creating the Product entity. To add an entity class, right click on the Core project and add a class, then name the class Product.
using System.ComponentModel.DataAnnotations;
namespace ProductApp.Core
{
    public class Product
    {
        public int Id { get; set; }
 [Required]
 [MaxLength(100)]
        public string Name { get; set; }
 [Required]
        public double Price { get; set; }
        public bool inStock { get; set; }
    }
}
We have annotated the Product entity properties with Required and MaxLength. Both of these annotations are part of System.ComponentModel.DataAnnotations. Here, we have considered restriction as part of the domain, hence used data annotations in the core project itself.
We have created Product Entity class and also applied data annotation to that. Now let us go ahead and create Repository interface. But before we create that, let us understand, what is a Repository Interface?
The repository interface defines all the database operations possible on the domain entities. All database operations that can be performed on the domain entities are part of the domain information, hence we will put the repository interface in the core project. How these operations can be performed will be the part of Infrastructure project.
To create a Repository Interface, right click on the Core project and add a folder named Interfaces. Once the Interfaces folder is created, right click on the Interface folder and select add a new item, then from the Code tab select Interface. Name the Interface IProductRepository
using System.Collections.Generic;

namespace ProductApp.Core.Interfaces
{
    public interface IProductRepository
    {
        void Add(Product p);
        void Edit(Product p);
        void Remove(int Id);
        IEnumerable GetProducts(); Product FindById(int Id); } } 
Now we have created a Product entity class and a Product Repository Interface. At this point, the core project should look like this:
Let us go ahead and build the core project to verify everything is in place and move ahead to create Infrastructure project.

Infrastructure Project
Main purpose of Infrastructure project is to perform database operations. Besides database operations, it can also consume web services, perform IO operations etc. So mainly, Infrastructure project may perform the following operations:
  • Database operations
  • Working with WCF and Web Services
  • IO operations
We can use any database technology to perform database operations. In this post we are going to use Entity Framework. So we are going to create database using the Code First approach. In the Code First approach, database gets created on basis of the classes. Here database will be created on the basis of the Domain entities from the Core Project.
To create the database from the Core project domain entity, we need to perform these tasks:
  1. Create DataContext class
  2. Configure the connection string
  3. Create DataBase Initalizer class to seed data in the database
  4. Implement IProductRepsitory interface

Adding References
First let’s add references of the Entity Framework and ProductApp.Core project. To add the Entity Framework, right click on the Infrastructure project and click on Manage Nuget Package. In the Package Manager Window, search for Entity Framework and install the latest stable version.
To add a reference of the ProductApp.Core project, right click on the Infrastructure project and click on Add Reference. In the Reference Window, click on the Project tab and select ProductApp.Core.
DataContext class
The objective of the DataContext class is to create the DataBase in the Entity Framework Code First approach. We pass a connection string in the constructor of DataContext class. By reading the connection string, the Entity Framework create the database. If a connection string is not specified then the Entity Framework creates the database in a local database server.
In the DataContext class:
  • Create a DbSet type property. This is responsible for creating the table for the Product entity
  • In the constructor of the DataContext class, pass the connection string to specify information to create database, for example server name, database name, login information etc. We need to pass name of the connection string. name where database would be created
  • If connection string is not passed, Entity Framework creates with the name of data context class in the local database server.
  • ProductDataContext class inherits the DbContext class
 The ProductDataContext class can be created as shown in the listing below:
using ProductApp.Core;
using System.Data.Entity;

namespace ProductApp.Infrastructure
{
    public class ProductContext  : DbContext
    {
        public ProductContext()
           : base("name=ProductAppConnectionString")
       {
       }
        public DbSet Products { get; set; } } } 
Next we need to work on the Connection String. As discussed earlier, we can either pass the connection string to specify database creation information or reply on the Entity Framework to create default database at default location for us. We are going to specify the connection string that is why, we passed a connection string name ProductAppConnectionString in the constructor of ProductDataContext class. In the App.Config file the ProductAppConnectionString connection string can be created as shown in the listing below:
  
  <add name="ProductAppConnectionString" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ProductAppJan;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>

Database Initializer class
We create a database initializer class to seed the database with some initial value at time of the creation. To create the Database initializer class, create a class which inherits from DropCreateDatabaseIfModelChnages. There are other options of classes available to inherit in order to create a database initializer class. If we inherit DropCreateDatabaseIfModelChnages class then each time a new database will be created on the model changes. So for example, if we add or remove properties from the Product entity class, Entity Framework will drop the existing database and create a new one. Of course this is not a great option, since data will be lost too, so I recommend you explore other options to inherit the database initializer class.
The database initializer class can be created as shown in the listing below. Here we are seeding the product table with two rows. To seed the data:
  1. Override Seed method
  2. Add product to Context.Products
  3. Call Context.SaveChanges()
using ProductApp.Core;
using System.Data.Entity;

namespace ProductApp.Infrastructure
{
    public class ProductInitalizeDB : DropCreateDatabaseIfModelChanges { protected override void Seed(ProductContext context) { context.Products.Add(new Product { Id = 1, Name = "Rice", inStock = true, Price = 30 }); context.Products.Add(new Product { Id = 2, Name = "Sugar", inStock = false, Price = 40 }); context.SaveChanges(); base.Seed(context); } } } 
So far, we have done all the Entity Framework Code First related work to create the database. Now let’s go ahead and implement IProductRepository interface from the Core project in a concrete ProductRepository class.

Repository Class
This is the class which will perform database operations on the Product Entity. In this class, we will implement the IProductRepository interface from the Core project. Let us start with adding a class ProductRepository to the Infrastructure project and implement IProductRepository interface. To perform database operations, we are going to write simple LINQ to Entity queries. ProductRepositry class can be created as shown in the listing below:
using ProductApp.Core.Interfaces;
using System.Collections.Generic;
using System.Linq;
using ProductApp.Core;

namespace ProductApp.Infrastructure
{
    public class ProductRepository : IProductRepository
    {
        ProductContext context = new ProductContext();
        public void Add(Product p)
        {
            context.Products.Add(p);
            context.SaveChanges();
        }

        public void Edit(Product p)
        {
            context.Entry(p).State = System.Data.Entity.EntityState.Modified;
        }

        public Product FindById(int Id)
        {
            var result = (from r in context.Products where r.Id == Id select r).FirstOrDefault();
            return result;
        }

        public IEnumerable GetProducts() { return context.Products; } public void Remove(int Id) { Product p = context.Products.Find(Id); context.Products.Remove(p); context.SaveChanges(); } } } 
So far we have created a Data Context class, a Database Initializer class, and the Repository class. Let us build the infrastructure project to make sure that everything is in place. The ProductApp.Infrastructure project will look as given in the below image:
 
Now we’re done creating the Infrastructure project. We have written all the database operations-related classes inside the Infrastructure project, and all the database-related logic is in a central place. Whenever any changes in database logic is required, we need to change only the infrastructure project.

Test Project
The biggest advantage of Repository Pattern is the testability. This allows us to unit test the various components without having dependencies on other components of the project. For example, we have created the Repository class which performs the database operations to verify correctness of the functionality, so we should unit test it. We should also be able to write tests for the Repository class without any dependency on the web project or UI. Since we are following the Repository Pattern, we can write Unit Tests for the Infrastructure project without any dependency on the MVC project (UI).
To write Unit Tests for ProductRepository class, let us add following references in the Test project.
  1. Reference of ProductApp.Core project
  2. Reference of ProductApp.Infrastructure project
  3. Entity Framework package

To add the Entity Framework, right click on the Test project and click on Manage Nuget Package. In the Package Manger Windows, search for Entity Framework and install the latest stable version.
To add a reference of the ProductApp.Core project, right click on the Test project and click on Add Reference. In the Reference Window, click on Project tab and select ProductApp.Core.
To add a reference of the ProductApp.Infrastructure project, right click on the Test project and click on Add Reference. In the Reference Window, click on Project tab and select ProductApp.Infrastructure.
Copy the Connection String
Visual Studio always reads the config file of the running project. To test the Infrastructure project, we will run the Test project. Hence the connection string should be part of the App.Config of the Test project. Let us copy and paste the connection string from Infrastructure project in the Test project.
We have added all the required references and copied the connection string. Let’s go ahead now and set up the Test Class. We’ll create a Test Class with the name ProductRepositoryTest. Test Initialize is the function executed before the tests are executed. We need to create instance of the ProductRepository class and call the ProductDbInitalize class to seed the data before we run tests. Test Initializer can be written as shown in the listing below:
[TestClass]
    public class ProductRepositoryTest
    {
        ProductRepository Repo; 
 [TestInitialize]
        public void TestSetup()
        {
            ProductInitalizeDB db = new ProductInitalizeDB();
            System.Data.Entity.Database.SetInitializer(db);
            Repo = new ProductRepository();
        }
    }
Now we’ve written the Test Initializer. Now let write the very first test to verify whether ProductInitalizeDB class seeds two rows in the Product table or not. Since it is the first test we will execute, it will also verify whether the database gets created or not. So essentially we are writing a test:
  1. To verify database creation
  2. To verify number of rows inserted by the seed method of Product Database Initializer
[TestMethod]
        public void IsRepositoryInitalizeWithValidNumberOfData()
        {
            var result = Repo.GetProducts();
            Assert.IsNotNull(result);
            var numberOfRecords = result.ToList().Count;
            Assert.AreEqual(2, numberOfRecords);
        }
As you can see, we’re calling the Repository GetProducts() function to fetch all the Products inserted while creating the database. This test is actually verifying whether GetProducts() works as expected or not, and also verifying database creation. In the Test Explorer window, we can run the test for verification.
To run the test, first build the Test project, then from the top menu select Test->Windows-Test Explorer. In the Test Explorer, we will find all the tests listed. Select the test and click on Run.
Let’s go ahead and write one more test to verify Add Product operation on the Repository:
 [TestMethod]
        public void IsRepositoryAddsProduct()
        {
            Product productToInsert = new Product
            {
                Id = 3,
                inStock = true,
                Name = "Salt",
                Price = 17

            };
            Repo.Add(productToInsert);
            // If Product inserts successfully, 
            //number of records will increase to 3 
            var result = Repo.GetProducts();
            var numberOfRecords = result.ToList().Count;
            Assert.AreEqual(3, numberOfRecords);
        }
To verify insertion of the Product, we are calling the Add function on the Repository. If Product gets added successfully, the number of records will increase to 3 from 2 and we are verifying that. On running the test, we will find that the test has been passed.
In this way, we can write tests for all the Database operations from the Product Repository class. Now we are sure that we have implemented the Repository class correctly because tests are passing, which means the Infrastructure and Core project can be used with any UI (in this case MVC) project.

MVC or Web Project
Finally we have gotten to the MVC project! Like the Test project, we need to add following references
  1. Reference of ProductApp.Core project
  2. Reference of ProductApp.Infrastructure project
To add a reference of the ProductApp.Core project, right click on the MVC project and click on Add Reference. In the Reference Window, click on Project tab and select ProductApp.Core.
To add a reference of the ProductApp.Infrastructure project, right click on the MVC project and click on Add Reference. In the Reference Window, click on Project tab and select ProductApp.Infrastructure.

Copy the Connection String
Visual Studio always reads the config file of the running project. To test the Infrastructure project, we will run the Test project, so the connection string should be part of the App.Config of the Test project. To make it easier, let’s copy and paste the connection string from Infrastructure project in the Test project.

Scaffolding the Application
We should have everything in place to scaffold the MVC controller. To scaffold, right click on the Controller folder and select MVC 5 Controller with Views, using Entity Framework as shown in the image below:
Next we will see the Add Controller window. Here we need to provide the Model Class and Data context class information. In our project, model class is the Product class from the Core project and the Data context class is the ProductDataContext class from the Infrastructure project. Let us select both the classes from the dropdown as shown in the image below:
Also we should make sure that the Generate Views, Reference script libraries, and Use a layout page options are selected.
On clicking Add, Visual Studio will create the ProductsController and Views inside Views/Products folder. The MVC project should have structure as shown in the image below:
At this point if we go ahead and run the application, we will be able to perform CRUD operations on the Product entity.
Problem with Scaffolding
But we are not done yet! Let’s open the ProductsController class and examine the code. On the very first line, we will find the problem. Since we have used MVC scaffolding, MVC is creating an object of the ProductContext class to perform the database operations.
Any dependencies on the context class binds the UI project and the Database tightly to each other. As we know the Datacontext class is an Entity Framework component. We do not want the MVC project to know which database technology is being used in the Infrastructure project. On the other hand, we haven’t tested the Datacontext class; we’ve tested the ProductRepository class. Ideally we should use ProductRepository class instead of the ProductContext class to perform database operations in the MVC Controller.  To summarize,
  1. MVC Scaffolding uses Data context class to perform database operations. The data context class is an Entity Framework component, so its uses tightly couples UI (MVC) with the Database (EF) technology.
  2. The data context class is not unit tested so it’s not a good idea to use that.
  3. We have a tested ProductRepository class. We should use this inside Controller to perform database operations. Also, the ProductRepository class does not expose database technology to the UI.
To use the ProductRepository class for database operations, we need to refactor the ProductsController class. To do so, there are two steps we need to follow:
  1. Create an object of ProductRepository class instead of ProductContext class.
  2. Call methods of ProductRepository class to perform database operations on Product entity instead of methods of ProductContext class.
In the listing below, I have commented codes using ProductContext and called ProductRepository methods. After refactoring, the ProductController class will look like the following:
using System;
using System.Net;
using System.Web.Mvc;
using ProductApp.Core;
using ProductApp.Infrastructure;

namespace ProductApp.Web.Controllers
{
    public class ProductsController : Controller
    {
        //private ProductContext db = new ProductContext();
        private ProductRepository db = new ProductRepository();

     
        public ActionResult Index()
        {
            //return View(db.Products.ToList());
            return View(db.GetProducts());
        }

    
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            // Product product = db.Products.Find(id);
            Product product = db.FindById(Convert.ToInt32(id));
            if (product == null)
            {
                return HttpNotFound();
            }
            return View(product);
        }

     
        public ActionResult Create()
        {
            return View();
        }

 [HttpPost]
 [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Name,Price,inStock")] Product product)
        {
            if (ModelState.IsValid)
            {
                // db.Products.Add(product);
                //db.SaveChanges();
                db.Add(product);
                return RedirectToAction("Index");
            }

            return View(product);
        }

       
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Product product = db.FindById(Convert.ToInt32(id));
            if (product == null)
            {
                return HttpNotFound();
            }
            return View(product);
        }

 [HttpPost]
 [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Name,Price,inStock")] Product product)
        {
            if (ModelState.IsValid)
            {
                //db.Entry(product).State = EntityState.Modified;
                //db.SaveChanges();
                db.Edit(product);
                return RedirectToAction("Index");
            }
            return View(product);
        }

   
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Product product = db.FindById(Convert.ToInt32(id));
            if (product == null)
            {
                return HttpNotFound();
            }
            return View(product);
        }

 
 [HttpPost, ActionName("Delete")]
 [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            //Product product = db.FindById(Convert.ToInt32(id));
            // db.Products.Remove(product);
            // db.SaveChanges();
            db.Remove(id);
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                //db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
After refactoring, let’s go ahead and build and run the application – we should be able to do so and perform the CRUD operations.
Injecting the Dependency
Now we’re happy that the application is up and running, and it was created using the Repository pattern. But still there is a problem: we are directly creating an object of the ProductRepository class inside the ProductsController class, and we don’t want this. We want to invert the dependency and delegate the task of injecting the dependency to a third party, popularly known as a DI container. Essentially, ProductsController will ask the DI container to return the instance of IProductRepository.
There are many DI containers available for MVC applications. In this example we’ll use the simplest Unity DI container. To do so, right click on the MVC project and click Manage Nuget Package. In the Nuget Package Manager search for Unity.Mvc and install the package.
Once the Unity.Mvc package is installed, let us go ahead and open App_Start folder. Inside the App_Start folder, we will find the UnityConfig.cs file. In the UnityConfig class, we havr to register the type. To do so, open RegisterTypes function in UnityConfig class and register the type as shown in the listing below:
public static void RegisterTypes(IUnityContainer container)
        {
            

            // TODO: Register your types here
            container.RegisterType(); } 
We have registered the type to Unity DI container. Now let us go ahead and do a little bit of refactoring in the ProductsController class.  In the constructor of ProductsController we will pass the reference of the repository interface. Whenever required by the application, the Unity DI container will inject the concrete object of ProductRepository in the application by resolving the type. We need to refactor the ProductsController as shown in the listing below:
  public class ProductsController : Controller
    {
        IProductRepository db;
        public ProductsController(IProductRepository db)
        {

            this.db = db;
        }
Let us go ahead and build and run the application. We should have the application up and running, and we should able to perform CRUD operations using Repository Pattern and Dependency Injection!
Conclusion
In this article, we learned in a step by step manner how to create an MVC application following the Repository pattern. In doing so, we can put all the database logic in one place and whenever required, we only need to change the repository and test that. The Repository Pattern also loosely couples the application UI with the Database logic and the Domain entities and makes your application more testable.