ASP.NET Core 8.0 Web API - my controller
looks like this:
[HttpGet("teacher/{source}/{id}"]
public async Task<ActionResult<Teacher?>> GetTeacher(TeacherEnumSource source, string id)
{
var result = await _teacherData.GetTeacher(source, id);
return result == null ? StatusCode(404, $"No Teacher found for Source: {source} and ID: {id}") : Ok(result);
}
Notice the source
param is an enum
:
public enum TeacherEnumSource
{
SCHOOL,
UNIVERSITY,
KINDERGARTEN
}
If I pass a bad param to my API as source that is not in the enum
list, I am automatically getting this error which is kind of nice:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"source": [
"The value 'camping' is not valid."
]
},
"traceId": "00-4e2baa0235572f8359e0e15225fffd3e-4ccac5f22f8ede03-00"
}
If I put breakpoints, it is not even running the _teacherData.GetTeacher(source, id)
line so no need to show that code.
I have not added error handling yet and I have even commented out these two lines from my program.cs
to make sure:
//app.UseStatusCodePages();
//app.UseExceptionHandler();
So who is doing this error handling for me and more importantly: how can I customize it a bit because I do want to LOG that incident to my external logger (DataDog in my case).
You should choose to use a
Model and use Model validator (post not get)
Manually validate the enum value to test if the value is valid
Validate in your route using a route constraint:
public class RangeConstraint : IRouteConstraint
{
private readonly int _min;
private readonly int _max;
public RangeConstraint(int min, int max)
{
_min = min;
_max = max;
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.TryGetValue(routeKey, out var value) && int.TryParse(value.ToString(), out int intValue))
{
return intValue >= _min && intValue <= _max;
}
return false;
}
}
and integrate it using:
services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("range", typeof(RangeConstraint));
});