There are several ways to handle WCF exceptions:
The first is to set Includeexceptiondetailinfaults to true in the configuration file
<behavior name= "Servicedebubehavior" ><servicedebug includeexceptiondetailinfaults= "true"/></ Behavior>
However, this approach can lead to the risk of sensitive information leaks, generally we only open the property when debugging, if it has been released, for security, we will generally set to false.
The second method is to customize the error, specifying the error message directly through FaultException.
[ServiceBehavior (Includeexceptiondetailinfaults = True)]
public class Calculatorservice:icalculator
{
throw new FaultException ("Dividend y cannot be zero!");
}
But then we must also explicitly throw an exception for the WCF method, if it can be like. NET, in global directly catch the global exception, and write log4net log how good, there is no way in WCF if an exception, the Exception log write to the server is broken, and throw to the client?
It takes three steps to achieve this.
Step one: We need to implement the Ierrorhandler interface to implement his two methods
BOOL HandleError (Exception error); void Providefault (Exception error, messageversion version, ref Message fault);
Where HandleError is true indicates that the current session is terminated
In the Providefault method we can write a custom error that we want to throw to the client, and we can write the exception Log on the server side.
We implement a Globalexceptionhandler, inherited from Ierrorhandler, while in Providefault through the log4net write server-side logs, as follows:
Namespace Wcfservice
{using System; Using System.ServiceModel; Using System.ServiceModel.Channels; Using System.ServiceModel.Dispatcher;
//<summary> //Globalexceptionhandler //</ Summary> public class Globalexceptionhandler:ierrorhandler { & nbsp; //<summary> //test log4net //</summary> private static ReadOnly log4net. ILog log = log4net. Logmanager.getlogger (typeof (Globalexceptionhandler));
#region Ierrorhandler members //<summary> //HandleError //</summary> //<param name= "ex" >ex</param > //<returns>true</returns> public bool HandleError (Exception ex) { return true; }
//<summary> // Providefault ///</summary> //<param name= "ex" >ex</param> //<param name= " Version ">version</param> //<param name=" MSG ">msg</ param> public void Providefault (Exception ex, messageversion version, Ref Message msg) { ////write log4net log. Error ("WCF exception", ex); var Newex = new FaultException (string. Format ("WCF interface error {0}", ex.) Targetsite.name)); Messagefault Msgfault = Newex.createmessagefault (); msg = message.createmessage (version, Msgfault, Newex.action); } #endregion }}
Step two: Now we need to create a custom service behaviour Attribute, and let WCF know that when any exception to WCF happens, we handle it through this custom Attribute. To implement this requires inheriting the IServiceBehavior interface, and in this class of constructors, we get the error type.
Once the applydispatchbehavior behavior is invoked, we create the error handler through Activator.CreateInstance and add the error to each channeldispatcher.
ApplyDispatchBehavior
ChannelDispatcher Chinese is called the Channel dispatcher, and when our ServiceHost calls the Open method, WCF creates our multiple channel distributors (ChannelDispatcher), Each channeldispatcher will have a channel listener (Channellistener), Channellistener has been on the fixed port listening, wait until the arrival of the message, Call the Acceptchannel build channel to form a channel stack and begin processing the message.
Using system;using system.collections.objectmodel;using system.servicemodel;using System.ServiceModel.Channels; Using system.servicemodel.description;using System.ServiceModel.Dispatcher; Namespace wcfservice{public class Globalexceptionhandlerbehaviourattribute:attribute, IServiceBehavior {p Rivate readonly Type _errorhandlertype; Public Globalexceptionhandlerbehaviourattribute (Type errorhandlertype) {_errorhandlertype = Errorhandle Rtype; } #region IServiceBehavior members public void Validate (servicedescription description, ServiceHostBase servicehostbase) {} public void Addbindingparameters (ServiceDescription D Escription, ServiceHostBase ServiceHostBase, collection<serviceendpoint> Endpoints, BindingParameterCollection Paramet ERS) { } public void ApplyDispatchBehavior (servicedescription description, Ser Vicehostbase servicehostbase) {var handler = (Ierrorhandler) activator.createinstance (_e Rrorhandlertype); foreach (Channeldispatcherbase dispatcherbase in servicehostbase.channeldispatchers) { var channeldispatcher = dispatcherbase as ChannelDispatcher; if (ChannelDispatcher! = null) CHANNELDISPATCHER.ERRORHANDLERS.ADD (handler); }} #endregion}}
Step three: On our WCF class, add Globalexceptionhandlerbehaviour
Using System; namespace wcfservice{ [Globalexceptionhandlerbehaviour (typeof (Globalexceptionhandler))] public class Someservice:isomeservice { #region Isomeservice members public string somefailingoperation () { throw new Exception ("Kaboom"); return null; } #endregion }}
Handling WCF global exceptions with attribute and Ierrorhandler