API Controllers – Creating API in ASP.NET Core

API Controllers – Creating API in ASP.NET Core

API controllers are just like regular controllers except that their action methods produce responses which contain data objects and are sent to the client without HTML markup. Since not all clients are browsers so to provide them with data we your API Controllers.

Create the Example Project

In this tutorial you will need 2 create 2 separate projects, one for API Controllers and other for doing the consume of API.

Project – API Controllers

For the API Controllers project, use ASP.NET Core Web Application (.NET Core) template to create a new Empty Project and name it ‘APIControllers’. Remember to select the framework as .NET Core and version as ASP.NET Core 2.0.

Model & Repository

Create Models folder in the root of the application and add a class called ‘Reservation.cs’ to it. Add the following code to this class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace APIControllers.Models
{
    public class Reservation
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string StartLocation { get; set; }
        public string EndLocation { get; set; }
    }
}

Next add a file called IRepository.cs to the Models folder and used it to define the interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace APIControllers.Models
{
    public interface IRepository
    {
        IEnumerable<Reservation> Reservations { get; }
        Reservation this[int id] { get; }
        Reservation AddReservation(Reservation reservation);
        Reservation UpdateReservation(Reservation reservation);
        void DeleteReservation(int id);
    }
}

Finally add a class file called Repository.cs to the Models folder and used it to define a non-persistent store of reservations, by implementation of the IRepository interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace APIControllers.Models
{
    public class Repository : IRepository
    {
        private Dictionary<int, Reservation> items;
        public Repository()
        {
            items = new Dictionary<int, Reservation>();
            new List<Reservation> {
                new Reservation {Id=1, Name = "Ankit", StartLocation = "New York", EndLocation="Beijing" },
                new Reservation {Id=2, Name = "Bobby", StartLocation = "New Jersey", EndLocation="Boston" },
                new Reservation {Id=3, Name = "Jacky", StartLocation = "London", EndLocation="Paris" }
                }.ForEach(r => AddReservation(r));
        }
        public Reservation this[int id] => items.ContainsKey(id) ? items[id] : null;
        public IEnumerable<Reservation> Reservations => items.Values;
        public Reservation AddReservation(Reservation reservation)
        {
            if (reservation.Id == 0)
            {
                int key = items.Count;
                while (items.ContainsKey(key)) { key++; };
                reservation.Id = key;
            }
            items[reservation.Id] = reservation;
            return reservation;
        }
        public void DeleteReservation(int id) => items.Remove(id);
        public Reservation UpdateReservation(Reservation reservation) => AddReservation(reservation);
    }
}

The Repository class creates 3 set of reservation objects when it is instantiated, and since there is no persistent storage, any changes will be lost when the application is stopped or restarted.

The Class contains methods to do CRUD Operations and all the reservations are stored in a Dictionary type object.

CRUD stand for CREATE, READ, UPDATE and DELETE of objects. Normally in a class each of these operations are done by a specific function.

Configuration in the Startup Class

To enable the MVC Framework and the middleware components required for development, make the changes to the Startup.cs file as shown in the code below.

I used the AddSingleton method to set up the service mapping for the model repository.

The updated code for the Startup.cs class is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using APIControllers.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace APIControllers
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IRepository, Repository>();
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseStatusCodePages();
            app.UseDeveloperExceptionPage();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }
    }
}

Changing the URL Port

To make it easier to remember, change the App URL port to 8888. You can do it by right clicking the project in the Solution Explorer and selecting properties. On the window that opens, select the Debug tab and there you will find the App URL field.

Change the port to 8888 and then press Ctrl+S to save the changes.

See the below image:

change url

API Controllers

Now comes the most important part of creating an API Controller. Remember that the API Controller is just a normal controller that allows data in the model to be retrieved or modified, and then deliver it to some client, without having to use the actions provided by the regular controllers.

The data delivery is done by following a pattern known by name as REST. REST Stands for Representational State Transfer pattern, which contains 2 things:

1. Action Methods to do specific operations, and then deliver some data to the client. These methods are decorated with attributes that makes them to be invoked only by HTTP requests.

2. URL to which an operation will be applied. Operations can be – sending full or part of a data, adding, deleting or updating records.

So create Controllers folder in the root of the project and to it add a new Controller called Reservation, and add the following code to it:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using APIControllers.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace APIControllers.Controllers
{
    [Route("api/[controller]")]
    public class ReservationController : Controller
    {
        private IRepository repository;
        public ReservationController(IRepository repo) => repository = repo;

        [HttpGet]
        public IEnumerable<Reservation> Get() => repository.Reservations;

        [HttpGet("{id}")]
        public Reservation Get(int id) => repository[id];

        [HttpPost]
        public Reservation Post([FromBody] Reservation res) =>
        repository.AddReservation(new Reservation
        {
            Name = res.Name,
            StartLocation = res.StartLocation,
            EndLocation = res.EndLocation
        });

        [HttpPut]
        public Reservation Put([FromBody] Reservation res) => repository.UpdateReservation(res);

        [HttpPatch("{id}")]
        public StatusCodeResult Patch(int id, [FromBody]JsonPatchDocument<Reservation> patch)
        {
            Reservation res = Get(id);
            if (res != null)
            {
                patch.ApplyTo(res);
                return Ok();
            }
            return NotFound();
        }

        [HttpDelete("{id}")]
        public void Delete(int id) => repository.DeleteReservation(id);
    }
}

The Controller gets the Reservation class object through Dependency Injection feature.

Route of the API Controller

The route by which API controllers are reached can be defined only using the Route attribute. They cannot be defined in the Configure() method of the Startup class.

My Controller is reached through the URL ‘/api/Reservation’.

[Route("api/[controller]")]
public class ReservationController : Controller
{
...
}

API Controller Action Methods

It is also to note that by default ASP.NET CORE MVC:

1. Sends the data to the client as string, if the action method returns a string, and also sets the Content-Type header of the response as text/plain.

2. Sends the data to the client as JSON, if the action method return type is anything but not string like int, datetime, object, simple type,complex type,etc, and also sets the Content-Type header of the response as application/json.

The API Controller action methods have been applied some HTTP attributes. So they are invoked only by the specific HTTP method known as VERBS.

Examples of VERBS are – GET, POST, PUT, PATCH, DELETE and HEAD.

In short these HTTP Attributes correspond to the VERBS. So a specific VERB can only invoke an action that has a corresponding HTTP Attribute.

HTTP Attributes are defined in the below table:

Name Description
HttpGet It specifies that the action method can be invoked only by HTTP requests that use the GET verb.
HttpPost It specifies that the action method can be invoked only by HTTP requests that use the POST verb.
HttpDelete It specifies that the action method can be invoked only by HTTP requests that use the DELETE verb.
HttpPut It specifies that the action method can be invoked only by HTTP requests that use the PUT verb.
HttpPatch It specifies that the action method can be invoked only by HTTP requests that use the PATCH verb.
HttpHead It specifies that the action method can be invoked only by HTTP requests that use the HEAD verb.

Note – to specify multiple attributes use the attribute AcceptVerbs.

[HttpGet] Action Methods

There are two [HttpGet] methods that will be invoked on Http request of type GET.

1. The first action method delivers all the reservation records to the client in JSON. The default return type of a Controller’s action is JSON so when a class object is delivered then it is done by JSON.

The HttpGet attribute does not contain a routing segment, which is ‘id’, so the URL to invoke this action method is – ‘/api/Reservation’.

[HttpGet]
public IEnumerable<Reservation> Get() => repository.Reservations;

2. The second action method contains the ‘id’ routing segment as the argument. It then delivers the reservation record for that particular ‘id’ only in JSON format.

The URL to invoke this Action method is – ‘/api/Reservation/1’, ‘/api/Reservation/2’, ‘/api/Reservation/3’, etc.

[HttpGet("{id}")]
public Reservation Get(int id) => repository[id];

HTTP GET requests can be made directly from the browser. Run your application and go to the URL ‘/api/Reservation’, where you will see a JSON containing all the reservations, as shown in the image below:

all reservations json

Similarly if you go to the URL – ‘/api/Reservation/1’ in your browser, then you will get the JSON for the first Reservation, as shown by the image below:

1st reservation json

[HttpPost] Action

The HttpPost Action method is used to create a new Reservation. It receives the Reservation object in its argument. The [FromBody] attribute applied to its argument ensures the body content send from the client will be decoded, and put to this argument, using the Model Binding concept.

The URL to invoke this Action method is – ‘/api/Reservation’. Note that although its URL is same as that of the Get Action, the presence of [HttpPost] attribute ensures that it is invoked only for Http request of type POST.

This action returns the newly added Reservation object in JSON format. The reservation object also contains the value of the created ‘Id’ field.

[HttpPost]
public Reservation Post([FromBody] Reservation res) =>
repository.AddReservation(new Reservation
{
    Name = res.Name,
    StartLocation = res.StartLocation,
    EndLocation = res.EndLocation
});

[HttpPut] Action

The HttpPut Action is used for doing the update of a Reservation object. It will be invoked when Http request of type PUT is made to the URL – ‘/api/Reservation’.

[HttpPut]
public Reservation Put([FromForm] Reservation res) => repository.UpdateReservation(res);

The [FromForm] attribute on the argument ensure that the form data sent by the client will be used to bind this Reservation object using Model Binding.

This action method returns the Updated Reservation object in JSON format.

You can also use [FromBody] attribute instead of [FromForm] attribute on the argument. The only difference is sending the data from the client side. Data has to be send in JSON format if you use FromBody attribute, else for ‘FromForm’ attribute it has to be send in Form data.

[HttpDelete] Action

The HttpDelete action deletes a reservation from the repository. This method is called when Http request of type DELETE is initiated on the URL – ‘/api/Reseration/1’, ‘/api/Reseration/2’, ‘/api/Reseration/3’, etc.

The ‘id’ of the reservation to be deleted is passed on the 3rd segment of the URL.

[HttpDelete("{id}")]
public void Delete(int id) => repository.DeleteReservation(id);

[HttpPatch] Action

The HttpPatch Action will do multiple operations, like Add, Removing, Updating, Copying, etc, of a Reservation object which is sent from the client. The client only sends a specific set of Reservation properties in JSON format.

The JSON format looks like:

[
{ "op": "replace", "path": "Name", "value": "Ram"},
{ "op": "replace", "path": "StartLocation", "value": "Moscow"}
]

The JSON has ‘op’ property which specifies the type of operation, and a ‘path’ property which specifies where the operation will be applied. The ‘value’ property specifies its new value.

ASP.NET Core MVC will automatically process the JSON data and sends it to the action method as a JsonPatchDocument object, where T is the type of the model object to be modified (here ‘Reservation’ object).

The JsonPatchDocument object can then be used to modify an object from the repository using the ApplyTo() method.

[HttpPatch("{id}")]
public StatusCodeResult Patch(int id, [FromBody]JsonPatchDocument<Reservation> patch)
{
    Reservation res = Get(id);
    if (res != null)
    {
        patch.ApplyTo(res);
        return Ok();
    }
    return NotFound();
}

The table given below summarizes the working details for each of these action methods:

HTTP Request Type URL Data from Client Returns
GET /api/Reservation No data Returns all the reservations in JSON
GET /api/Reservation/1, /api/Reservation/2, etc No data Returns the reservation data of the id which is sent to its parameter in JSON
POST /api/Reservation The Reservation object in JSON. Returns the newly created Reservation object in JSON
PUT /api/Reservation The Reservation object in JSON. Returns the newly updated Reservation object in JSON
DELETE /api/Reservation/1, /api/Reservation/2, etc No data None
PATCH /api/Reservation/1, /api/Reservation/2, etc A JSON that contains set of modifications to be applied. Returns confirmation that the changes have been applied.

The link to download the full source code of this tutorial is given below:

Download

Conclusion

In this way the API is created in ASP.NET Core. In the next tutorial I will consume this API, link is – How to Consuming an API in ASP.NET Core.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "WordPress, SEO, jQuery, HTML" and more.