Credo di poter affermare che l’approccio all’uso di Wcf è fatto da due fasi fondamentali:
  • “Neonatale”: lo sviluppatore utilizza WCF limitandosi ai template di progetto offerti da Visual Studio e ai proxy prodotti da Visual Studio/svcutil.exe;
  • “Curiosa”: se lo sviluppatore è passato attraverso Web Services e in particolare attraverso WSE comincia a farsi tante domande sul perchè Wcf (e in particolare la sua infrastruttura) sia così apparentemente (e non solo apparentemente) complesso(a)….
L’altra cosa che si scopre molto rapidamente è che Wcf è una brutta bestia… veramente una brutta bestia caratterizzata da due cose che stanno agli antipodi:
  • uno degli aspetti positivi, “più” positivi, è la ab-norme (cit.) possibilità di customizzazione e la capillarità della customizzazione;
  • uno degli aspetti negativi che resta, anche nella versione 4.0, il vero tallone d’achille è la gestione della configurazione: quello che manca fondamentalmente è un tool degno del suo nome che permetta di gestire le infinite possibbilità di configurazione e l’infinita complessità a cui la configurazione può tendere;
Man mano che cominciate a customizzare Wcf e quindi a manipolare la configurazione cominciate sempre più spesso a csontrarvi con gli errori più assurdi, e meno parlanti, della storia della programmazione… il vero problema è che spessissimo è anche impossibile piazzare il fatidico breakpoint perchè l’errore si verifica ben prima che il flusso del codice arrivi al vostro codice; ecco che nasce quindi la necessità di poter intercettare tutti gli errori che avvengono all’interno della pipeline di Wcf server side.
ErrorLoggingBehavior
Dopo un bel po’ di ricerche, si perchè scoprite molto rapidamente che la documentazione su Wcf è un’altro dei punti deboli del sistema, approdate ad una cosa che ricade sotto il cappello di “Behavior”, un behavior è, molto all’acqua di rose, qualcosa che potete iniettare in un punto (in base al tipo di behavior) della pipeline di Wcf al fine di customizzare il comportamento di Wcf stesso, un esempio è proprio la necessità di intercettare tutti gli errori:
public class Log4NetErrorLoggingServiceBehavior : IServiceBehavior, IErrorHandler
{
static readonly ILog logger = LogManager.GetLogger( typeof( Log4NetErrorLoggingServiceBehavior ) );

public void Validate( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase ) { }

public void AddBindingParameters( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters ) { }

public void ApplyDispatchBehavior( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase )
{
foreach( ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers )
{
var channelDispatcher = channelDispatcherBase as ChannelDispatcher;
if( channelDispatcher != null )
{
channelDispatcher.ErrorHandlers.Add( this );
}
}
}

public void ProvideFault( Exception error, MessageVersion version, ref Message fault )
{

}

public bool HandleError( Exception error )
{
logger.Fatal( error );
return false;
}
}
Fonte: Radical Winking smile
Direi veramente banale, dopo che avete scoperto come farlo… Smile la domanda che resta però ancora in sospeso è: bello… ok… ma come faccio ad agganciarlo al mio servizio Wcf? Nulla di più “facile” Smile
BehaviorExtensionElement
public class Log4NetErrorLoggingServiceSection : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new Log4NetErrorLoggingServiceBehavior();
}

public override Type BehaviorType
{
get { return typeof( Log4NetErrorLoggingServiceBehavior ); }
}
}
Che ci permette di fare questo:
<system.serviceModel>
  <services>
    <service name="MyService">
      <endpoint address="" behaviorConfiguration="myBehaviorConfiguration"
        binding="basicHttpBinding" bindingConfiguration=""
        contract="IMyService" />
    service>
  services>
  <extensions>
    <behaviorExtensions>
      <add name="log4NetErrorLoggingServiceBehavior" type="Topics.Radical.ServiceModel.Behaviors.Log4NetErrorLoggingServiceSection, Radical.ServiceModel, Version=1.0.0.23094, Culture=neutral, PublicKeyToken=null" />
    behaviorExtensions>
  extensions>
  <behaviors>
    <endpointBehaviors>
      <behavior name="myBehaviorConfiguration">
        <inlineWsdlEndpointExtension />
      behavior>
    endpointBehaviors>
    <serviceBehaviors>
      <behavior name="">
        <log4NetErrorLoggingServiceBehavior />
      behavior>
    serviceBehaviors>
  behaviors>
system.serviceModel>
In questo modo possiamo agganciare e sganciare il nostro behavior on-the-fly senza toccare il codice del servizio e avere finalmente accesso ad informazioni importantissime per capire quali sono i problemi che stanno impedendo al nostro servizio di funzionare correttamente… questo è fondamentale in particolare quando usate Wcf da un client Silverlight e cominciate a scontrarvi con il simpatico “NotFound”… Smile with tongue out
Happy Wcf-ing Open-mouthed smile
.m