Browsing:

Category: NoSQL

Getting started with ASP.NET API with MongoLab part 3

This is the sequel to this post
We will be using MongoLab as a backend for our Web Api.

We are using the AddressBook again in this example, but for clarity we're building it from scratch.

Creating the MongoLab database

Head over to MongoLab and create an account!

  • First create a new database. Make sure you choose the free plan. Name the database 'addressbook'.
  • Click to create a new user.
  • Add a new collection (equivalent for a table) named persons.

Please take note of the connectionstring:

2013-11-01 08_12_03-MongoLab_ MongoDB-as-a-Service

Setting up the Web Api project in Visual Studio

Fire up Visual Studio 2013 and hit File -> New -> Project.
Choose Empty ASP.NET Web Application with a Web API and name the project AddressBook.

2013-11-01 08_07_48-New ASP.NET Project - AddressBook

We must install the Mongo Csharp Driver:

Install-Package MongoCsharpDriver

Now open App_Start\WebApiConfig.cs and add json formatting to it (see my previous post why):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace AddressBook
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

//This section you need to add:
            var json = config.Formatters.JsonFormatter;
            json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
            config.Formatters.Remove(config.Formatters.XmlFormatter);
        }
    }
}

Connecting to the MongoLab

Let's not reinvent the wheel if you don't have to. This article is a great introduction to Mongo and C#. I borrowed their MongoConnectionHandler.

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AddressBook
{
    public class MongoConnectionHandler
    {
        public MongoCollection MongoCollection { get; private set; }

 public MongoConnectionHandler()
        {
            const string connectionString = "mongodb://:@ds031108.mongolab.com:31108/addressbook";
            //const string connectionString = "mongodb://localhost:27017";
            //// Get a thread-safe client object by using a connection string
            var mongoClient = new MongoClient(connectionString);

            //// Get a reference to a server object from the Mongo client object
            var mongoServer = mongoClient.GetServer();

            //// Get a reference to the database object 
            //// from the Mongo server object
            const string databaseName = "persons";
            var db = mongoServer.GetDatabase(databaseName);

            //// Get a reference to the collection object from the Mongo database object
            //// The collection name is the type converted to lowercase + "s"
            MongoCollection = db.GetCollection(typeof(T).Name.ToLower() + "s");
        }
    }
}

The Person class

I want the Person_Id to be the same as the document id, so I can retrieve documents easily. I'm not sure though if this is best practice. But it works.

public class Person 
    {
        public Person()
        {
            Person_Id = ObjectId.GenerateNewId().ToString();
        }

        [BsonId]
        public string Person_Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
        public string Blog { get; set; }
        public string Facebook { get; set; }
        public string Twitter { get; set; }
        public string LinkedIn { get; set; }
        public string Googleplus { get; set; }
    }

And here's the POST method:

public class PersonController : ApiController
    {
        public MongoConnectionHandler collection = new MongoConnectionHandler();

        public HttpResponseMessage Post([FromBody] Person person)
        {
            collection.MongoCollection.Insert(person);
            var response = Request.CreateResponse(HttpStatusCode.Created, person);

          
            string uri = Url.Link("DefaultApi", new { id = person.Person_Id });
            response.Headers.Location = new Uri(uri);
            return response;

        }


    }
      

You can use the API with Fiddler.

2013-11-01 14_33_36-Fiddler Web Debugger

Look at the results it has returned:

2013-11-01 14_35_25-Fiddler Web Debugger

It returned the new URI with the new Id as you can see.

Now let's check MongoLab, and lo and behold:

2013-11-01 14_39_53-MongoLab_ MongoDB-as-a-Service

Here's the remainder of the CRUD methods:

        public IEnumerable Get()
        {
            return collection.MongoCollection.FindAll().AsEnumerable();

        }


        public Person Get(string id) {

            //var query = Query.EQ(p => p.Person_Id, id);
            return collection.MongoCollection.FindOne(Query.EQ("_id", id));

        }

        public void Delete(string id)
        {
            collection.MongoCollection.Remove(Query.EQ("_id", id));

        }

        public HttpResponseMessage Put([FromBody] Person person)
        {
            
            var p = collection.MongoCollection.FindOne(Query.EQ("_id", person.Person_Id));

            if (p != null)
            {
                collection.MongoCollection.Save(person);
            }
           
            return Request.CreateResponse(HttpStatusCode.OK, person);
        }

So, that works.
Next time, let's consume this WebApi with Angularjs.

And here's all the code: here

I have changed 'Person' to 'Contact' in the sourcecode


And now for the NOSQL movement

As I wrote in my last post from (shame on me!) last year, I don't like to focus on databases that much. I'd rather spend my time with domain objects instead of thinking about inner joins, cross outer joins, views and stored procedures. Why? Because I always had to do things twice: designing a domain model and then designing the database for persistence. Or, even work with an existing database! And those two often clashed (the famous object-relational impedance mismatch).

Object Relational Mapping (ORM) like SubSonic and nHibernate are great in this respect but the mapping can be somewhat complex (which might be not true anymore for the most recent version of nHibernate which I haven't checked out yet). Then Microsoft introduced Linq 2 SQL which is great to quickly generate classes from a database (not the other way round unfortunately). But rumour has it Microsoft is turning Linq 2 SQL into legacy.

In "The end of SQL and relational databases?" the author states "With the growing trend of ORMs (Object Relational Mapping), some software developers are saying that SQL is becoming less relevant." Now whether that statement is true or false, it sure is very interesting to investigate some Object Databases, the alternative method for data persistance.

Object Databases aren't a new phenonemon, as you can see here there are quite a few of them. I decided to give MongoDB a shot, with a little help from this article.

Download MongoDB (Windows 32 bits for me) and extract it to c:\data\db (this is the default). You can start the database with mongod.exe
Capture

Next, download these 2 dll's to talk to MongoDB from C#.
Fire up Visual Studio and create a new C# console application. Add a reference to those two dll's like this:
Capture

And finally some code:

static void Main(string[] args)
      {
         //create a new Mongo instance
         var mongo = new Mongo();
         //connect to it
         mongo.Connect();

         //connect to DB (or create new if it not exists)
         var db = mongo.getDB("Frots");

         //connect to the collection (like a table)
         var frotten = db.GetCollection("frotten");

         //create a document (like a record)
         var newFrot = new Document();
         newFrot["titel"] = "nosql";
         newFrot["tekst"] = "Frotten zonder RDBMS is goed";
         frotten.Insert(newFrot);

         //find a document
         var zoekFrot = new Document();
         zoekFrot["titel"] = "nosql";
         var gezochteFrot = frotten.FindOne(zoekFrot);
          Console.WriteLine(gezochteFrot["tekst"]);
        }

This results in the following:

Capture3

While this may not look spectacular, it could be if I would have created a fancier app. But the simplicity is overwhelming. I didn't need to create tables or schemas or setup primary keys. It just worked like that.

So, I think these NoSQL databases could be a hit for .NET.

I am not saying RMDB's are bad though. I just think Object Databases are a great and simple way to store your objects.

And a very elegant way, at that.