Getting Started with MongoDB and .NET Core 1.1 Web API
Coming from the Microsoft Stack, many .NET developers may overlook NoSQL databases. With amazing tools like Entity Framework, SQL Express, SQL Object Explorer built right into Visual Studio, why would you want to use something else? There are many reasons for picking a NoSQL database over a SQL database, you can read about some of them here.
In this post we'll look at building a .NET Core 1.1 WebApi project connected to a MongoDB database. Web API's are some of the most common use cases for NoSQL databases.
Prerequisites
You have a little bit of ASP.NET MVC experience
You have Visual Studio 2018 installed
You have .NET Core 1.1 SDK installed
MongoDB
First we'll setup MongoDB on our machine.
Download
Grab the Community edition from their website.
Installation & Setup
Run the installer which will install MongoDB to the following directory:c:\ Program Files\MongoDB
Navigate to C:\Program Files\MongoDB\Server\3.4\bin
and create a config file named mongodb-config.cfg which tells MongoDB where to store data and logs. Here's what to write in it:
systemLog:
destination: file
path: "C:\\db\\mongodb\\log\\mongo.log"
logAppend: true
storage:
dbPath: "C:\\db\\mongodb\\data"
security:
authorization: disabled
Open up a command prompt and navigate to the same directory and run mongod.exe --config mongodb-config.cfg
. Note: You can set a PATH variable so you can run mongoDB from anywhere.
Robomongo
In the bin
directory you may have noticed 2 executables, mongod
and mongo
. mongod
is the server daeemon and mongo
is a client used to connect to the server. I prefer using Robomongo as the client. It provides a nice GUI to explore the database. Download it here.
Once it's installed, startup Robomongo and setup your connection as shown below:
Explore
Congratulations! You have a running database and a client connected to it. Take some time to play around here and add some data to get a feel for how it works.
.NET WebApi Application
Now we will create the web api.
Create Project
Open up VS2017 and go to File > New > Project and set it up as outlined below:
Hit OK. On the next screen select the Web API Template as shown before. Verify you're using .NET Core 1.1 as shown below:
The template inclues a simple controller to test things out with. Run the app and you should see something like this in your browser:
Connect to MongoDB
Install the MongoDB Driver for .NET. Open up Nuget Package Manager and search for "MongoDB.Driver" as shown below:
Select our project and click Install. At the time of writing, their latest version is 2.4.3.
Note: You may see a package called mongocsharpdriver. This is their legacy driver and they recommend you use the new package.
After agreeing to the terms and installing all the dependencies, we're ready to do some coding.
Model
Let's begin by creating our model. Create a Models folder in your project and inside add the following class:
using MongoDB.Bson.Serialization.Attributes;
namespace MongoWebApiDemo.Models
{
public class Book
{
[BsonId]
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public double Price { get; set; }
}
}
Note: The BsonId element is necessary on one of your properties so that MongoDB has a unique identifier.
DBContext
With the model created, let's build our DBContext. It looks like this:
using MongoDB.Driver;
using MongoWebApiDemo.Models;
using System.Collections.Generic;
namespace MongoWebApiDemo.DAL
{
public class MongoDBContext
{
private readonly IMongoDatabase _database = null;
public MongoDBContext()
{
var client = new MongoClient("mongodb://localhost:27017");
if (client != null)
_database = client.GetDatabase("BookDemoDb");
}
public IMongoCollection Books
{
get
{
return _database.GetCollection("Books");
}
}
}
}
As you can see, we've hard coded our connection string. This should come from a config file but to keep this short we will leave it as is.
CRUD
The Repository pattern is effective when communicating with the database, but to keep this tutorial simple, we will add simple CRUD operations directly into the MongoDBContext class. After adding these calls, it will look like this:
using MongoDB.Driver;
using MongoWebApiDemo.Models;
using System.Collections.Generic;
namespace MongoWebApiDemo.DAL
{
public class MongoDBContext
{
private readonly IMongoDatabase _database = null;
public MongoDBContext()
{
var client = new MongoClient("mongodb://localhost:27017");
if (client != null)
_database = client.GetDatabase("BookDemoDb");
}
public IMongoCollection Books
{
get
{
return _database.GetCollection("Books");
}
}
public IEnumerable GetBooks()
{
return this.Books.Find(b => true).ToList();
}
public Book GetBook(int id)
{
var filter = Builders.Filter.Eq("BookId", id);
return this.Books.Find(filter).FirstOrDefault();
}
public Book InsertBook(Book book)
{
this.Books.InsertOne(book);
return book;
}
public void ReplaceBook(Book book)
{
var filter = Builders.Filter.Eq("BookId", book.BookId);
this.Books.ReplaceOne(filter, book);
}
public void RemoveBook(int id)
{
var filter = Builders.Filter.Eq("BookId", id);
this.Books.DeleteOne(filter);
}
}
}
Seed Data
With the context class ready, let's add some seed data. Create a new file in the DAL folder named Initializer.cs
using MongoDB.Driver;
using MongoWebApiDemo.Models;
using System.Collections.Generic;
namespace MongoWebApiDemo.DAL
{
public class DbInitializer
{
public static void SeedDatabase(MongoDBContext context)
{
//db has books already
if (context.Books.Find(b => true).Count() != 0) return;
var books = new List()
{
new Book{BookId = 0, Author = "J.K. Rowling", Title = "Harry Potter", Price = 18.99},
new Book{BookId = 1, Author = "J.R.R. Tolkien", Title = "Lord of the Rings", Price = 22.99},
new Book{BookId = 2, Author = "Moby Dick", Title = "Herman Mellvile", Price = 11.99},
new Book{BookId = 3, Author = "Hamlet", Title = "William Shakespear", Price = 14.99},
};
context.Books.InsertMany(books);
}
}
}
In Startup.cs
, call the SeedDatabase function.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
MongoDBContext context = new MongoDBContext();
DbInitializer.SeedDatabase(context);
}
Run the application and verify the data is there with RoboMongo.
Controller
Time to hook everything up to the controller. Create a new named BooksController.cs
.
using Microsoft.AspNetCore.Mvc;
using MongoWebApiDemo.DAL;
using MongoWebApiDemo.Models;
using System.Collections.Generic;
namespace MongoWebApiDemo.Controllers
{
[Route("api/[controller]")]
public class BooksController : Controller
{
MongoDBContext _context;
public BooksController()
{
_context = new MongoDBContext();
}
// GET api/books
[HttpGet]
public IEnumerable Get()
{
return _context.GetBooks();
}
// GET api/books/5
[HttpGet("{id}")]
public Book Get(int id)
{
return _context.GetBook(id);
}
// POST api/books
[HttpPost]
public void Post([FromBody]Book book)
{
_context.InsertBook(book);
}
// PUT api/books/5
[HttpPut]
public void Put([FromBody]Book book)
{
_context.ReplaceBook(book);
}
// DELETE api/books/5
[HttpDelete("{id}")]
public void Delete(int id)
{
_context.RemoveBook(id);
}
}
}
Run
Before launching the application, let's update the launchUrl
since we changed the name of the controller. In LaunchSettings.json
replace the launchUrl
values from api/values
to api/books
.
Launch the application and our simple WebApi using MongoDB is ready to go! Try out the different calls we created. I like to use PostMan to quickly review API calls.
Thanks for Reading
I hope this made it easy for .NET developers that haven't taken the plunge into NoSql databases to get their hands dirty. Leave any questions or comments below!