65.9K
CodeProject 正在变化。 阅读更多。
Home

将 ASMX 服务迁移到 WCF 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (7投票s)

2012年1月9日

CPOL

5分钟阅读

viewsIcon

60635

downloadIcon

1409

创建一个 WCF 服务来替换现有的 ASMX 服务。

问题与目标

许多公司仍然拥有使用 .NET 2.0 ASMX 技术实现的 Web 服务,并且其客户拥有已使用 .NET 2.0 技术创建了代理的工具。通常,引入 WCF 端点将需要重新设计这些工具,这是一个巨大的问题,应尽可能避免。在这种过程中,只有一个修改被认为是可接受的,那就是更改客户端的端点 URL。这是因为 ASMX 服务通常的 URL 为 http://host/Service.asmx,而 WCF 服务为 http://host/Service.svc。目标是在现有客户端工具不知情的情况下更改服务实现,至少在无需修改代码的意义上。

本文讨论了在尝试实现此迁移过程的解决方案时遇到的问题、解决方案和可能的陷阱。

术语

在 WCF 之前,客户端中创建了一个 .NET 2.0 Web 引用,它充当代理,促进与 Web 服务的通信。 .NET3.5 引入了一种新的机制来创建与 WCF 服务器端技术兼容的代理。

为简化起见,本文将每种技术称为

  • Client20
  • Client30

拟议解决方案

有两种方法可以管理这种过渡。

解决方案 1

使 ASMX 和 WCF 层充当实际功能实现的包装器层。这意味着在任何时候都会暴露两个独立的端点,它们将调用重定向到一个公共函数。所有现有客户端将连接到旧端点,所有新客户端将连接到新端点。

解决方案 2

使 WCF 服务充当 ASMX 服务。

研究问题

研究此问题最简单的方法是在一个简单的解决方案中重现它,该解决方案复制现有基础结构并尝试在所有部分(旧的和新的)之间实现有效的连接。

服务器端

为简化起见,创建了一个通用的契约接口,所有服务都实现了该接口。

public interface IStringService 
{ 
    string StringConcat(string value1, string value2);
}

在 ServiceLayer 中创建了两个不同的项目,它们为 IStringService 契约提供 ASMX 和 WCF 服务。

两个服务实现都由通用引用程序集中的一个函数提供。

客户端

创建了不同的客户端项目,它们为上述服务提供代理类。一个项目使用 Client20 进行代理,另一个项目使用 Client30。每个代理类都应该能够实现一个通用接口。此时,所有客户端都可以连接到所有服务,从而形成以下组合。

  • Client20 - ASMX 服务
  • Client20 - WCF 服务
  • Client30 - ASMX 服务(已弃用)
  • Client30 - WCF 服务

Client30 - ASMX 服务组合已弃用。

public interface IStringServiceClient
{
   string StringConcat(string value1, string value2);
}

至此,我们已经满足了解决方案 1 的要求。

对于解决方案 2,目标是创建一个 WCFAsASMX 服务项目,该项目公开实现 IStringService 契约的 WCF 服务,以成功替换上述所有服务。

  • Client20 在不进行代码修改的情况下有效连接,确保了向后兼容性。
  • Client30 在不进行代码修改的情况下有效连接,确保了 WCF 的更改不会阻碍未来的实现。(也就是说,我们不仅仅是改变了实现中的技术名称,而是能够获得 WCF 提供的所有当前和未来的好处。)

可以通过以下步骤实现此目标

  • '''目标 1''' 配合解决方案 2,通过更改 Client20 的 URL 端点来实现成功调用。
  • '''目标 2''' 配合解决方案 2,无需任何更改即可实现成功调用。

目标 1

强制 WCFAsASMX 项目中的 WCF 服务接受 Client20 的请求。在这种情况下,服务名称空间为 "http://tempuri.org/",但也可以是正确指定的名称空间。基于此名称空间,所需的更改是

  • 用以下内容注解服务
  • [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  • 用以下内容注解服务中的方法
  • [WebMethod]
    [OperationContract(Action=@"http://tempuri.org/StringConcat")]
  • 如果您使用的是基本类型的数组,例如 string[],则还需要用以下内容注解服务
  • [XmlSerializerFormat]

    现在,Client20 仅通过更改端点就可以连接到 WCF 服务。从 http://host/Service.asmxhttp://host/Service.svc

目标 2

通过让 IIS 服务处理 ASMX 请求(使用 WCF)来实现此目标。以下是所需的更改

  • 通过在 system.web/compilation 节点中添加以下内容来修改 web.config 文件
  • <buildProviders>
        <remove extension=".asmx">
        <add extension=".asmx" 
          type="System.ServiceModel.Activation.ServiceBuildProvider, 
                System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, 
                PublicKeyToken=31bf3856ad364e35" />
    </buildProvider>
  • 将 SVC 文件中的内容复制到 ASMX 文件中。

比较解决方案

两种解决方案都存在固有的局限性。它们无法在不破坏向后兼容性的情况下为两个客户端提供 WCF 功能。因此,重要的是要理解 Client20 实现应尽快淘汰,因为它们极大地限制了技术迁移的好处。

解决方案 1

优点

  • WCF 服务实现保持不变,不进行任何修改,以保持向后兼容性。这是引入新解决方案时每个人都希望的优点。现有客户端无需修改。

缺点

  • 暴露了两组不同的物理服务层,并且需要维护这两层,它们充当实际功能实现的包装器。
  • 现有客户端不连接到实际的 WCF 技术堆栈,因此它们无法获得新技术的优势,例如性能。
  • 感觉代理生成工具需要支持两种不同的技术。

解决方案 2

优点

  • 虽然暴露了两组逻辑服务层,但只有一组实际的物理服务层。这减少了需要维护的层。
  • 现有工具连接到 WCF 堆栈并受益于新技术优势。

缺点

  • WCF 服务需要进行一些小的修改。尽管这些修改看起来足够简单,但它们是为了向后兼容性而设计的,这一点必须始终予以考虑。积极的一面是,从长远来看,一旦 Client20 实现被淘汰,移除这些修改将非常简单。
© . All rights reserved.