Thursday, August 22, 2013

ASP.NET and Mongo Databases

In this post I will try to show you how to use MongoDB in your .Net MVC project and how to simplify your life in repositories development, by using MongoRepository NuGet. 

  1. Install NuGet Packages for Mongo usage

Go to Manage NuGet Packages and search mongo, then install Official MongoDB driver and MongoRepository



Before starting to write code, please look in your web.config file and set you database name:
  
    
    
    
  

2. Create some entities...

**Author entity

    public class Author:Entity
    {
        [Required]
        //[RegularExpression(@"([a-zA-Z\d]+[\w\d]*|)[a-zA-Z]+[\w\d.]*", ErrorMessage = "Invalid name")]
        public string name { get; set; }
        public HashSet books { get; set; }

        public Author()
        {
            this.books=new HashSet();
        }

        public override int GetHashCode()
        {
            return this.name.GetHashCode()*2;
        }

        public override bool Equals(object obj)
        {
            if (obj is Author)
            {
                Author a = (Author)obj;
                if (a.Id == this.Id)
                {
                    return true;
                }
            }

            return false;
        }

        public override string ToString()
        {
            return this.Id + " " + this.name;
        }
    }
**Book entity
    public class Book:Entity
    {
        public string name { get; set; }
        public string publisher { get; set; }
        public List authors { get; set; }

        public Book()
        {
            this.authors = new List();
        }

        public override int GetHashCode()
        {
            return this.name.GetHashCode() * 2;
        }

        public override bool Equals(object obj)
        {
            if (obj is Book)
            {
                Book b = (Book)obj;
                if (b.Id == this.Id)
                {
                    return true;
                }
            }

            return false;
        }

        public override string ToString()
        {
            return this.Id + " " + this.name;
        }
    }
1) Note that I created a many-to-many relationship between entities

2) Our entities extends Entity class and we do this because that's how MongoRepository works and this helps for automatically creating ObjectId for every document

3.Repository layer

I'm not gone show you the entire code for both repositories because the idea is the same

**IRepositoryAuthor interface
    public interface IRepositoryAuthor
    {
        IList getAll();
        void save(Author author);
        void update(Author author);
        void delete(Author author);
        Author findById(string id);
        void deleteAll();
    }
**RepositoryAuthor implementation
    public class RepositoryAuthor:IRepositoryAuthor
    {
        private MongoRepository repository;

        public RepositoryAuthor()
        {
            this.repository = new MongoRepository();
        }

        public IList getAll()
        {
            return repository.ToList();
        }

        public void save(Models.Author author)
        {
            this.repository.Add(author);
        }

        public void update(Models.Author author)
        {
            this.repository.Update(author);
        }

        public void delete(Models.Author author)
        {
            repository.Delete(author.Id);
        }

        public Models.Author findById(string id)
        {
            return repository.GetById(id);
        }

        public void deleteAll()
        {
            repository.DeleteAll();
        }
    }
I created a MongoRepository object which helps us to perfom CRUD operations.This is the idea of MongoRepository NuGet and I think is very useful

3.Last thing is to create a controller which use the repository

  I agree that this not the best approach to use repositories in controllers, but this is just a basic example

**Controller class
    public class AuthorController : Controller
    {
        //
        // GET: /Author/ 
        private IRepositoryAuthor repAuthor;
        private IRepositoryBook repBook;

        public AuthorController(IRepositoryAuthor repAuthor,IRepositoryBook repBook)
        {
            this.repAuthor = repAuthor;
            this.repBook = repBook;
        }

        public ActionResult Index()
        {
            return View(repAuthor.getAll());
        }

        //
        // GET: /Author/Details/5

        public ActionResult Details(string id)
        {
            var author=repAuthor.findById(id);
            if (author == null)
            {
                return HttpNotFound();
            }
            return View(author);
        }

        //
        // GET: /Author/Create

        public ActionResult Create()
        {
            ViewBag.Books = repBook.getAll().Select(i=>new SelectListItem { 
                Value=i.Id,
                Text=i.name
            });
            return View();
        }

        //
        // POST: /Author/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Author author,string[] books)
        {
            try
            {
                // TODO: Add insert logic here
                ViewBag.Books = repBook.getAll().Select(i => new SelectListItem
                {
                    Value = i.Id,
                    Text = i.name
                });

                ModelState.Remove("books");

                if (ModelState.IsValid)
                {
                    HashSet author_books = new HashSet();

                    if (books != null)
                    {
                        foreach (var id in books)
                        {
                            var book = repBook.findById(id);
                            if (book != null)
                            {
                                author_books.Add(book);
                            }
                        }
                    }

                    author.books = author_books;
                    repAuthor.save(author);

                    return RedirectToAction("Index");
                }

                return View(author);
            }
            catch
            {
                return View(author);
            }
        }

        //
        // GET: /Author/Edit/5

        public ActionResult Edit(int id)
        {
            return View();
        }

        //
        // POST: /Author/Edit/5

        [HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add update logic here

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        //
        // GET: /Author/Delete/5

        public ActionResult Delete(string id)
        {
            var author = repAuthor.findById(id);
            if (author == null)
            {
                return HttpNotFound();
            }
            return View(author);
        }

        //
        // POST: /Author/Delete/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Delete(Author author)
        {
            try
            {
                // TODO: Add delete logic here
                repAuthor.delete(author);

                return RedirectToAction("Index");
            }
            catch
            {
                return View(author);
            }
        }
    }
The views and the controllers are the same as when we work with enity framework or nhibernate. The only problem is that we can't use scaffolding so quickly, but we can generate first controllers, update the actions and then create views from templates.  And for views I will give you an example of how it looks the HTML for Create page:
@model MongoMVC.Models.Author

@{
    ViewBag.Title = "Create";
}

Create

@using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary(true)
Author
@Html.LabelFor(model => model.name)
@Html.EditorFor(model => model.name) @Html.ValidationMessageFor(model => model.name)
@Html.Label("books") @* @{ var items=Model.books.Select(i => new SelectListItem { Value = i.Id, Text = i.name }); }*@ @Html.ListBox("Books",null, new { style="width:70px"})
}
ASP.NET MVC, .Net, MVC, HTML helpers, ASP.MVC Forms, Models, SelectList, Mongo Database, NoSql, MongoRepository, RedirectToAction

No comments:

Post a Comment