This is very similar, but my question is different: Return content with IHttpActionResult for non-OK response
Considering the question is different, I'm asking for a more concise answer, if it exists.
My architecture is the following:
- Javascript/jQuery call to a backend controller
- Backend controller calls a WebAPI service
- WebAPI service queries db (etc) and returns data
I have the following simplified code (Web API)...
Example 1 return error if product id doesn't exist:
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
Example 2 return empty data if product id doesn't exist:
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
return Ok(product);
}
Client side JS:
$.getJSON("example.json", function() {
alert("success");
})
.done(function() { alert('Product retrieved'); })
.fail(function() { alert('Product doesn't exist. '); })
.always(function() { ... });
I've read many many times that using exceptions to control flow is bad practice, which is in effect what will happen if I use NotFound()
since it will hit the .fail
function, suggesting there was an error (which there wasn't).
In another case when the comment has to be approved by someone other than the person who inserted the comment:
public IHttpActionResult ApproveComment(int rowId, string userName)
{
try {
return Ok(BusinessLogicLayer.ApproveComment(rowId, userName));
}
catch(Exception ex)
{
// elmah.logerr...
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.InnerException == null ? ex.Message : ex.InnerException.Message));
}
}
BusinessLogicLayer:
public string ApproveComment(int rowId, string userName)
{
if (userName == _repository.GetInsertedCommentUserName()) {
return "You cannot approve your own comment.";
}
if(_repository.ApproveComment(rowId, userName)){
return "Comment approved";
}
}
OR
public string ApproveComment(int rowId, string userName)
{
if (userName == _repository.GetInsertedCommentUserName()) {
throw new Exception("You cannot approve your own comment.");
}
if(_repository.ApproveComment(rowId, userName)){
return "Comment approved";
}
}
What is a clean and elegant way to return an appropriate message to the user, without using exceptions?
Or is my thinking wrong, is the 'exceptional' circumstance from the users point of view? IE., "I am expecting to get a product returned when I pass in this ID, but alas it doesn't exist!" From a developers/testers point of view I don't think this would be an exceptional case but from an end user's point of view - maybe.