【问题标题】:Dynamic endpoints in ServiceReferences.ClientConfigServiceReferences.ClientConfig 中的动态端点
【发布时间】:2011-11-13 16:52:06
【问题描述】:

在构建应用程序时,它通常部署在不同的环境(测试、开发、生产)中,因此端点地址会发生变化。由于 ServiceReferences.ClientConfig 是作为 Silverlight 的 .xap 文件的一部分构建的,因此在构建解决方案后很难更改端点,就像使用 web.config 所做的那样。

我已经搜索了很多,但我无法弄清楚这里的最佳做法是什么,所以我的问题是:

关于 Silverlight 中动态 wcf 端点地址配置的最佳实践是什么?

澄清一下,根据应用所在的服务器(测试、开发、生产),端点会发生变化:

  <endpoint
    name="MyService"
    address="http://testserv/MyService.svc"
    binding="basicHttpBinding"
    bindingConfiguration="MybasicHttpBinding"
    contract="MyApp.MyService"
             />

  <endpoint
    name="MyService"
    address="http://prodserv/MyService.svc"
    binding="basicHttpBinding"
    bindingConfiguration="MybasicHttpBinding"
    contract="MyApp.MyService"
             />

在某种程度上,我需要 silverlight 客户端知道要使用哪一个,这取决于它在哪个服务器上/编译了哪个版本。

【问题讨论】:

  • 您能否澄清一下,是您的网站使用服务还是只是 Silverlight 客户端引用网站服务?
  • silverlight 客户端正在使用/引用具有动态地址的 wcf 服务,具体取决于我们所在的服务器(产品、测试、开发)。

标签: c# silverlight wcf-binding


【解决方案1】:

看看这里:

http://weblogs.asp.net/srkirkland/archive/2009/10/13/common-web-config-transformations-with-visual-studio-2010.aspx

那么这里

http://www.funkymule.com/post/2010/03/08/XML-Transform-on-Silverlight-ClientConfig-Files.aspx

它使用 web.config 转换背后的相同原理(即 web.config 根据您正在编译的配置(即发布、调试)进行更改,以便在编译时根据您的突发奇想更改 serviceref.config . 很有魅力

【讨论】:

  • Funky Mule 网页链接已损坏。
【解决方案2】:

您可以在运行时使用 SL 中 WCF 客户端的构造函数来执行此操作,该构造函数采用端点配置名称和地址。在您的示例中,端点配置名称只是“MyService”。您提供的地址参数将覆盖 ClientConfig 中包含的地址参数。

在运行时从 SL 计算服务地址的一种方法是(我不保证它适用于所有环境配置):

  1. 计算您网站的根目录,例如通过找到共同的部分 Application.Current.Host.Source.AbsoluteUri 和 HtmlPage.Document.DocumentUri.AbsoluteUri。基本上,你拿 较短路径开头的字符,只要它们 匹配其他路径中不区分大小写的字符。
  2. 如果有的话,将相对路径附加到服务(这里似乎不是这种情况)。
  3. 附加 MyService.svc

额外信息:

当您有许多服务时,这可能看起来很复杂,但是这一切都可以很好地重构,并且在 Unity 的帮助下变得非常容易用于任何服务。例如,我使用一个辅助函数来注册服务客户端,它的调用如下所示: ServicesHelper.RegisterService( "MyService" );当我需要创建服务客户端的实例时,我只需使用 Unity 解析 MyServiceContractClient 类型,它使用注入构造函数来创建已经正确配置的服务的新实例。它还可以处理 HTTPS 情况。如果您需要更多信息,请告诉我。

【讨论】:

  • 这可以工作,但在某些设置中,wcf 服务和 silverlight 应用程序不在同一台服务器上。如果是这种情况,我认为我可以只使用 address="../MyService/service.svc" 这样的相对路径?
  • 你的意思是你使用跨域调用?如果不是,并且您只是在同一个 Web 应用程序中托管 WCF 服务和 SL 应用程序,那么即使您从不同的服务器访问您的应用程序,上述解决方案也将起作用。
  • 顺便说一句,当你使用 SL 4 时,你可以使用相对路径:see here
  • 我的 WCF 服务将始终位于 Silverlight XAP 的本地,因此该解决方案非常适合我。不得不拆分 .xap 并更改 ServicesReferences.ClientConfig,甚至使用 Web 转换,确实违反了自动构建和部署的基本原则。
【解决方案3】:

在阅读了 sLedgem 的帖子和一些谷歌搜索后,我找到了使 ServiceReferences 像 web.config 一样的完美解决方案。

首先: 手动创建不同的文件;

ServiceReferences.Debug.ClientConfig
ServiceReferences.Release.ClientConfig

如果您在 Visual Studio 中有两个以上的默认配置,您也可以添加自己的配置。

第二: 在 Project.csproj 文件中添加文件依赖(在文本编辑器中打开项目文件):

  <ItemGroup>
    <None Include="Properties\AppManifest.xml" />
    <Content Include="ServiceReferences.ClientConfig">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Content Include="ServiceReferences.Debug.ClientConfig">
      <DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
    </Content >
    <Content Include="ServiceReferences.Release.ClientConfig">
      <DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
    </Content >
  </ItemGroup>

现在,当您重新加载项目时,您将看到 ServiceReferences.Release.ClientConfig 在解决方案资源管理器中是可展开的,当您展开它时,您将看到 Release 和 Debug 文件。

第三:在关闭&lt;/Project&gt;之前将Transformation规则添加到Project文件中

(再次,在文本编辑器中打开它)

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
  Other similar extension points exist, see Microsoft.Common.targets.   -->
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists('ServiceReferences.$(Configuration).ClientConfig')">
  <!-- Generate transformed ServiceReferences config in the intermediate directory -->
  <TransformXml Source="ServiceReferences.ClientConfig" Destination="$(IntermediateOutputPath)$(TargetFileName).ClientConfig" Transform="ServiceReferences.$(Configuration).ClientConfig" />
  <!-- Force build process to use the transformed configuration file from now on. -->
  <ItemGroup>
    <ServiceReferencesConfigWithTargetPath Remove="ServiceReferences.ClientConfig" />
    <ServiceReferencesConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).ClientConfig">
      <TargetPath>$(TargetFileName).ClientConfig</TargetPath>
    </ServiceReferencesConfigWithTargetPath>
  </ItemGroup>
</Target>

它的作用是根据您的配置查看相应的服务引用文件,并使用 web.config 使用的相同 TransformXML 库复制/替换代码。

例子:

在我的 ServiceReferences.ClientConfig 我有以下代码:

  <endpoint name="ICatalogueService" 
            address="address" 
            binding="basicHttpBinding"
            bindingConfiguration="My_basicHttpBinding" 
            contract="Services.ServiceInterfaces.ICatalogueService"/>

ServiceReferences.Release.ClientConfig:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.serviceModel>
    <client>
      <endpoint
        name="ICatalogueService"       
        address="http://server/Services/CatalogueService.svc"
        binding="basicHttpBinding"
        bindingConfiguration="My_basicHttpBinding"
        contract="Services.ServiceInterfaces.ICatalogueService"
        xdt:Transform="Replace" xdt:Locator="Match(name)" />
    </client>
    <extensions />
  </system.serviceModel>
</configuration>

如您所见,端点将被替换,并且匹配在 name 属性上完成。

如果您有任何问题,请告诉我:)

【讨论】:

  • 这是我见过的“最棒”、最伟大、最辉煌的事情。正是我所需要的......我将它用于我自己的包含其他类型配置的 XML 文件。非常感谢你发布这个。完美运行! +1
【解决方案4】:

randoms 的反应很到位,除了一件小事。不要将 .Debug.ClientConfig 和 .Release.ClientConfig 标记为“内容”。将它们标记为“无”。这样,您的 .Debug.ClientConfig 和 .Release.ClientConfig 就不会被放入您的 .xap 文件中。这是我的 Silverilght 项目文件中的内容(效果很好):

<Content Include="ServiceReferences.ClientConfig">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="ServiceReferences.DEV.ClientConfig">
  <DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>
<None Include="ServiceReferences.TEST.ClientConfig">
  <DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>
<None Include="ServiceReferences.PROD.ClientConfig">
  <DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>

【讨论】:

    【解决方案5】:

    解决问题的好方法
    我无法让&lt;ItemGroup&gt;&lt;/ItemGroup&gt; 部分在我的解决方案中有效工作。
    我将其删除并将以下脚本添加到项目中的 Prebuild 事件中:

    del $(ProjectDir)ServiceReferences.ClientConfig;
    copy $(ProjectDir)ServiceReferences.$(ConfigurationName).ClientConfig $(ProjectDir)ServiceReferences.ClientConfig;
    

    【讨论】:

      猜你喜欢
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 2016-10-16
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 2013-07-05
      相关资源
      最近更新 更多