Create Web API in ASP.NET Core

Creating Web API in ASP.NET Core is similar to creating Web API in ASP.NET MVC with a few differences. These differences are briefly summerized below :

  • Web API is no longer a separate framework. It has been merged with ASP.NET Core MVC.
  • Earlier a Web API class used to inherit from ApiController base class. As a result of the merging mentioned above the Web API no longer inherits from ApiController, rather it inherits from the same Controller class that other controllers inherit from.
  • Since Web API is now just another controller, you can have as many actions you want. Of course, to create a REST style service you still need to have those standard Get(), Post(), Put() and Delete() actions as before.
  • You can define the HTTP verb and action mapping at the action level using attributes such as [HttpPost], [HttpPut] and [HttpDelete]. This is different than before where verbs used to auto-map with the actions by default.

Ok. With this much background let's go ahead and build a simple REST style Web API that performs CRUD operations on the Customers table of the Northwind database.

Begin by creating a new ASP.NET Core project using Visual Studio and pick the Web API project template.

The project contains ValuesController in the Controllers folder. Notice that the ValuesController inherits from Controller base class just like any other MVC controller.

Rename the default Web API class to CustomerServiceController. We need database support for our service and hence you must add NuGet packages for Entity Framework Core. You can do that through Project.json file:

....
"Microsoft.EntityFrameworkCore": "1.0.1",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1"
....

Open the Startup class and modify it as shown below:

public class Startup
{
    public void ConfigureServices
           (IServiceCollection services)
    {
        services.AddMvc();
        services.AddEntityFrameworkSqlServer();
    }

    public void Configure
               (IApplicationBuilder app)
    {
        app.UseStaticFiles();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}
                           /{action=Index}
                           /{id?}");
        });
    }
}

The ConfigureServices() method adds MVC and Entity Framework Core to the services collection. The Configure() method configures the MVC routing. This routing is not needed by the Web API as such but is needed for local clients while consuming the Web API (as you will see in later parts).

Then add Models and Views folders to the project. Add Customer model class in the Models folder as shown below:

[Table("Customers")]
public class Customer
{
    [Key]
    public string CustomerID { get; set; }
    public string CompanyName { get; set; }
    public string ContactName { get; set; }
    public string Country { get; set; }
}

The Customer class is decorated with [Table] attribute that maps it to the Customers table. It contains four public properties namely CustomerID, CompanyName, ContactName and Country. The CustomerID is marked as the primary key using the [Key] attribute.

Then add NorthwindDbContext class to the Models folder and write the following code to it:

public class NorthwindDbContext:DbContext
{
    public DbSet<Customer> Customers { get; set; }

    protected override void OnConfiguring
         (DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("data source=.;
              initial catalog=northwind;
              integrated security=true");
    }
}

The NorthwindDbContext class acts as the DbContext for our data access and inherits from the DbContext class. The NorthwindDbContext defines Customers DbSet. The OnConfiguring() method configures the DbContext to use the SQL Server database with the specified connection string. Make sure to adjust the connection string to suit your environment.

Now, open the CustomerServiceController and write the following code to it:

[Route("api/[controller]")]
public class CustomerServiceController : Controller
{
    [HttpGet]
    public List<Customer> Get()
    {
        using (NorthwindDbContext db = 
               new NorthwindDbContext())
        {
            return db.Customers.OrderBy(
                   i => i.CustomerID).ToList();
        }
    }

    [HttpGet("{id}")]
    public Customer Get(string id)
    {
        using (NorthwindDbContext db = 
               new NorthwindDbContext())
        {
            return db.Customers.Where(
            i => i.CustomerID == id).SingleOrDefault();
        }
    }

    [HttpPost]
    public string Post([FromBody]Customer obj)
    {
        using (NorthwindDbContext db = 
               new NorthwindDbContext())
        {
            db.Customers.Add(obj);
            db.SaveChanges();
            return "Customer added successfully!";
        }
    }

    [HttpPut("{id}")]
    public string Put(string id, [FromBody] Customer obj)
    {
        using (NorthwindDbContext db = 
               new NorthwindDbContext())
        {
            db.Entry(obj).State = EntityState.Modified;
            db.SaveChanges();
            return "Customer modified successfully!";
        }
    }

    [HttpDelete("{id}")]
    public string Delete(string id)
    {
        using (NorthwindDbContext db = 
               new NorthwindDbContext())
        {
            var obj = db.Customers.Where(
              i => i.CustomerID == id).SingleOrDefault();
            db.Customers.Remove(obj);
            db.SaveChanges();
            return "Customer deleted successfully!";
        }
    }
}

Notice the following about the Web API you just created:

  • The CustomerServiceController is decorated with [Route] attribute that configure the routing for the Web API. The route adds /api followed by the name of the controller. So, our Web API will be located at /api/CustomerService.
  • The Web API consists of five actions namely Get(), Get(id), Post(), Put(), Delete().
  • The HTTP verb to action mapping is done using the attributes - [HttpGet], [HttpPost], [HttpPut] and [HttpDelete] respectively.
  • The Customer parameter of the actions is model bound using the [FormBody] attribute indicating that the parameter values will be coming from the request's body.
  • These attributes also specify the id route parameter wherever necessary.

We won't go into the details of the Entity Framework Core code that is contained in these actions. If you ever worked with EF before that code should be familiar to you. These actions basically implement CRUD (create, read, update and delete) operations for the Customers table.

Ok. This completes the CustomerService Web API. Run the application and see the output. If all goes well you should see JSON customer objects emitted in the browser.

Returning IActionResult and HTTP status codes

In the preceding example the actions returned the specific types such as List<Customer>, Customer and string. However, that's not necessary. You may return a generic IActionResult from all the Web API action methods. This technique comes handy when you wish to indicate HTTP status codes along with the return values.

Consider the Put() method shown below:

[HttpPut("{id}")]
public IActionResult Put(string id, 
          [FromBody] Customer obj)
{
    using (NorthwindDbContext db = 
           new NorthwindDbContext())
    {
        db.Entry(obj).State = EntityState.Modified;
        db.SaveChanges();
        return new ObjectResult
              ("Customer modified successfully!");
    }
}

The Put() now returns IActionResult instead of a string. Inside, the code creates a new ObjectResult object to return a string value back to the caller. The ObjectResult sets the HTTP status code to 200 (Ok) and then returns the specific value to the caller. All the actions of our CustomerService Web API can be modified to use this technique.

If you don't want to return anything from an action (void) then you can use NoContentResult object instead of ObjectResult. The NoContentResult returns HTTP status 204 (no content).

You can also use certain inbuilt methods to indicate the HTTP status code. Some of them are as follows:

  • Ok() : Returns HTTP status code of 200 (ok).
  • BadRequest() : Returns HTTP status code of 400 (bad request).
  • NotFound() : Returns HTTP status code of 404 (not found).

The following code shows Get(id) action modified to use NotFound() method.

[HttpGet("{id}")]
public IActionResult Get(string id)
{
    using (NorthwindDbContext db = 
            new NorthwindDbContext())
    {
        var data= db.Customers.Where
           (i => i.CustomerID == id).SingleOrDefault();
        if(data==null)
        {
            return NotFound("Invalid CustomerID!");
        }
        return new ObjectResult(data);
    }
}

As you can see, the code now checks whether data is null nr not. If it is null it indicates that the CustomerID was not found in the database and hence NotFound() method is called with a custom error message.

That's it for now! In this part of the article you created a Web API. In the next part you will learn how to consume the Web API you just created.

Till then keep coding!!


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a meditation teacher and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his ASP.NET online courses go here. More details about his Kriya and Meditation online course are available here.

Posted On : 31 October 2016