WCF服务编程读书笔记(6):错误
Example 6-1. The FaultException<T> class
using System;
using System.Runtime;
using System.Runtime.Serialization;
using System.Security;
using System.ServiceModel.Channels;
namespace System.ServiceModel
{
[Serializable] // More attributes
public class FaultException : CommunicationException
{
public FaultException( );
public FaultException( string reason);
public FaultException(FaultReason reason);
public virtual MessageFault CreateMessageFault( );
// More members
}
[Serializable]
public class FaultException<T> : FaultException
{
public FaultException(T detail);
public FaultException(T detail, string reason);
public FaultException(T detail,FaultReason reason);
// More members
}
}
View Code
Example 6-2. Throwing a FaultException<T>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCFServiceProgramming.Library
{
[ServiceContract]
interface ICalculator
{
[OperationContract]
double Divide( double number1, double number2);
// More methods
}
class Calculator : ICalculator
{
public double Divide( double number1, double number2)
{
if (number2 == 0 )
{
DivideByZeroException exception = new DivideByZeroException();
throw new FaultException<DivideByZeroException> (exception);
}
return number1 / number2;
}
// Rest of the implementation
}
}
View Code
Example 6-3. Defining a fault contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCFServiceProgramming.Library
{
[ServiceContract]
interface ICalculator
{
[OperationContract]
double Add( double number1, double number2);
[OperationContract]
[FaultContract( typeof (DivideByZeroException))]
double Divide( double number1, double number2);
// More methods
}
}
View Code
Example 6-4. Including the service exception in the fault message
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace WCFServiceProgramming.Library
{
[ServiceContract]
public interface IMyContract
{
[OperationContract]
void MethodWithError();
}
class MyService : IMyContract
{
public void MethodWithError()
{
InvalidOperationException exception = new InvalidOperationException( " Some error " );
ExceptionDetail detail = new ExceptionDetail(exception);
throw new FaultException<ExceptionDetail> (detail, exception.Message);
}
}
}
View Code
Example 6-5. Processing the included exception
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Runtime.Serialization;
using WCFServiceProgramming.Library;
using System.Diagnostics;
namespace WCFServiceProgramming.Client
{
class MyContractClient : ClientBase<IMyContract> , IMyContract
{
public void MethodWithError()
{
Channel.MethodWithError();
}
}
class Program
{
static void Main( string [] args)
{
MyContractClient proxy = new MyContractClient();
try
{
proxy.MethodWithError();
}
catch (FaultException<ExceptionDetail> exception)
{
Debug.Assert(exception.Detail.Type == typeof (InvalidOperationException).ToString());
Debug.Assert(exception.Message == " Some error " );
}
}
}
}
View Code
Example 6-6. SettingIncludeExceptionDetailInFaults to true in debug only
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace WCFServiceProgramming.Library
{
[ServiceContract]
public interface IMyContract
{
[OperationContract]
void MethodWithError();
}
public static class DebugHelper
{
public const bool IncludeExceptionDetailInFaults =
#if DEBUG
true ;
#else
false ;
#endif
}
[ServiceBehavior(IncludeExceptionDetailInFaults = DebugHelper.IncludeExceptionDetailInFaults)]
class MyService : IMyContract
{
public void MethodWithError()
{
InvalidOperationException exception = new InvalidOperationException( " Some error " );
ExceptionDetail detail = new ExceptionDetail(exception);
throw new FaultException<ExceptionDetail> (detail, exception.Message);
}
}
}
View Code
Example 6-7. ServiceHost<T> and returning unknown exceptions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Diagnostics;
using System.ServiceModel.Channels;
namespace WCFServiceProgramming.Host
{
public class ServiceHost<T> : ServiceHost
{
public bool IncludeExceptionDetailInFaults
{
set
{
if (State == CommunicationState.Opened)
{
throw new InvalidOperationException( " Host is already opened " );
}
ServiceBehaviorAttribute debuggingBehavior =
Description.Behaviors.Find <ServiceBehaviorAttribute> ();
debuggingBehavior.IncludeExceptionDetailInFaults = value;
}
get
{
ServiceBehaviorAttribute debuggingBehavior =
Description.Behaviors.Find <ServiceBehaviorAttribute> ();
return debuggingBehavior.IncludeExceptionDetailInFaults;
}
}
}
}
View Code
Example 6-8. Administratively including exceptions in the fault message
<? xml version="1.0" encoding="utf-8" ?>
< configuration >
< system.serviceModel >
< services >
< service name ="MyService" behaviorConfiguration ="Debugging" >
</ service >
</ services >
< behaviors >
< serviceBehaviors >
< behavior name ="Debugging" >
< serviceDebug includeExceptionDetailInFaults ="true" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
</ system.serviceModel >
</ configuration >
View Code
Example 6-9. Callback contract with fault contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace WCFServiceProgramming.Library
{
[ServiceContract(CallbackContract = typeof (IMyContractCallback))]
public interface IMyContract
{
[OperationContract]
void DoSomething();
}
interface IMyContractCallback
{
[OperationContract]
[FaultContract( typeof (InvalidOperationException))]
void OnCallback();
}
}
View Code
Example 6-10. Fault handling in out-of-band invocation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace WCFServiceProgramming.Library
{
[ServiceContract(CallbackContract = typeof (IMyContractCallback))]
public interface IMyContract
{
[OperationContract]
void DoSomething();
}
interface IMyContractCallback
{
[OperationContract]
[FaultContract( typeof (InvalidOperationException))]
void OnCallback();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class MyService : IMyContract
{
static List<IMyContractCallback> m_Callbacks =
new List<IMyContractCallback> ();
public void DoSomething()
{
IMyContractCallback callback =
OperationContext.Current.GetCallbackChannel <IMyContractCallback> ();
if (m_Callbacks.Contains(callback) == false )
{
m_Callbacks.Add(callback);
}
}
public static void CallClients()
{
Action <IMyContractCallback> invoke = delegate (IMyContractCallback callback)
{
try
{
callback.OnCallback();
}
catch (FaultException<InvalidOperationException> exception)
{ }
catch (FaultException exception)
{ }
catch (CommunicationException exception)
{ }
};
m_Callbacks.ForEach(invoke);
}
}
}
View Code
Example 6-11. Creating an alternative fault
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace WCFServiceProgramming
{
class MyErrorHandler : IErrorHandler
{
#region IErrorHandler Members
public bool HandleError(Exception error)
{
// ...
return true ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
FaultException < int > faultException = new FaultException< int >( 3 );
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
#endregion
}
}
View Code
Example 6-12. Exception promotion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace WCFServiceProgramming
{
class MyErrorHandler : IErrorHandler
{
#region IErrorHandler Members
public bool HandleError(Exception error)
{
// ...
return true ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
FaultException <InvalidOperationException> faultException =
new FaultException<InvalidOperationException>( new InvalidOperationException(error.Message));
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
#endregion
}
}
View Code
Example 6-13. Logging the error log to a logbook service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
using WCFServiceProgramming.Library;
namespace WCFServiceProgramming
{
class MyContractClient : ClientBase<IMyContract> , IMyContract
{
public void DoSomething()
{
Channel.DoSomething();
}
}
class MyErrorHandler : IErrorHandler
{
#region IErrorHandler Members
public bool HandleError(Exception error)
{
try
{
MyContractClient proxy = new MyContractClient();
proxy.DoSomething();
proxy.Close();
}
catch
{ }
return false ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
#endregion
}
}
View Code
Example 6-14. Adding an error extension object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
namespace WCFServiceProgramming.Library
{
class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
}
public interface IMyContract
{
[OperationContract]
void DoSomething();
}
class MyService : IMyContract, IServiceBehavior
{
#region IMyContract Members
public void DoSomething()
{
}
#endregion
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase host)
{
IErrorHandler handler = new MyErrorHandler();
foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(handler);
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
}
}
View Code
Example 6-15. Supporting IErrorHandler by the service class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
namespace WCFServiceProgramming.Library
{
class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
}
public interface IMyContract
{
[OperationContract]
void DoSomething();
}
class MyService : IMyContract, IServiceBehavior, IErrorHandler
{
#region IMyContract Members
public void DoSomething()
{
}
#endregion
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase host)
{
foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add( this );
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
#region IErrorHandler Members
public bool HandleError(Exception error)
{
return false ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
#endregion
}
}
View Code
Example 6-16. The ErrorHandlerBehavior attribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
namespace WCFServiceProgramming.Library
{
public class ErrorHandlerBehaviorAttribute : Attribute, IServiceBehavior, IErrorHandler
{
protected Type ServiceType
{
get ;
set ;
}
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription description, ServiceHostBase host,
Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase host)
{
ServiceType = description.ServiceType;
foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add( this );
}
}
public void Validate(ServiceDescription description, ServiceHostBase host)
{
}
#endregion
#region IErrorHandler Members
public bool HandleError(Exception error)
{
return false ;
}
public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
{
}
#endregion
}
}
View Code
Example 6-17. Implementing AddErrorHandler( )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Diagnostics;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Collections.ObjectModel;
using WCFServiceProgramming.Library;
namespace WCFServiceProgramming.Host
{
public class ServiceHost<T> : ServiceHost
{
class ErrorHandlerBehavior : IServiceBehavior, IErrorHandler
{
IErrorHandler m_ErrorHandler;
public ErrorHandlerBehavior(IErrorHandler errorHandler)
{
m_ErrorHandler = errorHandler;
}
#region IErrorHandler Members
public bool HandleError(Exception error)
{
return false ;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
#endregion
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription description, ServiceHostBase host,
Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase host)
{
foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add( this );
}
}
public void Validate(ServiceDescription description, ServiceHostBase host)
{
}
#endregion
}
List <IServiceBehavior> m_ErrorHandlers = new List<IServiceBehavior> ();
public void AddErrorHandler(IErrorHandler errorHandler)
{
if (State == CommunicationState.Opened)
{
throw new InvalidOperationException( " Host is already opened " );
}
IServiceBehavior errorHandlerBehavior = new ErrorHandlerBehavior(errorHandler);
m_ErrorHandlers.Add(errorHandlerBehavior);
}
public void AddErrorHandler()
{
if (State == CommunicationState.Opened)
{
throw new InvalidOperationException( " Host is already opened " );
}
IServiceBehavior errorHandlerBehavior = new ErrorHandlerBehaviorAttribute();
m_ErrorHandlers.Add(errorHandlerBehavior);
}
protected override void OnOpening()
{
foreach (IServiceBehavior behavior in m_ErrorHandlers)
{
Description.Behaviors.Add(behavior);
}
base .OnOpening();
}
// Rest of the implementation
}
}
View Code
Example 6-18. Implementing IEndpointBehavior
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WCFServiceProgramming.Library;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
namespace WCFServiceProgramming
{
class MyClient : IMyContractCallback, IEndpointBehavior
{
#region IMyContractCallback Members
public void OnCallback()
{
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime behavior)
{
IErrorHandler handler = new MyErrorHandler();
behavior.CallbackDispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(handler);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher dispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
}
}
View Code
Example 6-19. Implementing CallbackErrorHandlerBehavior attribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
namespace WCFServiceProgramming.Library
{
public class CallbackErrorHandlerBehaviorAttribute :
ErrorHandlerBehaviorAttribute, IEndpointBehavior
{
public CallbackErrorHandlerBehaviorAttribute(Type clientType)
{
ServiceType = clientType;
}
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime behavior)
{
behavior.CallbackDispatchRuntime.ChannelDispatcher.ErrorHandlers.Add( this );
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher dispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
}
}
View Code
查看更多关于WCF服务编程读书笔记(6):错误的详细内容...