public void Register(ApiSchema schema) { var methods = typeof(TInterface).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); foreach (var methodInfo in methods) { if (methodInfo.Name == nameof(IOperation.Register)) { continue; } var isQuery = methodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(QueryAttribute)); var isMutation = methodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(MutationAttribute)); if (!isQuery && !isMutation) { isQuery = true; } var apiOperation = isQuery ? schema.Query : schema.Mutation; var parameters = methodInfo.GetParameters(); if (parameters.Length != 1) { throw new GraphException($"An operation method must have one input parameter. Operation: {typeof(TInterface).Name}.{methodInfo.Name}"); } var fieldName = methodInfo.Name.ToCamelCase(); var fieldDescription = ""; var queryArguments = GraphArguments.FromModel(parameters[0].ParameterType).GetQueryArguments(); // Add function as operation var returnType = TypeLoader.GetBaseType(methodInfo.ReturnType, out bool isList); schema.MapOutput(returnType, autoMapChildren: true, overwriteMap: false); var graphType = TypeLoader.GetGraphType(methodInfo.ReturnType); apiOperation.Field(graphType, fieldName, fieldDescription, queryArguments, context => { var inputModel = ApiOperation.GetInputFromContext(context, parameters[0].ParameterType); ValidationError.ValidateObject(inputModel); var operationValues = new OperationValues() { Context = context, FieldName = fieldName, Fields = new InputField[0], FunctionAttributes = methodInfo.GetCustomAttributes(true).OfType <Attribute>().ToArray(), Input = inputModel, }; operationValues = schema.Container.GetInstance <ApiSchema>().RunOperationFilters(OperationFilterType.Pre, operationValues); var graphClient = GetGraphClient(); var query = graphClient.AddSelectionQuery(fieldName, inputModel, context.FieldAst.SelectionSet.Selections.OfType <Field>()); var graphOutput = isQuery ? graphClient.RunQueries() : graphClient.RunMutations(); if (graphOutput.HasErrors) { graphOutput.ThrowErrors(); } operationValues.Output = query.Data.ToObject(methodInfo.ReturnType); if (PostOperations.ContainsKey(fieldName)) { operationValues.Output = PostOperations[fieldName](context, fieldName, operationValues.Output); } operationValues = schema.Container.GetInstance <ApiSchema>().RunOperationFilters(OperationFilterType.Post, operationValues); return(operationValues.Output); }); } }
protected void Application_Start() { var container = new GraphQLContainer(); container.Options.AllowOverridingRegistrations = false; container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle(); container.RegisterWebApiControllers(GlobalConfiguration.Configuration); container.Register <IContainer>(() => container); var data = new Data(); container.Register <Data>(() => data); var authorizationMap = new AuthorizationMap() { AllowMissingAuthorizations = true }; container.Register <AuthorizationMap>(() => authorizationMap); //Graph Schema container.Register <ResolverInfoManager>(Lifestyle.Scoped); container.RegisterSingleton <ApiSchema>(() => { var apiSchema = new ApiSchema(container); apiSchema.AddPropertyFilter <string>((context, propertyInfo, name, value) => { Debug.WriteLine($"PropertyFilter for {name}"); return(value); }); apiSchema.AddPropertyFilter <Uri>((context, propertyInfo, name, value) => { Debug.WriteLine($"Replacing host for Uri {value}"); var builder = new UriBuilder(value) { Host = "www.replacement.com" }; return(builder.Uri); }); apiSchema.AddPropertyFilter((context, propertyInfo, name, value) => { Debug.WriteLine($"Generic property filter"); return(value); }); // map a type with a type mapping //apiSchema.MapOutput<Lego, LegoMap>(); apiSchema.MapAssemblies(Assembly.GetAssembly(typeof(HumanObject))); // map a type without GraphObject implementation //apiSchema.MapOutput<Robot, Output.RobotOutput>(); apiSchema.MapOutput <RobotOutput>(autoMapChildren: true, overwriteMap: true); // map an operation without IOperation implementation var proxy = apiSchema.Proxy <ILegoOperation>(() => new GraphClient("http://localhost:51365/api", new HttpClient())); //proxy.AddPostOperation(nameof(ILegoOperation.Lego), (context, name, value) => //{ // Debug.WriteLine($"PostOperation for {name}"); // return value; //}); proxy.AddPostOperation(i => nameof(i.Lego), (context, name, value) => { Debug.WriteLine($"PostOperation for {name}"); return(value); }); apiSchema.Lock(); return(apiSchema); }); container.Verify(); GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); GlobalConfiguration.Configuration.MapHttpAttributeRoutes(); GlobalConfiguration.Configuration.EnsureInitialized(); GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, Formatting = Formatting.Indented, ContractResolver = new CamelCasePropertyNamesContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter()); }