Basic Setup
Tags: csharp, dotnet
Published: 2021-02-14 01:08:16

Over the next few weeks I'll cover building an ASP.NET Core Web API from start to finish. This week, we'll focus on creating the project, a simple user model, a mock repository, and a basic users controller.

I'll be using VSCode throughout this series, however, you should be able to follow along regardless of which editor you use. If you're using Visual Studio, you'll want to look for the project template named 'ASP.NET Core Web Application', and select 'API' after naming the project, otherwise you can create the project template with the following command.

```
dotnet new webapi -n AspNetCoreWebApiIntro
```

The template will generate two files which we are going to remove before we get started. From the project directory, remove `Controllers/WeatherForecastController.cs` and `WeatherForecast.cs`.

Now, we're going to add two folders. From the root directory of the project, add a folder named 'Models', and a folder named 'Data'. Your root directory should look similar to the following.

```
Controllers
Data
Models
Properties
appsettings.json
AspNetCoreWebApiIntro.csproj
Program.cs
Startup.cs
```

You will likely have other folders and files in your root directory, however, we won't need to worry about any of those throughout this series.

We'll begin by creating a user model. In the 'Models' folder, create a new file named 'User.cs' and add the following code.

```csharp
namespace AspNetCoreWebApiIntro.Models
{
    public class User
    {
        public int Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }
    }
}
```

We will need to revisit the user model once we set up our database, and we'll take advantage of Entity Framework to add attributes to our model and create migrations. For now, we will simply create mock users to get things up and running.

Let's create our mock repository now. In the 'Data' folder, create a new file named 'MockRepo.cs' and add the following code.

```csharp
using System.Collections.Generic;
using System.Linq;

using AspNetCoreWebApiIntro.Models;

namespace AspNetCoreWebApiIntro.Data
{
    public class MockRepo
    {
        private readonly List<User> _users = new List<User>
        {
            new User { Id = 1, FirstName = "Jane", LastName = "Doe" },
            new User { Id = 2, FirstName = "John", LastName = "Doe" },
            new User { Id = 3, FirstName = "John", LastName = "Smith" }
        };

        public IEnumerable<User> GetAllUsers()
        {
            return this._users;
        }

        public User GetUserById(int id)
        {
            return this._users.FirstOrDefault(u => u.Id == id);
        }
    }
}
```

Here, we are creating a private field of users, and exposing two methods; one which allows us to get all of the users, and one which allows us to get a single user via the `Id` property.

We will do something quite different when working with real data, again utilizing Entity Framework to handle communication with the database, although the methods we expose here will be very similar within our actual repository.

Now, we just need to create our controller and a few endpoints. Within the 'Controllers' folder, create a new file named 'UsersController.cs' and add the following code.

```csharp
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

using AspNetCoreWebApiIntro.Data;
using AspNetCoreWebApiIntro.Models;

namespace AspNetCoreWebApiIntro.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UsersController : ControllerBase
    {
        private readonly MockRepo _repo = new MockRepo();

        [HttpGet]
        public ActionResult<IEnumerable<User>> Index()
        {
            return Ok(this._repo.GetAllUsers());
        }

        [HttpGet("{id}")]
        public ActionResult<User> Show(int id)
        {
            User user = this._repo.GetUserById(id);

            if (user != null)
                return Ok(this._repo.GetUserById(id));
            return NotFound();
        }
    }
}
```

Here we're applying a property of `[ApiController]` to the class; this essentially implements behavior for us to ensure that our actions always generate a JSON response, even in the event of an error.

You'll notice that we're adding a `[Route("api/[controller]")]` property to the class as well, which places the root of our users resources at `api/users`. You could instead use `[Route("api/users")]` if you want, in order to prevent the location from changing in the event that the name of your controller should change.

We also apply a property of `[HttpGet]` to our `Index` and `Show` methods to account for the verb used by the request and capture parameters; we'll learn more about this as we move forward and implement actions for POST, PATCH, and DELETE.

Each of our actions return an `ActionResult<T>` at the moment, where `T` represents the data type we are returning in the body of our response. We use a number of methods provided for us by the `ControllerBase` class which we inherited from to generate an appropriate response for each scenario; we'll learn of a few others as we progress.

Now, open up `Properties/launchSettings.json` and look for the `applicationUrl` property of `AspNetCoreWebApiIntro`; by default, this value should be `https://localhost:5001;http://localhost:5000`. In any case, you'll want to visit the first address delimited by the semi-colon in your browser.

Build and run the project (`dotnet run` in terminal). Assuming you're using the port listed above, the following endpoints should give you the response listed beneath.

```
https://localhost:5001/api/users
[{"id":1,"firstName":"Jane","lastName":"Doe"},{"id":2,"firstName":"John","lastName":"Doe"},{"id":3,"firstName":"John","lastName":"Smith"}]

https://localhost:5001/api/users/1
{"id":1,"firstName":"Jane","lastName":"Doe"}

https://localhost:5001/api/users/2
{"id":2,"firstName":"John","lastName":"Doe"}

https://localhost:5001/api/users/3
{"id":3,"firstName":"John","lastName":"Smith"}
```

With that milestone achieved we'll take a break. In the next part of this series we'll set up a database, create an actual repository, and use Entity Framework to manage the database transactions within our application.