Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self hosted Wcf serves wsdl but 404's when invoked

I'm trying to self-host a singleton instance of a service and I'm obviously getting lost at a level of indirection...

I've got a base address of http://localhost:8050/. I'm not too bothered where the service endpoint is as long as it's predictable. For the moment, I'm trying to use /Manage/.

I'm able to browse to the base address and see a wsdl. If I scan through the wsdl, it points at /Manage/..

<wsdl:service name="EngineService">
    <wsdl:port name="BasicHttpBinding_IEngineService" binding="tns:BasicHttpBinding_IEngineService">
        <soap:address location="http://localhost:8050/Manage/"/>
    </wsdl:port>
</wsdl:service>

When I consume the wsdl using the WcfTestClient, it lists all the correct methods, but calling any of them throw the following exception

System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://localhost:8050/Manage that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at IEngineService.SupportedAgents()
   at EngineServiceClient.SupportedAgents()

Inner Exception:
The remote server returned an error: (404) Not Found.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Log messages show my instance methods never get called. The service doesn't enter a faulted state, it just looks like it's not there.

I'm listening as follows:

    public static ServiceHost Listen<TServiceContract>(
            TServiceContract instance,
            int port,
            string name
        ) {

        //Added this for debugging, was previously just "name"
        string endpoint = String.Format("http://localhost:{0}/{1}/", port, name);

        var svcHost = new ServiceHost(
            instance,
            new Uri[] { new Uri(String.Format("http://localhost:{0}/", port)) });

        /* Snip: Add a Faulted handler but it's never called */

        ServiceEndpoint serviceHttpEndpoint = svcHost.AddServiceEndpoint(
            typeof(TServiceContract),
            new BasicHttpBinding {
                HostNameComparisonMode = HostNameComparisonMode.WeakWildcard
            }, endpoint); /*Using name instead of endpoint makes no difference beyond removing the trailing slash */

        /* Snip: Add a ServiceDebugBehavior with IncludeExceptionDetailInFaults = true */
        /* Snip: Add a ServiceMetadataBehavior with HttpGetEnabled = true */

        try {
            log.Trace("Opening endpoint");
            svcHost.Open();
        } catch () {
            /* Lots of catches for different problems including Exception
             * None of them get hit */
        }


        log.Info("Service contract {0} ready at {1}", typeof(TServiceContract).Name, svcHost.BaseAddresses.First());
        return svcHost;

And calling the Listen() method as follows:

        IEngineService wcfInstance = Resolver.Resolve<IEngineService>();
        service = WcfHoster.Listen(wcfInstance, 8050, "Manage");

How can I track down what the problem is/debug further?

Additional info: The Service contract and minimal implementation:

[ServiceContract]
interface IEngineService {
    [OperationContract]
    List<string> Agents();

    [OperationContract]
    string Test();

    [OperationContract]
    List<string> SupportedAgents();

    [OperationContract]
    string Connect(string AgentStrongName, string Hostname);
}

And the implementation:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class EngineService : IEngineService {
    IAgentManager agentManager;
    public EngineService(IAgentManager AgentManager) {
        log.Debug("Engine webservice instantiating");
        this.agentManager = AgentManager;
    }

    public string Connect(string AgentStrongName, string Hostname) {
        log.Debug("Endpoint requested for [{0}], [{1}]", Hostname, AgentStrongName);
        return agentManager.GetSession(AgentStrongName, Hostname);
    }

    public List<string> Agents() {
        log.Debug("Current agents queried");
        throw new NotImplementedException();
    }

    public List<string> SupportedAgents() {
        log.Debug("Supported agents queried");
        return agentManager.SupportedAgents().ToList();
    }

    public string Test() {
        log.Warn("Test query");
        return "Success!";
    }
}

The test client can see the service and methods but throws the exception above when I click Invoke...

enter image description here

Edit: localhost resolves to IPv6 by default so I've tried using 127.0.0.1 explicitly at both ends. No difference.

I've tried taking the above code into a new project and get the same issue. Running the whole thing on someone else's machine didn't help either.

Service Trace viewer

Running a service trace on the server side, then examining the results in the viewer gives:

Failed to lookup a channel to receive an incoming message. Either the endpoint or the SOAP action was not found.

enter image description here

Config file: Since I need the executable to be able to make a decision about which Wcf service to present at runtime, I don't have any Wcf-related code in the config file.

like image 692
Basic Avatar asked Apr 20 '15 13:04

Basic


1 Answers

This is probably a client / service binding mismatch. Please check the test client binding. You should also create a unit test by generating a proxy from the wsdl.

Ok. I have tried to reproduce your issue and I managed calling the host by removing "HostNameComparisonMode = HostNameComparisonMode.WeakWildcard" in order to get a default basichttp endpoint. Why do you need this?

like image 194
christophe vialatte Avatar answered Nov 02 '22 21:11

christophe vialatte