| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Runtime;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Diagnostics.Application;
- class ErrorBehavior
- {
- IErrorHandler[] handlers;
- bool debug;
- bool isOnServer;
- MessageVersion messageVersion;
- internal ErrorBehavior(ChannelDispatcher channelDispatcher)
- {
- this.handlers = EmptyArray<IErrorHandler>.ToArray(channelDispatcher.ErrorHandlers);
- this.debug = channelDispatcher.IncludeExceptionDetailInFaults;
- this.isOnServer = channelDispatcher.IsOnServer;
- this.messageVersion = channelDispatcher.MessageVersion;
- }
- void InitializeFault(ref MessageRpc rpc)
- {
- Exception error = rpc.Error;
- FaultException fault = error as FaultException;
- if (fault != null)
- {
- string action;
- MessageFault messageFault = rpc.Operation.FaultFormatter.Serialize(fault, out action);
- if (action == null)
- action = rpc.RequestVersion.Addressing.DefaultFaultAction;
- if (messageFault != null)
- rpc.FaultInfo.Fault = Message.CreateMessage(rpc.RequestVersion, messageFault, action);
- }
- }
- internal IErrorHandler[] Handlers
- {
- get
- {
- return handlers;
- }
- }
- internal void ProvideMessageFault(ref MessageRpc rpc)
- {
- if (rpc.Error != null)
- {
- ProvideMessageFaultCore(ref rpc);
- }
- }
- void ProvideMessageFaultCore(ref MessageRpc rpc)
- {
- if (this.messageVersion != rpc.RequestVersion)
- {
- Fx.Assert("System.ServiceModel.Dispatcher.ErrorBehavior.ProvideMessageFaultCore(): (this.messageVersion != rpc.RequestVersion)");
- }
- this.InitializeFault(ref rpc);
- this.ProvideFault(rpc.Error, rpc.Channel.GetProperty<FaultConverter>(), ref rpc.FaultInfo);
- this.ProvideMessageFaultCoreCoda(ref rpc);
- }
- void ProvideFaultOfLastResort(Exception error, ref ErrorHandlerFaultInfo faultInfo)
- {
- if (faultInfo.Fault == null)
- {
- FaultCode code = new FaultCode(FaultCodeConstants.Codes.InternalServiceFault, FaultCodeConstants.Namespaces.NetDispatch);
- code = FaultCode.CreateReceiverFaultCode(code);
- string action = FaultCodeConstants.Actions.NetDispatcher;
- MessageFault fault;
- if (this.debug)
- {
- faultInfo.DefaultFaultAction = action;
- fault = MessageFault.CreateFault(code, new FaultReason(error.Message), new ExceptionDetail(error));
- }
- else
- {
- string reason = this.isOnServer ? SR.GetString(SR.SFxInternalServerError) : SR.GetString(SR.SFxInternalCallbackError);
- fault = MessageFault.CreateFault(code, new FaultReason(reason));
- }
- faultInfo.IsConsideredUnhandled = true;
- faultInfo.Fault = Message.CreateMessage(this.messageVersion, fault, action);
- }
- //if this is an InternalServiceFault coming from another service dispatcher we should treat it as unhandled so that the channels are cleaned up
- else if (error != null)
- {
- FaultException e = error as FaultException;
- if (e != null && e.Fault != null && e.Fault.Code != null && e.Fault.Code.SubCode != null &&
- string.Compare(e.Fault.Code.SubCode.Namespace, FaultCodeConstants.Namespaces.NetDispatch, StringComparison.Ordinal) == 0 &&
- string.Compare(e.Fault.Code.SubCode.Name, FaultCodeConstants.Codes.InternalServiceFault, StringComparison.Ordinal) == 0)
- {
- faultInfo.IsConsideredUnhandled = true;
- }
- }
- }
- void ProvideMessageFaultCoreCoda(ref MessageRpc rpc)
- {
- if (rpc.FaultInfo.Fault.Headers.Action == null)
- {
- rpc.FaultInfo.Fault.Headers.Action = rpc.RequestVersion.Addressing.DefaultFaultAction;
- }
- rpc.Reply = rpc.FaultInfo.Fault;
- }
- internal void ProvideOnlyFaultOfLastResort(ref MessageRpc rpc)
- {
- this.ProvideFaultOfLastResort(rpc.Error, ref rpc.FaultInfo);
- this.ProvideMessageFaultCoreCoda(ref rpc);
- }
- internal void ProvideFault(Exception e, FaultConverter faultConverter, ref ErrorHandlerFaultInfo faultInfo)
- {
- ProvideWellKnownFault(e, faultConverter, ref faultInfo);
- for (int i = 0; i < this.handlers.Length; i++)
- {
- Message m = faultInfo.Fault;
- handlers[i].ProvideFault(e, this.messageVersion, ref m);
- faultInfo.Fault = m;
- if (TD.FaultProviderInvokedIsEnabled())
- {
- TD.FaultProviderInvoked(handlers[i].GetType().FullName, e.Message);
- }
- }
- this.ProvideFaultOfLastResort(e, ref faultInfo);
- }
- void ProvideWellKnownFault(Exception e, FaultConverter faultConverter, ref ErrorHandlerFaultInfo faultInfo)
- {
- Message faultMessage;
- if (faultConverter != null && faultConverter.TryCreateFaultMessage(e, out faultMessage))
- {
- faultInfo.Fault = faultMessage;
- return;
- }
- else if (e is NetDispatcherFaultException)
- {
- NetDispatcherFaultException ndfe = e as NetDispatcherFaultException;
- if (this.debug)
- {
- ExceptionDetail detail = new ExceptionDetail(ndfe);
- faultInfo.Fault = Message.CreateMessage(this.messageVersion, MessageFault.CreateFault(ndfe.Code, ndfe.Reason, detail), ndfe.Action);
- }
- else
- {
- faultInfo.Fault = Message.CreateMessage(this.messageVersion, ndfe.CreateMessageFault(), ndfe.Action);
- }
- }
- }
- internal void HandleError(ref MessageRpc rpc)
- {
- if (rpc.Error != null)
- {
- HandleErrorCore(ref rpc);
- }
- }
- void HandleErrorCore(ref MessageRpc rpc)
- {
- bool handled = HandleErrorCommon(rpc.Error, ref rpc.FaultInfo);
- if (handled)
- {
- rpc.Error = null;
- }
- }
- bool HandleErrorCommon(Exception error, ref ErrorHandlerFaultInfo faultInfo)
- {
- bool handled;
- if (faultInfo.Fault != null // there is a message
- && !faultInfo.IsConsideredUnhandled) // and it's not the internal-server-error one
- {
- handled = true;
- }
- else
- {
- handled = false;
- }
- try
- {
- if (TD.ServiceExceptionIsEnabled())
- {
- TD.ServiceException(null, error.ToString(), error.GetType().FullName);
- }
- for (int i = 0; i < this.handlers.Length; i++)
- {
- bool handledByThis = handlers[i].HandleError(error);
- handled = handledByThis || handled;
- if (TD.ErrorHandlerInvokedIsEnabled())
- {
- TD.ErrorHandlerInvoked(handlers[i].GetType().FullName, handledByThis, error.GetType().FullName);
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- return handled;
- }
- internal bool HandleError(Exception error)
- {
- ErrorHandlerFaultInfo faultInfo = new ErrorHandlerFaultInfo(this.messageVersion.Addressing.DefaultFaultAction);
- return HandleError(error, ref faultInfo);
- }
- internal bool HandleError(Exception error, ref ErrorHandlerFaultInfo faultInfo)
- {
- return HandleErrorCommon(error, ref faultInfo);
- }
- internal static bool ShouldRethrowExceptionAsIs(Exception e)
- {
- return true;
- }
- internal static bool ShouldRethrowClientSideExceptionAsIs(Exception e)
- {
- return true;
- }
- // This ensures that people debugging first-chance Exceptions see this Exception,
- // and that the Exception shows up in the trace logs.
- internal static void ThrowAndCatch(Exception e, Message message)
- {
- try
- {
- if (System.Diagnostics.Debugger.IsAttached)
- {
- if (message == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
- }
- else
- {
- throw TraceUtility.ThrowHelperError(e, message);
- }
- }
- else
- {
- if (message == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
- }
- else
- {
- TraceUtility.ThrowHelperError(e, message);
- }
- }
- }
- catch (Exception e2)
- {
- if (!object.ReferenceEquals(e, e2))
- {
- throw;
- }
- }
- }
- internal static void ThrowAndCatch(Exception e)
- {
- ThrowAndCatch(e, null);
- }
- }
- }
|