C
C#10mo ago
SiloCitizen3

✅ Using services.PostConfigure<ApiBehaviorOptions> to log Model Validation errors in dotnet6?

Is this a safe implementation to log Model Validation errors in dotnet6?
public static IServiceCollection AddModelBindingErrorLogging(this IServiceCollection services)
{
services.PostConfigure<ApiBehaviorOptions>(options =>
{
var builtInFactory = options.InvalidModelStateResponseFactory;

options.InvalidModelStateResponseFactory = context =>
{
try //dont crash the entire app if we cant run this routine
{
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();

var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
var actionName = descriptor.ActionName;
var controllerName = descriptor.ControllerName;
var logger = loggerFactory.CreateLogger("ModelBindingExceptionLogger");

string methodName = $"{controllerName}Controller-{actionName}";
try
{
logger.LogError($"ModelValidation Errors invoking {methodName}. Details: {JsonConvert.SerializeObject(context.ModelState.Errors())}");
}
catch (Exception ex)
{
logger.LogError(ex, $"Unable to get ModelValidation Errors - {methodName}");
}
}
catch { }
return builtInFactory(context);
};
});
return services;
}
public static IServiceCollection AddModelBindingErrorLogging(this IServiceCollection services)
{
services.PostConfigure<ApiBehaviorOptions>(options =>
{
var builtInFactory = options.InvalidModelStateResponseFactory;

options.InvalidModelStateResponseFactory = context =>
{
try //dont crash the entire app if we cant run this routine
{
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();

var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
var actionName = descriptor.ActionName;
var controllerName = descriptor.ControllerName;
var logger = loggerFactory.CreateLogger("ModelBindingExceptionLogger");

string methodName = $"{controllerName}Controller-{actionName}";
try
{
logger.LogError($"ModelValidation Errors invoking {methodName}. Details: {JsonConvert.SerializeObject(context.ModelState.Errors())}");
}
catch (Exception ex)
{
logger.LogError(ex, $"Unable to get ModelValidation Errors - {methodName}");
}
}
catch { }
return builtInFactory(context);
};
});
return services;
}
15 Replies
JakenVeina
JakenVeina10mo ago
the try/catches are sus at least, the outer one is
Azrael
Azrael10mo ago
Why're you trying to log an error, just to log it on catch?
JakenVeina
JakenVeina10mo ago
and you shouldn't be serializing logs to JSON
Azrael
Azrael10mo ago
try
{
logger.LogError($"ModelValidation Errors invoking {methodName}. Details: {JsonConvert.SerializeObject(context.ModelState.Errors())}");
}
catch (Exception ex)
{
logger.LogError(ex, $"Unable to get ModelValidation Errors - {methodName}");
}
try
{
logger.LogError($"ModelValidation Errors invoking {methodName}. Details: {JsonConvert.SerializeObject(context.ModelState.Errors())}");
}
catch (Exception ex)
{
logger.LogError(ex, $"Unable to get ModelValidation Errors - {methodName}");
}
...?
JakenVeina
JakenVeina10mo ago
that's a result of trying to do formatting where it doesn't belong
Azrael
Azrael10mo ago
Just remove the formatting.
JakenVeina
JakenVeina10mo ago
formatting is the logger sink's resposibility
Azrael
Azrael10mo ago
And that try catch block. Wouldn't it be better to log the information with a model?
JakenVeina
JakenVeina10mo ago
....yes, exactly
Azrael
Azrael10mo ago
And then let the UI format it. For example, create a class with Error, Message, Stack trace, etc. Or however you want to create this model.
JakenVeina
JakenVeina10mo ago
in other words.... each sink serializes and formats how it wants to, yes
Azrael
Azrael10mo ago
Yes.
SiloCitizen3
SiloCitizen310mo ago
got it...thanks guys. yeah, I was mostly generally worried about my use of builtInFactory , descriptor ,actionName ,controllerName and services.PostConfigure<ApiBehaviorOptions> in general. A teammate rewrote an API to .net 6 minial apis with the <nullable> option on, and it made all the Models with things like string start throwing returning unexpected model validation errors, when null was passed, because of a rush to refactor. This is an attempt to capture these instance and to try and communicate to consumers to fix or for us to re-evaluate our model props and turn things like string back to string? lack of confidence in the implementation, really ^^' and unfamiliarity with options.InvalidModelStateResponseFactory in general.
Azrael
Azrael10mo ago
Ahh.
Accord
Accord10mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.