Big Data/Analytics Zone is brought to you in partnership with:

Sarfraz has posted 5 posts at DZone. You can read more from them at their website. View Full User Profile

Using MVC4 WebAPI for CRUD Operations on MongoDB

04.11.2013
| 5741 views |
  • submit to reddit

In this post I will  explain how can we write MVC 4 WebAPI to perform complete CRUD operations on any data source (In this sample I have used MongoDB).

Backgroud:

It is suggested that you review this post that will enable you to quickly understand MongoDB  connectivity Via .net

Web API is Microsoft’s promise of completely embracing HTTP protocol. For its reason of being the most simple/basic mechanism of exposing & consuming services, it primarily targets browsers, mobile devices & reaching wide audience.

Ingredients:

MongoDB, Visual Studio 2010, MVC4, Fiddler2

Recipe:

Creating WebAPI Project

Open Visual Studio 2010 > Add New Project > Web > MVC 4 Web Application

It will show a dialog box enlisting MVC4 Templates. > Select Web API & Click OK.

01

Creating Entity:

Today I am interested to work with a Vehicle entity. Therefore add a class with name “Vehicle” in Models Folder & add some attributes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MongoDB.Bson.Serialization.Attributes;

namespace VehicleWebAPI.Models
{
public class Vehicle
{
[BsonId]
public string Id { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Int32 Year { get; set; }
public float Price { get; set; }
}
}

Notice how we have decorated id attribute with BSONId, indicating that this attribute would contain MongoDB document id property.

Creating Entity Repository :

Next we want to use Repository Pattern, therefore add an interface in Models folder “IVehicleRepository” with following code

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using MongoDB;

using MongoDB.Driver;

using MongoDB.Driver.Builders;

namespace VehicleWebAPI.Models

{

public interface IVehicleRepository

{

IEnumerable<Vehicle> GetAllVehicles();

IEnumerable<Vehicle> GetAllVehiclesByMake(string vehicleMake);

IEnumerable<Vehicle> GetAllVehiclesByMake(string vehicleMake,int year);

bool Update(string objectId,Vehicle p);

Vehicle Add(Vehicle p);

bool Delete(string objectId);

}

}

Implementing Repository

Now we will incorporate Implementation detail of our Repository in Models. Add a class naming “VehicleRepository” .

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Configuration;

using MongoDB;

using MongoDB.Driver;

using MongoDB.Driver.Builders;

using MongoDB.Bson;

namespace VehicleWebAPI.Models

{

public class VehicleRepository : IVehicleRepository

{

MongoServer mongoServer = null;

MongoDatabase mDB = null;

MongoCollection mCollection = null;

#region TestData

Vehicle[] _TestData = new Vehicle[]

{

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Toyota”, Model =”Hilux”, Year = 2001 , Price =2400000 },

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Honda”, Model =”Accord”, Year = 2001, Price =3200000},

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Toyota”, Model =”Hilux”, Year = 2002 , Price =2700000 },

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Honda”, Model =”Accord”, Year = 2002, Price =3500000},

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Toyota”, Model =”Hilux”, Year = 2003 , Price =2900000 },

new Vehicle { Id = Guid.NewGuid().ToString(),  Make = “Honda”, Model =”Accord”, Year = 2003, Price =3800000},

};

#endregion

private List<Vehicle> vehicles = new List<Vehicle>();

public VehicleRepository()

{

#region INIT_MongoCredentials

try

{

mongoServer = MongoServer.Create();

mongoServer.Connect();

mDB = mongoServer.GetDatabase(“dbVehicleStore”); /// Move this info to Configuration

mCollection = mDB.GetCollection<Vehicle>(“VehicleRecords”);

}

catch (Exception ex)

{

throw;

}

#endregion

}

public IEnumerable<Vehicle> GetAllVehicles()

{

#region GetFromDB

if (Convert.ToInt32(mCollection.Count()) > 0)

{

vehicles.Clear();

var VehicleCollection = mCollection.FindAs(typeof(Vehicle), Query.NE(“Make”, “null”));

if (VehicleCollection.Count() > 0)

{

foreach (Vehicle objVehicle in VehicleCollection)

{

vehicles.Add(objVehicle);

}

}

}

else

{

#region Add some test data since our DB is empty

mCollection.RemoveAll();

foreach (Vehicle iVehicle in _TestData)

{

vehicles.Add(iVehicle);

//save data to collection

Add(iVehicle);

}

#endregion

}

#endregion

var results = vehicles.AsQueryable();

return results;

}

public IEnumerable<Vehicle> GetAllVehiclesByMake(string vehicleMake)

{

if (string.IsNullOrEmpty(vehicleMake))

{

vehicleMake = (string.IsNullOrEmpty(vehicleMake)) ? ConfigurationManager.AppSettings["VehicleDefaultMake"] : vehicleMake;

}

vehicles.Clear();

var VehicleCollection = mCollection.FindAs(typeof(Vehicle), Query.EQ(“Make”, vehicleMake));

if (VehicleCollection.Count() > 0)

{

foreach (Vehicle objVehicle in VehicleCollection)

{

vehicles.Add(objVehicle);

}

}

return vehicles.AsQueryable();

}

public IEnumerable<Vehicle> GetAllVehiclesByMake(string make,int year)

{

if (string.IsNullOrEmpty(make))

{

make = (string.IsNullOrEmpty(make)) ? ConfigurationManager.AppSettings["VehicleDefaultMake"] : make;

}

vehicles.Clear();

var iQuery = Query.And(Query.EQ(“Make”, make),Query.EQ(“Year”, year));

var VehicleCollection = mCollection.FindAs(typeof(Vehicle), iQuery );

if (Convert.ToInt32(VehicleCollection.Count()) > 0)

{

foreach (Vehicle objVehicle in VehicleCollection)

{

vehicles.Add(objVehicle);

}

}

return vehicles.AsQueryable();

}

public bool Update(string objectId , Vehicle vehicle )

{

UpdateBuilder updateBuilder = MongoDB.Driver.Builders.Update.Set(“Make”, vehicle.Make)

.Set(“Model”, vehicle.Model)

.Set(“Year”, vehicle.Year)

.Set(“Price”, vehicle.Price);

mCollection.Update(Query.EQ(“_id”, objectId), updateBuilder);

return true;

}

public Vehicle Add(Vehicle vehicle)

{

if (string.IsNullOrEmpty(vehicle.Id))

{

vehicle.Id = Guid.NewGuid().ToString();

}

mCollection.Save(vehicle);

return vehicle;

}

public bool Delete(string objectId)

{

mCollection.Remove(Query.EQ(“_id”, objectId));

return true;

}

}

}

Notice how testData is used to fill some default data.

Good times are coming. We have our repository ready.

Creating Controller:

We need to add a controller file to handle HTTP requests.

Go to Controller folder > Delete ValuesContainer Class > Add a new controller > Use “Empty API Container” Template.

Notice that this container class is derived from APIController.

Now we need following definition.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Web.Http;

using VehicleWebAPI.Models;

namespace VehicleWebAPI.Controllers

{

public class VehicleController : ApiController

{

private static readonly IVehicleRepository _VehicleRepository = new VehicleRepository();

public VehicleController()

{}

// GET api/Vehicles

public IEnumerable<Vehicle> GetAllVehicles()

{

return _VehicleRepository.GetAllVehicles();

}

public IEnumerable<Vehicle> GetAllVehiclesByMake(string make)

{

return _VehicleRepository.GetAllVehiclesByMake(make);

}

public IEnumerable<Vehicle> GetAllDinasaursByFamilyAndYear(string make,int  year)

{

return _VehicleRepository.GetAllVehiclesByMake(make,year);

}

public Vehicle Post(Vehicle p)

{

_VehicleRepository.Add(p);

return p;

}

public HttpResponseMessage Put(string id, Vehicle vehicle)

{

if (!_VehicleRepository.Update(id,vehicle))

{

return Request.CreateErrorResponse(HttpStatusCode.NotFound, “Unable to Update the Vehicle for the Given ID”);

}

else

{

return Request.CreateResponse(HttpStatusCode.OK);

}

}

public HttpResponseMessage DeleteVehicle(string id)

{

_VehicleRepository.Delete(id);

return new HttpResponseMessage(HttpStatusCode.NoContent);

}

}

}

We have now our Web API Ready.It contains 6 methods that are accessible via Http requests. Each of these method in Controller is mapped to a URI

// GET : api/Vehicle

GetAllVehicles() : Returns a list of all Vehicle Objects that exist in data source

// GET :  api/Vehicle?make=

GetAllVehiclesByMake(string make) : Returns a list of all Vehicle Objects of a Certain Make ( eg: Honda / Toyota)

// GET : api/Vehicle?make=Honda&&year=2003

GetAllDinasaursByFamilyAndYear(string make,int  year) : Returns a list of all Vehicle Objects of a Certain Make & year.

//POST :  api/Vehicle

Post(Vehicle p) : Returns a single Vehicle Object that has been just added to datasource

//PUT :  api/Vehicle?id=

Put(string id, Vehicle vehicle) : Returns a HTTPResponseMessage

// DELETE : api/Vehicle?id=

DeleteVehicle(string id) : Returns a HTTPResponseMessage

Notice how i have named GetAllDinasaursByFamilyAndYear() method which will fetch vehicles of certain make & year. This is to hint that WebAPI has nothing to do with Names , It will search for method starting with GET &  appropriate parameters.

Testing your application

Via Fiddler

In this section i will demonstrate how to test your web Api with Fiddler

Run your Web API Project from Visual Studio.

Launch Fiddler. Go to Composer Tab & provide the URL of your web API.

GET Requests

Start testing with GET Request . Provide your WEB API URL ( eg : http://localhost:8085/api/vehicle)

Click on Execute Button.

02Fidd

Now you should be able to see a response result in left most result window. Double clicking the JSON result would open the Inspector tab & the JSON result.

Now if you just make a small change in the request header in Composer Tab

Content-type : application/xml

Now Hit Execute again, You should be able to see a XML result in the results window. Double clicking it would show the same data in XML format.

Now provide a filter in URL , under composer tab.

http://localhost:8085/api/vehicle?make=Honda

This would result a JSON/XML result listing all Vehicles from Data source from Honda.( Result format depends on content type we use.

03Fidd

POST Request

We now want to test POST Request therefore we would select POST request & provide default URL http://localhost:8085/api/vehicle

Also we need to provide new record information in Request Body pane

{“Make”:”Honda”,”Model”:”Accord”,”Year”:2013,”Price”:4500000.0}

Hit Execute to Insert this data in our data source.

04Fidd

You can now use GET requests to see if current record has been inserted into the system

PUT Request

We now want to test PUT Request therefore we would select PUT request & provide default URL http://localhost:8085/api/vehicle?id=xxxxxxxxxxx

We need to provide VehicleID & a vehicle object that would be used to update existing values.

Therefore we would provide Id in URI & new record information in Request Body pane

{“Make”:”Honda”,”Model”:”Accord”,”Year”:2015,”Price”:8500000.0}

Hit Execute to Update this data in our data source.

You can now use GET requests to see if previous record was Updated correctly into the system.

DELETE Request

We now want to test DELETE Request therefore we would select DELETE request & provide default URL http://localhost:8085/api/vehicle?id=xxxxxxxxxxx

We need to provide VehicleObject ID in URI.

Hit Execute to Delete record.

You can now use GET requests to validate your DELETE action.

*It is very Important to know that the filter values we provide are case sensitive.

I hope this post has provided you a quick insight on Implementing CRUD in MVC4 – WebAPI.

Published at DZone with permission of its author, Sarfraz Khan.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)