Building Your First Web API with ASP.NET Core and Visual Studio Code

After completing the Building Your First Web API with ASP.NET Core MVC and Visual Studio tutorial, I decided to try building the same API using Visual Studio Code and the .NET Core CLI. I’ve focused only on the steps required, so you should refer to the original tutorial should any concepts require further explanation. Let’s dive in.

Prerequisites

  1. Install Visual Studio Code
  2. Install the .NET Core SDK (you need 1.0.0-rc4-004771 or newer)
  3. Install Postman

Create the project

Open the command prompt (or terminal) and navigate to the folder where you would like to create the project. Execute the following commands:

mkdir TodoApi
cd TodoApi
dotnet new webapi
dotnet restore

Next, open the project in VS Code using the following command:

code .

Within VS Code Explorer, open Startup.cs.

You will be prompted to install the ‘C#’ extension. Click Show Recommendations and then click Install.

Click Reload. After reloading, VS Code will begin Updating C# dependencies.

Once complete, you will be prompted to add the missing assets to build and debug the project. Click Yes.

You can now launch the project by pressing F5, and navigate to http://localhost:5000/api/values to load the default controller.

Press Shift + F5 to stop debugging.

Add a model class

Within the main project folder, add a folder named Models and then create a new file named TodoItem.cs.

Define a TodoItem class as follows:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TodoApi.Models
{
    public class TodoItem
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Key { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

Add a database context and repository class

For this project, we’ll be using the new Entity Framework Core InMemory database provider. This database provider allows Entity Framework Core to be used with an in-memory database.

Update your TodoApi.csproj file to include a reference to the provider as follows:

<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="1.1.0" />

Once complete, you will be prompted to restore unresolved dependencies. Click Restore.

Within the Models folder, add a new file named TodoContext.cs.

Define the TodoContext class as follows:

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
    public class TodoContext : DbContext
    {
        public TodoContext(DbContextOptions<TodoContext> options) : base(options)
        {
        }

        public DbSet<TodoItem> TodoItems { get; set; }
    }
}

Within the Models folder, add a new file named ITodoRepository.cs.

Define the ITodoRepository interface as follows:

using System.Collections.Generic;

namespace TodoApi.Models
{
    public interface ITodoRepository
    {
        void Add(TodoItem item);
        IEnumerable<TodoItem> GetAll();
        TodoItem Find(long key);
        void Remove(long key);
        void Update(TodoItem item);
    }
}

Within the Models folder, add a new file named TodoRepository.cs.

Implement the TodoRepository class as follows:

using System;
using System.Collections.Generic;
using System.Linq;

namespace TodoApi.Models
{
    public class TodoRepository : ITodoRepository
    {
        private readonly TodoContext _context;

        public TodoRepository(TodoContext context)
        {
            _context = context;
            Add(new TodoItem { Name = "Item1" });
        }

        public IEnumerable<TodoItem> GetAll()
        {
            return _context.TodoItems.ToList();
        }

        public void Add(TodoItem item)
        {
            _context.TodoItems.Add(item);
            _context.SaveChanges();
        }

        public TodoItem Find(long key)
        {
            return _context.TodoItems.FirstOrDefault(t => t.Key == key);
        }

        public void Remove(long key)
        {
            var entity = _context.TodoItems.First(t => t.Key == key);
            _context.TodoItems.Remove(entity);
            _context.SaveChanges();
        }

        public void Update(TodoItem item)
        {
            _context.TodoItems.Update(item);
            _context.SaveChanges();
        }
    }
}

Register the database context and repository

Open the Startup.cs file and add the following using directives:

using TodoApi.Models;
using Microsoft.EntityFrameworkCore;

Update the ConfigureServices method as follows:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddDbContext<TodoContext>(options => options.UseInMemoryDatabase());
    services.AddSingleton<ITodoRepository, TodoRepository>();
}

Add a controller

In the Controllers folder, add a new TodoController.cs file.

Implement the TodoController class as follows:

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using TodoApi.Models;

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    public class TodoController : Controller
    {
        public TodoController(ITodoRepository todoItems)
        {
            TodoItems = todoItems;
        }

        public ITodoRepository TodoItems { get; set; }

        [HttpGet]
        public IEnumerable<TodoItem> GetAll()
        {
            return TodoItems.GetAll();
        }

        [HttpGet("{id}", Name = "GetTodo")]
        public IActionResult GetById(long id)
        {
            var item = TodoItems.Find(id);
            if (item == null)
            {
                return NotFound();
            }
            return new ObjectResult(item);
        }

        [HttpPost]
        public IActionResult Create([FromBody] TodoItem item)
        {
            if (item == null)
            {
                return BadRequest();
            }
            TodoItems.Add(item);
            return CreatedAtRoute("GetTodo", new { id = item.Key }, item);
        }

        [HttpPut("{id}")]
        public IActionResult Update(long id, [FromBody] TodoItem item)
        {
            if (item == null || item.Key != id)
            {
                return BadRequest();
            }

            var todo = TodoItems.Find(id);
            if (todo == null)
            {
                return NotFound();
            }

            todo.Name = item.Name;
            todo.IsComplete = item.IsComplete;

            TodoItems.Update(todo);
            return new NoContentResult();
        }

        [HttpDelete("{id}")]
        public IActionResult Delete(long id)
        {
            var todo = TodoItems.Find(id);
            if (todo == null)
            {
                return NotFound();
            }

            TodoItems.Remove(id);
            return new NoContentResult();
        }
    }
}

Press F5 to launch the application, and navigate to http://localhost:5000/api/todo to load the new controller.

Testing the project

We will now test all actions on the controller using Postman.

Testing GetAll

Launch PostMan, and configure as shown above. Specifically:

  1. Set the HTTP method to GET
  2. Set the URL to http://localhost:5000/api/todo
  3. Click Send

Testing GetById

Open a new tab, and configure as follows:

  1. Set the HTTP method to GET
  2. Set the URL to http://localhost:5000/api/todo/1
  3. Click Send

Testing Create

Open a new tab, and configure as follows:

  1. Set the HTTP method to POST
  2. Set the URL to http://localhost:5000/api/todo/
  3. Select Body
  4. Select raw
  5. Set the content type to JSON (application/json)
  6. In the editor, enter a todo item, such as: { "name": "This is a new item.", "isComplete": false }
  7. Click Send

Testing Update

Open a new tab, and configure as follows:

  1. Set the HTTP method to PUT
  2. Set the URL to http://localhost:5000/api/todo/1
  3. Select Body
  4. Select raw
  5. Set the content type to JSON (application/json)
  6. In the editor, enter a todo item, such as: { "key":"1", "name": "Item1", "isComplete": true }
  7. Click Send

Note that a successful result should be: 204 No Content.

Testing Delete

Open a new tab, and configure as follows:

  1. Set the HTTP method to DELETE
  2. Set the URL to http://localhost:5000/api/todo/1
  3. Click Send

Note that a successful result should be: 204 No Content.

Next Steps

That’s all it takes to build your first Web API using ASP.NET Core and Visual Studio Code. If you ran into any issues, you can review the source code here. I’m planning to write some additional posts to expand this demo further, including:

  1. Adding unit tests with xUnit.net
  2. Deploying to Azure

Thanks for reading, feel free to post any questions or comments below.

7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Thiago Sobral
7 years ago

Cool! All worked great as I followed the steps. Cheers

Jason Taylor
7 years ago
Reply to  Thiago Sobral

Thanks Thiago, glad you like it. 🙂

Duncan Hunter
7 years ago

Great article thanks for sharing.

I had a slow start having issues getting the latest 1.1 SDK working and had to go get it from here https://github.com/dotnet/cli after deleting old versions as per this blog https://andrewlock.net/troubleshooting-asp-net-core-1-1-0-install-problems/.

I also had to manually configure my launch.json as per the image missing the pathcomment image

Can you guess I am on a mac? way cool that it is working !!!!

Was nice to do it on vscode too!

Thanks for sharing

Jason Taylor
7 years ago
Reply to  Duncan Hunter

No worries and thanks for sharing your experience. 🙂

Regarding launch.json, I’ve found VS Code’s behaviour to be strange. Most of the time, when I load Startup.cs it will prompt me to install the required assets to build and debug, but on occasion it doesn’t. Yesterday, I received the prompt immediately after navigating to the Debug screen. I think the key is patience!

Ella Salford
Ella Salford
7 years ago

Now install nuget package that reference Net Framework 4.5 in Libs projects. Can you?

Jason Taylor
7 years ago
Reply to  Ella Salford

Hi Ella. In relation to this project, the NuGet package would need to reference .NET Core 1.0.