使用 ServiceStack 构建跨平台 Web 服务
本文主要来自MSDN杂志《Building Cross-Platform Web Services with ServiceStack》,Windows Communication Foundation (WCF) 是一个相当优秀的服务框架,当我们讨论跨平台的服务的时候,虽然WCF对WebService的支持还行,在面对一些高级应用的不太好,微软重新发展了ASP.NET WebAPI框架,关于这两个框架的讨论可以看我另外一篇文章《WCF和ASP.NET Web API在应用上的选择》 。在讨论跨平台的Web服务上,ASP.NET Web API是一个重要选项,在本文中,我将展示如何利用 ServiceStack (开放源代码.NET 和Mono REST 服务框架) 来完成这一任务,不用离开 Visual Studio 或 Microsoft.NET/Mono,除了 ServiceStack 之外还有个Nancy的框架,具体可以看《.NET的微型Web框架 Nancy》。
一个典型的 Web 服务结构如下:

- 服务层是您定义您的Web 服务接口的地方。 这也是,客户端和你的 Web 服务进行交互的一层。
- 业务层通常是业务逻辑
- 数据层是为了封装数据访问和操纵在业务层提供抽象的数据模型。
- Web服务通常有远程过程调用(RPC)和RESTful (HTTP)两类,现在占据主导地位的Web服务是RESTful (HTTP),具体内容可以参看文章《REST在企业中获得成功了么?》,贴一张文章里的图片:

2年前REST就已经成为Web API部署方式的主流了,而且一直保持这种发展势头,现在基本上都是REST服务,SOAP在企业内网还存在。
远程过程调用 (RPC) ,每个请求旨在类似于函数调用:
public interface IService
{
string DoSomething(int input);
}
RPC 方法对服务的修改非常不友好。 例如前面的代码段,如果要求从客户端来执行更高版本的 Web 服务的 DoSomething 方法的两个输入参数 — 或需要返回字符串值之外的另一个字段 —— 给老客户重大更改是不可避免的。 当然,您始终可以创建平行的 DoSomething_v2 方法,要带两个输入的参数,但久而久之会搞乱您的 Web 服务接口和消费者,服务变得越来越丑,用WCF实现的Web服务就是属于这种情况,下面我们介绍ServiceStack。
ServiceStack是.Net和Mono的开源框架,相对WCF,MVC及Web API而言它是开发Web服务与Web应用的有力替代品,它越来越普及。 用 ServiceStack 生成的 web 服务可以运行在 Windows 环境中,.NET 代码或Mono支持 Linux 环境中。 Mono支持的操作系统包括:
- Linux
- Mac OS X, iOS
- Sun Solaris
- BSD
- Microsoft Windows
- Nintendo Wii
- Sony PlayStation 3
ServiceStack是一系列事物的综合体:
- 包含高性能Razor Engine的Web应用框架
- 支持例如HTML,XML,JSON,SOAP等多种格式的基于消息的Web服务框架
- 包含内建IOC的容器
- 若干内建库文件,诸如:Text serializer,Redis Client,ORM以及caching providers
- 除了ASP.NET Hosting和Mono Hosting之外,还包含self-hosting选项
ServiceStack 强制远程 Web 服务最佳实践、 基于公约 DTO 标准为其 Web 服务接口,ServiceStack 还提供预置的响应状态对象,可用于撰写 DTO,鼓励更加直接和简单的错误处理方案,显然和WCF是明显不同的路线。
本文假定您有一些熟悉 WCF 和.NET 框架。 为了更好地展示WCF 概念可以如何转化为 ServiceStack 的概念,首先会在WCF中实现服务层。我会告诉你如何通过将WCF Web 服务移植到等效的使用 ServiceStack 转换为跨平台的 Web 服务。
WCF 使用数据合同建立的客户端和服务器之间的通信手段。 ServiceStack和WCF相同。 WCF 需要何数据对象和数据成员打上标记; 否则,WCF 简单地忽略它们。 这是 ServiceStack 和 WCF 与的不同的地方。 ServiceStack 支持所有POCO 的对象作为契约:
WCF的契约:
[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; }
}
[ServiceContract]
public interface ITicketService
{
/// <summary>
/// 检索当前队列中的所有门票的完整清单
/// </summary>
/// <returns></returns>
[OperationContract]
List<Ticket> GetAllTicketsInQueue();
/// <summary>
/// 新增新门票
/// </summary>
/// <param name="ticket"></param>
[OperationContract]
void QueueTicket(Ticket ticket);
/// <summary>
/// 从队列拉出一张票
/// </summary>
/// <returns></returns>
[OperationContract]
Ticket PullTicket();
}
}
把它转换为ServiceStack的契约:
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; }
}
public class GetAllTicketsInQueueRequest
{
}
public class QueueTicketRequest
{
public Ticket Ticket { get; set; }
}
public class PullTicketRequest
{
}
public interface ISCTicketService
{
List<Ticket> Any(GetAllTicketsInQueueRequest request);
void Any(QueueTicketRequest request);
Ticket Any(PullTicketRequest request);
}
ServiceStack 规定每个唯一的请求是对象所标识唯一的请求,这意味着你不能重用 DTO 跨多个服务实现与 ServiceStack 的请求。ServiceStack 支持不同的操作,如有 Get 和 Post。 您的选择在这里仅影响的 HTTP 请求。 指定任何 Web 服务请求是指可以通过 HTTP GET 和 HTTP POST 调用操作。 这种强制措施,简化了 rest 风格的 Web 服务实现。要将您的 ServiceStack Web 服务变成 rest 风格的 Web 服务,只需添加 URL [Route(...)]向您的 Web 服务请求声明属性。
//Request DTO
public class Hello
{
public string Name { get; set; }
}
//Response DTO
public class HelloResponse
{
public string Result { get; set; }
public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized
}
//Can be called via any endpoint or format, see: http://servicestack.net/ServiceStack.Hello/
public class HelloService : Service
{
public object Any(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
//REST Resource DTO
[Route("/todos")]
[Route("/todos/{Ids}")]
public class Todos : IReturn<List<Todo>>
{
public long[] Ids { get; set; }
public Todos(params long[] ids)
{
this.Ids = ids;
}
}
[Route("/todos", "POST")]
[Route("/todos/{Id}", "PUT")]
public class Todo : IReturn<Todo>
{
public long Id { get; set; }
public string Content { get; set; }
public int Order { get; set; }
public bool Done { get; set; }
}
public class TodosService : Service
{
public TodoRepository Repository { get; set; } //Injected by IOC
public object Get(Todos request)
{
return request.Ids.IsEmpty()
? Repository.GetAll()
: Repository.GetByIds(request.Ids);
}
public object Post(Todo todo)
{
return Repository.Store(todo);
}
public object Put(Todo todo)
{
return Repository.Store(todo);
}
public void Delete(Todos request)
{
Repository.DeleteByIds(request.Ids);
}
}
以ASP.NET Hosting承载ServiceStack,创建一个空的ASP.NET应用,使用 NuGet 包管理器控制台将 ServiceStack 引用添加到 ServiceStack.Host.AspNet中所示

Web.config 会增加下面的配置
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<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.WebHost.End 继承实现端点。
public class AppHost : AppHostBase
{
public AppHost() //Tell ServiceStack the name and where to find your web services
: base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly) { }
public override void Configure(Funq.Container container)
{
//Set JSON web services to return idiomatic JSON camelCase properties
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
//Configure User Defined REST Paths
Routes
.Add<Hello>("/hello")
.Add<Hello>("/hello/{Name*}");
//Uncomment to change the default ServiceStack configuration
//SetConfig(new EndpointHostConfig {
//});
//Enable Authentication
//ConfigureAuth(container);
//Register all your dependencies
container.Register(new TodoRepository());
}
/* Uncomment to enable ServiceStack Authentication and CustomUserSession
private void ConfigureAuth(Funq.Container container)
{
var appSettings = new AppSettings();
//Default route: /auth/{provider}
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new CredentialsAuthProvider(appSettings),
new FacebookAuthProvider(appSettings),
new TwitterAuthProvider(appSettings),
new BasicAuthProvider(appSettings),
}));
//Default route: /register
Plugins.Add(new RegistrationFeature());
//Requires ConnectionString configured in Web.Config
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
container.Register<IUserAuthRepository>(c =>
new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
var authRepo = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>();
authRepo.CreateMissingTables();
}
*/
public static void Start()
{
new AppHost().Init();
}
}
ServiceStack Web 应用程序启动时,您的服务合同列出作为元数据操作,如图所示:

相关文章:
SignalR, Filters and ServiceStack
采访ServiceStack的项目领导Demis Bellot——第1部分
采访ServiceStack的项目领导Demis Bellot——第2部分
使用 ServiceStack 构建跨平台 Web 服务的更多相关文章
- 使用 ServiceStack 构建跨平台 Web 服务(转)
出处:http://www.cnblogs.com/shanyou/p/3348347.html 本文主要来自MSDN杂志<Building Cross-Platform Web Service ...
- 使用RpcLite构建SOA/Web服务
使用RpcLite构建SOA/Web服务 SOA框架系列 1. 使用RpcLite构建SOA/Web服务 提到Web服务最先想到的就是WebService此外常用的还有WCF.ServiceStack ...
- 基于IIS构建Pyathon Web服务
本文简单叙述了在Windows下,如何利用IIS构建Python Web服务. 其主要步骤如下: 1.在IIS下构建一个站点,如图: 2.配置Python文件的处理程序,如图: 3.最后,在对应站点根 ...
- Guzzle – 构建 RESTful Web 服务的 PHP HTTP 框架
Guzzle 减轻了发送 HTTP 请求和创建 Web 服务客户端的痛苦.它包含建立一个强大的网络服务客户端的工具,包括:服务描述定义的输入和输出的 API,资源迭代器遍历分页资源,尽可能有效地发送大 ...
- WCF:为 SharePoint 2010 Business Connectivity Services 构建 WCF Web 服务(第 1 部分,共 4 部分)
转:http://msdn.microsoft.com/zh-cn/library/gg318615.aspx 摘要:通过此系列文章(共四部分)了解如何在 Microsoft SharePoint F ...
- 使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务
原文地址:http://www.ibm.com/developerworks/cn/web/wa-restful/ 简介: Spring,构建 Java™ 平台和 Enterprise Edition ...
- 如何快速搭建一个基于ServiceStack框架的web服务
ServiceStack是一个高性能的.NET Web Service 平台,能够简化开发高性能的REST (支持JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式 ...
- SpringBoot实战(十)之使用Spring Boot Actuator构建RESTful Web服务
一.导入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...
- 基于jersey和Apache Tomcat构建Restful Web服务(二)
基于jersey和Apache Tomcat构建Restful Web服务(二) 上篇博客介绍了REST以及Jersey并使用其搭建了一个简单的“Hello World”,那么本次呢,再来点有趣的东西 ...
随机推荐
- windows 用默认软件打开文档
System.Diagnostics.Process.Start("Explorer.exe", string.Format("/e, \"{0}\" ...
- thinkphp导入导出excel表单数据
在PHP项目经常要导入导出Excel表单. 先去下载PHPExcel类库文件,放到相应位置. 我在thinkphp框架中的位置为ThinkPHP/Library/Org/Util/ 导入 在页面上传e ...
- javascript 转盘抽奖代码和计数器代码
要介绍了javascript圆盘抽奖程序实现原理和完整代码例子,需要的朋友可以参考下 看到网页上有不少大转盘抽奖的应用,心血来潮也想弄个.于是找了点资料自己研究... 效果预览: 一.模拟抽奖的实 ...
- 【leetcode】Length of Last Word
题目简述 Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return ...
- [OPENCV] 第一个程序 识别颜色
它可以鉴别出图像中含有给定颜色的所有像素,该算法输入的是图像以及颜色,并返回表示含有指定颜色的像素的二值图像.该算法还需要指定另外一个参数,即对颜色偏差的容忍度. 实现效果 实现后 #include ...
- dir命令只显示文件名
dir /b 就是ls -f的效果 1057 -- FILE MAPPING_web_archive.7z 2007 多校模拟 - Google Search_web_archive.7z 2083 ...
- Python-模块的使用
基础概念 - 模块是Python组织代码的基本方式 - 一个Python脚本可以单独运行,也可以导入到另一个脚本中运行,当脚本被导入运行时,我们将其称为模块(module) - 所有的.py文件都可以 ...
- 实时控制软件设计作业_01——汽车ABS系统分析
制动防抱死系统(antilock brake system)简称ABS.作用就是在汽车制动时,自动控制制动器制动力的大小,使车轮不被抱死,处于边滚边滑(滑移率在20%左右)的状态,以保证车轮与地面的附 ...
- Daily Scrum Meeting ——SecondDay(Beta)12.10
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1. 修复两个Alpha版本所遗留的BUG 2. 着手修改参与者与发布者的侧滑框,改 ...
- [翻译svg教程]svg 中的g元素
svg 中的<g>元素用来组织svg元素.如果一组svg元素被g元素包裹了,你可以通过对g元素进行变换(transform),被g元素包裹的元素也将被变换,就好这些被svg包裹的元素是一个 ...