Building a Blog API with Dapper and MongoDB in .NET Core 9

Vineet Sharma
5 min readJan 9, 2025

In today’s development landscape, building efficient and scalable APIs is crucial for modern applications. This tutorial will guide you through creating a simple blog API using .NET Core 9, Dapper, and MongoDB. This combination provides a lightweight ORM with the flexibility of a NoSQL database, enabling efficient data operations.

Prerequisites

Before we begin, ensure you have the following:

  • .NET SDK (version 9.0 or higher)
  • A MongoDB instance running locally or accessible via a connection string (you can use MongoDB Atlas for a cloud-based solution)
  • Basic knowledge of C# and ASP.NET Core
  • A code editor (like Visual Studio or Visual Studio Code)

Step 1: Set Up Your Project

1. Create a New ASP.NET Core Web API Project

Open your terminal or command prompt and create a new project:

dotnet new webapi -n BlogApi
cd BlogApi

2. Add Required NuGet Packages

Next, add the necessary NuGet packages for MongoDB and Dapper. Run the following commands in your terminal:

dotnet add package MongoDB.Driver
dotnet add package Dapper

Step 2: Create the Blog Post Model

Create a model class that represents a blog post. This class will define the structure of the data we will be working with. In the Models directory, create a file named BlogPost.cs:

using System;

namespace BlogApi.Models
{
public class BlogPost
{
public string Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; } // To track updates
}
}

Step 3: Set Up MongoDB Context

Next, create a class to manage the MongoDB connection and operations. In the Data directory, create a file named MongoDbContext.cs:

using MongoDB.Driver;

namespace BlogApi.Data
{
public class MongoDbContext
{
private readonly IMongoDatabase _database;
public MongoDbContext(string connectionString, string databaseName)
{
var client = new MongoClient(connectionString);
_database = client.GetDatabase(databaseName);
}
public IMongoCollection<BlogPost> BlogPosts => _database.GetCollection<BlogPost>("BlogPosts");
}
}

Best Practices for Connection Strings

  • Keep your connection string secure. Consider using environment variables or a configuration file to store sensitive data.
  • Use MongoDB Atlas for cloud-based solutions and take advantage of their features like backups and scaling.

Step 4: Create a Repository

To handle data operations, create a repository that encapsulates the logic for accessing blog posts. In the Repositories directory, create a file named BlogPostRepository.cs:

using Dapper;
using MongoDB.Bson;
using MongoDB.Driver;
using BlogApi.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace BlogApi.Repositories
{
public class BlogPostRepository
{
private readonly MongoDbContext _context;
public BlogPostRepository(MongoDbContext context)
{
_context = context;
}
public async Task<IEnumerable<BlogPost>> GetAllPostsAsync()
{
var posts = await _context.BlogPosts.Find(_ => true).ToListAsync();
return posts;
}
public async Task<BlogPost> GetPostByIdAsync(string id)
{
var post = await _context.BlogPosts.Find(p => p.Id == id).FirstOrDefaultAsync();
return post;
}
public async Task AddPostAsync(BlogPost post)
{
post.CreatedAt = DateTime.UtcNow; // Set creation date
post.UpdatedAt = DateTime.UtcNow; // Set initial update date
await _context.BlogPosts.InsertOneAsync(post);
}
public async Task UpdatePostAsync(string id, BlogPost post)
{
post.UpdatedAt = DateTime.UtcNow; // Update the timestamp
await _context.BlogPosts.ReplaceOneAsync(p => p.Id == id, post);
}
public async Task DeletePostAsync(string id)
{
await _context.BlogPosts.DeleteOneAsync(p => p.Id == id);
}
}
}

Enhancing the Repository

  • The UpdatePostAsync method allows you to modify existing blog posts while keeping track of updates.
  • The DeletePostAsync method provides functionality to remove posts.

Step 5: Configure Services in Startup

Now we need to register our MongoDB context and repository in the Startup.cs file. Modify the ConfigureServices method:

using BlogApi.Data;
using BlogApi.Repositories;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Configure MongoDB context
services.AddSingleton<MongoDbContext>(provider =>
{
var connectionString = Environment.GetEnvironmentVariable("MONGODB_CONNECTION_STRING");
var databaseName = "BlogDatabase"; // Update with your database name
return new MongoDbContext(connectionString, databaseName);
});
services.AddScoped<BlogPostRepository>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}

Storing Connection Strings Securely

  • Use environment variables to store sensitive information such as your MongoDB connection string.
  • Access the connection string using Environment.GetEnvironmentVariable() in your code.

Step 6: Create a Controller

To expose our API endpoints, create a controller for managing blog posts. In the Controllers directory, create a file named BlogPostsController.cs:

using Microsoft.AspNetCore.Mvc;
using BlogApi.Models;
using BlogApi.Repositories;
using System.Collections.Generic;
using System.Threading.Tasks;

[Route("api/[controller]")]
[ApiController]
public class BlogPostsController : ControllerBase
{
private readonly BlogPostRepository _repository;
public BlogPostsController(BlogPostRepository repository)
{
_repository = repository;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<BlogPost>>> GetPosts()
{
var posts = await _repository.GetAllPostsAsync();
return Ok(posts);
}
[HttpGet("{id}")]
public async Task<ActionResult<BlogPost>> GetPost(string id)
{
var post = await _repository.GetPostByIdAsync(id);
if (post == null)
{
return NotFound();
}
return Ok(post);
}
[HttpPost]
public async Task<ActionResult> AddPost([FromBody] BlogPost post)
{
await _repository.AddPostAsync(post);
return CreatedAtAction(nameof(GetPost), new { id = post.Id }, post);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdatePost(string id, [FromBody] BlogPost post)
{
var existingPost = await _repository.GetPostByIdAsync(id);
if (existingPost == null)
{
return NotFound();
}
await _repository.UpdatePostAsync(id, post);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeletePost(string id)
{
var existingPost = await _repository.GetPostByIdAsync(id);
if (existingPost == null)
{
return NotFound();
}
await _repository.DeletePostAsync(id);
return NoContent();
}
}

Enhancements in the Controller

  • The controller now includes methods for updating and deleting blog posts, expanding the API’s functionality.
  • HTTP response codes are returned appropriately for different scenarios (e.g., 404 for not found, 204 for no content).

Step 7: Testing the API

Running Your Application

Make sure your MongoDB server is running, then execute your application:

dotnet run

Testing Endpoints with Postman

You can use Postman to interact with your API. Here are some example requests:

Get all posts:

Get a specific post by ID:

Add a new post:

{
"title": "My First Blog Post",
"content": "This is the content of my first blog post."
}

Update an existing post:

{
"title": "Updated Blog Post Title",
"content": "Updated content for the blog post."
}

Delete a post:

Conclusion

In this tutorial, we built a fully functional blog API using .NET Core 9, Dapper, and MongoDB. This setup allows for efficient data handling and provides a solid foundation for building more complex applications.

Future Enhancements

You can expand this API further by adding features such as:

  • Authentication and Authorization: Implement JWT or OAuth2 for secure access.
  • Pagination: Add pagination to the GetPosts method to handle large datasets efficiently.
  • Search Functionality: Allow users to search for blog posts by title or content.
  • Input Validation: Implement validation to ensure data integrity.
  • Testing: Write unit tests to ensure your API behaves as expected.

With these enhancements, you can create a robust and scalable blogging platform. Happy coding!

Sign up to discover human stories that deepen your understanding of the world.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Responses (1)

Write a response

Hello,
Why did you set up Dapper and where did you use it? I didn't see any code related to Dapper in the article?

20