Browsing:

Month: May 2010

ASP.NET MVC and MongoDb Part 2

In the former blogpost we've explored MongoDb and we've created a very basic MVC application with the norm.dll. We created a User and a Bug class, but we've only implemented some CR (and not UD) for the User class.
In this post I will explore how to deal with a one-to-many relationship in a document based database, i.e. a non relational database.
classdiagram

One user can submit more bugs, so there is a one to many relationship between the user and the bugs. But how to implement that in an app where there is no relational database and where there are no constraints?

This were the ViewModel pattern comes in.

Below I created a new class, the BugViewModel class, which is a combination of attributes or fields from the Bug and the User class:

namespace BugBase.ViewModels
{
    public class BugViewModel
    {
        public ObjectId Id { get; set; }
        public ObjectId UserId { get; set; }
        public string ShortDescription { get; set; }
        public string LongDescription { get; set; }
        public DateTime? Date { get; set; }
        public bool Status { get; set; }
        public string Email { get; set; }
        public string UserName { get; set; }
    }
}

So, that's great. Thank you Framework! But however do I map those attributes to the User and Bug classes?
There is AutoMapper, an object to object mapper by Jimmy Bogard, available here. But I think Automapper is a bit complex to use. For simple scenario's, like BugBase, there is a solution in the ASP.NET MVC futures assembly. This assembly provides a static class, the ModelCopier, that can also use for copying values between View Model objects and Domain model objects. It's available here at Codeplex. The dll is called Microsoft.Web.Mvc.dll. Add a reference to it in BugBase and you're good to go.

The controller create method, would look like this:

[HttpPost]
 public ActionResult Create(BugViewModel bugviewmodel)
   {
       var bug = new Bug();
       ModelCopier.CopyModel(bugviewmodel, bug);

       using (var session = new MongoSession())
        {
         string username = bugviewmodel.UserName;
            var user = session.users
              .Where(u => u.UserName == username)
                  .FirstOrDefault();

                bug.User = user;
                session.Save(bug);                
         }
      return RedirectToAction("Index");
      }
 }

You see how easy it is to add a user to a bug using the ViewModel Pattern and copy the viewmodel to the original domain class.

Next time we'll spice up the userinterface and we'll add some jQuery and Ajax.


(Another) ASP.NET MVC 2.0 app with MongoDb Part 1

I have been fiddling around with Db4o and well.. I did not finish my app. Which probably means that it is time to try out yet another document based database. So. Let's cover MongoDb this time.

I will now create a webapplication where users can submit bugs for a certain software project. Let's call it BugBase.

The first step is to create the folders c:\data and c:\data\db. These are the default folders that you can override if you wish. The next step is to download the Mongo binaries and extract them in c:\data\db.

As with many nosql databases they're obscenely trivial to install. Click on mongod.exe in the bin folder and the Mongo server is running:

mongodb

Let's see if this works. Let's create a bug record for "unable to save" in a database.

C:\data\db\bin>mongo
MongoDB shell version: 1.4.2
url: test
connecting to: test
type "exit" to exit
type "help" for help
> b = { description : "unable to save" };
{ "description" : "unable to save" }
> b = { bugtext : "unable to save the records"};
{ "bugtext" : "unable to save the records" }
> db.bugbase.save(b);
> db.bugbase.find();
{ "_id" : ObjectId("4c03a7fa0e6c000000004226"), "bugtext" : "unable to save the
records" }
>

mongocli

Apparently it does work 😉
I inserted a record in a document (ie table) and Mongo created a unique identifier for me. Cool.

Put Mongo in an ASP.NET MVC 2 app

First step is to create an MVC2 app in Visual Studio 2010 and get rid of all the standard stuff from the template.

Did somebody actually write a MongoDb to Linq provider? But yes of course! My hero Rob Conery did. And Andrew Theken took it further and hosts the project on Github.

What a surprise, only yesterday Andrew uploaded a new version. Wherever would I be without the efforts of these brilliant people? Download the latest Norm project (should I use Github) and compile it in Visual Studio. Grab the norm.dll from the bin folder and add a reference to it in the BugBase project.

Next I need an example as of how to use this dll. At Codeplex Shiju Varghese wrote an example application, which I will use as a reference. But you don't need to check out all these examples. It's just to give the credits to the people that made all this possible.

For BugBase we need at least 2 classes. Bug and User. Create them in the Models folder.

 public class User
    {
        [MongoIdentifier]
        public ObjectId Id { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public List Bugs { get; set; }

        public User() {
            Bugs = new List();
        }
    }
public class Bug
    {
        [MongoIdentifier]
        public ObjectId Id { get; set; }
        public string ShortDescription { get; set; }
        public string LongDescription { get; set; }
        public DateTime? Date { get; set; }
        public bool Status { get; set; }
        public User User { get; set; } 
    }

Now, let's add a folder called Infrastructure to put all the data layer stuff in. Create a new class called MongoSession.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Norm;
using Norm.Collections;
using Norm.Linq;
using Norm.Responses;
using BugBase.Models;

namespace BugBase.Infrastructure
{
    internal class MongoSession : IDisposable
    {
        private readonly MongoQueryProvider provider;

        public MongoSession()
        {
            var mongo = new Mongo("BugBase", "localhost", "27017", "");
            this.provider = new MongoQueryProvider(mongo);
        }

        public IQueryable Bugs
        {
            get { return new MongoQuery(this.provider); }
        }
        public IQueryable users
        {
            get { return new MongoQuery(this.provider); }
        }
        public MongoQueryProvider Provider
        {
            get { return this.provider; }
        }

        public void Add(T item) where T : class, new()
        {
            this.provider.DB.GetCollection().Insert(item);
        }

        public void Dispose()
        {
            this.provider.Server.Dispose(); 
        }
        public void Delete(T item) where T : class, new()
        {
            this.provider.DB.GetCollection().Delete(item);
        }

        public void Drop()
        {
            this.provider.DB.DropCollection(typeof(T).Name);
        }

        public void Save(T item) where T : class,new()
        {
            this.provider.DB.GetCollection().Save(item);            
        }
    }    
  }

We've got the models in place and the datalayer, so let's create a UserController.

usercontroller

Let's create a view.

usercreateview

Create a strongly typed view with the BugBase.Models.User View Data Class and Create as View Content.

Now let's add the controllermethods to create a user and list them:

 public ActionResult Index()
        {
            using (var session = new MongoSession())
            {
                var userlist = session.users.AsEnumerable();
                return View(userlist);
            }
        }
 [HttpPost]
        public ActionResult Create(User user)
        {
            using (var session = new MongoSession())
            {
                session.Save(user);
            }
            return new RedirectResult("/User");
        }

Compile the project and behold the result:

usercreate

And the list: (OK, never mind the poor security of this app)

userlist

Next time let's implement the bugs. You can download the very beta beta beta BugBase App here.