0

I have a ASP.NET Core Controller that returns a single object. Lets say this object is of type/class, Person. You call the API function is question takes a single parameter which represents the name of the person. So the purpose of the API is to return a single person by name. If a person is not found, what is the best practice return? Should I return null? Should I return/throw an exception?

return new ObjectResult(person); 
return NotFound(); // NotFound() is framework function - returns 404

I'm worried that Not Found generally means in HTTP that the resource itself was not found. Can/should Not Found also be used to mean the queried object was not found?

Sheldon Cooper
  • 627
  • 4
  • 15
  • Seems relevant: http://stackoverflow.com/q/11746894/728795 – Andrei Jun 16 '16 at 15:49
  • In fact, here is the guide on asp.net website suggesting just the same: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/action-results – Andrei Jun 16 '16 at 15:56
  • There is no "correct" answer to this, only opinions. The answers on the question @Andrei linked to demonstrate that, and why SO discourages questions which are primarily opinion based. – Heretic Monkey Jun 16 '16 at 15:59

1 Answers1

2

The proper REST way of doing this is to return a HTTP 404 status code.

A Person IS a resource in the context of your API, so it should be fine. REST clients and developers know how to handle HTTP errors, and the 404 error is very meaningful.

You can write in the 404 response body a reason, but I wouldn't mind that.

To expand further on the use of HTTP Status Code for REST API responses, if you were returning a set instead of a single object, for example the Employees under a specific Department, you could yield a HTTP 204 (NO CONTENT) status if the department does exist but there are no employees under it (meaning an empty set for an existing department), or a HTTP 404 (NOT FOUND) status if there is no such department. You should always document you API and the semantics of the returned status codes.


Another way of approaching this is to have a standardized JSON response which includes success/error information, together with the payload. For example, all your controller's "JSON" actions could return a class inheriting from this base classe:

public class ApiResponse {
    // I use lowercase properties so that the JSON follows common JavaScript naming conventions
    public bool success { get; set; }
    public String errorMessage { get; set; }
    public int? errorCode { get; set; }
}

And your controller method that returns the person could use something like this:

public class GetPersonResponse : ApiResponse {
    public PersonModel person { get; set; }
}

In your controller you could do something like this:

public GetPersonResponse Person(string id) {
    var person = FindPersonByName(id);
    var response = new GetPersonResponse {
        success = person != null,
        person = person
    }
    if (person == null) {
        response.errorCode = 404, // suggestion only
        response.errorMessage = "Person not found"
    }        
    return response;
}

Since JSON serializers won't serialize (by default) null properties the above code get you covered by not serializing the payload (person) when it is not found, or not serializing error information if it is.

Loudenvier
  • 8,362
  • 6
  • 45
  • 66
  • 1
    Great. I actually wanted to know the proper REST way of doing it, so thanks. It's crucial that you pointed out that the person IS a resource. I was worried that the proper REST way of looking at it is that the query endpoint (URI) itself was the resource, and that the person (or other query object) is just a technicality or metadata of that resource. – Sheldon Cooper Jun 16 '16 at 16:20
  • @SheldonCooper To add a little more insight, if your resource would be a list, for example all the employees on a department, you could return error 204 (NO CONTENT) if the department exists but there are no employees on it (an empty set, ergo NO CONTENT), and 404 if the department does not exist (NOT FOUND). But remember to document your API stating the meaning of each returned status code for each "resource"! – Loudenvier Jun 16 '16 at 17:33