【问题标题】:Self hosted Wcf serves wsdl but 404's when invoked自托管的 Wcf 服务于 wsdl,但在调用时提供 404
【发布时间】:2015-04-20 13:21:30
【问题描述】:

我正在尝试自托管服务的单例实例,但显然我在间接级别上迷路了......

我的基址是http://localhost:8050/。只要它是可预测的,我就不会太在意服务端点在哪里。目前,我正在尝试使用/Manage/

我能够浏览到基地址并查看 wsdl。如果我扫描 wsdl,它指向 /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>

当我使用 WcfTestClient 使用 wsdl 时,它会列出所有正确的方法,但调用其中任何一个都会引发以下异常

System.ServiceModel.EndpointNotFoundException:http://localhost:8050/Manage 上没有可以接受消息的端点监听。这通常是由不正确的地址或 SOAP 操作引起的。有关详细信息,请参阅 InnerException(如果存在)。

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)

日志消息显示我的实例方法永远不会被调用。服务没有进入故障状态,只是看起来不存在。

我正在听如下:

    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;

并调用Listen()方法如下:

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

如何进一步追踪/调试问题所在?

附加信息:服务合同和最小实现:

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

    [OperationContract]
    string Test();

    [OperationContract]
    List<string> SupportedAgents();

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

以及实现:

[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!";
    }
}

测试客户端可以看到服务和方法,但是点击Invoke时抛出上面的异常...

编辑:localhost 默认解析为 IPv6,因此我尝试在两端显式使用 127.0.0.1。没有区别。

我尝试将上述代码放入一个新项目并遇到同样的问题。在别人的机器上运行整个事情也没有帮助。

服务跟踪查看器

在服务器端运行service trace,然后在查看器中检查结果:

未能查找通道以接收传入消息。未找到端点或 SOAP 操作。

配置文件:由于我需要可执行文件来决定在运行时呈现哪个 Wcf 服务,因此我在配置文件中没有任何与 Wcf 相关的代码。

【问题讨论】:

  • 你的异常发生在哪一行代码?
  • 在使用服务的客户端,而不是进程托管服务本身,因此我很难调试
  • 能否请您更具体一些,例如 try catch 或其他地方?
  • 我的实际捕获有 CommunicationObjectFaultedExceptionTimeoutExceptionException 的块。他们都没有受到打击。据我从主机进程中可以看出,服务加载正常,服务wsdl等......只是当调用任何方法时,我在客户端得到一个404。据我所知,主持人甚至没有看到那个电话。我显示的异常消息来自 Visual Studio 附带的 Wcf 测试客户端,用于测试正在使用的 Web 服务。如果你能澄清你想抓住什么,我会添加一个 try/catch
  • 很抱歉,我无法为您提供更多帮助。当你修好它时请告诉我:) 祝你好运。

标签: c# web-services wcf soap wsdl


【解决方案1】:

这可能是客户端/服务绑定不匹配。请检查测试客户端绑定。您还应该通过从 wsdl 生成代理来创建单元测试。

好的。我试图重现您的问题,并通过删除“HostNameComparisonMode = HostNameComparisonMode.WeakWildcard”来管理调用主机,以获得默认的 basichttp 端点。为什么需要这个?

【讨论】:

  • 如问题中所述,客户端是 WcfTestClient,它完全从 Wsdl 生成配置和绑定。自动生成的绑定的客户端节点如下:&lt;client&gt;&lt;endpoint address="http://localhost:8050/Manage" binding="wsHttpBinding" bindingConfiguration="ManageWs_IEngineService" contract="IEngineService" name="ManageWs_IEngineService" /&gt;&lt;/client&gt;
  • 有趣,这是由于在代码中以这种形式提供 BaseUri 的问题:http://*:1234/http://+:1234/ 会引发异常。 (这些方法需要 Uri[] 并且 Uri 类在使用通配符语法时抱怨主机名无效。0.0.0.0 有效,但 Wsdl 在无效的链接中使用了0.0.0.0。来自文档WeakWildcard: If no strong or exact match was found, ignores the hostname when matching.)。让我测试一下并回复你,谢谢提示
  • 是的,删除HostNameComparisonMode = HostNameComparisonMode.WeakWildcard 就成功了。感谢您的帮助,我希望赏金在这里给您一个启动。
  • 谢谢,WCF 是我最喜欢的 .Net 技术。我希望你也会喜欢它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
相关资源
最近更新 更多