在.NET中管理多个服务引用的最佳方法

问题描述 投票:3回答:3

我有一个带有15个WCF / ASMX服务引用的C#ASP.NET项目。每个服务都部署到三个不同的服务器; teststaginglive

通常我们需要将这些服务引用的URL更改为不同的服务器,以便能够使用正确的服务和正确的实现和数据进行调试。

管理这些服务引用时,我很难保持URL同步。在创建服务引用FooService时,它将URL存储在三个单独的文件中:

  • FooService.disco
  • configuration.svcinfo
  • Reference.svcmap

随着在endpoint中创建一个带有URL的Web.config节点。

如果我在Web.config中更改端点URL并重建项目,它不会更新其他文件中的URL,因此它不同步。因此,当我右键单击FooService并单击Update Service Reference时,它不使用存储在Web.config中的URL,它使用其他文件中的URL。

因此,唯一的方法是右键单击FooService并单击Configure Service Reference并输入新的URL。但这并不总是有效,因为有时它会在Web.config中创建一个名为FooService1的新节点,所以在运行我的应用程序时会出现错误,说有两个相同端点的实例。

因此,我经常需要浏览Web.config并删除端点的重复项,这非常令人沮丧。

经常更改URL到服务时,管理多个WCF服务引用的最佳方法是什么?

asp.net .net wcf visual-studio-2012 service-reference
3个回答
6
投票

First an overview

我处理它的方式是不通过Visual Studio添加服务引用。我所拥有的是每个服务在解决方案中都有自己的代理项目,代理是使用简单的一行批处理文件创建的。然后将其中的每一个作为“香草”参考包含在网站中。终结点在Web配置中以maunally配置。我有三个部署选项:Debug(本地),Staging和Release。在web.config级别,不同的地址由web.config transformations处理。配置代理项目文件,以便根据解决方案配置使用正确的端点地址。但是,重要的是要注意web.config转换仅适用于发布解决方案。

在VS2010之前,我有3个变种的web.config文件,它们会覆盖活动的web.config;但是以这种方式覆盖web.config总是让我觉得“冒险”。在这种情况下,我认为使用转换进行发布仍然有效,但在实际的web.config文件中有一些连接块,当您想要调试登台或开发服务器时,可以对这些连接进行注释。

我只有2个服务,所以我的设置非常简单,15个设置将涉及相当多的工作,但从长远来看,它将为您节省头痛。

Implementation

首先备份一切!!

还可以随时使用现有web.config的副本来帮助稍后配置端点。

另请注意,如果您的解决方案位于名称中包含空格的路径中,则批处理文件将不起作用,例如:默认位置VS放置其项目。我的所有项目都是以下结构C:\Source\vs2008\C:\Source\vs2010\等。我会看看我是否能找到更好的解决方案。

0以管理员身份运行VisualStudio

右键单击开始菜单中的Visual Studio,然后选择“以管理员身份运行”。我们需要这样做,因为VS将编写文件。

1删除现有服务引用

你不应该需要任何帮助。

2添加代理项目

现在这样做意味着您只需要为test | staging | live配置一次解决方案。

从文件菜单中选择“添加”,然后选择“新建项目”,然后从“Visual C#”中选择“类库”,并将其命名为合理的。我将在这个例子中使用FooService.proxy。重命名类文件,我将在本例中使用FooService_proxy.cs

将以下引用添加到项目中:

  • System.Runtime.Serialization
  • System.ServiceModel

为每个服务添加一个项目。我们稍后会回来并更新这些项目。

3配置解决方案以处理test | staging | live

我假设你在本地机器上开发asp.net网站时使用test

通过在Build Configuration下拉菜单中选择它来打开“Configuration Manager”。

在“Active Solution Configuration”下拉列表中选择“New”

对于名称,我建议“暂存”并选中“创建新项目混淆”复选框。

在Solution Explorer中,右键单击Web.Config并选择“Add config transforms”。这将为staging web.config转换添加一个新文件。单击展开箭头,您将看到三个子文件:Web.Debug.Config,Web.Release.Config,Web.Staging Config。

4设置代理

通过单击解决方案资源管理器中的项目并选择“添加>新项”,将批处理文件添加到每个代理项目。使用文本文件并将其命名为“CreateProxy.bat。

将以下内容插入新文件并保存:

:: ============================================================================================
:: Create the proxy file from the service wsdl
:: Input parameters
:: SDK Path The location of svcutil.exe
:: WSDL File Arg1 (%1)
:: Output Proxy .CS file Arg2 (%2)
::
:: Called by the build process of the BeforeBuild target to re-gen the proxy code.
:: Make sure to change FooService.proxy
:: ============================================================================================

svcutil %1 /ct:System.Collections.Generic.List`1 /serializer:DataContractSerializer  /tcv:Version35  /n:*,FooService.Proxy /out:%2

现在右键单击代理项目并单击“卸载项目”,如果出现提示则保存。这将使我们能够进入并修改项目文件。右键单击现在为灰色的代理项目名称,然后选择“编辑”。

添加以下内容仅适用于结束</project>标记。请注意,您可能需要根据SDKPath的位置更改路径svcutil。还要确保将FooService_proxy.cs命名为代理文件。

<PropertyGroup>
  <!-- These properties are used by the svcutil batch file task in the BeforeBuild Target to regen the proxy code -->

  <SDKPath Condition="'$(SDKPath)'==''">C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin</SDKPath>
  <WSDLPath Condition="'$(WSDLPath)'=='' and '$(Configuration)' == 'Debug'">http://[Path to TEST Server Service]</WSDLPath>
  <WSDLPath Condition="'$(WSDLPath)'=='' and '$(Configuration)' == 'Staging'">http://[Path to STAGING server Service]</WSDLPath>
  <WSDLPath Condition="'$(WSDLPath)'=='' and '$(Configuration)' == 'Release'">http://[Path to LIVE Server Service]</WSDLPath>
  <SkipProxyRegen Condition="'$(SkipProxyRegen)'==''">false</SkipProxyRegen>
</PropertyGroup>
<Target Name="BeforeBuild">
  <Message Importance="normal" Text="Rebuilding the proxy code from batch file '$(ProjectDir)CreateProxy.bat'" Condition="'$(SkipProxyRegen)'=='false'" />
  <Exec Command="$(ProjectDir)CreateProxy.bat $(WSDLPath) $(ProjectDir)FooService_proxy.cs" WorkingDirectory="$(SDKPath)" Condition="'$(SkipProxyRegen)'=='false'" />
</Target>

保存更改,然后右键单击灰色的项目名称,然后选择“重新加载项目”。

右键单击项目并选择构建,确保现在填充了代理文件。

设置每个代理项目,使其始终只构建到其'\bin目录,例如不是bin\debug等。右键单击代理项目并选择“属性”。选择“构建”选项卡,然后将“配置”下拉菜单更改为“所有配置”。将“输出路径”设置为bin\

5将代理参考和结束点添加到您的网站

通过右键单击“引用>添加引用”,然后转到“项目”选项卡,将对每个代理项目的引用添加到您的网站。

现在打开web.config文件并添加绑定,使用以前的web.config作为指南。

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="fooServiceEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
                    maxBytesPerRead="8192" maxNameTableCharCount="2147483647" />
                <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
            <!-- Insert other binding as required -->
        </basicHttpBinding>
    </bindings>
    <client>
        <!-- Test Server Endpoints - Used for day-to-day development -->
        <endpoint address="http:[Path to TEST Server service]"
        binding="basicHttpBinding" bindingConfiguration="fooServiceEndpoint"
        contract="FooService.Proxy.IFooService" name="fooServiceEndpoint" />
        <!-- Add Other endpoints as required -->

        <!-- Staging Server End Points - Used Occasionaly
        <endpoint address="http:[Path to STAGING Server service]"
        binding="basicHttpBinding" bindingConfiguration="fooServiceEndpoint"
        contract="FooService.Proxy.IFooService" name="fooServiceEndpoint" />
        <other end points here too />
        -->

        <!-- LIVEServer End Points - Used Rarely and with CAUTION
        <endpoint address="http:[Path to LIVE Server service]"
        binding="basicHttpBinding" bindingConfiguration="fooServiceEndpoint"
        contract="FooService.Proxy.IFooService" name="fooServiceEndpoint" />
        <other end points here too />
        -->
    </client>
</system.serviceModel>

现在,您只需根据要进行调试的服务器修改带有注释的Web配置

6设置web.config转换以进行部署

展开解决方案资源管理器中的web.config节点。

打开web.staging.config文件并添加以下内容:

<system.serviceModel>
    <client>
        <endpoint address="http:[Path to STAGING server Service]"
        binding="basicHttpBinding" bindingConfiguration="fooServiceEndpoint"
        contract="FooService.Proxy.IFooService" name="fooServiceEndpoint" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </client>
    <!-- Repeat for additional end points -->
</system.serviceModel>

现在将相同内容添加到Web.Release.Config,将路径更改为LIVE服务器路径。现在,使用VisualStudio发布命令发布时,将使用相应的端点。

例如。如果部署STAGING版本的网站,请从Build Configuraion下拉列表中选择“Staging”。右键单击解决方案expolorer中的WebSite项目,然后选择“发布”。选择您希望发布的方式,然后单击“发布”按钮。然后整个解决方案将重建,代理将从Staging服务器生成,web.config文件将与Staging设置一起发布。

多数民众赞成,你已经完成了

您现在拥有将根据您的构建配置生成的代理,一个通过注释进行调试以更改路径的位置,以及在publising上自动更新web.config。

更新

作为OP的Gaui已经创建了一个小的exe,简化了这一点。它可以在GitHub上获得


1
投票

一种技术是获取端点并在代码中替换URL(例如,您可以从数据库中执行此操作),具体如下:

endpoint.Endpoint.Address = new System.ServiceModel.EndpointAddress(remoteUrl);

1
投票

我也遇到了很多问题。但我最终找到了一个简单易行的方法。我的例子有一个虚假的服务地址:

  • 创建命令行EXE
  • 使用地址https://service.somePortal.com/FooConnector.svc和名称空间“MyServiceReference”添加服务引用
  • 假设该服务提供了一个接口“IFooConnector”。选择“确定”以生成(大量)代码以使用该服务。

之后,在App.config文件中,您将看到一个新的serviceModel部分:

<system.serviceModel>
    <bindings>
        <customBinding>
            <binding name="NetHttpsBinding_IFooConnector">
                <binaryMessageEncoding />
                <httpsTransport />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="https://service.somePortal.com/FooConnector.svc"
            binding="customBinding" bindingConfiguration="NetHttpsBinding_IFooConnector"
            contract="MyServiceReference.IFooConnector" name="NetHttpsBinding_IFooConnector" />
    </client>
</system.serviceModel>

您现在可以使用这样的服务方法:

using TestClient.MyServiceReference;

namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var client = new FooConnector())
            {
                client.DoSomething();
            }
        }
    }
}

现在重要的部分:

要使用相同服务的三个墨迹,如DEV(开发),TEST(测试)和PROD(生产)在不同的地址,但具有相同的界面,您只需手动编辑您的App.config并使用不同的构造函数实例化客户端!


这是带有更改的serviceModel部分的新App.config:

<system.serviceModel>
    <bindings>
        <customBinding>
            <binding name="NetHttpsBinding_IFooConnector">
                <binaryMessageEncoding />
                <httpsTransport />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="https://dev-service.somePortal.com/FooConnector.svc"
            binding="customBinding" bindingConfiguration="NetHttpsBinding_IFooConnector"
            contract="MyServiceReference.IFooConnector" name="DEV" />

        <endpoint address="https://test-service.somePortal.com/FooConnector.svc"
            binding="customBinding" bindingConfiguration="NetHttpsBinding_IFooConnector"
            contract="MyServiceReference.IFooConnector" name="TEST" />

        <endpoint address="https://service.somePortal.com/FooConnector.svc"
            binding="customBinding" bindingConfiguration="NetHttpsBinding_IFooConnector"
            contract="MyServiceReference.IFooConnector" name="PROD" />
    </client>
</system.serviceModel>

如您所见,我们现在有三个具有不同服务地址的端点部分。我还更改了端点名称属性以匹配我想要的DEV,TEST和PROD命名。

要调用所需的服务,您现在可以使用客户端的不同构造函数,其中包含一个参数:string endpointConfigurationName。因此,您现在可以在其三个墨迹中使用相同的服务方法,如下所示:

using TestClient.MyServiceReference;

namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var client = new FooConnector("DEV"))
            {
                //Call method in DEV
                client.DoSomething();
            }

            using (var client = new FooConnector("TEST"))
            {
                //Call method in TEST
                client.DoSomething();
            }

            using (var client = new FooConnector("PROD"))
            {
                //Call method in PROD
                client.DoSomething();
            }
        }
    }
}

而已! :-)

P.S。:在我的真实项目中,我有一个枚举用户设置,可以选择DEV,TEST,PROD来通过配置更改使用过的服务。

© www.soinside.com 2019 - 2024. All rights reserved.