using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; namespace Strata.KitchenSink.Api.Controllers { [ApiController] [ApiVersion("1.0")] [Route("api/v{api-version:apiVersion}/[controller]")] public class ErrorsController : ControllerBase { public ErrorsController() { } [HttpGet("404")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public IActionResult Throw404() { return NotFound(); } [HttpGet("403")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public IActionResult Throw403() { return Forbid(); } [HttpGet("500")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult Throw500() { // Known exceptions are when you specifically catch an exception from your biz code and return a friendly message to the client. // This message will be shown in both dev and prod environments try { new FakeService().DoSomethingBad(); return Ok(); } catch // your code should catch specific exception types if possible { // make sure you are sending back a 4xx / 5xx response for errors so in DataDog, we can easily identify all calls that resulted in an error return StatusCode(500, new { message = "Custom error message from server" }); } } [HttpGet("unhandled")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult ThrowUnhandled() { // Unhandled exception is usually something thrown in your Biz code and it gets bubbled up to the client. // In Dev environment, the message and stack trace will be sent to the client // In Prod environment, a generic "Error has occurred" message will be sent to the client new FakeService().DoSomethingBad(); return Ok(); } public class FakeService { public void DoSomethingBad() { throw new Exception("Custom error message from server that only appears in Dev, not Prod environment"); } } } }