ConvertedActivity ConvertCore(
            Activity activity, 
            Job parent, 
            ExceptionFilter[] inheritedExceptionFilters)
        {
            if (activity == null)
                return new ConvertedActivity(null, Enumerable.Empty<Job>());

            var singleAwait = activity as SingleActivity;

            return singleAwait != null
                ? ConvertSingleActivityToContinuation(singleAwait, parent, inheritedExceptionFilters)
                : ConvertActivityGroupToContinuation((ActivityGroup) activity, parent, inheritedExceptionFilters);
        }
예제 #2
0
        public void CaptureSpan(string name, string type, Action capturedAction, string subType = null, string action = null)
        {
            var span = StartSpan(name, type, subType, action);

            try
            {
                capturedAction();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, span))
            {
            }
            finally
            {
                span.End();
            }
        }
예제 #3
0
        public void CaptureTransaction(string name, string type, Action action)
        {
            var transaction = StartTransaction(name, type);

            try
            {
                action();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.End();
            }
        }
예제 #4
0
        public void CaptureTransaction(string name, string type, Action action, DistributedTracingData distributedTracingData = null)
        {
            var transaction = StartTransaction(name, type, distributedTracingData);

            try
            {
                action();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.End();
            }
        }
예제 #5
0
        public async Task InvokeAsync(HttpContext context)
        {
            var transaction = StartTransaction(context);

            try
            {
                await _next(context);
            }
            catch (Exception e) when(transaction != null &&
                                     ExceptionFilter.Capture(e, transaction, context, _configurationReader, _logger))
            {
            }
            finally
            {
                StopTransaction(transaction, context);
            }
        }
예제 #6
0
        public async Task InvokeAsync(HttpContext context)
        {
            var transaction = Agent.Tracer.StartTransaction($"{context.Request.Method} {context.Request.Path}",
                                                            Transaction.TYPE_REQUEST);

            transaction.Context = new Context
            {
                Request = new Request
                {
                    Method = context.Request.Method,
                    Socket = new Socket
                    {
                        Encrypted      = context.Request.IsHttps,
                        Remote_address = context.Connection?.RemoteIpAddress?.ToString()
                    },
                    Url = new Url
                    {
                        Full     = context.Request?.Path.Value,
                        HostName = context.Request.Host.Host,
                        Protocol = GetProtocolName(context.Request.Protocol),
                        Raw      = context.Request?.Path.Value //TODO
                    },
                    HttpVersion = GetHttpVersion(context.Request.Protocol)
                }
            };

            try
            {
                await next(context);
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.Result =
                    $"{GetProtocolName(context.Request.Protocol)} {context.Response.StatusCode.ToString()[0]}xx";
                transaction.Context.Response = new Response
                {
                    Finished    = context.Response.HasStarted, //TODO ?
                    Status_code = context.Response.StatusCode
                };

                transaction.End();
            }
        }
예제 #7
0
파일: BasePage.cs 프로젝트: zdtx/zdtx
 /// <summary>
 /// 处理异常,为以下顺序
 /// 1. 如果为 false,则表明没处理,让 BasePage_Error 处理
 /// 2. 如果重载为 true,则由页面处理
 /// </summary>
 /// <param name="ex">异常</param>
 /// <param name="step">哪个环节出现的</param>
 /// <param name="id">额外的 id 信息</param>
 /// <returns></returns>
 protected virtual bool _HandleException(Type callerType,
                                         ExceptionFilter exFilter, string step, Action <string> msgSend = null)
 {
     // 首次加载报的错
     if (!IsPostBack && !_IsPartial)
     {
         if (exFilter.Exception != null)
         {
             new
             DTException.DataSetter(exFilter.Exception.Data)
             .Record("BASE.Step", step)
             .Record("BASE.PageUrl", Request.RawUrl);
             throw exFilter.Exception;
         }
     }
     if (!exFilter.Handled)
     {
         string msg = exFilter.Exception.Message;
         exFilter.DT(ex =>
         {
             if (ex is TTableRecordNotFound)
             {
                 msg = "您好,数据未能访问 ";
             }
             if (ex.Data != null && ex.Data.Count > 0)
             {
                 msg += "\r\n参考(用于运维):\r\n----------";
                 foreach (var key in exFilter.Exception.Data.Keys)
                 {
                     msg += string.Format("\r\n  {0}:{1} ",
                                          key.ToStringEx(), exFilter.Exception.Data[key].ToStringEx());
                 }
                 msg += "\r\n----------";
             }
         });
         if (msgSend != null)
         {
             msgSend(msg);
         }
         else
         {
             _JS.Alert(msg);
         }
     }
     return(true);
 }
예제 #8
0
        public void OnException_WithUncheckedException_ReturnsResultInternalServerError()
        {
            var exception = Mock.Of <Exception>();

            context.Exception = exception;

            var filter = new ExceptionFilter();

            filter.OnException(context);

            var jsonResult = context.Result as JsonResult;
            var resultObj  = JsonConvert.DeserializeObject <ErrorResult>(JsonConvert.SerializeObject(jsonResult.Value));


            Assert.AreEqual(500, jsonResult.StatusCode);
            Assert.AreEqual(500, resultObj.Status);
            Assert.AreEqual("An unknown error has occured", resultObj.Message);
        }
예제 #9
0
        public void OnException_should_not_set_context_result_for_unkown_controller()
        {
            var errorContext = CreateExceptionContext(new DbUpdateException());

            ((ControllerActionDescriptor)errorContext.ActionDescriptor).ControllerTypeInfo = typeof(object).GetTypeInfo();
            var loggerMock = new Mock <ILogger <ExceptionFilter> >();
            var sut        = new ExceptionFilter(loggerMock.Object);

            sut.OnException(errorContext);

            Assert.Null(errorContext.Result);

            errorContext.ActionDescriptor = new ActionDescriptor();

            sut.OnException(errorContext);

            Assert.Null(errorContext.Result);
        }
예제 #10
0
        internal static T CaptureSpan <T>(ISpan span, Func <T> func)
        {
            var retVal = default(T);

            try
            {
                retVal = func();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, span))
            {
            }
            finally
            {
                span.End();
            }

            return(retVal);
        }
예제 #11
0
        public void OnException_WithArgumentException_ReturnsResultBadRequest()
        {
            var exception = Mock.Of <ArgumentException>(
                e => e.Message == "ArgumentException message"
                );

            context.Exception = exception;

            var filter = new ExceptionFilter();

            filter.OnException(context);

            var jsonResult = context.Result as JsonResult;
            var resultObj  = JsonConvert.DeserializeObject <ErrorResult>(JsonConvert.SerializeObject(jsonResult.Value));

            Assert.AreEqual(400, jsonResult.StatusCode);
            Assert.AreEqual(400, resultObj.Status);
            Assert.AreEqual("ArgumentException message", resultObj.Message);
        }
예제 #12
0
        public T CaptureTransaction <T>(string name, string type, Func <ITransaction, T> func)
        {
            var transaction = StartTransaction(name, type);
            var retVal      = default(T);

            try
            {
                retVal = func(transaction);
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.End();
            }

            return(retVal);
        }
예제 #13
0
        public T CaptureTransaction <T>(string name, string type, Func <T> func, DistributedTracingData distributedTracingData = null)
        {
            var transaction = StartTransaction(name, type, distributedTracingData);
            var retVal      = default(T);

            try
            {
                retVal = func();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.End();
            }

            return(retVal);
        }
예제 #14
0
        public T CaptureSpan <T>(string name, string type, Func <T> func, string subType = null, string action = null)
        {
            var span   = StartSpan(name, type, subType, action);
            var retVal = default(T);

            try
            {
                retVal = func();
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, span))
            {
            }
            finally
            {
                span.End();
            }

            return(retVal);
        }
        static void DispatchCore(ExceptionFilter filter, Exception exception, JobContext context, 
            IDependencyScope scope)
        {
            var instance = scope.GetService(filter.Type);

            foreach (var argument in filter.Arguments)
            {
                var exceptionContext = argument as ExceptionContext;
                if (exceptionContext != null)
                {
                    exceptionContext.ActivityType = context.ActivityType;
                    exceptionContext.Method = context.Method;
                    exceptionContext.Arguments = context.Arguments;
                    exceptionContext.Exception = exception;
                    exceptionContext.DispatchCount = context.DispatchCount;
                }
            }

            var method = filter.Type.GetMethod(filter.Method);
            method.Invoke(instance, filter.Arguments);
        }
예제 #16
0
        public virtual IHttpActionResult Get(int id)
        {
            HttpResponseMessage response = new HttpResponseMessage();

            try
            {
                BaseService <TEntity> service = new BaseService <TEntity>();

                var entidade = service.Find(id);

                response = Request.CreateResponse(HttpStatusCode.OK, entidade);
                response.Headers.Add("X-Server-Message", $"{typeof(TEntity).Name} encontrado.");
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
                response = ExceptionFilter.Find(ref response, ex);
            }

            return(ResponseMessage(response));
        }
        public void TestExceptionFilterUnauthorizedAccessException()
        {
            ActionContext           context          = this.GetActionContextMock();
            IList <IFilterMetadata> filters          = new List <IFilterMetadata>();
            ExceptionContext        exceptionContext = new ExceptionContext(context, filters)
            {
                Exception = new UnauthorizedAccessException()
            };

            ExceptionFilter ex = new ExceptionFilter();

            ex.OnException(exceptionContext);

            HttpResponse response = exceptionContext.HttpContext.Response;
            string       body     = GetResponseBody(response);

            Assert.IsNotNull(ex);
            Assert.IsNotNull(response);
            Assert.IsNotNull(body);
            Assert.AreEqual(401, response.StatusCode);
        }
예제 #18
0
        /// <summary>
        /// Registers a continuation on the task.
        /// Within the continuation it ends the transaction and captures errors
        /// </summary>
        /// <param name="task">Task.</param>
        /// <param name="transaction">Transaction.</param>
        private void RegisterContinuation(Task task, ISpan span)
        {
            task.ContinueWith((t) =>
            {
                if (t.IsFaulted)
                {
                    if (t.Exception != null)
                    {
                        if (t.Exception is AggregateException aggregateException)
                        {
                            ExceptionFilter.Capture(
                                aggregateException.InnerExceptions.Count == 1
                                    ? aggregateException.InnerExceptions[0]
                                    : aggregateException.Flatten(), span);
                        }
                        else
                        {
                            ExceptionFilter.Capture(t.Exception, span);
                        }
                    }
                    else
                    {
                        span.CaptureError("Task faulted", "A task faulted", new StackTrace().GetFrames());
                    }
                }
                else if (t.IsCanceled)
                {
                    if (t.Exception == null)
                    {
                        span.CaptureError("Task canceled", "A task was canceled", new StackTrace().GetFrames()); //TODO: this async stacktrace is hard to use, make it readable!
                    }
                    else
                    {
                        span.CaptureException(t.Exception);
                    }
                }

                span.End();
            }, System.Threading.CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
        }
            public void When_HandlingNotFoundException_Expect_NotFoundObjectResult()
            {
                // Arrange
                TestNotFoundException exception = new TestNotFoundException(Guid.NewGuid().ToString());

                ExceptionContext context = new ExceptionContext(this.actionContext, new List <IFilterMetadata>())
                {
                    Exception = exception,
                };

                ExceptionFilter exceptionFilter = new ExceptionFilter(new MockProblemDetailsFactory());

                // Act
                exceptionFilter.OnException(context);

                // Assert
                NotFoundObjectResult objectResult   = Assert.IsType <NotFoundObjectResult>(context.Result);
                ProblemDetails       problemDetails = Assert.IsType <ProblemDetails>(objectResult.Value);

                Assert.Equal((int)HttpStatusCode.NotFound, problemDetails.Status);
                Assert.Equal(exception.Message, problemDetails.Detail);
            }
예제 #20
0
        public Job(
            Guid id,
            Type type,
            string method,
            object[] arguments,
            DateTime createdOn,
            Guid? rootId = null,
            Guid? parentId = null,
            Guid? correlationId = null,                        
            JobStatus status = JobStatus.Ready,
            int dispatchCount = 0,
            DateTime? retryOn = null,
            ExceptionFilter[] exceptionFilters = null,
            Continuation continuation = null,
            bool? suspended = null)
        {
            if(type == null) throw new ArgumentNullException("type");
            if (arguments == null) throw new ArgumentNullException("arguments");
            if (string.IsNullOrWhiteSpace(method)) throw new ArgumentException("A valid method is required.");

            Method = method;
            Id = id;
            Type = type;
            Arguments = arguments;
            CreatedOn = createdOn;

            RootId = rootId ?? id;
            ParentId = parentId;
            CorrelationId = correlationId ?? id;
            Status = status;
            DispatchCount = dispatchCount;
            RetryOn = retryOn;

            Properties = new Dictionary<string, object>();

            ExceptionFilters = exceptionFilters ?? new ExceptionFilter[0];
            Continuation = continuation;
            Suspended = suspended ?? false;
        }
예제 #21
0
        public async Task <T> CaptureTransaction <T>(string name, string type, Func <Task <T> > func, DistributedTracingData distributedTracingData = null, IEnumerable <SpanLink> links = null)
        {
            var transaction = StartTransaction(name, type, distributedTracingData, links: links);

            try
            {
                return(await func());
            }
            catch (OperationCanceledException ex)
            {
                transaction.CaptureError("Task canceled", "A task was canceled", new StackTrace(ex).GetFrames());

                throw;
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                transaction.End();
            }
            return(default);
        static void DispatchCore(ExceptionFilter filter, Exception exception, JobContext context,
                                 IDependencyScope scope)
        {
            var instance = scope.GetService(filter.Type);

            foreach (var argument in filter.Arguments)
            {
                var exceptionContext = argument as ExceptionContext;
                if (exceptionContext != null)
                {
                    exceptionContext.ActivityType  = context.ActivityType;
                    exceptionContext.Method        = context.Method;
                    exceptionContext.Arguments     = context.Arguments;
                    exceptionContext.Exception     = exception;
                    exceptionContext.DispatchCount = context.DispatchCount;
                }
            }

            var method = filter.Type.GetMethod(filter.Method);

            method.Invoke(instance, filter.Arguments);
        }
예제 #23
0
        public T DeserialiseResponseBody <T>( )
        {
            if (HttpWebResponse == null)
            {
                throw new InvalidOperationException("No web response is available; have you submitted your web request?");
            }

            var stream = HttpWebResponse.GetResponseStream( );

            if (stream == null)
            {
                throw new InvalidOperationException("No web response stream is available; have you submitted your web request?");
            }

            T obj;

            if (!stream.CanSeek || stream.Length > 0)
            {
                var reader           = new StreamReader(stream);
                var responseAsString = reader.ReadToEnd( );
                obj = JSON.Deserialize <T>(responseAsString, Options);

                if (typeof(T) == typeof(HttpError))
                {
                    var existingError = obj as HttpError;

                    if (existingError != null)
                    {
                        obj = ( T )( object )ExceptionFilter.DeserializeHttpError(existingError);
                    }
                }
            }
            else
            {
                obj = default(T);
            }

            return(obj);
        }
예제 #24
0
        public virtual IHttpActionResult Delete(int id)
        {
            HttpResponseMessage response = new HttpResponseMessage();

            try
            {
                BaseService <TEntity> service = new BaseService <TEntity>();

                bool wasDeleted = service.Delete(id);

                if (wasDeleted)
                {
                    response = Request.CreateResponse(HttpStatusCode.NoContent);
                    response.Headers.Add("X-Server-Message", $"{typeof(TEntity).Name} excluido com sucesso.");
                }
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
                response = ExceptionFilter.Find(ref response, ex);
            }

            return(ResponseMessage(response));
        }
예제 #25
0
        public void ShouldReturnSerializedExceptionWhenInDevelopment(Exception exception)
        {
            // Arrange
            var environmentMock = new Mock <IHostingEnvironment>();

            environmentMock
            .Setup(e => e.EnvironmentName)
            .Returns("Development");

            var filter        = new ExceptionFilter(environmentMock.Object);
            var filterContext = FilterContextProvider.GetExceptionContext(exception);

            // Act
            filter.OnException(filterContext);

            // Assert
            filterContext.HttpContext.Response.StatusCode.ShouldBe((int)HttpStatusCode.InternalServerError);

            var result = filterContext.Result as JsonResult;

            result.ShouldNotBeNull();
            result.Value.ShouldBeOfType <Exception>();
            ((Exception)result.Value).Message.ShouldBe(exception.Message);
        }
예제 #26
0
        static void Main(string[] args)
        {
            UsingStatic.Execute();

            NameOf.Execute();

            AutoPropertyInitializer.Execute();

            ExpressionBodiedMember.Execute();

            DictionaryInitializer.Execute();

            ExceptionFilter.Execute();

            PropertyConstructorInitializer.Execute();

            StringInterpolation.Execute();

            AsyncCathFinally.Execute();

            NullConditional.Execute();

            DelegateNull.Execute();
        }
예제 #27
0
        public async Task InvokeAsync(HttpContext context)
        {
            var transaction = _tracer.StartTransactionInternal($"{context.Request.Method} {context.Request.Path}",
                                                               ApiConstants.TypeRequest);

            var url = new Url
            {
                Full     = context.Request?.Path.Value,
                HostName = context.Request.Host.Host,
                Protocol = GetProtocolName(context.Request.Protocol),
                Raw      = context.Request?.Path.Value            //TODO
            };

            Dictionary <string, string> requestHeaders = null;

            if (_configurationReader.CaptureHeaders)
            {
                requestHeaders = new Dictionary <string, string>();

                foreach (var header in context.Request.Headers)
                {
                    requestHeaders.Add(header.Key, header.Value.ToString());
                }
            }

            transaction.Context.Request = new Request(context.Request.Method, url)
            {
                Socket = new Socket
                {
                    Encrypted     = context.Request.IsHttps,
                    RemoteAddress = context.Connection?.RemoteIpAddress?.ToString()
                },
                HttpVersion = GetHttpVersion(context.Request.Protocol),
                Headers     = requestHeaders
            };

            try
            {
                await _next(context);
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                Dictionary <string, string> responseHeaders = null;

                if (_configurationReader.CaptureHeaders)
                {
                    responseHeaders = new Dictionary <string, string>();

                    foreach (var header in context.Response.Headers)
                    {
                        responseHeaders.Add(header.Key, header.Value.ToString());
                    }
                }

                transaction.Result           = $"{GetProtocolName(context.Request.Protocol)} {context.Response.StatusCode.ToString()[0]}xx";
                transaction.Context.Response = new Response
                {
                    Finished   = context.Response.HasStarted,                   //TODO ?
                    StatusCode = context.Response.StatusCode,
                    Headers    = responseHeaders
                };

                transaction.End();
            }
        }
예제 #28
0
        public void SetProxyFactory(IProxyFactory proxyFactory)
        {
            AlternateType<IExceptionFilter> sut = new ExceptionFilter(proxyFactory);

            Assert.Equal(proxyFactory, sut.ProxyFactory);
        }
예제 #29
0
 public ExceptionFilterTests()
 {
     exception = GenerateException();
     logger    = Substitute.For <ILogger>();
     filter    = new ExceptionFilter(logger);
 }
예제 #30
0
        public async Task InvokeAsync(HttpContext context)
        {
            Transaction transaction;

            if (context.Request.Headers.ContainsKey(TraceParent.TraceParentHeaderName))
            {
                var headerValue = context.Request.Headers[TraceParent.TraceParentHeaderName].ToString();

                var distributedTracingData = TraceParent.TryExtractTraceparent(headerValue);
                if (distributedTracingData != null)
                {
                    _logger.Debug()
                    ?.Log(
                        "Incoming request with {TraceParentHeaderName} header. DistributedTracingData: {DistributedTracingData}. Continuing trace.",
                        TraceParent.TraceParentHeaderName, distributedTracingData);

                    transaction = _tracer.StartTransactionInternal(
                        $"{context.Request.Method} {context.Request.Path}",
                        ApiConstants.TypeRequest,
                        distributedTracingData);
                }
                else
                {
                    _logger.Debug()
                    ?.Log(
                        "Incoming request with invalid {TraceParentHeaderName} header (received value: {TraceParentHeaderValue}). Starting trace with new trace id.",
                        TraceParent.TraceParentHeaderName, headerValue);

                    transaction = _tracer.StartTransactionInternal($"{context.Request.Method} {context.Request.Path}",
                                                                   ApiConstants.TypeRequest);
                }
            }
            else
            {
                _logger.Debug()?.Log("Incoming request. Starting Trace.");
                transaction = _tracer.StartTransactionInternal($"{context.Request.Method} {context.Request.Path}",
                                                               ApiConstants.TypeRequest);
            }

            if (transaction.IsSampled)
            {
                FillSampledTransactionContextRequest(context, transaction);
            }

            try
            {
                await _next(context);
            }
            catch (Exception e) when(ExceptionFilter.Capture(e, transaction))
            {
            }
            finally
            {
                //fixup Transaction.Name - e.g. /user/profile/1 -> /user/profile/{id}
                var routeData = (context.Features[typeof(IRoutingFeature)] as IRoutingFeature)?.RouteData;
                if (routeData != null)
                {
                    var name = GetNameFromRouteContext(routeData.Values);

                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        transaction.Name = $"{context.Request.Method} {name}";
                    }
                }

                transaction.Result = Transaction.StatusCodeToResult(GetProtocolName(context.Request.Protocol), context.Response.StatusCode);

                if (transaction.IsSampled)
                {
                    FillSampledTransactionContextResponse(context, transaction);
                    FillSampledTransactionContextUser(context, transaction);
                }

                transaction.End();
            }
        }
        ConvertedActivity ConvertSingleActivityToContinuation(
            SingleActivity singleActivity,
            Job parent,
            ExceptionFilter[] inheritedExceptionFilters)
        {
            var job = new Job(Guid.NewGuid(),
                singleActivity.Type,
                singleActivity.Name,
                singleActivity.Arguments,
                _now(),
                rootId: parent.RootId,
                parentId: parent.Id,
                status: JobStatus.Created,
                exceptionFilters: inheritedExceptionFilters.Concat(singleActivity.ExceptionFilters).ToArray());

            var jobs = new List<Job>(new[] {job});

            var continuation = new Continuation
            {
                Id = job.Id,
                Type = ContinuationType.Single,
                ContinueAfterHandlingFailure = singleActivity.CanContinueAfterHandlingFailure
            };

            var onNext = ConvertCore(singleActivity.Next, parent, inheritedExceptionFilters);
            continuation.Next = onNext.Continuation;
            jobs.AddRange(onNext.Jobs);

            var onFailed = ConvertCore(singleActivity.OnFailed, parent, inheritedExceptionFilters);
            continuation.OnAllFailed = onFailed.Continuation;
            jobs.AddRange(onFailed.Jobs);

            var onCancel = ConvertCore(singleActivity.OnCancel, parent, inheritedExceptionFilters);
            if (onCancel.Continuation != null)
                onCancel.Continuation.CompensateForCancellation = true;
            continuation.OnCancelled = onCancel.Continuation;
            jobs.AddRange(onCancel.Jobs);

            return new ConvertedActivity(continuation, jobs.AsEnumerable());
        }
예제 #32
0
        public void ReturnOneMethod(IProxyFactory proxyFactory)
        {
            AlternateType<IExceptionFilter> sut = new ExceptionFilter(proxyFactory);

            Assert.Equal(1, sut.AllMethods.Count());
        }
예제 #33
0
 public void SetUp()
 {
     exception = GenerateException();
     logger    = Substitute.For <ILogger>();
     filter    = new ExceptionFilter(logger);
 }
 public ExceptionFilterTests()
 {
     _exceptionLoggerMock = new Mock <IExceptionLogger>();
     _filter = new ExceptionFilter(_exceptionLoggerMock.Object);
 }
예제 #35
0
        public void CreatesAPlaceholderForExceptionContext()
        {
            var handler = ExceptionFilter.From <ExceptionFilterForMethodFacts>((c, h) => h.Log(c));

            Assert.IsType <ExceptionContext>(handler.Arguments[0]);
        }
예제 #36
0
        // todo: directives
        public static async Task <IEnumerable <FieldSelection> > CollectFields(
            VariableValues variableValues,
            IDictionary <string, InputType> variableTypes,
            GraphQLObject gqlObject,
            IEnumerable <Selection> selectionSet,
            IEnumerable <FragmentDefinition> fragments,
            List <GraphQLError> errors,
            ILogger logger,
            ExceptionFilter exceptionFilter,
            CancellationToken token)
        {
            var result = new List <FieldSelection>();

            foreach (var selection in selectionSet)
            {
                switch (selection)
                {
                case Ast.Field field:
                {
                    IValueAccessor valueAccessor;
                    var            selectionFieldSelectionSet = Enumerable.Empty <FieldSelection>();

                    if (!gqlObject.Fields.TryGetValue(field.Name, out var objectField))
                    {
                        valueAccessor = new NullValueAccessor();

                        errors.Add(new GraphQLError(
                                       $"Invalid field '{field.Name}' specified on '{gqlObject.GetTypeName()}'.",
                                       new[] { field.Location }));
                    }
                    else
                    {
                        var fieldArguments = field.Arguments ?? Enumerable.Empty <Argument>();

                        if (!ValidateArguments(variableTypes, gqlObject, errors, objectField, fieldArguments))
                        {
                            valueAccessor = new NullValueAccessor();
                        }
                        else
                        {
                            var astFieldArguments = fieldArguments
                                                    .ToDictionary(x => x.Name);
                            var argumentValues = new Dictionary <string, object>();
                            var hasErrors      = false;

                            foreach (var argument in objectField.Arguments)
                            {
                                var hasArgument = astFieldArguments.TryGetValue(argument.Key, out var argumentValue);
                                var value       = hasArgument
                                            ? argumentValue.Value.GetValue(variableValues)
                                            : new Optional();
                                var variable = argumentValue?.Value as Variable;

                                var preamble = variable != null
                                            ? $"Variable '${variable.Name}'"
                                            : $"Argument '{argument.Key}'";

                                var locations = new List <GraphQLLocation>();

                                if (variable != null)
                                {
                                    locations.Add(variable.Location);
                                }
                                if (hasArgument)
                                {
                                    locations.Add(argumentValue.Location);
                                }

                                // need to be able to get a type adapter from an AST node

                                //var target = variable != null
                                //    ? new BoundGraphQLTypeAdapter(null, variableTypes[variable.Name].GetTypeAdapter())
                                //    : argument.Value;

                                var target = argument.Value;

                                var coercionResult = target.CoerceInput(argument.Key, value.Value);

                                if (coercionResult.Errors != null && coercionResult.Errors.Any())
                                {
                                    errors.AddRange(coercionResult.Errors
                                                    .Select(x => new GraphQLError(
                                                                $"{preamble} expected value of type '{argument.Value.GetTypeDescription()}' but got: {value}. {x}",
                                                                locations,
                                                                null,
                                                                new Dictionary <string, object>
                                        {
                                            {
                                                "InputError",
                                                new
                                                {
                                                    Input  = x.Name,
                                                    Reason = "Coercion",
                                                }
                                            },
                                        }))
                                                    .ToList()
                                                    );

                                    hasErrors = true;
                                }
                                else
                                {
                                    argumentValues.Add(argument.Key, coercionResult.Value);
                                }
                            }

                            if (hasErrors)
                            {
                                valueAccessor = new NullValueAccessor();
                            }
                            else
                            {
                                try
                                {
                                    valueAccessor = await objectField.Resolve(argumentValues, token);

                                    selectionFieldSelectionSet = valueAccessor.GraphQLType.Unwrap() is GraphQLObject graphQLObject
                                                ? await CollectFields(
                                        variableValues,
                                        variableTypes,
                                        graphQLObject,
                                        field.SelectionSet,
                                        fragments,
                                        errors,
                                        logger,
                                        exceptionFilter,
                                        token)
                                                : null;
                                }
                                catch (GraphQLException ex)
                                {
                                    errors.AddRange(ex.Errors);

                                    valueAccessor = new NullValueAccessor();
                                }
                                catch (Exception ex)
                                {
                                    if (ex is TargetInvocationException || ex is AggregateException)
                                    {
                                        ex = ex.InnerException ?? ex;
                                    }

                                    if (ex is GraphQLException gex)
                                    {
                                        errors.AddRange(gex.Errors);
                                    }
                                    else
                                    {
                                        if (exceptionFilter != null && await exceptionFilter.HandleExceptionAsync(ex))
                                        {
                                            throw;
                                        }

                                        if (logger != null)
                                        {
                                            logger.LogError(ex, "Error resolving field in FieldCollector");
                                        }

                                        errors.Add(new GraphQLError(
                                                       "Internal server error",
                                                       null,
                                                       null,
                                                       null));
                                    }

                                    valueAccessor = new NullValueAccessor();
                                }
                            }

                            var fieldSelection = new FieldSelection(
                                field.Name,
                                field.Alias,
                                field.Arguments,
                                field.Directives,
                                selectionFieldSelectionSet,
                                objectField,
                                field.Location,
                                valueAccessor
                                );

                            var index = result
                                        .FindIndex(x => x.Alias == field.Alias && x.Name == field.Name);

                            if (index >= 0)
                            {
                                result[index] = result[index].MergeWith(fieldSelection);
                            }
                            else
                            {
                                result.Add(fieldSelection);
                            }
                        }
                    }
                }

                break;

                case FragmentSpread fragmentSpread:
                {
                    var fragment = fragments
                                   .Where(x => x.FragmentName == fragmentSpread.FragmentName)
                                   .FirstOrDefault() ?? throw new InvalidOperationException("Invalid fragment");

                    if (fragment.TypeCondition == gqlObject.GetTypeName())
                    {
                        var fields = await CollectFields(
                            variableValues,
                            variableTypes,
                            gqlObject,
                            fragment.SelectionSet,
                            fragments,
                            errors,
                            logger,
                            exceptionFilter,
                            token
                            );

                        foreach (var field in fields)
                        {
                            var index = result
                                        .FindIndex(x => x.Alias == field.Alias && x.Name == field.Name);

                            if (index >= 0)
                            {
                                result[index] = result[index].MergeWith(field);
                            }
                            else
                            {
                                result.Add(field);
                            }
                        }
                    }
                }

                break;

                case InlineFragment inlineFragment:
                {
                    if (inlineFragment.TypeCondition == gqlObject.GetTypeName())
                    {
                        var fields = await CollectFields(
                            variableValues,
                            variableTypes,
                            gqlObject,
                            inlineFragment.SelectionSet,
                            fragments,
                            errors,
                            logger,
                            exceptionFilter,
                            token
                            );

                        foreach (var field in fields)
                        {
                            var index = result
                                        .FindIndex(x => x.Alias == field.Alias && x.Name == field.Name);

                            if (index >= 0)
                            {
                                result[index] = result[index].MergeWith(field);
                            }
                            else
                            {
                                result.Add(field);
                            }
                        }
                    }
                }

                break;
                }
            }

            return(result);
        }