/// <summary>
        /// Processes the given <see cref="IGraphDirectiveRequest" /> against this instance
        /// performing the operation as defined by this entity and generating a response.
        /// </summary>
        /// <param name="context">The  context containing the necessary data to resolve
        /// the directive and produce a result.</param>
        /// <param name="cancelToken">The cancel token monitoring the execution of a graph request.</param>
        /// <returns>Task&lt;IGraphPipelineResponse&gt;.</returns>
        public async Task Resolve(DirectiveResolutionContext context, CancellationToken cancelToken = default)
        {
            var action = _directiveTemplate.FindMethod(context.Request.LifeCycle);

            // if no action is found skip processing of this directive
            if (action == null)
            {
                return;
            }

            IGraphActionResult result;

            try
            {
                // create a scoped controller instance for this invocation
                var directive = context
                                .ServiceProvider?
                                .GetService(_directiveTemplate.ObjectType) as GraphDirective;

                if (directive == null)
                {
                    result = new RouteNotFoundGraphActionResult(
                        $"The directive '{_directiveTemplate.InternalFullName}' " +
                        "was not found in the scoped service provider.");
                }
                else
                {
                    // invoke the right action method and set a result.
                    var task = directive.InvokeActionAsync(action, context);

                    var returnedItem = await task.ConfigureAwait(false);

                    result = this.EnsureGraphActionResult(returnedItem);
                }
            }
            catch (Exception ex)
            {
                // :(
                result = new InternalServerErrorGraphActionResult("Operation failed.", ex);
            }

            // resolve the final graph action output using the provided field context
            // in what ever manner is appropriate for the result itself
            await result.Complete(context);
        }
Exemple #2
0
        /// <summary>
        /// Called by the runtime to invoke the middleware logic. In most cases, the middleware component should return the task
        /// generated by calling the next delegate in the request chain with the provided context.
        /// </summary>
        /// <param name="context">The invocation request governing data in this pipeline run.</param>
        /// <param name="next">The next delegate in the chain to be invoked.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <returns>Task.</returns>
        public async Task InvokeAsync(GraphFieldExecutionContext context, GraphMiddlewareInvocationDelegate <GraphFieldExecutionContext> next, CancellationToken cancelToken)
        {
            IEnumerable <IDirectiveInvocationContext> directives = context.Request.InvocationContext.Directives ?? Enumerable.Empty <IDirectiveInvocationContext>();

            if (context.IsValid)
            {
                // generate requests contexts for each directive to be processed
                bool cancelPipeline = false;
                foreach (var directive in directives)
                {
                    var directiveArguments = directive.Arguments.Merge(context.VariableData);
                    var request            = new GraphDirectiveRequest(
                        directive.Directive,
                        directive.Location,
                        directive.Origin,
                        context.Request.Items);

                    var beforeResolutionRequest = request.ForLifeCycle(
                        DirectiveLifeCycle.BeforeResolution,
                        context.Request.DataSource);

                    var directiveContext = new DirectiveResolutionContext(context, beforeResolutionRequest, directiveArguments);

                    await this.ExecuteDirective(directiveContext, cancelToken).ConfigureAwait(false);

                    context.Messages.AddRange(directiveContext.Messages);
                    cancelPipeline = cancelPipeline || directiveContext.IsCancelled;
                }

                if (cancelPipeline)
                {
                    this.CancelPipeline(context);
                }
            }

            // ---------------------------------
            // continue the pipeline
            // ---------------------------------
            await next(context, cancelToken).ConfigureAwait(false);

            // ---------------------------------
            // execute after completion directives
            // ---------------------------------
            if (context.IsValid)
            {
                bool cancelPipeline = false;
                foreach (var directive in directives)
                {
                    var directiveArguments = directive.Arguments.Merge(context.VariableData);
                    var request            = new GraphDirectiveRequest(
                        directive.Directive,
                        directive.Location,
                        directive.Origin,
                        context.Request.Items);

                    var afterResolutionRequest = request.ForLifeCycle(
                        DirectiveLifeCycle.AfterResolution,
                        context.Request.DataSource);

                    var directiveContext = new DirectiveResolutionContext(context, afterResolutionRequest, directiveArguments);

                    await this.ExecuteDirective(directiveContext, cancelToken).ConfigureAwait(false);

                    context.Messages.AddRange(directiveContext.Messages);

                    cancelPipeline = cancelPipeline || directiveContext.IsCancelled;
                }

                if (cancelPipeline)
                {
                    this.CancelPipeline(context);
                }
            }
        }
Exemple #3
0
 /// <summary>
 /// Executes the directive context allowing hte resolver to process the request and response dictated by their operations.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="cancelToken">The cancel token.</param>
 /// <returns>An instruction on how to proceed after.</returns>
 private Task ExecuteDirective(
     DirectiveResolutionContext context,
     CancellationToken cancelToken)
 {
     return(context.Request.Directive.Resolver.Resolve(context, cancelToken));
 }