graphql-dotnet: How to properly use "UnhandledExceptionDelegate" in GraphQLMiddleware "ExecuteAsync" class?
I am working on investigating a weird issue which is happening in below code. I am seeing NRE being thrown where HttpContext is null.
I have below ExecuteAsync code in my GraphQL middleware class -
private async Task ExecuteAsync(HttpContext context, ISchema schema)
{
var loggingService = context.RequestServices.GetService<ILoggingService>();
var loggingContext = new LoggingContext(context.Request.Headers);
context.Items["logRequest"] = new RequestInfo();
using (var logTimer = new LogTimer(loggingService, loggingContext, "Debug Logs", GetEndpoint(context), "start"))
{
try
{
var request = Deserialize<GraphQLRequest>(context.Request.Body);
var result = await _executer.ExecuteAsync(opts =>
{
opts.Schema = schema;
opts.Query = request?.Query;
opts.OperationName = request?.OperationName;
opts.Inputs = request?.Variables.ToInputs();
opts.RequestServices = context.RequestServices;
opts.UserContext = _settings.BuildUserContext?.Invoke(context);
opts.ValidationRules = DocumentValidator.CoreRules.Concat(new[] { new InputValidationRule() });
opts.EnableMetrics = _settings.EnableMetrics;
if (_settings.EnableMetrics)
{
opts.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
}
opts.UnhandledExceptionDelegate = async ctx =>
{
// called from here when that NRE exception happens.
await HandleErrors(context, ctx.Exception, loggingService, loggingContext);
};
});
await WriteResponseAsync(context, result);
logTimer.StatusCode = context.Response.StatusCode;
logTimer.Message = ((RequestInfo)context.Items["logRequest"]).Value;
}
catch (Exception ex)
{
await HandleErrors(context, ex, loggingService, loggingContext);
logTimer.StatusCode = context.Response.StatusCode;
logTimer.Message = ((RequestInfo)context.Items["logRequest"]).Value;
}
}
}
And below is my HandleErrors method -
private async Task HandleErrors(HttpContext context, Exception ex, ILoggingService loggingService, LoggingContext loggingContext)
{
if (ex == null)
{
// log here
return;
}
int statusCode;
var title = "GraphQLMiddleware";
var error = ex.Source;
var message = ex.Message;
var stackTrace = ex.StackTrace;
string eventName = null;
switch (ex)
{
// bunch of cases here
default:
message = $"Exception handling: {ex.Message}";
statusCode = StatusCodes.Status500InternalServerError;
eventName = "Default Exception";
break;
}
// log error here
// now this below line throws exception as "System.NullReferenceException" and I am confuse why?
context.Response.StatusCode = statusCode;
}
Whenever below line is called in ExecuteAsync method and then it calls HandleErrors method which throws exception at context.Response.StatusCode = statusCode where I am confuse why it could do that?
opts.UnhandledExceptionDelegate = async ctx =>
{
// called from here when that exception happens.
await HandleErrors(context, ctx.Exception, loggingService, loggingContext);
};
Is it because it is synchronous and had to be done that way? I see GQL doesn’t support async for “UnhandledExceptionDelegate”
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 23 (16 by maintainers)
That answers my question. Thanks @Shane32. Appreciate your help!
Thanks @Shane32. So I am gonna go with below code then by removing async/await altogether-
HandleError method -
I opened a new issue for the feature request to allow async unhandled exception delegate. I suggest closing this issue at your leisure.