2017-03-03 17 views
1

自己ホストWCF Serviceを作成しています。サービスのFaultedStateによってWCF.ServiceChannelが通信できません

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] 
public interface IStateChecker 
{ 
    [OperationContract] 
    void SetState(string state); 
} 

これは私のServiceです:

public class StateCheckerService : IStateChecker 
{ 
    public void SetState(string state) 
    { 
     Console.WriteLine($"{DateTime.Now.ToString("dd.MM.yyyy HH:mm:sss")} : {state}"); 
    } 
} 

そして、この私の実装:

//Define baseaddres: 
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service"); 

//create host: 
ServiceHost selfHost = new ServiceHost(typeof(StateCheckerService), baseAddress); 

try 
{ 
    //Add endpoint to host: 
    selfHost.AddServiceEndpoint(typeof(IStateChecker), new WSHttpBinding(), "StateCheckerService"); 

    //Add metadata exchange: 
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); 
    smb.HttpGetEnabled = true; 
    selfHost.Description.Behaviors.Add(smb); 


    selfHost.Faulted += SelfHost_Faulted; 

    //Start service 
    selfHost.Open(); 

    Console.WriteLine("Starting Service..."); 
    if (selfHost.State == CommunicationState.Opened) 
    { 
     Console.WriteLine("The service is ready."); 
    } 

    Console.WriteLine("Press <ENTER> to terminate service."); 
    Console.ReadLine(); 

    //Shutdown service 
    selfHost.Close(); 
} 
catch (CommunicationException ce) 
{ 
    Console.WriteLine("An exception occurred: {0}", ce.Message); 
    selfHost.Abort(); 
} 

private static void SelfHost_Faulted(object sender, EventArgs e) 
{ 
    ServiceHost host = sender as ServiceHost; 
    Console.WriteLine(host?.State); 
    Console.WriteLine(e?.ToString()); 

    host?.Open(); 
} 

今ではクライアントに来るとき、私はエラーを取得します。

try 
{ 
    //Works using the ServiceReference (wsdl ... created by VisualStudio): 
    using (StateCheckerServiceReference.StateCheckerClient client = new StateCheckerClient()) 
    { 
     client.SetState("Test"); 
    } 

    //Does not work: 
    EndpointAddress endpointAddress = new EndpointAddress("http://localhost:8000/ServiceModelSamples/Service"); 
    using (ChannelFactory<IStateCheckerChannel> factory = new ChannelFactory<IStateCheckerChannel>("WSHttpBinding_IStateChecker", endpointAddress)) 
    { 
     using (IStateCheckerChannel channel = factory.CreateChannel(endpointAddress)) 
     { 
      channel?.SetState("Test"); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    Console.WriteLine(ex.Message); 
} 

例外:

The communication object, "System.ServiceModel.Channels.ServiceChannel", 
cannot be used for communication because it is in the Faulted state. 

私はSelfHost_Faultedに入ることはありませんも私はEndpointを変更したいので、私はこれをやっている私のサービス

上の任意のException sがありますクライアントは実行時に接続する必要があります。

もし私が間違っていたら、教えてください。そうでなければ、私のコードで何が間違っているかについてのヒントは高く評価されます。

答えて

2

問題は非常に些細ですが、WCFインフラストラクチャ(標準パターンの奇妙な実装)によって隠されています。

あなたは

channel?.SetState("Test"); 

try 
{ 
    channel?.SetState("Test"); 
} 
catch (Exception ex) 
{ 
    Console.WriteLine(ex.Message); 
} 

に変更する場合は、2件のメッセージが表示されます。

は、メッセージを受け入れることができる http://localhost:8000/ServiceModelSamples/Serviceで聞いて何のエンドポイントではありませんでした。これは、しばしば不正なアドレスまたはSOAPアクションによって引き起こされます。詳細については、InnerException(存在する場合)を参照してください。

通信対象が障害状態であるため、System.ServiceModel.Channels.ServiceChannelは、通信のために使用することができません。

最初のものはcatchでキャッチされた実際の例外(タイプEndpointNotFoundException)です。

秒(誤解)例外はタイプCommunicationObjectFaultedExceptionのものであり、channel.Dispose()によってスローされた(?!)あなたのusingブロックの最後に呼ばれ、したがって、元の1が非表示になります。 WCFの実装は、単にDispose()が投げてはならないというルールに従っていません!

これは、クライアントのエンドポイントに問題があると言われています。サービスの設定によれば、"baseAddress/StateCheckerService"であるべきですが、現在はちょうど"baseAddress"です。正しいエンドポイントアドレスを使用するだけです。

var endpointAddress = new EndpointAddress(
    "http://localhost:8000/ServiceModelSamples/Service/StateCheckerService"); 

この問題は解決されます。