.NET Web 服务

使用 ServiceStack 构建跨平台 Web 服务

Ngan Le

下载代码示例

工作与 Windows 通信基础 (WCF),因为有优秀的支持,在 Visual Studio 中的框架一样 我发现它相当容易生成 WCF Web 服务从零开始,并会把它和我的开发环境中运行,无需安装额外的工具和可再发行组件。 我将讨论跨平台开发,在这里,我的经历所以你可能对此文章感兴趣,如果符合下列条件:

  • 你已经熟悉 WCF 和 C#。
  • 你需要建立一个跨平台的 Web 服务。

我认为我们都同意编写跨平台应用程序是在造成最少不便,但有时不可避免。 如果你像我一样东西 — — Windows 绑定和大量投资在 C# 中 — — 放在一起的跨平台的 Web 服务可能会引起很大的开销。 这包括重新配置您心爱的 Windows 计算环境,以适应一种完全不同的开发工具集和可能学习另一种编程语言。 在本文中,我将展示如何利用 WCF ServiceStack (开放源代码.NET 和单声道其余 Web 服务框架) 来完成这一任务,不用离开 Visual Studio 或 Microsoft.NET 框架环境的形像。

有关 Web 服务

一个典型的 Web 服务在描绘出奠定了图 1

A Typical Web Service Layout
图 1 典型的 Web 服务布局

服务层是您定义您的 Web 服务接口的地方。 这是,客户端需要消耗您的 Web 服务进行交互的唯一层。

业务层通常是重与业务逻辑,很明显。 这是驻留的 Web 服务实现的肉,保持你的服务层光和合同客户端/服务器和通信为重点。

数据层是为了封装数据访问和操纵在业务层提供抽象的数据模型。

在本文中,我将重点在服务层。

远程过程调用与数据传输对象

某些 Web 服务采取的远程过程调用 (RPC) 的方法,每个请求旨在类似于函数调用:

public interface IService {
  string DoSomething(int input);
}

RPC 方法往往使 Web 服务更容易打破界面的更改。 例如,在前面的代码段,如果更高版本的 Web 服务的要求从客户端来执行 DoSomething 方法的两个输入 — — 或需要返回字符串值之外的另一个字段 — — 给老客户重大更改是不可避免的。 当然,您始终可以创建平行的 DoSomething_v2 方法,要带两个输入的参数,但久而久之会搞乱您的 Web 服务接口和混淆你的消费者,旧的和新的风险。

传统智慧偏爱面向数据传输对象 (DTO) 模型的定义 Web 服务接口。 下面的代码演示如何在 DTO 模式下可以变成 Web 方法做些什么:

public class DoSomethingRequest {
  public int Input { get; set; }
}
public class DoSomethingResponse {
  public string Result { get; set; }
}
public interface IService {
  DoSomethingResponse DoSomething(DoSomethingRequest request);
}

继此学派,每个 Web 方法采用单个 DTO 请求并返回单个 DTO 响应。 想法是添加新的域 DTO 的请求和响应 DTO 不会打破旧的客户端。

值得注意 RPC 样式和 DTO 样式的 Web 服务接口 WCF 支持的但 ServiceStack 仅支持的 DTO 样式。 ServiceStack 拥抱的远程 Web 服务接口,较少比较烦琐,所以和 Web 服务接口设计中的更多 chunkiness 的 DTO 样式的原则。 这是 ServiceStack,了解的关键,因为该框架旨在强化原则的方式。

ServiceStack 是什么?

如前所述,ServiceStack 是一个开源的跨平台的单声道 Web 服务框架,和它越来越普及。 用 ServiceStack 生成的 web 服务可以运行在 Windows 环境中,.NET 代码或单声道的支持 Linux 环境中。 由单声道支持的操作系统包括:

  • Linux
  • Mac OS X iOS
  • Sun Solaris
  • BSD
  • Microsoft Windows
  • 任天堂 wii 游戏机
  • 索尼 PlayStation 3

有关单声道所支持的平台的详细信息,请参阅单声道-project.com/Supported_Platforms

如果您喜欢使用的.NET 框架和 WCF,需要部署.NET Web 服务不是 Windows 环境中的,ServiceStack 将是一个理想的选择。 由于 ServiceStack 和 WCF 的相似性,过渡到另一个需要在开发环境和工具的小调整。 你要继续写 Visual Studio 里面的 C# 代码。

ServiceStack 强制远程 Web 服务最佳实践、 基于公约 DTO 标准为其 Web 服务接口,而 WCF 留给您自由定义 Web 服务 API,你看看合适。 ServiceStack 还提供预置的响应状态对象,可用于撰写 DTO,鼓励更加直接和简单的错误处理方案的反应。 可以轻松地实现这与 WCF,虽然它不是明显的路线。 最新版本的 ServiceStack 也提供了类似于基于异常的错误处理机制 — — 虽然不是偏爱­ticated 作为 — — WCF 基于过失的错误处理通过故障的合同。

由 ServiceStack 强制执行的标准容易实现在 WCF 与一个小的额外打字。 然而,除了便携性,ServiceStack 是一个可行的办法,建立一个 rest 风格的 Web 服务,因为它建立了简化路由的 HTTP URI 的公约。 同时,ServiceStack 部队每个 Web 服务请求,将在一个单独的类,促进自然分离关注 rest 风格的服务模型。

ServiceStack 还提供了其他好处,预置的伐木和基本数据验证实用程序。 你可以阅读更多关于在 servicestack ServiceStack。 净。

本文假定您有一些熟悉 WCF 和.NET 框架。 为了更好地展示 WCF 概念可以如何转化为 ServiceStack 的概念,我首先会在 WCF 中实现服务层。 我会告诉你如何通过将它移植到等效的 Web 服务使用 ServiceStack 转变为跨平台的 Web 服务的 WCF Web 服务。

构建一个简单的 WCF Web 服务

为了演示如何 ServiceStack 可以作为替代 WCF 在多平台环境中,我会用一个简单的 WCF Web 服务启动。

Web 服务是琐细的餐厅的票务系统,称为 TicketService,实现以下服务合同:

[ServiceContract]
public interface ITicketService {
  [OperationContract]
  List<Ticket> GetAllTicketsInQueue();
  [OperationContract]
  void QueueTicket(Ticket ticket);
  [OperationContract]
  Ticket PullTicket();
}

TicketService 允许其客户端队列新票证、 拉出一张票从队列和检索当前队列中的所有门票的完整清单。

Web 服务三个 Visual Studio 项目,如图所示,在图 2(运行我的样品溶液,可在下载 archive.msdn.microsoft.com/mag201308Services,需要与 Web 开发人员工具和.NET 框架 4.5 Visual Studio 2012)。

WCF Ticket Service Visual Studio Projects
图 2 WCF 票务服务 Visual Studio 项目

这三个项目简要说明如下:

  • TicketSystem.ServiceContract 项目是服务接口定义的位置。
  • TicketSystem.TicketProcessor 项目包含 Web 服务的业务逻辑的实现细节。 此项目不包含引用 wcf。
  • WcfServer 项目实现票务­System.ServiceContracts 和 Web 主机在 IIS 中的服务。

我还把 WCF 客户端使用 TicketService。 WCF 客户端是一个控制台应用程序使用从将 WCF 服务引用添加到 TicketService 生成的代码与在 IIS 中使用 SOAP 的 Web 服务进行通信。 下面是客户端控制台执行:

static void Main(string[] args) {
  Console.Title = "WCF Console Client";
  using (TicketServiceClient client = new TicketServiceClient()) {
    Ticket[] queuedTickets = client.GetAllTicketsInQueue();
    foreach (Ticket ticket in queuedTickets) {
      PrintTicket(ticket);
    }
  }
}

中所示的信息服务的客户端代码执行图 3

The WCF Console Client
图 3 控制台 WCF 客户端

建立等效 ServiceStack Web 服务

先决条件与 ServiceStackServiceStack 与工作,首先必须下载可再发行组件。 若要执行此操作最简单的方法是通过 NuGet Visual Studio 拓­sion 使您可以轻松地安装和更新第三方库和工具。 你可以下载并安装客户端从 NuGet nuget.codeplex.com。 NuGet 安装后,您应该看到在 Visual Studio 中的菜单项所示图 4

The NuGet Package Manager Console in Visual Studio
图 4 在 Visual Studio 中,NuGet 包管理器控制台

现在我会做分步攻略关于如何创建一个 ServiceStack Web 服务,相当于我先前建立的 WCF Web 服务。

首先,采取的 WCF Web 服务示例作为起始点。 然后从解决方案中删除 WcfClient 和 WcfServer 项目。 这些项目是特定于 WCF,和以后他们就会替换与 ServiceStack 兼容的项目。

在软件包管理器控制台窗口中,选择 TicketSystem.ServiceContract 的项目。 在命令提示符下,键入"安装包 ServiceStack,"如图所示,在图 5

Installing ServiceStack Redistributables with NuGet Package Manager
图 5 安装可再发行组件 ServiceStack 与 NuGet 包管理器

这一步下载最新的可再发行组件有必要建立一个使用 ServiceStack 的.NET Web 服务。 可再发行组件名称"软件包"放置在您的 Visual Studio 解决方案根文件夹文件夹下上演。 另外,DLL 的引用添加到 TicketSystem.ServiceContract 项目。 是在您的项目根文件夹中创建一个 packages.config 文件为您提供每个 ServiceStack dll 的版本和运行时信息:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="ServiceStack" version="3.9.46" 
    targetFramework="net45" />
  <package id="ServiceStack.Common” version=“3.9.46”
    targetFramework="net45" />
  <package id="ServiceStack.OrmLite.SqlServer" version="3.9.45"
    targetFramework="net45" />
  <package id="ServiceStack.Redis" version="3.9.45"
    targetFramework="net45" />
  <package id="ServiceStack.Text" version="3.9.46"
    targetFramework="net45" />
</packages>

下一步,将转换到 ServiceStack 可以理解的东西 TicketSystem.ServiceContract 项目中定义的 WCF 数据合同。

WCF 数据合同转换数据合同 ServiceStack WCF 使用数据合同建立的客户端和服务器之间的通信手段。 ServiceStack 相同。 WCF 需要适当的属性都放任何数据对象和数据成员,您想要序列化和送丝 ; 否则,WCF 简单地忽略它们。 这是 ServiceStack 和 WCF 与的不同。 ServiceStack 将所有平原旧 CLR 对象序列 (思卡尔) 的服务合同中引用和使其可见到客户端。 下面是 WCF 和 TicketService 接口在同一票数据合同参考 ServiceStack 代码表示。

这里是 WCF <Ticket> 合同的数据:

[DataContract]
public class Ticket {
  [DataMember]
  public int TicketId { get; set; }
  [DataMember]
  public int TableNumber { get; set; }
  [DataMember]
  public int ServerId { get; set; }
  [DataMember]
  public List<Order> Orders { get; set; }
  [DataMember]
  public DateTime Timestamp { get; set; }
}

这里是 ServiceStack <Ticket> 合同的数据:

public class Ticket {
  public int TicketId { get; set; }
  public int TableNumber { get; set; }
  public int ServerId { get; set; }
  public List<Order> Orders { get; set; }
  public DateTime Timestamp { get; set; }
}

服务的主要区别­堆栈和 WCF 服务接口就是 ServiceStack 放的服务接口的附加限制。 ServiceStack 规定每个唯一的请求是对象所标识唯一的请求,因为没有任何概念的 Web 服务"操作"(即,方法名称) 在世界中的 ServiceStack。 这意味着你不能重用 DTO 跨多个服务实现与 ServiceStack 的请求。 ServiceStack Web 服务操作的所有合同将都等同于类似于以下的 WCF 服务合同:

[ServiceContract]
public interface ITicketService {
  [OperationContract]
  List<Ticket> GetAllTicketsInQueue(GetAllTicketsInQueueRequest request);
  [OperationContract]
  void QueueTicket(QueueTicketRequest request);
  [OperationContract]
  Ticket PullTicket(PullTicketRequest request);
}

前面的代码是什么比原始的 RPC 样式 TicketService WCF 服务接口所示,但转换以拥抱 DTO 公约:

[ServiceContract]
public interface ITicketService {
  [OperationContract]
  List<Ticket> GetAllTicketsInQueue();
  [OperationContract]
  void QueueTicket(Ticket ticket);
  [OperationContract]
  Ticket PullTicket();
}

这里是等效的 TicketService ServiceStack 服务接口:

public class GetAllTicketsInQueueRequest {}
public class QueueTicketRequest {
  public Ticket Ticket { get; set; }
}
public class PullTicketRequest {}
public interface ITicketService {
  List<Ticket> Any(GetAllTicketsInQueueRequest request);
  void Any(QueueTicketRequest request);
  Ticket Any(PullTicketRequest request);
}

ServiceStack 支持不同的操作,如有 Get 和 Post。 您的选择在这里仅影响的 HTTP 请求。 指定任何 Web 服务请求是指可以通过 HTTP GET 和 HTTP POST 调用操作。 这种强制措施,简化了 rest 风格的 Web 服务实现,这已经超出了本文的范围。 要将您的 ServiceStack Web 服务变成 rest 风格的 Web 服务,只需添加 URL [Route(...)]向您的 Web 服务请求声明属性。

创建 ASP.NET 承载 ServiceStack Web 服务现在,你有 ServiceStack Web 服务定义的 Web 服务接口,它是执行它,把它推出的时间。

首先,添加 ASP.NET 空 Web 应用程序。 这是线在选择以主机为方便我 ServiceStack Web 服务的方式。 它不是唯一的宿主 Web 服务建立在 ServiceStack 基础上的方法。 你还可以承载内部 Windows 服务或在运行下一个 Web 服务器,或甚至独立的一个控制台应用程序的窗体中的服务。

此 Visual Studio 项目 ServiceStackServer 的名字 它是相当于 WCF 服务的代码示例中的 WcfServer 项目。

使用 NuGet 包管理器控制台将 ServiceStack 引用添加到 ServiceStackServer 中所示图 6

Add ServiceStack Library References to the ServiceStackServer Project
图 6 ServiceStack 库项目添加引用 ServiceStackServer

现在你有你的需要来实现 ITicketService 接口。 TicketService 类必须扩展 ServiceStack.Service­Interface.Service 类提供的框架下,像这样:

public class TicketService : ServiceStack.ServiceInterface.Service,
  ITicketService {
  public List<Ticket> Any(GetAllTicketsInQueueRequest request) {
    // Implement ...
}
  public void Any(QueueTicketRequest request) {
    // Implement ...
}
  public Ticket Any(PullTicketRequest request) {
    // Implement ...
}
}

一切都是 WCF 执行相同。

接下来,添加全局应用程序类命名 Global.asax 到 ServiceStackServer 项目,如中所示图 7。 这是在您初始化 ASP.NET Web 应用程序。

Add Global.asax to ServiceStackServer
图 7 添加 Global.asax ServiceStackServer

你需要从 ServiceStack.WebHost.End 继承­点。如果您想要您的 ASP.NET 应用程序内的 Web 服务主机的 AppHostBase 类。 有关示例,请参见图 8

图 8 承载 ASP.NET 里面 ServiceStack Web 服务

public class Global : System.Web.HttpApplication {
  public class TicketServiceHost : 
    ServiceStack.WebHost.Endpoints.AppHostBase {
    // Register your Web service with ServiceStack.
public TicketServiceHost()
      : base("Ticket Service", typeof(TicketService).Assembly) {}
    public override void Configure(Funq.Container container) {
      // Register any dependencies your services use here.
}
  }
  protected void Application_Start(object sender, EventArgs e) {
    // Initialize your Web service on startup.
new TicketServiceHost().Init();
  }
}

如果在运行 IIS 7 下及更高版本,配置项中展出图 9 必须添加到 Web.config 文件。

图 9 Web.config File 的 IIS 7 和更高版本

<configuration>
  <system.web>...</system.web>
  <!--Required for IIS 7 (and above) -->
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <add path="*" name="ServiceStack.Factory"
        type="ServiceStack.WebHost.Endpoints.
ServiceStackHttpHandlerFactory, ServiceStack"
        verb="*" preCondition="integratedMode"
          resourceType="Unspecified"
        allowPathInfo="true" />
    </handlers>
  </system.webServer>
</configuration>

ServiceStack Web 应用程序启动时,您的服务合同列出作为元数据操作,如图所示,在图 10。 现在您的 Web 服务是准备接受客户端请求。 在下一节中,我将提供一些消费者例子 ServiceStack Web 服务。


图 10 TicketService 元数据

ServiceStack 内置的客户端

发展集团是非常坦率的反对 ServiceStack 生成 Web 服务客户端代码,所以框架提供了一套服务下所列的内置 Web 服务客户端的­Stack.ServiceClient.Web 命名空间。 所有内置的客户端执行 ServiceStack.Service.IServiceClient。 那些支持其余执行 ServiceStack.Service.IRestClient。

可用的客户包括:

  • JsonServiceClient
  • JsvServiceClient
  • XmlServiceClient
  • MsgPackServiceClient
  • ProtoBufServiceClient
  • Soap11ServiceClient
  • Soap12ServiceClient

每个支持一种不同的序列化/反序列化格式。 它们的用法是可以互换的因为他们实施了一套通用的接口。

为了简单起见,创建控制台应用程序中调用 ServiceStackClient 来消耗你的 ServiceStack 票­使用 JsvServiceClient 的服务。 如果你想要尝试一下不同的客户端,只需替换以前列出的可用客户任何的端 JsvServiceClient 以下代码:

static void Main(string[] args) {
  Console.Title = "ServiceStack Console Client";
  using (var client = new JsvServiceClient("http://localhost:30542")) {
    List<Ticket> queuedTickets =
      client.Send<List<Ticket>>(new GetAllTicketsInQueueRequest());
    if (queuedTickets != null) {
      foreach (Ticket ticket in queuedTickets) {
        PrintTicket(ticket);
      }
    }
  }
}

控制台应用程序中执行以下操作:

  • 查询 TicketService 队列中的所有车票。
  • 打印出它从 TicketService 回来的结果票。

在控制台输出是完全相同作为生成 WCF 客户端上,所示的图 3

更多优惠

这篇文章只皮毛上 ServiceStack 已提供 WCF 用户寻求跨平台解决方案。 我甚至还没有讨论进行流式处理,异步请求和消息队列,例如 ServiceStack 的支持。

正如你所看到的几个额外的步骤生成所需 ServiceStack Web 服务,而不是一个 WCF Web 服务。 不过,这种努力是相当微不足道,变换成一个多平台的 ServiceStack Web 服务的 Windows 绑定 WCF Web 服务的服务层。 如果去不同的路线,寻找平台的独立性 — — 例如,使用 Java Web 服务 — — 的努力和学习曲线会一直大得多的比较。

综合考虑,如果您的 Web 服务注定的只能在 Windows 操作系统上运行,然后 WCF 是可以说的更好的解决方案。 有较少的系统开销构建 WCF Web 服务在 Windows 环境中,从零开始时和你没有另一个第三方发行,维护和部署到目标系统。

Ngan Le  是高级软件工程师密切合作,与 WCF 最近开始为 Web 服务的跨平台解决方案探索 ServiceStack.

衷心感谢以下技术专家对本文的审阅:安德鲁 Oakley (Microsoft)
安德鲁 Oakley 是高级项目经理模式 & 团队的做法。 之前成为项目经理,安德鲁花了两年时间,作为技术的福音传教士,Visual Studio 和.NET 平台。 他当前项目的重点是围绕建设不羁的持久性系统使用关系和 NoSQL 数据存储的数据访问指导。