2013-09-05 1 views
2

Nous avons un service WCF qui implémente la découverte. Cela fonctionne bien, mais nous avons un gestionnaire d'erreur qui semble capter un message sur le réseau au moment où je ne suis pas sûr que ce soit invalide ou non. Après avoir utilisé un moniteur de réseau, il semble gérer/ignorer d'autres messages liés à la découverte, mais pas celui-ci.Traitement des erreurs du service WCF Message WS-Discovery Resolve

Ma question: Y a-t-il une sorte de configuration supplémentaire que je peux ajouter à mon service pour gérer élégamment ce (type de) message? Je me demandais juste s'il manquait quelque chose. S'il n'y a pas de solution simple, je suis heureux de laisser notre service gérer comme une faille comme c'est le cas actuellement.

est ici la faute:

System.ServiceModel.FaultException: The message with To '' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree. at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message) Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing) HandleError: System.InvalidOperationException: The supplied message cannot be sent because the destination is unknown. This transport requires that either Message.Headers.To or Message.Properties.Via be set to a valid value on the outgoing message. at System.ServiceModel.Channels.ServerUdpOutputChannel.GetSendSockets(Message message, IPEndPoint& remoteEndPoint, Exception& exceptionToBeThrown 
at System.ServiceModel.Channels.UdpOutputChannel.SendAsyncResult.Initialize(Message message 
at System.ServiceModel.Channels.UdpOutputChannel.SendAsyncResult..ctor(UdpOutputChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.UdpOutputChannel.OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.OutputChannel.BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Dispatcher.DuplexChannelBinder.DuplexRequestContext.OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.RequestContextBase.BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.RequestContextBase.BeginReply(Message message, AsyncCallback callback, Object state 
at System.ServiceModel.Dispatcher.ChannelHandler.ProvideFaultAndReplyFailure(RequestContext request, Exception exception, ErrorHandlerFaultInfo& faultInfo, Boolean& replied, Boolean& replySentAsync) HandleError: System.ServiceModel.FaultException: The message with To '' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree. at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message) ProvideFault: System.ServiceModel.FaultException: The message with To '' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree. at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message) Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing) HandleError: System.InvalidOperationException: The supplied message cannot be sent because the destination is unknown. This transport requires that either Message.Headers.To or Message.Properties.Via be set to a valid value on the outgoing message. at System.ServiceModel.Channels.ServerUdpOutputChannel.GetSendSockets(Message message, IPEndPoint& remoteEndPoint, Exception& exceptionToBeThrown 
at System.ServiceModel.Channels.UdpOutputChannel.SendAsyncResult.Initialize(Message message 
at System.ServiceModel.Channels.UdpOutputChannel.SendAsyncResult..ctor(UdpOutputChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.UdpOutputChannel.OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.OutputChannel.BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Dispatcher.DuplexChannelBinder.DuplexRequestContext.OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.RequestContextBase.BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, Object state 
at System.ServiceModel.Channels.RequestContextBase.BeginReply(Message message, AsyncCallback callback, Object state 
at System.ServiceModel.Dispatcher.ChannelHandler.ProvideFaultAndReplyFailure(RequestContext request, Exception exception, ErrorHandlerFaultInfo& faultInfo, Boolean& replied, Boolean& replySentAsync) HandleError: System.ServiceModel.FaultException: The message with To '' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree. at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message) 

Voici le message:

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery"><soap:Header><wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To><wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Resolve</wsa:Action><wsa:MessageID>urn:uuid:2729e487-0e96-42e9-a3fb-96c32c6193de</wsa:MessageID></soap:Header><soap:Body><wsd:Resolve><wsa:EndpointReference><wsa:Address>urn:uuid:1c852a4d-b800-1f08-abcd-2c59e5c16898</wsa:Address></wsa:EndpointReference></wsd:Resolve></soap:Body></soap:Envelope> 

Et voici mon exemple d'application qui est basé sur la valeur par défaut WCF nouveau modèle de projet:

Program.cs:

using System; 
using System.Diagnostics; 
using System.Net; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Discovery; 
using System.ServiceModel.Dispatcher; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       Uri baseAddress = new Uri(String.Format("net.tcp://{0}:8004/Service", Dns.Resolve(Dns.GetHostName()).HostName)); 
       ServiceHost serviceHost = new ServiceHost(typeof(Service1), baseAddress); 

       // Setup the binding and open the WCF service 
       NetTcpBinding binding = new NetTcpBinding(SecurityMode.None); 
       OptionalReliableSession reliableSession = binding.ReliableSession; 
       reliableSession.Enabled = false; 
       reliableSession.InactivityTimeout = TimeSpan.MaxValue; 
       binding.ReceiveTimeout = TimeSpan.MaxValue; 
       binding.MaxBufferSize = 1000000000; 
       binding.MaxReceivedMessageSize = 1000000000; 
       binding.MaxBufferPoolSize = 524288; 
       binding.TransferMode = TransferMode.Buffered; 
       binding.ReaderQuotas.MaxStringContentLength = int.MaxValue; 
       binding.ReaderQuotas.MaxArrayLength = int.MaxValue; 
       binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue; 

       ServiceEndpoint serveEnd = serviceHost.AddServiceEndpoint(typeof(IService1), binding, String.Empty); 

       ServiceDiscoveryBehavior serviceDiscoveryBehavior = new ServiceDiscoveryBehavior(); 
       serviceHost.Description.Behaviors.Add(serviceDiscoveryBehavior); 

       UdpDiscoveryEndpoint discEnd = new UdpDiscoveryEndpoint(); 
       serviceHost.AddServiceEndpoint(discEnd); 

       serviceHost.Open(); 

       Console.WriteLine(baseAddress); 
       Debug.WriteLine(baseAddress); 

       Console.Read(); 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine(ex); 
       //throw; 
      } 
     } 
    } 
} 

IService1.cs et Service1.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 
    [ServiceContract] 
    public interface IService1 
    { 
     [OperationContract] 
     string GetData(int value); 

     [OperationContract] 
     CompositeType GetDataUsingDataContract(CompositeType composite); 

     // TODO: Add your service operations here 
    } 

    // Use a data contract as illustrated in the sample below to add composite types to service operations. 
    [DataContract] 
    public class CompositeType 
    { 
     bool boolValue = true; 
     string stringValue = "Hello "; 

     [DataMember] 
     public bool BoolValue 
     { 
      get { return boolValue; } 
      set { boolValue = value; } 
     } 

     [DataMember] 
     public string StringValue 
     { 
      get { return stringValue; } 
      set { stringValue = value; } 
     } 
    } 
} 


using System; 
using System.Diagnostics; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 

namespace ConsoleApplication1 
{ 
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together. 
    public class Service1 : IService1, IErrorHandler, IServiceBehavior 
    { 
     public string GetData(int value) 
     { 
      return string.Format("You entered: {0}", value); 
     } 

     public CompositeType GetDataUsingDataContract(CompositeType composite) 
     { 
      if (composite == null) 
      { 
       throw new ArgumentNullException("composite"); 
      } 
      if (composite.BoolValue) 
      { 
       composite.StringValue += "Suffix"; 
      } 
      return composite; 
     } 

     public bool HandleError(Exception error) 
     { 
      Debug.WriteLine("HandleError: {0}", error); 
      Console.WriteLine("HandleError: {0}", error); 

      return false; 
     } 

     public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault) 
     { 
      Debug.WriteLine("ProvideFault: {0} {1}", error, version); 
      Console.WriteLine("ProvideFault: {0} {1}", error, version); 
     } 

     #region IServiceBehavior Members 

     public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
     { 
      return; 
     } 

     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
     { 
      foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) 
      { 
       channelDispatcher.ErrorHandlers.Add(this); 
      } 
     } 

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

     #endregion 


    } 
} 

Cheers, Chris.

+0

Toute résolution à ce sujet? Qu'est-il arrivé? –

+0

Salut - Non, je n'ai pas obtenu une résolution. À la fin, j'ai ajouté un hack à l'implémentation IErrorHandler.HandlerError dans notre code pour vérifier la chaîne "destination is unknown" et ignorer l'erreur dans ces cas. Horrible je sais mais ça a fait l'affaire. – Chris

Répondre

1

J'ai rencontré le même problème: Les choses fonctionnent, mais le point de terminaison de découverte continue d'envoyer un message nulle part, toutes les 5 minutes environ, causant 2 exceptions, comme indiqué dans le message de trace.

J'ai réussi à trouver le point de terminaison préconfiguré sous le nom de contrat TargetService et l'adresse urn: docs-oasis-open-org: ws-dd: ns: découverte: 2009: 01. Et j'ai passé la main sur googled autour et trouvé aucun fil mentionnant ceci.

J'ai tendance à croire qu'il s'agit d'un défaut dans ce point de terminaison préconfiguré WCF.

J'ai utilisé une solution de contournement similaire à celle de Chris.

J'ai un service Ping avec son propre hôte de classe et de service, et cette classe ne sera pas accrochée avec le gestionnaire d'erreur, donc n'émettra pas de messages d'erreur mystérieux dans le fichier journal. Les autres fonctions métier vont à d'autres classes et à un autre hôte de service, avec un gestionnaire d'erreurs pour récupérer les exceptions non interceptées. En outre, étant donné que la détection de point de terminaison est environ 200 fois plus lente que l'adressage direct, j'ai une classe wrapper pour mettre en mémoire tampon l'adresse de base trouvée dans la première reconnaissance Ping through. Et les appels clients suivants utiliseront l'adresse.

0

Vous ne voulez probablement pas handler erreurs sur les paramètres du système de toute façon, de sorte que vous pouvez utiliser ce code pour éviter d'ajouter un gestionnaire, sauf le cas échéant:

public class LogUnhandledExceptionBehavior : IServiceBehavior 
{ 
    ... 
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (var channelDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>()) 
     { 
      // Don't add error handler on channelDispatcher with system endpoints, as they can throw spurious errors 
      // and ones we cannot do anything about anyway. 
      if (channelDispatcher.Endpoints.Any(dispatcher => dispatcher.IsSystemEndpoint)) 
       continue; 

      channelDispatcher.ErrorHandlers.Add(GenericErrorHandler.StaticInstance); 
     } 
    ... 
    }