Getting started
Creating a dotnet web API run : dotnet new webapi -o BookStoreApi
in your terminal, after that, then cd BookStoreApi
. With the help of these commands, a fresh ASP.NET Core Web API project is created, which is then opened in Visual Studio Code.
dotnet new webapi -o BookStoreApi
cd BookStoreApi
As soon as the Omnisharp servers launch, a dialog asks Required assets to build and debug are missing from 'BookStoreApi'. Add them?. Select Yes. As displayed in the screenshot below:
Add an entity model
The project root should now have a Models directory.
Now, add a
Book
class to the Models directory with the following code:
using System.Text.Json.Serialization;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace BookStoreApi.Models
{
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
[BsonElement("Name")]
[JsonPropertyName("Name")]
public string BookName { get; set; } = null!;
public decimal Price{ get; set; }
public string Category{ get; set; } = null!;
public string Author { get; set; } = null!;
}
}
Detailed explanation of the above code example:
The
Id
property is required for mapping the CLR(Common Language Runtime) object to the MongoDB collection.It annotate with
[BsonId]
to make this property the document's primary key.It also, annotate with
[BsonRepresentation(BsonType.ObjectId)]
to allow passing the parameter as typestring
instead of an ObjectId structure. Mongo handles the conversion fromstring
toObjectId
.The
BookName
property is annotated with the[BsonElement]
attribute. The attribute's value ofName
represents the property name in the MongoDB collection.The
[JsonPropertyName]
attribute's value ofName
represents the property name in the web API's serialized JSON response.
How can I configure the model?
To configure the database model, add a database configuration settings class to the model by just creating a class in the Models folder or directory and name it BookStoreDatabaseSettings
with the extension .cs
.
Now, copy and paste the code below in the BookStoreDatabaseSettings.cs
file:
namespace BookStoreApi.Models;
public class BookStoreDatabaseSettings
{
public string ConnectionString { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
public string BooksCollectionName { get; set; } = null!;
}
Detailed explanation of the above code example:
The values for the BookStoreDatabase
field in the appsettings.json
file are stored in the 'BookStoreDatabaseSettings' class.To make the mapping process easier, the property names in both JSON and C# are same.
Let's add a controller
Now, let's add a controller class named BooksController
to the Controllers folder or directory. After that, add the following code:
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
Detailed explanation of the above code example:
The controller performs CRUD operations using the "BooksService" class.
Action methods for supporting HTTP GET, POST, PUT, and DELETE requests are provided by the controller.
Returns an HTTP 201 response when CreatedAtAction is called in the 'Create' action method. The typical answer to an HTTP POST method that adds a new resource to the server is status code 201. Additionally, the response's "Location" header is added by "CreatedAtAction." The URL of the freshly generated book is specified in the 'Location' header.
Incorporate a CRUD operations service.
To the project root, add a Services directory. After that, add the following code to the Services directory to create a class named BooksService
:
using BookStoreApi.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
namespace BookStoreApi.Services;
public class BooksService
{
private readonly IMongoCollection<Book> _booksCollection;
public BooksService(
IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
{
var mongoClient = new MongoClient(
bookStoreDatabaseSettings.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(
bookStoreDatabaseSettings.Value.DatabaseName);
_booksCollection = mongoDatabase.GetCollection<Book>(
bookStoreDatabaseSettings.Value.BooksCollectionName);
}
public async Task<List<Book>> GetAsync() =>
await _booksCollection.Find(_ => true).ToListAsync();
public async Task<Book?> GetAsync(string id) =>
await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
public async Task CreateAsync(Book newBook) =>
await _booksCollection.InsertOneAsync(newBook);
public async Task UpdateAsync(string id, Book updatedBook) =>
await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);
public async Task RemoveAsync(string id) =>
await _booksCollection.DeleteOneAsync(x => x.Id == id);
}
Detailed explanation of the above code example:
The following MongoDB.Driver
members are used by the BooksService
class to perform CRUD operations on the database.
MongoClient
: Carries out database operations by reading the server instance.IMongoDatabase
: serves as a running representation of the Mongo database. In this article, we obtain data in a particular collection using the interface's generalGetCollection<TDocument>(collection)
method. Use the collection for CRUD operations after calling this function. In theGetCollection<TDocument>(collection)
method call:
collection
: represents the collection name.
TDocument
: represents the CLR(Common Language Runtime) object type stored in the collection.
GetCollection<TDocument>(collection)
returns a MongoCollection object representing the collection. In this article, the following methods are invoked on the collection:
DeleteOneAsync
: Removes one document that matches the given search criteria.
Find<TDocument>
: Returns all collection documents that meet the specified search criteria.
InsertOneAsync
: Adds the supplied objects to the collection as a new document.
ReplaceOneAsync
: Replaces the specified object with the solitary document that matches the provided search parameters.
You will find several problems in your code as you write it. To fix this issue, update the following files:
Update Program.cs
Now, update the Program.cs
file with the code below:
using BookStoreApi.Models;
using BookStoreApi.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<BookStoreDatabaseSettings>(builder.Configuration.GetSection("BookStoreDatabase"));
builder.Services.AddSingleton<BooksService>();
builder.Services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
// builder.Services.AddEndpointsApiExplorer();
// builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
// app.UseSwagger();
// app.UseSwaggerUI();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
You'll see that the "Program.cs" file has some new code in it. Let's now discuss the functions of the codes:
.AddJsonOptions(
options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
After the aforementioned modification, the property names in the serialized JSON response from the web API match those in the CLR (Common Language Runtime) object type. For instance, the Author
property of the Boo
class serializes as Author
rather than author
.
builder.Services.AddSingleton<BooksService>();
The BooksService
class is registered with Dependency Injection (DI) in the above code to facilitate constructor injection in consuming classes. Because BooksService
directly depends on MongoClient
, the singleton service lifespan is the most suitable. The MongoClient
object should be registered in DI(Dependency Injection) with a singleton service lifetime in accordance with the standard Mongo Client reuse guidelines.
The BooksService
class in this article uses the MongoDB.Driver
components to perform CRUD operations on the database.
builder.Services.Configure<BookStoreDatabaseSettings>(
builder.Configuration.GetSection("BookStoreDatabase"));
The configuration instance that the appsettings.json
file's BookStoreDatabase
section binds is registered in the Dependency Injection (DI) container in the code that comes before it. For instance, the BookStoreDatabase:ConnectionString
field of the appsettings.json
object is used to populate the ConnectionString
property of the BookStoreDatabaseSettings
object.
Update appsettings.json
To the file appsettings.json
, insert the following code:
"BookStoreDatabase": {
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookStore",
"BooksCollectionName": "Books"
},
Updated appsettings.json
file code example:
{
"BookStoreDatabase": {
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookStore",
"BooksCollectionName": "Books"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
We have completed the implementations at this time. Press Ctrl + F5 on your keyboard or type dotnet run
in your terminal to launch the web API.
Would you like the source code? If yes, click this link.
Also interested in learning more about the Asp.Net Core Web API? Click this link.
Thanks for reading...
Happy Coding!
Top comments (0)