【问题标题】:WCF set Endpoint and Binding dynamically in codeWCF 在代码中动态设置 Endpoint 和 Binding
【发布时间】:2011-08-26 20:52:50
【问题描述】:

是的,我已阅读 SO、MSDN 和其他网站上的其他问题,但没有找到我能理解的清晰答案。我需要设置相对于从中加载它的站点的 Silverlight 应用程序的 WCF 引用,但我无法让它工作。服务本身没有问题,它正在工作。当我从本地移动到我的真实服务器时,我的 SL 应用程序中出现错误,抱怨未连接到本地主机。

这是我的ServiceReferences.ClientConfig 文件:

    <configuration>
        <system.serviceModel>
            <bindings>
                <customBinding>
                    <binding name="CustomBinding_AccountManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                    <binding name="CustomBinding_FileManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                    <binding name="CustomBinding_SiteManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="http://localhost:60322/AccountManager.svc"
                    binding="customBinding" bindingConfiguration="CustomBinding_AccountManager"
                    contract="AccountManager.AccountManager" name="CustomBinding_AccountManager" />
                <endpoint address="http://localhost:60322/FileManager.svc" binding="customBinding"
                    bindingConfiguration="CustomBinding_FileManager" contract="FileManager.FileManager"
                    name="CustomBinding_FileManager" />
                <endpoint address="http://localhost:60322/SiteManager.svc" binding="customBinding"
                    bindingConfiguration="CustomBinding_SiteManager" contract="SiteManager.SiteManager"
                    name="CustomBinding_SiteManager" />
            </client>
        </system.serviceModel>
    </configuration>

是的,我优化缓冲区/消息大小,并且我知道可能的 DoS 漏洞,暂时忘记它,我需要它们来传输大文件。我尝试的一种方法是在实例化客户端时,我使用了以下代码:

    fileManager = new FileManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));
    accManager = new AccountManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/AccountManager.svc"));

Settings.Host 是我自己的方法,它返回运行 SL 应用程序的主机,经过测试,可以正常工作。当我上传我的 XAP 并尝试时,它仍然想去http://localhost:60322/AccountManager.svc,经过进一步调查,我意识到在看不见的文件中仍然有 很多 对 localhost 的引用:

AccountManager.disco:

<?xml version="1.0" encoding="utf-8"?>
<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
  <contractRef ref="http://localhost:60322/AccountManager.svc?wsdl" docRef="http://localhost:60322/AccountManager.svc" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
</discovery>

AccountManager.wsdl 的部分内容: ... &lt;wsdl:import namespace="" location="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" /&gt;... ...[大量的操作声明]...

<wsdl:service name="AccountManager">
    <wsdl:port name="CustomBinding_AccountManager" binding="tns:CustomBinding_AccountManager">
      <soap12:address location="http://localhost:60322/AccountManager.svc" />
      <wsa10:EndpointReference>
        <wsa10:Address>http://localhost:60322/AccountManager.svc</wsa10:Address>
      </wsa10:EndpointReference>
    </wsdl:port>
  </wsdl:service>

AccountManager1.xsd的一部分:

&lt;xs:import schemaLocation="http://localhost:60322/AccountManager.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/Leftouch.Data.Summary" /&gt;

configuration.svcinfo的一部分:

<endpoint normalizedDigest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:60322/AccountManager.svc&quot; binding=&quot;customBinding&quot; bindingConfiguration=&quot;CustomBinding_AccountManager&quot; contract=&quot;AccountManager.AccountManager&quot; name=&quot;CustomBinding_AccountManager&quot; /&gt;" digest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:60322/AccountManager.svc&quot; binding=&quot;customBinding&quot; bindingConfiguration=&quot;CustomBinding_AccountManager&quot; contract=&quot;AccountManager.AccountManager&quot; name=&quot;CustomBinding_AccountManager&quot; /&gt;" contractName="AccountManager.AccountManager" name="CustomBinding_AccountManager" />

Reference.svcmap的一部分:

</ClientOptions>
  <MetadataSources>
    <MetadataSource Address="http://localhost:60322/AccountManager.svc" Protocol="http" SourceId="1" />
  </MetadataSources>
  <Metadata>
    <MetadataFile FileName="AccountManager2.xsd" MetadataType="Schema" ID="e473b2d5-7af3-4390-87c3-a4fc3f54fb96" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd2" />
    <MetadataFile FileName="AccountManager1.xsd" MetadataType="Schema" ID="fd3a1ae0-b38b-4586-8622-5b0ee07e39fb" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd0" />
    <MetadataFile FileName="AccountManager.xsd" MetadataType="Schema" ID="6a49ee64-6eac-40e2-bcff-26418435e777" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd1" />
    <MetadataFile FileName="AccountManager.disco" MetadataType="Disco" ID="9ec9a8cc-0cf0-4264-a526-b5a6c08f7d36" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?disco" />
    <MetadataFile FileName="AccountManager1.wsdl" MetadataType="Wsdl" ID="54a5b2c0-9d0e-4043-a7e4-d27ae6674bfc" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" />
    <MetadataFile FileName="AccountManager.wsdl" MetadataType="Wsdl" ID="f8923013-3a6c-412b-b7da-bee5a5a7bb64" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl" />

..所有这些也适用于其他 2 项服务。

我不是网络服务/绑定/端点/操作合同或任何相关内容的大师。我只想让我已经很好工作(当 URI 被硬编码时)系统为相对 URI 工作,这就是我所需要的。必须有一个简单的解决方案。有人可以解释究竟这些文件类型和声明类似于什么,哪些是重要的,哪些是可选的,以及如何以最简洁的形式创建动态服务引用。请附上解释。我已经看过很多关于动态服务绑定和引用的帖子和文章,但老实说,一切都变得一团糟,我最终对此一无所知。欢迎任何建设性的批评和解决方案。

【问题讨论】:

  • 您可以发布您正在使用的服务配置文件吗?

标签: wcf web-services silverlight-4.0 webservice-client wcfserviceclient


【解决方案1】:

您的服务(而不是客户端)的配置文件是否使用具有完全限定地址的端点(如您的客户端配置)?如果是这样,您看到所有这些 localhost 引用的原因是,当您添加服务引用时,它将在生成的文件中传递该地址。

更新服务配置文件中的端点以使用该机器上的完全限定地址(即http://somname.com/service.svc),或将配置文件中的 baseAddresses 设置为机器名称。

此外,如果您使用的是 WCF 4.0 (VS 2010/.NET 4.0),您可以通过完全从配置文件中省略端点来让 WCF 为您的服务创建一个默认端点(据我所知 -我们现在只是在工作中迁移到 4.0,所以我还没有玩过新功能)。

编辑添加

新方法,相同的基本思想(URI 是从某个地方导入的)。根据您下面的 cmets,听起来您的服务配置设置得很好,没有指向 localhost 的硬编码 URI。

当您将应用程序移动到目标服务器时,您是同时更新对服务的引用(通过添加服务引用),还是只是将本地机器生成的文件移动到目标服务器?

如果您是,我想知道这是否可能是您的问题的根源。我认为在创建客户端时指定服务地址应该覆盖与 WSDL 相关的文件中的任何内容,但也许不是。

尝试一下:

从您的 Web.config 中删除 &lt;client&gt; 部分。然后,当你创建客户端时,这样做:

fileManager = new FileManagerClient(new BasicHttpBinding("CustomBinding_FileManager"), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));

确保您在 BasicHttpBinding 构造函数中传递绑定配置部分的名称,否则您将获得具有默认值的绑定,而不是您指定的较大值。

这里的想法是消除客户端配置文件设置覆盖您在创建 FileManagerClient 时传递的内容的任何可能性。

我认为必须为每个单独的服务器的每次部署更新服务参考并不理想 - 您尝试完成的工作是有意义的。我在我编写的 n 层应用程序中做了类似的事情 - 唯一的区别是我不使用服务引用,我通过 SvcUtil 生成代理,然后通过 ChannelFactory&lt;T&gt; 生成通道,这是您可能想要的另一条路线看看。

如果这些都没有帮助,请随时给我发电子邮件(我的电子邮件地址在我的个人资料中) - 通过电子邮件交换可能更容易解决这个问题,然后发布最终解决方案。

【讨论】:

  • 你到底在说什么文件?我查看了我的 web.config 和 .svc 标记,但没有关于域的内容。顺便说一句,是的,我正在使用 .NET 4.0
  • 我说的是服务的 Web.config 文件。该文件中的端点有什么?
  • &lt;service name="Web.FileManager"&gt; &lt;endpoint binding="customBinding" bindingConfiguration="Web.FileManager.customBinding0" contract="Web.FileManager" /&gt; &lt;endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt; &lt;/service&gt; 和 2 个具有其他服务名称的副本。
  • 您在服务配置中是否指定了任何基地址或 uri?
  • 我到底应该发布什么?我的服务是我网站的一部分,我已经粘贴了相关部分。我不明白你还问什么。我没有在任何地方找到并硬编码 URI,但我肯定会遗漏一些东西。只要告诉我你要的文件的哪一部分,我会粘贴它
猜你喜欢
  • 1970-01-01
  • 2018-07-03
  • 2012-03-30
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 2021-02-10
相关资源
最近更新 更多