How to build more RESTful APIs with .NET's ApiController methods

Two weekends ago, I was fiddling with .NET Core, following this tutorial as is my habit and I came across these Methods of the ApiController class that are an elegant way of manipulating the HTTP Responses of API methods 😍 😍 😍.

At first, I thought I had discovered something that had been newly added to .NET Core and was about to come share the good news with everyone.

Good News, everyone!!!

I decided to check to see if it was in ASP.NET MVC, and there it was ... They'd always been there and I never did notice (* insert shamefaced smiley *).

Shamefaced Dog

Folks, see why you should study the documentation of the stack you use? 😒😒😒

Now, even if it's not as new as I thought, it's still relevant enough to share, don't you think so?

I do!

And so, here we are. I am about to ...

About .NET's ApiController methods

The ASP.NET WebAPI framework was built to adhere to the guidelines given by the RESTful specification.

This is why there are expectations for how the HTTP Verbs GET, HEAD, POST, PUT, DELETE and PATCH [behave](https://restful-api-design.readthedocs.io/en/latest/methods.html
).

This is also why we have HTTP Status Codes, which I must admit, are a bit much and can be easily mixed up ... ssssh! 😁.

Every HTTP response should have a status code that gives the client an idea of how well the request was received and responded to (to put in light terms) by the server.

Before today, I rarely manipulated the status codes returned from API endpoints I wrote code for. It was usually controlled by the server and could be one of 200 (success), 404 (not found), 400 (bad request), 500 (internal server), 302 (redirect), depending the server and request state.

If for any reason, I had to manipulate the response status code, I'd write code like:

System.Web.HttpContext.Current.Response.StatusCode = 404;  

Tell me it's a joke

No, you can't be serious

This sets the status code for the current request explicitly, which isn't so bad if you're not so pedantic about clean code.

Now, I'd write:

return NotFound();  

Which kind of explains itself -> The server couldn't find the requested resource, without leaving you wondering what a 404 means.

Hey, don't be too cocky just because you knew it before me 😋.

Back to ApiController Methods

There's a long list of them, each useful in its own regard. I'll do my best to explain them.

And they are:

BadRequest():

So there's something wrong with the HTTP request, and I don't mean errors like improperly formatted JSON, which are detectable by the system, and you want to inform the client?

return BadRequest();  
return BadRequest(ModelState); //tells what went wrong  
return BadRequest("Invalid Id"); //explicit message  

Read more about Http Status 400

Conflict():

What if for some reason, the server cannot complete the request at the current time because of a conflict within the server state? Again, the ApiController class has got you covered.

return Conflict();  

Read more about Http Status 409

Content():

When you want to maintain flexibility in the content-type of your API method's return value, this method is built for you.

return Content(Foo);  
return Content(Foo, "application/json");  
return Content(Foo, "application/xml");  

Created():

Use this with POST and PUT requests when a new API resource has been created. You can specify the URL for the new resource such as:

return Created("[new-resource-url-here]", Foo);  
return Created(new Uri("[new-resource-url-here]"), Foo);  

So what's the benefit of this? Your client knows exactly how to GET the resource it just created.

CreatedAtRoute():

I really like this one because it's an improvement on the Created() method by linking the new resource to a particular Route.

return CreatedAtRoute("[routeName]", [routeValues], Foo);  

See more here

Json():

This is quite popular in usage, and is used to return objects as JSON content. It also explicitly sets the content-type header to application/json, so there's no mistaking the type of data being received.

return Json(Foo);  
return Json(Foo, JsonRequestBehavior.AllowGet);  

Ok():

I still can't believe I never noticed this 😅 ... Yea, laugh all you want 😝. So with this method, you simply tell ASP.NET to return a response with http status code 200, which means SUCCESS/OK.

Perhaps the reason I never noticed it is because by default, if no Exceptions are thrown, ASP.NET returns status code 200. So it's a bit redundant. Still, mind-blown!

Read more about Http Status 200

return Ok();  
return Ok(Foo);  

NotFound():

There's perhaps no method listed here that aids readability as much as this little guy ... Do I even need to explain what it does? Just in case, it tells you the requested resource was not found.

return NotFound();  

Redirect():

Sometimes, the URI location for a requested resource changes and you have to redirect there instead.

If you come from an ASP.NET Web Forms background, you're perhaps used to the Response.Redirect("url") method which stops execution of the current request.

Well, you don't have to anymore, because the ApiController method contains the Redirect() method.

return Redirect("url");  
return Redirect(new Uri("url"));  

RedirectToRoute():

This redirects to a route within the application rather than a URI ....

return RedirectToRoute(routeName, routeData);  

Validate():

You perhaps know about ModelState.IsValid which tells you whether the models bound to the current request are in a valid state or not based on the Validation Attributes for those models.

The Validate() method differs in that it tells you whether a particular Model is valid, and not just the current instance of the model-state dictionary.

return Validate(Foo);  

I hope you had fun laughing at my oversight and as much fun learning about these as I did.

Click the recommend button in the comments section below and feel free to ask if you have any questions, or give corrections if you spot any.

Cheers!

Bye!

Show Comments