public void multiple_innerExceptions() { var error = new ExecutionError("Test error message", new ArgumentNullException(null, new ArgumentOutOfRangeException())); error.Data.Add("test1", "object1"); error.Data.Add("test2", 15); error.Data.Add("test3", new Dictionary <string, object>() { { "test4", "object4" } }); error.AddLocation(new Location(5, 6)); error.AddLocation(new Location(7, 8)); var info = new ErrorInfoProvider().GetInfo(error); info.Message.ShouldBe(error.Message); info.Extensions.ShouldNotBeNull(); info.Extensions.Count.ShouldBe(3); info.Extensions.ShouldContainKeyAndValue("code", error.Code); info.Extensions.ShouldContainKey("codes"); info.Extensions["codes"].ShouldBeAssignableTo <IEnumerable <string> >().ShouldBe( new[] { ErrorInfoProvider.GetErrorCode <ArgumentNullException>(), ErrorInfoProvider.GetErrorCode <ArgumentOutOfRangeException>() }); info.Extensions.ShouldContainKey("data"); info.Extensions["data"].ShouldBeAssignableTo <IDictionary>().ShouldBe(error.Data); }
public void Issue1189_Should_Work(Type resolverType, string errorMessage, string code) { Builder.Types.Include <Issue1189_Query>(); Builder.Types.For("Character").Type = typeof(Issue1189_Character); Builder.Types.Include(resolverType); var schema = Builder.Build(_typeDefinitions); schema.Initialize(); var error = new ExecutionError(errorMessage); error.AddLocation(1, 18); error.Path = new string[] { "hero", "friend" }; error.Code = code; var queryResult = new ExecutionResult { Executed = true, Data = new { hero = new { id = "1", name = "R2-D2", friend = default(Issue1189_Character) } }, Errors = new ExecutionErrors { error } }; AssertQuery( _ => { _.Schema = schema; _.Query = _query; _.ThrowOnUnhandledException = false; }, queryResult); }
public TType Argument <TType>(string name) { if (!Arguments.ContainsKey(name)) { var error = new ExecutionError($"An argument with name \"{name}\" does not exist."); if (FieldAst?.SourceLocation != null) { error.AddLocation(FieldAst.SourceLocation.Line, FieldAst.SourceLocation.Column); } throw error; } var arg = Arguments[name]; var inputObject = arg as Dictionary <string, object>; if (inputObject != null) { var type = typeof(TType); if (type.Namespace?.StartsWith("System") == true) { return((TType)arg); } return((TType)inputObject.ToObject(type)); } return(arg.GetPropertyValue <TType>()); }
public void unhandled_exception_delegate_can_rethrow_custom_message_from_field_resolver() { var def = @" type Query { hello2: Int } "; Builder.Types.Include <Query>(); var expectedError = new ExecutionError("Test error message", new ApplicationException()); expectedError.AddLocation(1, 3); expectedError.Path = new[] { "hello2" }; AssertQuery(options => { options.Schema = Builder.Build(def); options.Query = "{ hello2 }"; options.UnhandledExceptionDelegate = ctx => { if (ctx.Exception is ApplicationException) { ctx.ErrorMessage = "Test error message"; } }; }, new ExecutionResult { Errors = new ExecutionErrors { expectedError }, Data = new { hello2 = (object)null }, Executed = true }); }
protected virtual void ValidateNodeResult(ExecutionContext context, ExecutionNode node) { var result = node.Result; // Validate result IGraphType fieldType = node.FieldDefinition.ResolvedType; var objectType = fieldType as IObjectGraphType; if (fieldType is NonNullGraphType nonNullType) { objectType = nonNullType?.ResolvedType as IObjectGraphType; if (result == null) { var type = nonNullType.ResolvedType; var error = new ExecutionError($"Cannot return null for non-null type. Field: {node.Name}, Type: {type.Name}!."); error.AddLocation(node.Field, context.Document); throw error; } } if (result == null) { return; } if (fieldType is IAbstractGraphType abstractType) { objectType = abstractType.GetObjectType(result); if (objectType == null) { var error = new ExecutionError( $"Abstract type {abstractType.Name} must resolve to an Object type at " + $"runtime for field {node.Parent.GraphType.Name}.{node.Name} " + $"with value {result}, received 'null'."); error.AddLocation(node.Field, context.Document); throw error; } if (!abstractType.IsPossibleType(objectType)) { var error = new ExecutionError($"Runtime Object type \"{objectType}\" is not a possible type for \"{abstractType}\""); error.AddLocation(node.Field, context.Document); throw error; } } if (objectType?.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError($"Expected value of type \"{objectType}\" but got: {result}."); error.AddLocation(node.Field, context.Document); throw error; } }
internal async Task <ExecutionResult> Execute( object rootObject, string query, string operationName, Inputs inputs, IUserContext userContext, bool enableValidation = true, bool enableProfiling = false, IEnumerable <IValidationRule> rules = null, CancellationToken cancellationToken = default(CancellationToken)) { if (!enableValidation) { rules = new[] { new NoopValidationRule() }; } var configuration = new ExecutionOptions { Schema = _schema, Root = rootObject, Query = query, OperationName = operationName, Inputs = inputs, UserContext = userContext, ValidationRules = rules, CancellationToken = cancellationToken, }; if (userContext is IDataLoaderContextProvider) { configuration.Listeners.Add(new DataLoaderListener()); } if (enableProfiling) { configuration.FieldMiddleware.Use <InstrumentFieldsMiddleware>(); } var result = await _documentExecutor.ExecuteAsync(configuration).ConfigureAwait(false); if (result.Errors != null) { var errors = new ExecutionErrors(); foreach (var executionError in result.Errors) { var exception = new FieldResolutionException(executionError); var error = new ExecutionError(exception.Message, exception); error.SetCode(exception.InnerException ?? exception); foreach (var location in executionError.Locations ?? new ErrorLocation[0]) { error.AddLocation(location.Line, location.Column); } error.Path.AddRange(executionError.Path); errors.Add(error); } result.Errors = errors; } return(result); }
private void GenerateError( ExecutionContext context, Field field, Exception ex, IEnumerable <string> path) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), ex); error.AddLocation(field, context.Document); error.Path = path; context.Errors.Add(error); }
private ExecutionError GenerateError( ExecutionContext context, string message, Field field, IEnumerable <string> path, Exception ex = null) { var error = new ExecutionError(message, ex); error.AddLocation(field, context.Document); error.Path = path; return(error); }
public ExecutionErrors Transform(ExecutionErrors errors) => errors.Aggregate(new ExecutionErrors(), (result, executionError) => { var exception = new FieldResolutionException(executionError); var error = new ExecutionError(exception.Message, exception); foreach (var location in executionError.Locations ?? Enumerable.Empty <ErrorLocation>()) { error.AddLocation(location.Line, location.Column); } error.Path = executionError.Path; result.Add(error); return(result); });
public async Task <TResult> TryAsyncResolve <TResult>(Func <ResolveFieldContext <TSource>, Task <TResult> > resolve, Func <ExecutionErrors, Task <TResult> > error = null) { try { return(await resolve(this)); } catch (Exception ex) { if (error == null) { var er = new ExecutionError(ex.Message, ex); er.AddLocation(FieldAst, Document); er.Path = Path; Errors.Add(er); return(default);
private ResolveEventStreamResult GenerateError( ResolveEventStreamResult resolveResult, Field field, ExecutionContext context, Exception exc, IEnumerable <string> path) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); error.Path = path; context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); }
public void Very_Long_Number_Should_Return_Error_For_Int() { var query = "{ int }"; var error = new ExecutionError("Error trying to resolve field 'int'.", new OverflowException()); error.AddLocation(1, 3); error.Path = new object[] { "int" }; var expected = new ExecutionResult { Errors = new ExecutionErrors { error }, Data = new { @int = (object)null } }; AssertQueryIgnoreErrors(query, expected, renderErrors: true, expectedErrorCount: 1); }
public void async_field_with_errors() { var error = new ExecutionError("Error trying to resolve testasync."); error.AddLocation(1, 3); var errors = new ExecutionErrors { error }; AssertQueryIgnoreErrors( "{ testasync }", CreateQueryResult(@"{ ""testasync"": null }", errors), expectedErrorCount: 1, renderErrors: true); }
public void use_undefined_fragment() { var query = @" query someDroids { r2d2: droid(id: ""3"") { ...unknown_fragment name } } "; var errors = new ExecutionErrors(); var error = new ExecutionError(@"Unknown fragment ""unknown_fragment""."); error.AddLocation(4, 25); errors.Add(error); AssertQuery(query, CreateQueryResult(null, errors), null, null); }
public void should_add_extension_object_when_exception_is_thrown_with_error_code() { string query = "{ firstSync }"; string code = "FIRST"; var errors = new ExecutionErrors(); var error = new ExecutionError("Error trying to resolve field 'firstSync'.", new SystemException("Just inner exception 1", new DllNotFoundException("just inner exception 2"))) { Code = code }; error.AddLocation(1, 3); error.Path = new[] { "firstSync" }; errors.Add(error); var expectedResult = @"{ ""firstSync"": null}"; AssertQuery(query, CreateQueryResult(expectedResult, errors), null, null); }
public void when_argument_provided_cannot_be_parsed() { var query = @" { fieldWithDefaultArgumentValue(input: WRONG_TYPE) } "; var error = new ExecutionError("Argument \u0022input\u0022 has invalid value WRONG_TYPE.\nExpected type \u0022String\u0022, found WRONG_TYPE."); error.AddLocation(3, 45); error.Code = "5.3.3.1"; var expected = new ExecutionResult { Errors = new ExecutionErrors { error }, }; AssertQueryIgnoreErrors(query, expected, renderErrors: true, expectedErrorCount: 1); }
public async Task should_not_add_extension_object_when_exception_is_thrown_without_error_code() { string query = "{ uncodedSync }"; var result = await Executer.ExecuteAsync(_ => { _.Schema = Schema; _.Query = query; }); var errors = new ExecutionErrors(); var error = new ExecutionError("Error trying to resolve uncodedSync."); error.AddLocation(1, 3); error.Path = new[] { "uncodedSync" }; errors.Add(error); var expectedResult = "{uncodedSync: null}"; AssertQuery(query, CreateQueryResult(expectedResult, errors), null, null); }
public static void SetArrayItemNodes(ExecutionContext context, ArrayExecutionNode parent) { var listType = (ListGraphType)parent.GraphType; var itemType = listType.ResolvedType; if (itemType is NonNullGraphType nonNullGraphType) { itemType = nonNullGraphType.ResolvedType; } var data = parent.Result as IEnumerable; if (data == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(parent.Field, context.Document); throw error; } var index = 0; var arrayItems = new List <ExecutionNode>(); foreach (var d in data) { var path = AppendPath(parent.Path, (index++).ToString()); ExecutionNode node = BuildExecutionNode(parent, itemType, parent.Field, parent.FieldDefinition, path); node.Result = d; if (node is ObjectExecutionNode objectNode) { SetSubFieldNodes(context, objectNode); } arrayItems.Add(node); } parent.Items = arrayItems; }
public static IObjectGraphType GetOperationRootType(Document document, ISchema schema, Operation operation) { IObjectGraphType type; ExecutionError error; switch (operation.OperationType) { case OperationType.Query: type = schema.Query; break; case OperationType.Mutation: type = schema.Mutation; if (type == null) { error = new ExecutionError("Schema is not configured for mutations"); error.AddLocation(operation, document); throw error; } break; case OperationType.Subscription: type = schema.Subscription; if (type == null) { error = new ExecutionError("Schema is not configured for subscriptions"); error.AddLocation(operation, document); throw error; } break; default: error = new ExecutionError("Can only execute queries, mutations and subscriptions."); error.AddLocation(operation, document); throw error; } return(type); }
public async Task <object> ResolveAsync(ResolveFieldContext context) { try { var logger = (context.UserContext as IServiceProvider).GetRequiredService <ILoggerFactory>().CreateLogger <Resolver>(); logger.LogInformation("Resolving field {0}", context.FieldName); var result = func(context); if (result is Task t) { await t.ConfigureAwait(false); result = t.GetProperyValue(nameof(Task <object> .Result)); } logger.LogInformation("Finished resolving field {0}", context.FieldName); return(result); } catch (Exception ex) { var err = new ExecutionError(ex.Message); err.AddLocation(context.FieldAst, context.Document); context.Errors.Add(err); return(null); } }
public static FieldType GetFieldDefinition(Document document, ISchema schema, IObjectGraphType parentType, Field field) { if (field.Name == SchemaIntrospection.SchemaMeta.Name && schema.Query == parentType) { return(SchemaIntrospection.SchemaMeta); } if (field.Name == SchemaIntrospection.TypeMeta.Name && schema.Query == parentType) { return(SchemaIntrospection.TypeMeta); } if (field.Name == SchemaIntrospection.TypeNameMeta.Name) { return(SchemaIntrospection.TypeNameMeta); } if (parentType == null) { var error = new ExecutionError($"Schema is not configured correctly to fetch {field.Name}. Are you missing a root type?"); error.AddLocation(field, document); throw error; } return(parentType.Fields.FirstOrDefault(f => f.Name == field.Name)); }
public PizzaOrderQuery(IOrderDetailsService orderDetailsService, IPizzaDetailsService pizzaDetailsService) { Name = nameof(PizzaOrderQuery); //this.AuthorizeWith(Constants.AuthPolicy.CustomerPolicy, Constants.AuthPolicy.RestaurantPolicy); FieldAsync <ListGraphType <OrderDetailsType> >( name: "newOrders", resolve: async context => await orderDetailsService.GettAllNewOrdersAsync()); //.AuthorizeWith(Constants.AuthPolicy.RestaurantPolicy); FieldAsync <PizzaDetailsType>( name: "pizzaDetails", arguments: new QueryArguments(new QueryArgument <IntGraphType> { Name = "id" }), resolve: async context => await pizzaDetailsService.GetPizzaDetailsAsync(context.GetArgument <int>("id"))); FieldAsync <OrderDetailsType>( name: "orderDetails", arguments: new QueryArguments(new QueryArgument <IntGraphType> { Name = "id" }), resolve: async context => await orderDetailsService.GetOrderDetailsAsync(context.GetArgument <int>("id"))) .AuthorizeWith(Constants.AuthPolicy.AdminPolicy); Connection <OrderDetailsType>() .Name("completedOrders") .Unidirectional() .PageSize(10) .Argument <CompletedOrderOrderByInputType>("orderBy", "Pass field & direction on which you want to sort data") .ResolveAsync(async context => { var pageRequest = new PageRequest { First = context.First, Last = context.Last, After = context.After, Before = context.Before, OrderBy = context.GetArgument <SortingDetails <CompletedOrdersSortingFields> >("orderBy") }; var pageResponse = await orderDetailsService.GetCompletedOrdersAsync(pageRequest); (string startCursor, string endCursor) = CursorHelper.GetFirstAndLastCursor(pageResponse.Nodes.Select(x => x.Id)); var edge = pageResponse.Nodes.Select(x => new Edge <OrderDetails> { Cursor = CursorHelper.ToCursor(x.Id), Node = x }).ToList(); var connection = new Connection <OrderDetails>() { Edges = edge, TotalCount = pageResponse.TotalCount, PageInfo = new PageInfo { HasNextPage = pageResponse.HasNextPage, HasPreviousPage = pageResponse.HasPreviousPage, StartCursor = startCursor, EndCursor = endCursor } }; return(connection); }); Field <PizzaDetailsType>( name: "exceptionDemo", resolve: context => { var data = new Dictionary <string, string> { { "key", "value" } }; var ex = new ExecutionError("Some error message", data); ex.AddLocation(20, 500); context.Errors.Add(ex); return(pizzaDetailsService.GetPizzaDetailsOrError()); }); }
public static void SetArrayItemNodes(ExecutionContext context, ArrayExecutionNode parent) { var listType = (ListGraphType)parent.GraphType; var itemType = listType.ResolvedType; if (itemType is NonNullGraphType nonNullGraphType) { itemType = nonNullGraphType.ResolvedType; } if (!(parent.Result is IEnumerable data)) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); throw error; } var index = 0; var arrayItems = (data is ICollection collection) ? new List <ExecutionNode>(collection.Count) : new List <ExecutionNode>(); foreach (var d in data) { if (d != null) { var node = BuildExecutionNode(parent, itemType, parent.Field, parent.FieldDefinition, index++); node.Result = d; if (node is ObjectExecutionNode objectNode) { SetSubFieldNodes(context, objectNode); } else if (node is ArrayExecutionNode arrayNode) { SetArrayItemNodes(context, arrayNode); } arrayItems.Add(node); } else { if (listType.ResolvedType is NonNullGraphType) { var error = new ExecutionError( "Cannot return null for non-null type." + $" Field: {parent.Name}, Type: {parent.FieldDefinition.ResolvedType}."); error.AddLocation(parent.Field, context.Document); error.Path = parent.Path.Append(index); context.Errors.Add(error); return; } var valueExecutionNode = new ValueExecutionNode(parent, itemType, parent.Field, parent.FieldDefinition, index++) { Result = null }; arrayItems.Add(valueExecutionNode); } } parent.Items = arrayItems; }
internal async Task <ExecutionResult> Execute( object rootObject, string query, string operationName, Inputs inputs, IUserContext userContext, IDependencyInjector dependencyInjector, ComplexityConfiguration complexityConfiguration, bool enableValidation = true, bool enableProfiling = false, IEnumerable <IValidationRule> rules = null, CancellationToken cancellationToken = default(CancellationToken)) { if (!enableValidation) { rules = new[] { new NoopValidationRule() }; } var configuration = new ExecutionOptions { Schema = _schema, Root = rootObject, Query = query, OperationName = operationName, Inputs = inputs, UserContext = UserContextWrapper.Create(userContext, dependencyInjector ?? new WrappedDependencyInjector(_constructor.TypeResolutionDelegate)), ValidationRules = rules != null && rules.Any() ? rules : null, ComplexityConfiguration = complexityConfiguration, CancellationToken = cancellationToken, }; if (userContext is IDataLoaderContextProvider) { configuration.Listeners.Add(new DataLoaderListener()); } if (enableProfiling) { configuration.FieldMiddleware.Use <InstrumentFieldsMiddleware>(); } foreach (var middleware in _middleware) { configuration.FieldMiddleware.Use(middleware); } var result = await _documentExecutor.ExecuteAsync(configuration).ConfigureAwait(false); if (result.Errors != null) { var errors = new ExecutionErrors(); foreach (var executionError in result.Errors) { var exception = new FieldResolutionException(executionError); var error = new ExecutionError(exception.Message, exception); foreach (var location in executionError.Locations ?? new ErrorLocation[0]) { error.AddLocation(location.Line, location.Column); } error.Path = executionError.Path; errors.Add(error); } result.Errors = errors; } return(result); }
/// <summary> /// Execute a single node /// </summary> /// <remarks> /// Builds child nodes, but does not execute them /// </remarks> protected virtual async Task <ExecutionNode> ExecuteNodeAsync(ExecutionContext context, ExecutionNode node) { context.CancellationToken.ThrowIfCancellationRequested(); if (node.IsResultSet) { return(node); } ResolveFieldContext resolveContext = null; try { var arguments = GetArgumentValues(context.Schema, node.FieldDefinition.Arguments, node.Field.Arguments, context.Variables); var subFields = SubFieldsFor(context, node.FieldDefinition.ResolvedType, node.Field); resolveContext = new ResolveFieldContext { FieldName = node.Field.Name, FieldAst = node.Field, FieldDefinition = node.FieldDefinition, ReturnType = node.FieldDefinition.ResolvedType, ParentType = node.GetParentType(context.Schema), Arguments = arguments, Source = node.Source, Schema = context.Schema, Document = context.Document, Fragments = context.Fragments, RootValue = context.RootValue, UserContext = context.UserContext, Operation = context.Operation, Variables = context.Variables, CancellationToken = context.CancellationToken, Metrics = context.Metrics, Errors = context.Errors, Path = node.Path, SubFields = subFields }; var resolver = node.FieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task task) { await task.ConfigureAwait(false); result = task.GetResult(); } node.Result = result; ValidateNodeResult(context, node); // Build child nodes if (node.Result != null) { if (node is ObjectExecutionNode objectNode) { SetSubFieldNodes(context, objectNode); } else if (node is ArrayExecutionNode arrayNode) { SetArrayItemNodes(context, arrayNode); } } } catch (ExecutionError error) { error.AddLocation(node.Field, context.Document); error.Path = node.Path; context.Errors.Add(error); node.Result = null; } catch (Exception ex) { if (context.ThrowOnUnhandledException) { throw; } UnhandledExceptionContext exceptionContext = null; if (context.UnhandledExceptionDelegate != null) { exceptionContext = new UnhandledExceptionContext(context, resolveContext, ex); context.UnhandledExceptionDelegate(exceptionContext); ex = exceptionContext.Exception; } var error = new ExecutionError(exceptionContext?.ErrorMessage ?? $"Error trying to resolve {node.Name}.", ex); error.AddLocation(node.Field, context.Document); error.Path = node.Path; context.Errors.Add(error); node.Result = null; } return(node); }