Recently I was tasked to put a simple WEB API together to manage a list of country capitals, so I decided to put this post together as a walk-through on how I did it.
What is a Web API?
ASP.Net Web API is a framework used to build HTTP services. By using HTTP this makes it easy to access WEB API across the internet, pretty much any platform or devices can can consumed WEB API with no problem.
In order to facilitate the client communication ASP.NET WEB API provides support for the following HTTP resources, such as GET, PUT, POST, DELETE verbs. In case you would like a more thorough explanation you can follow the tutorial from Microsoft here.
What WEB API I will be building?
This a WEB API will be use to manage country capitals information. It will be able to store, update, find and delete countries.
First create an ASP.NET Core project and name it “Countries”.
Once done simply build and run the app (CTRL+F5 to launch the app) and should see the same result page below.
Example: http://localhost:port/api/values
["value1","value2"]
Now that we have the foundation and know it’s working, let’s add the country model to the project.
Add the following Model for country:
namespace Countries.Models
{
public class Country
{
public long Id { get; set; }
public string Name { get; set; }
public string Capital { get; set; }
}
}
Add Database context
The database context is the main class that coordinates Entity Framework functionality for a given data model. This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.
using Microsoft.EntityFrameworkCore;
namespace Countries.Models
{
public class CountryContext:DbContext
{
public CountryContext(DbContextOptions
{
}
public DbSet
}
}
Register Database Context
Next, Register the DbContext via dependency injection (DI) container in order to make it available for use in the controller. ASP.NET core makes it easier since it provides built-in support for dependency injection.
Also, one of the great feature with ASP.NET Core I’ll use here is the “UseInMemoryDatabase” which will create or use a database with the name specified.
Let’s update the startup class with the following snippet.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Countries.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Countries
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
Next, let’s add the controller to put the methods such as the GET, PUT, POST, and DELETE. Let’s use this option to scaffold the different method for the country model.
As you can see in the controller constructor, it uses dependency injection to inject the DbContext CountryContext into the controller which makes it available to all the methods inside that controller.
using Countries.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Countries.Controllers
{
[Produces("application/json")]
[Route("api/Countries")]
public class CountriesController : Controller
{
private readonly CountryContext _context;
public CountriesController(CountryContext context)
{
_context = context;
}
// GET: api/Countries
[HttpGet]
public IEnumerable
{
return _context.Countries;
}
// GET: api/Countries/5
[HttpGet("{id}")]
public async Task
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var country = await _context.Countries.SingleOrDefaultAsync(m => m.Id == id);
if (country == null)
{
return NotFound();
}
return Ok(country);
}
// PUT: api/Countries/5
[HttpPut("{id}")]
public async Task
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != country.Id)
{
return BadRequest();
}
_context.Entry(country).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CountryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Countries
[HttpPost]
public async Task
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Countries.Add(country);
await _context.SaveChangesAsync();
return CreatedAtAction("GetCountry", new { id = country.Id }, country);
}
// DELETE: api/Countries/5
[HttpDelete("{id}")]
public async Task
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var country = await _context.Countries.SingleOrDefaultAsync(m => m.Id == id);
if (country == null)
{
return NotFound();
}
_context.Countries.Remove(country);
await _context.SaveChangesAsync();
return Ok(country);
}
private bool CountryExists(long id)
{
return _context.Countries.Any(e => e.Id == id);
}
}
}