CRUD Operations with ASP.Net Web API using FluentNHibernate, Repository pattern

Introduction

In this step-by-step article we will discuss all about CRUD (Create Read Update Delete) operations with Web API using Repository pattern.

Pre-requisites

To implement and play with the source code one should have:
– basic knowledge of asp.net MVC
– basic knowledge of REST services
– require Visual Studio 2012 or later with asp.net WebAPI support

Lets start creating asp.net Web API Project

  • Start your Visual studio and choose File -> New Project (ctrl + Shift + N)
  • From available dialog choose Web Templates -> Asp.Net MVC 4 Web Application
  • I named it as ‘CRUDWithWebAPI’ – you can choose your favorite one 🙂
Add asp.net web api application

Add asp.net web api application

  • Select Empty Web API using Razor View Engine
Add asp.net web api application

Add asp.net web api application

Folder Structure

By default we get these folders:

  • App_Data
  • App_Start: contain config classes required to initiate the app (eg. route collection etc.)
  • Controllers: controller of web api
  • Models: Contain model/classes
  • Scripts: all scripts and css
  • views
Default folder structure of asp.net Web API application

Default folder structure of asp.net Web API application

More explanation of each and every folder, mentioned above is beyond the scope of this article.

Installing FluentNHibernate

To Install FluentNHIbernate support to your project:
– Open ‘Package Manager Console’ using View-> Other Windows
– Now type ‘Install-Package FluentNHibenrate’ and hit enter

wait till FluentNHibernate get installed.

Models, Mappings and Repository Pattern

In this step, we will create Model its mapping and will add a repository.

adding models and their mappings

  • To add model, right click on Models folder from Solution explore and choose class name it ‘ServerData’
      public class ServerData
    	{
    		public virtual int Id { get; set; }
    		public virtual DateTime InitialDate { get; set; }
    		public virtual DateTime EndDate { get; set; }
    		public virtual int OrderNumber { get; set; }
    		public virtual bool IsDirty { get; set; }
    		public virtual string IP { get; set; }
    		public virtual int Type { get; set; }
    		public virtual int RecordIdentifier { get; set; }
    	}
     

Adding a model

Adding a model

  • add its mapping class, right click on Models folder from Solution explore and choose class name it ‘ServerDataMap’
      public class ServerDataMap : ClassMap<ServerData>
        {
            public ServerDataMap()
            {
                Table("ServerData");
    
                Id(x => x.Id, "Id").GeneratedBy.Identity().UnsavedValue(0);
    
                Map(x => x.InitialDate);
                Map(x => x.EndDate);
                Map(x => x.OrderNumber);
                Map(x => x.IsDirty);
                Map(x => x.IP).Length(11);
                Map(x => x.Type).Length(1);
                Map(x => x.RecordIdentifier);
    
            }
        }
     
  • do not forget to add following namespace:

     using FluentNHibernate.Mapping;
     

adding NHIbenrate support to your application

  • add new folder and name it as ‘Helper’
  • add a new class beneath ‘Helper’ folder and name it as ‘NHibernateHelper’

    In this class we need to configure NHibernate and build all sessionfactory so, our application will interact with database:

     private static void CreateSessionFactory()
    	{
    		_sessionFactory = Fluently.Configure()
    			.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString).ShowSql)
    			.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ServerData>())
    			.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, false))
    			.BuildSessionFactory();
    	}
     

    We are not going to discuss all these stuff in details as these are beyond the scope of this article.

  • create a new folder beneath ‘Models’ and name it as ‘Persistance’

  • add one Interface ‘IServerDataRepository’ under ‘Persistance’

     public interface IServerDataRepository
        {
            ServerData Get(int id);
            IEnumerable<ServerData> GetAll();
            ServerData Add(ServerData serverData);
            void Delete(int id);
            bool Update(ServerData serverData);
    
        }
     

  • add one class ‘ServerDataRepository’ under ‘Persistance’ and implement ‘IServerDataRepository’

     public class ServerDataRepository : IServerDataRepository
        {
    	 //method implementation goes here	
        }
     

    Now, we have ready with our Repository to start play 🙂

    refer: http://msdn.microsoft.com/en-us/library/ff649690.aspx for more details on Repository Pattern.

Add Web APi Controller

In this step we will create all the necessary action methods:
– Right click on folder ‘Controllers’ and add a new controller name it as ‘ServerDataController’ (remember to select an empty controller)
– It would look like:

  public class ServerDataController : ApiController
    {
    }
 

Add following line of code (it will initiate our repository).

 static readonly IServerDataRepository serverDataRepository = new ServerDataRepository();
 
Adding web API empty controller

Adding web API empty controller

Please note that in this article/demo we are not going to implement any DI pattern or Inversion of Control (IOC) framework.

We are now ready to start the game 🙂

 public IEnumerable<ServerData> GetServerData()
	{
		return serverDataRepository.GetAll();
	}
 

See above defined method, why we add ‘Get’ suffix, this is a good practice to add ‘Get’ with your method name, by convention it maps GET request.
This method do not have any parameter, so, you can say this maps uri which does not contain ‘id’ parameter.

  • add following method to get ServerData by id. This is an optional parameter as defined in our route and asp.net Web API framework automatically convert its type to int.
  • it will throw ‘HttpResponseException ‘ expception if id is not valid (in following method we converted the exception to 404 NOT Found exception)
     public ServerData GetServerDataById(int id)
    	{
    		var serverData = serverDataRepository.Get(id);
    
    		if (serverData == null)
    			throw new HttpResponseException(HttpStatusCode.NotFound);
    
    		return serverData;
    	}
     
  • following method is to get ServerData by its type:

      public IEnumerable<ServerData> GetServerDataByType(int type)
    	{
    		return serverDataRepository.GetAll().Where(d => d.Type == type);
    	}
     
  • to invoke above method we need to define new routes in ‘WebApiConfig.cs’ as follows:

     config.Routes.MapHttpRoute(
                    name: "ProductByType",
                    routeTemplate: "api/{controller}/type/{type}"
                );
     
  • similarly for :

     public IEnumerable<ServerData> GetServerDataByIP(string ip)
            {
                return serverDataRepository.GetAll().Where(d => d.IP.ToLower() == ip.ToLower());
            }
     
     config.Routes.MapHttpRoute(
                    name: "ProductByIP",
                    routeTemplate: "api/{controller}/ip/{ip}"
                );
     
  • Here we are going to delete serverdata using this method:

     public void DeletServerData(int id)
    	{
    		var serverData = serverDataRepository.Get(id);
    
    		if (serverData == null)
    			throw new HttpResponseException(HttpStatusCode.NotFound);
    		serverDataRepository.Delete(id);
    	}
     
  • Lets add a new method to our controller to add new record of ServerData

    	public ServerData PostServerData(ServerData serverData)
    	{
    		return serverDataRepository.Add(serverData);
    	}
     

will above method work? ofcourse, it works but its not an ideal or say its not quite complete, why?
– In above suffix is ‘Post’ which sounds it sends Http POST request
– also its noticeable parameter is of type ‘ServerData’.
– complex type parameters are deserialized from the requested body when we used Web API, also, we can say we expect serialized input from client
like either in xml or JSON.

In above method, we miss followings from HTTP response:
– Response code: by default it is 200 (Ok) but as per HTTP1.1 protocol, the server should reply 201 (created), while POST request resuts in the creation of a resource
– Location: server should include the URI of the new resource in the location header of the response, whenever it creates a resource.
– so, we can implement this as defined in following methods:

  public HttpResponseMessage PostServerData(ServerData serverData)
	{
		serverData = serverDataRepository.Add(serverData);

		var response = Request.CreateResponse<ServerData>(HttpStatusCode.Created, serverData);

		var uri = Url.Link("DefaultApi", new { id = serverData.Id });
		response.Headers.Location = new Uri(uri);

		return response;

	}
 
  • finally, we need to add an update method, its a streight forward:
     public void PutServerData(int id, ServerData serverData)
    	{
    		serverData.Id = id;
    
    		if (!serverDataRepository.Update(serverData))
    			throw new HttpResponseException(HttpStatusCode.NotFound);
    	}
     

from above, we can understand that web api matches this method to PUT request, above method is having two parameter id and serverdata. So, id is taken from URI path
and serverdata is deserialized from the request body.

Please note that bu default Web API framework takes simple parameter types from the route and complex types from the request body.

Set default result output type

We need result in JSON by default, lets add following line either in Global.asx.cs file or in the file where you are registering routes

	//return JSON response by default
	config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Testing Web API results

Here I used ‘Poster for Firefox’ plugin to test the out put. You can directly download this plugin from Plugin directory of Firefox:

Requesting a GET operation using Poster for Firefox

Requesting a GET operation using Poster for Firefox

Just enter the URI and press GET or whatever you want to play, you will get output accordingly:)

Response of a GET from Poster for Firefox

Response of a GET from Poster for Firefox

What to do next?

There is a very good video Tutorial from Questpond on ‘REST (Representational State Transfer)’ to understand about REST services:

Closing notes

I hope you enjoyed this article. I tried to make this as simple as I can. If you like this article, please rate it and share it to share the knowledge.

1 comment on “CRUD Operations with ASP.Net Web API using FluentNHibernate, Repository pattern”

  1. Pingback: Consuming ASP.NET WEB API using ASP.NET MVC4 and RestSharp – StdGod

Leave A Reply