Beispiel #1
0
 /// <summary>
 /// Apply operation behavior
 /// </summary>
 public void ApplyOperationBehavior(EndpointOperation operation, OperationDispatcher dispatcher)
 {
     dispatcher.DispatchFormatter = RestMessageDispatchFormatter.CreateFormatter(operation.Description.Contract.Type);
 }
        /// <summary>
        /// Provide the fault
        /// </summary>
        /// <param name="error"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public bool ProvideFault(Exception error, RestResponseMessage faultMessage)
        {
            try
            {
#if DEBUG
                this.m_tracer.TraceWarning("Error on pipeline: {0}", error);
#else
                if (error is TargetInvocationException tie)
                {
                    this.m_tracer.TraceWarning("{0} - {1} / {2}", RestOperationContext.Current?.EndpointOperation?.Description?.InvokeMethod?.Name, error.Message, error.InnerException?.Message);
                }
                else
                {
                    this.m_tracer.TraceWarning("{0} - {1}", RestOperationContext.Current?.EndpointOperation?.Description?.InvokeMethod?.Name, error.Message);
                }
#endif

                if (faultMessage == null)
                {
                    if (RestOperationContext.Current.OutgoingResponse == null)
                    {
                        this.m_tracer.TraceWarning("Client hangup");
                        return(false);
                    }
                    this.m_tracer.TraceWarning("For some reason the fault message is null - ");
                    faultMessage = new RestResponseMessage(RestOperationContext.Current.OutgoingResponse);
                }
                var ie = error;
                while (ie != null)
                {
                    this.m_tracer.TraceWarning("{0} - ({1}){2} - {3}", error == ie ? "" : "Caused By",
                                               RestOperationContext.Current.EndpointOperation?.Description.InvokeMethod.Name,
                                               ie?.GetType().FullName, ie.Message);

                    // TODO: Do we need this or can we just capture the innermost exception as the cause?
                    if (ie is RestClientException <RestServiceFault> || ie is SecurityException || ie is DetectedIssueException ||
                        ie is FileNotFoundException || ie is KeyNotFoundException)
                    {
                        error = ie;
                    }
                    ie = ie.InnerException;
                }
                faultMessage.StatusCode = WebErrorUtility.ClassifyException(error);

                object fault = (error as RestClientException <RestServiceFault>)?.Result ?? new RestServiceFault(error);

                if (error is FaultException && error?.GetType() != typeof(FaultException)) // Special classification
                {
                    fault = error?.GetType().GetRuntimeProperty("Body").GetValue(error);
                }

                var formatter = RestMessageDispatchFormatter.CreateFormatter(RestOperationContext.Current.ServiceEndpoint.Description.Contract.Type);
                if (formatter != null)
                {
                    formatter.SerializeResponse(faultMessage, null, fault);
                }
                else
                {
                    RestOperationContext.Current.OutgoingResponse.OutputStream.Write(System.Text.Encoding.UTF8.GetBytes(error.Message), 0, System.Text.Encoding.UTF8.GetByteCount(error.Message));
                }

                try
                {
                    if (ApplicationServiceContext.Current.GetService <IOperatingSystemInfoService>()?.OperatingSystem != OperatingSystemID.Android)
                    {
                        AuditUtil.AuditNetworkRequestFailure(error, RestOperationContext.Current.IncomingRequest.Url, RestOperationContext.Current.IncomingRequest.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.IncomingRequest.Headers[o]), RestOperationContext.Current.OutgoingResponse.Headers.AllKeys.ToDictionary(o => o, o => RestOperationContext.Current.OutgoingResponse.Headers[o]));
                    }
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Could not send network request failure - {0}", e);
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error providing fault: {0}", e);
            }
            return(true);
        }