I have the following use case for the GetProducts() method.
Good path: Returns array of type product: Product[]
Bad path: Returns status code of 500 and descriptive string error message.
(<?Type?> below is my own markup for the purposes of this post)
[Route("api/[controller]/[action]")]
[ApiController]
public class ProductsController : ControllerBase
{
[HttpGet]
public ActionResult<?Type?> GetProducts()
{
try
{
Product[] products = DataAccess.GetProductsFromDb();
return products;
}
catch
{
Response.StatusCode = 400;
return "Error retrieving products list"
}
}
}
Is there a way I can declare an action result of a generic type or perhaps two types so that this can work?
You would return an IActionResult. I highly recommend making is async as well. Here's how you can return anything through a controller method:
[Route("api/{controller}")]
public class ProductsController : Controller
{
[HttpGet]
public async Task<IActionResult> GetProducts()
{
var products = await DataAccess.GetProductsFromDb();
if (products is null)
{
return NotFound("Item not found!");
}
else
{
return Ok(products);
}
}
}
Note the Ok and NotFound are methods in the Controller abstract class which allows you to return any object you want, or no object at all.
I highly recommend before continuing using .net core you take a quick look at the example project template in Visual Studio, or if you're developing in another IDE run dotnet new mvc in your terminal.
If you want to handle an exception you should handle it on the lowest level. Assuming GetProductsFromDb() is the lowest level and you have no service layer (you'll regret this design choice later on!) you would put a try/catch.
[Route("api/{controller}")]
public class ProductsController : Controller
{
[HttpGet]
public async Task<IActionResult> GetProducts()
{
Products[] products;
try
{
products = await DataAccess.GetProductsFromDb();
}
catch(Exception e)
{
Log.Error(e, "Unable to receive products");
return InternalServerError("Unable to retrieve products, please try again later");
}
if (!products.Any())
{
return NotFound("No products were found");
}
else
{
return Ok(products);
}
}
}
Speed is NOT more important than stability in most cases, and certainly not at this stage of development. the cost of catching an exception is insignificant on something so high-level, especially since your database call is going to be several orders of magnitude slower than the overhead of catching a single exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With