Developing a CRUDAPI with ASP.NET Core, MongoDB Docker, Swagger.
Tags: dotnet, docker, mongodb, tutorial
Published: 2019-06-11 20:42:04

It has never been easier to use MongoDB and Dotnet core. Docker makes the process even easier  by eliminating the need of installing MongoDB on the local machine.  For this example, we'll create a supplement store CRUD API. 


##Prerequisites   

I assume that you have .NET Core 2.2 installed and Docker. I've used Visual Studio code to write this API.


##Creating the project

Go to your folder of choice, and on your command-line type 

```
dotnet new webapi -n SupplementCRUDAPI
```

Open the project on visual studio code and the terminal. Let's install all the dependencies that we need for the project. 

```
dotnet add package MongoDB.Driver --version 2.8.1
dotnet add package Swashbuckle.AspNetCore --version 4.0.1
```
##Creating the supplement class and a service

Create a Models folder and class named Supplement with following code


```c#
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;


namespace SupplementCRUDAPI.Models
{
    public class Supplement
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }

        [BsonElement("Name")]
        public string SupplementName { get; set; }

        [BsonElement("Price")]
        public decimal Price { get; set; }

        [BsonElement("Size")]
        public string Size { get; set; }

        [BsonElement("Type")]
        public string Type { get; set; }

        [BsonElement("Brand")]
        public string Brand { get; set; }
    }
}



```

##Modify appsettings.json

```
{
  "ConnectionStrings": {
    "SupplementDB": "mongodb://mongo:27017"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}
```



Create a services folder and class named SupplementService with following code


```c#
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using SupplementCRUDAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;



namespace SupplementCRUDAPI.Services
{
    public class SupplementService
    {
        private readonly IMongoCollection<Supplement> _supplement;

        public SupplementService(IConfiguration config)
        {
            // Connects to MongoDB.
            var client = new MongoClient(config.GetConnectionString("SupplementDB"));
            // Gets the supplementDB.
            var database = client.GetDatabase("SupplementDB");
            //Fetches the supplement collection.
            _supplement = database.GetCollection<Supplement>("Supplements");
        }

        public async Task<List<Supplement>> Get()
        {
            //Gets all supplements. 
            return await _supplement.Find(s => true).ToListAsync();
        }

        public async Task<Supplement> Get(string id)
        {
            //Get a single supplement. 
            return await _supplement.Find(s => s.Id == id).FirstOrDefaultAsync();
        }

        public async Task<Supplement> Create(Supplement s)
        {
            //Create a supplement.
            await _supplement.InsertOneAsync(s);
            return s;
        }

        public async Task<Supplement> Update(string id, Supplement s)
        {
            // Updates and existing supplement. 
             await _supplement.ReplaceOneAsync(su => su.Id == id, s);
             return s;
        }


        public async Task Remove(string id)
        {
            //Removes a supplement.
            await _supplement.DeleteOneAsync(su => su.Id == id);
        }

    }
}


```

##Modify the Startup

Let's update Startup.cs to add our service and Swagger configuration. On ConfigureServices, add the following lines. 

```c#
            services.AddScoped<SupplementService>();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Title = "Supplement API",
                    Version = "v1",
                    Description = "Supplement API tutorial using MongoDB",
                });
            });
```

On Configure, add the following lines.

```c#
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Supplement V1");
            });
```


##Create Supplement Controller 

Now on the controllers folder add create a new class SupplementController with following code. 

```c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SupplementCRUDAPI.Models;
using SupplementCRUDAPI.Services;

namespace SupplementCRUDAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SupplementController : ControllerBase
    {
        private readonly SupplementService _supplementService;

        public SupplementController(SupplementService supplementService)
        {
            _supplementService = supplementService;
        }
        // GET: api/Supplement
        [HttpGet]
        public async Task<ActionResult<List<Supplement>>> Get()
        {
            return await _supplementService.Get();
        }

        // GET: api/Supplement/5
        [HttpGet("{id}", Name = "Get")]
        public async Task<ActionResult<Supplement>> Get(string id)
        {
            var s = await _supplementService.Get(id);
            if(s == null)
            {
                return NotFound();
            }

            return s;
        }



        // POST: api/Supplement
        [HttpPost]
        public async Task<ActionResult<Supplement>> Create([FromBody] Supplement s)
        {
            await _supplementService.Create(s);
            return CreatedAtRoute("Get", new { id = s.Id.ToString() }, s);

        }

        // PUT: api/Supplement/5
        [HttpPut("{id}")]
        public  async Task<ActionResult<Supplement>> Put(string id, [FromBody] Supplement su)
        {
            var s = await _supplementService.Get(id);
            if (s == null)
            {
                return NotFound();
            }
            su.Id = s.Id;

            await _supplementService.Update(id, su);
            return CreatedAtRoute("Get", new { id = su.Id.ToString() }, su);
        }

        // DELETE: api/Supplement/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Supplement>> Delete(string id)
        {
            var s = await _supplementService.Get(id);
            if (s == null)
            {
                return NotFound();
            }

            return NoContent();

        }
    }
}
```
##Docker files

First let's create a file called Dockerfile on our main folder. This file is used to create a docker image to run our project. 


```docker
 FROM microsoft/dotnet:sdk AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out

# Build runtime image
FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "SupplementCRUDAPI.dll"]
```

On the same folder, create a file named docker-compose.yml. This files use the official image for mongoDB from Docker. 

```docker
version: '3.1'

services:

  mongo:
    container_name: mongo
    image: mongo
    restart: always
    volumes:
      - ${WEBAPP_STORAGE_HOME}/site:/data/db
      #- ./data:/data/db
    ports:
      - "27017:27017"

  web:
        build: .
        ports:
            - "8000:80"
            - "44348:443"
        depends_on:
            - mongo
        volumes:
            - ${HOME}/.microsoft/usersecrets/:/root/.microsoft/usersecrets
            - ${HOME}/.aspnet/https:/root/.aspnet/https/
        links:
          - mongo
```

## Running the API

We are finally ready to see the API working. First let's run the following commands on the terminal.

```
docker-compose build
docker-compose up
```
We should see the following lines if everything works. 
 ![Alt text of image](https://i.imgur.com/MaFWlyj.png)

##Using Swagger to interact with the API

Swagger is a great tool to visualize and test our API. 
Let's navigate to http://localhost:8000/swagger/index.html

 ![Alt text of image](https://i.imgur.com/uPZnUSF.png)

Let's post a supplement to our API.

![Alt text of image](https://i.imgur.com/JPVPeEi.png)

##Conclusion

I hoped that you enjoyed this tutorial. Here is the link for the project repository. 
https://github.com/etnicholson/SupplementAPIAspCoreMongoDB