2013-09-05 10 views
2

검색 기능을 구현하는 WCF 서비스가 있습니다. 괜찮 았지만 잘 모르겠다는 확신이 서지 않는 순간에 네트워크에서 메시지를 잡는 오류 처리기가 있습니다. 네트워크 모니터를 사용한 후에는 다른 디스커버리 관련 메시지를 처리 ​​/ 무시하는 것처럼 보입니다.WCF 서비스 오류 처리 WS-Discovery 메시지 해결

내 질문 :이 유형의 메시지를 우아하게 처리하기 위해 내 서비스에 추가 할 수있는 추가 구성이 있습니까?

나는 우리가 무엇인가 놓치고 있는지 궁금해했다. 간단한 해결책이 없다면 서비스가 현재와 같이 오류로 처리하게되어 기쁩니다. 여기

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) 

메시지입니다 : 여기

는 잘못

Program.cs : 여기

<?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> 

그리고 기본 WCF 새 프로젝트 템플릿을 기반으로 내 샘플 응용 프로그램은 다음과 같습니다

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 및 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 


    } 
} 

건배, 크리스.

+0

이에 대한 모든 해상도를? 어떻게 된 거예요? –

+0

안녕하세요 - 해결하지 못했습니다. 마지막으로 IErrorHandler.HandlerError 구현에 "destination is unknown"문자열을 확인하고이 경우 오류를 무시하기위한 해킹을 추가했습니다. Awful 나는 알고있다 그러나 트릭을했다. – Chris

답변

1

동일한 문제가 발생했습니다. 모든 작업이 작동하지만 추적 메시지에 표시된 것처럼 발견 엔드 포인트가 아무런 메시지도 보내지 않고 5 분마다 2 개의 예외가 발생합니다.

미리 구성된 끝점에 계약 이름 TargetService가 있고 urn : docs-oasis-open-org : ws-dd : ns : discovery : 2009 : 01 주소가 있다는 것을 알아 냈습니다. 그리고 나는 주위에 봤 거든이 스레드를 언급 아무런 발견.

나는 이것이이 WCF 사전 구성된 종단점의 결함이라고 생각하는 경향이 있습니다.

Chris와 비슷한 비슷한 해결 방법을 사용했습니다.

클래스와 서비스 호스트가있는 Ping 서비스가 있으며이 클래스는 오류 처리기에 연결되지 않으므로 로그 파일에 신비한 오류 메시지가 표시되지 않습니다. 다른 비즈니스 기능은 오류 처리기로 연결되어 잡히지 않은 예외를 잡아내는 다른 클래스와 다른 서비스 호스트로 이동합니다.

또한 엔드 포인트 검색이 직접 주소 지정보다 약 200 배 느리기 때문에 검색을 통해 첫 번째 Ping에서 찾은 기본 주소를 버퍼링하는 래퍼 클래스가 있습니다. 이후 클라이언트 호출은 주소를 사용하게됩니다.

0

당신은 아마 어쨌든 시스템 엔드 포인트에서 오류 처리기 싶지 않아, 그래서 당신은 적절한 경우를 제외하고는 핸들러를 추가 피하기 위해이 코드를 사용할 수 있습니다

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); 
     } 
    ... 
    }