Reputation: 5093
I am creating a selfhosted WCF Service
.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IStateChecker
{
[OperationContract]
void SetState(string state);
}
This is my Service
:
public class StateCheckerService : IStateChecker
{
public void SetState(string state)
{
Console.WriteLine($"{DateTime.Now.ToString("dd.MM.yyyy HH:mm:sss")} : {state}");
}
}
And this my Implementation:
//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();
}
Now when it comes to the client I get an error.
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);
}
Exception:
The communication object, "System.ServiceModel.Channels.ServiceChannel",
cannot be used for communication because it is in the Faulted state.
I never enter
SelfHost_Faulted
nor are there anyException
s on my Service
I am doing this because I want to change the Endpoint
the client should connect to at runtime.
If I'm doin it wrong please tell me. Otherwise any hints on what is wrong with my code are highly appreciated.
Upvotes: 3
Views: 15187
Reputation: 205629
The issue is quite trivial, but hidden by the WCF infrastructure (strange implementation of a standard pattern).
If you change
channel?.SetState("Test");
to
try
{
channel?.SetState("Test");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
you will see 2 messages:
There was no endpoint listening at http://localhost:8000/ServiceModelSamples/Service that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
and
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
The first one is the real exception (of type EndpointNotFoundException
) caught by the inner catch
.
The second (misleading) exception is of type CommunicationObjectFaultedException
and is thrown by channel.Dispose()
(?!) called at the end of your using
block, hence hides the original one. WCF implementation simply is not following the rule that Dispose()
should not throw!
With that being said, the problem is in your client endpoint. According to the service configuration, it should be "baseAddress/StateCheckerService"
while currently it's just "baseAddress"
. So simply use the correct endpoint address
var endpointAddress = new EndpointAddress(
"http://localhost:8000/ServiceModelSamples/Service/StateCheckerService");
and the issue will be solved.
Upvotes: 8