graphql-dotnet: Expanding documentation with error handling examples

The documentation is not very clear with regards to how to:

  • Create custom errors
  • Throw these custom errors
  • Customize the rendering of these errors to JSON (for example how to add fields to the errors response object)

Is there any example out there that showcases these?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 19 (12 by maintainers)

Most upvoted comments

@joemcbride Maybe I am fundamentally miss understanding async/await or the middleware. I tried that before and the catch block never gets executed.

I do agree, that would be the best case scenario for translating domain exceptiong as a cross-cutting concern.

public class ErrorHandlingFieldsMiddleware {
    public async Task<object> Resolve(
        ResolveFieldContext context,
        FieldMiddlewareDelegate next) {
        try {
            return await next(context);
        }
        catch (Exception e) {
            Console.WriteLine(e);
            throw;
        }
    }
}

I made a similar detour and couldn’t get it to work nicely without forking the project. For this current project I decided that our domain exceptions just inherit from ExecutionError.

I only had one idea left which I didn’t explore yet. In the GraphQL Middleware there might be a spot where I could translate domain exceptions in to ExecutionErrors.

        private async Task ExecuteAsync(HttpContext context, ISchema schema) {
            var request = Deserialize<GraphQLRequest>(context.Request.Body);
            var dataLoaderDocumentListener = serviceProvider.GetRequiredService<DataLoaderDocumentListener>();

            var result = await executer.ExecuteAsync(opt => {
                opt.Schema = schema;
                opt.Query = request.Query;
                opt.OperationName = request.OperationName;
                opt.Inputs = request.Variables.ToInputs();
                opt.UserContext = settings.BuildUserContext?.Invoke(context);
                opt.Listeners.Add(dataLoaderDocumentListener);
                opt.ThrowOnUnhandledException = true;
                opt.ExposeExceptions = env.IsDevelopment();
            });
            // --> Iterate result.Errors and replace them here.
            await WriteResponseAsync(context, result);
        }

As for your resolver structure. I used a mediator pattern with some rather large abstractions. My resolvers are only sending a message object with some props and the mediator is invoking the correct handler. That way my logic is agnostic of GraphQL (aside from the domain exceptions)