Rushing Labs

Creating a Web API w/ .NET Core

Create the Project

  • Open Visual Studio, select "Create a new project".
  • Choose ASP.NET Core Web Application
  • Give it a name, select a location to save it to, and we're off!

I'm calling mine TestWebApi, you can do whatever you want.

Then select an "API" specifically, and denote which version of .NET Core to use. Here, I'm using .NET Core 2.2. Finally, click "Create".

NOTE: For now, I'm leaving "Configure for HTTPS" selected, and not enabling Docker support.

First Run

At this point, we technically have a functional REST API. So...post over! We're done! Nah, let's make it intereting.

Looking at Controller Actions

Visual Studio does most of the boilerplate work for you, but there are few key things to be aware of.

Arguably, the most important feature to grab hold of here is how the requests via URLs map to the controller methods.

It's a little like this:

  • URL: https://localhost:44332/api/values
  • Retrieves the method, ValuesController.Get()

Paying attention to the /api/values portion of the URL, we can see /values matches up with class name ValuesController. (We're just not including the redundant naming, "controller", in our API URL calls.) Secondly, as this URL defaults to an HTTP GET request, and there is not provided parameter, we can determine it defaults the following method. The method attribute [HttpGet] denotes the method answers to a GET request.

[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
	return new string[] { "value1", "value2" };
}


The routing built into the web API code generated by Visual Studio takes care of routing our browser request, at the above URL, to the Get() method. See how the provided method at ValuesController.Get() returns a string array containing "value1" and "value2"? This is why we see those two values displayed in the browser.

Under the hood, our API is returning a JSON response, and this is why we get the special viewer/styling in Firefox when this data reaches the client.

To see a little more of this built-in routing in place, take a look at the next method down in the controller.

[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
	return "value";
}


We're overloading the Get() method, however two new things are happening:

  • allowing an "id" int parameter passed to the method
  • only returning a single string -> ActionResult<string>

To better demonstrate this I've changed the returned string response to include the

[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
	return $"value: {id}";
}

A Few Additions

Add the [Produces("application/json")] attribute

This is largely unnecessary, but I prefer for my code to be clear even if that sometimes calls for more verbosity. As specified here, a .NET Core Web API controller will automatically format POCO ("plain-old-csharp-object") responses into JSON responses to the client. However, this functionality is almost completely transparent, so I prefer to specify this attribute--especially when ActionResult types are not returned from a controller.

Ref: https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-2.2



More specific controller/action route

Visual Studio generates each controller to have a route defined as [Route("api/[controller]")]. My preference is to change this to be [Route("api/controllerName/[action]")]. Again, completely unnecessary, and some may argue it moves away from "pure RESTful" practice. However, when you're writing a non-public backend API this kind of explicitness in route names may help.

So, based on our example we would have:

[Route("api/Values/[action]")]
[ApiController]
[Produces("application/json")]
public class ValuesController : ControllerBase
{
	[HttpGet]
	public MyObject DoSomething()...

	[HttpGet("{id}")]
	public MyObject Single(int id)...

	[HttpPost]
	public void Post([FromBody] MyObject toInsert)...

	[HttpPut("{value}")]
	public void Put(int id, [FromBody] string value)...
	/* ...rest of the class */
}

Instead of:

[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]
public class ValuesController : ControllerBase
{
	[HttpGet]
	public ActionResult<IEnumerable<string>> Get()...

	[HttpGet("{id}")]
	public ActionResult<string> Get(int id)...

	[HttpPost]
	public void Post([FromBody] string value)...

	[HttpPut("{value}")]
	public void Put(int id, [FromBody] string value)...
    
	/* ...rest of the class */
}

Update: 2019-04-24