看WCF Web API的第一印象

标绘交流群 2011-09-23

每隔几天,就会打开http://aspnet.codeplex.com去看看有什么动态,前两天无意间打开后发现了一个新东西,WCF Web API,本来我对WWW(WCF,WF,WPF)没有啥好印象,虽然在各大招聘网站上好像需求量倒不小,但是我发现这个Web API貌似是有关REST的内容,于是就多看了两眼,发现果不其然。

不幸的是,现在Web API还是preview版本,文档少的可怜,只有源代码和一个几乎没有什么用的Sample,上网搜索也没有结果。前两天看到一句话,大概意思是:前两年大家都在考虑要不要REST,现在已经开始考虑如何REST了。

尽管如些,但是在.NET平台上,REST好像还只是一种概念,研究的人都很少,更不要说投入生产了。关于WCF,刚问世时我倒是学习过一段时间,也做了几个例子,但是引用WCF服务的那种方式我一直不喜欢,在客户端中生成一堆代码,然后再使用那个蹩脚的***Client来调用服务,这就让我产生一个疑问:在两个客户端中调用同一个服务,难道需要生两个Client不成?再则,既然是服务,那就应该是一个“开放”的东西,虽然WSDL名声显赫,然则过于庞大繁复,如果你想用浏览器来调用WCF的服务,从现实上来说似乎不太可能,如果从浏览器不能调用一个Web服务(当然是GET),那这个Web服务似乎就不太纯粹;最后,HTTP是一个完善的协议 ,对于操作数据尤为如此,无论多么复杂的需求,最终对于数据而言无外乎增删改查耳,HTTP都具有了,作为一个真正开放、通用的服务来说,使用HTTP的基本方法,几乎没有不能完成的任务。于是对于操作"用户"数据而言,使用GET、POST、PUT、DELETE足已,实在没有必要再自定义一些诸如GetUser,CreateUser之类的RPC方法,为啥一定得要人花一番工夫才能知道添加一个用户到底是用Create还是Add呢?从某种意义来说,每一个网站实际上都是一个Web服务,不是吗?基于HTTP,提供数据,只要你输入对URL,它永远都会将你想要的结果呈现在你的眼前,如果这样一个服务,你要使用类似WCF的框架去提供,使用这个Web服务的人会如何评价呢?他永远不知道在你的“服务”后面是加一个View还是Get抑或是Display...

然而,做技术的人往往喜欢把一个简单的问题想的无限大,然后再整出一个周身毛病的解决方案,等引诱人家去上当,到最终满头包时,才回归到问题本质,推出一个兼顾的方案,如果这还说的不透彻,那么试想,你现在需要剪刀,然而很快专家们就设计出了瑞士军刀,因为他们想到你以后很可能还会需要用...,到最后,你发现你使用几乎天天用剪刀,那些掏耳勺,镊子,起瓶器之类的几乎不用,最后,手里还是拿了把张小泉。记得以前看过一句话:请把牛B还给牛,我想说的是,请把HTTP还给HTTP,无论是在前端还是在服务端。

这两天映入眼帘的东西较多,有IronJS,MongoDB,还有就是正在说的这个WCF Web API了,其实这段时间我正在做一个类似的框架,是在ASP.NET MVC上开发一个轻量级的REST框架(说框架好像有点抬举自已了),基本思路是使用MVC的Action作为数据服务,使用M$的Syndication来做数据传递格式,使用WebRequest以及WebResponse来手工向服务发起请求以及回传响应,目前支持Atom和JSON格式的内容,核心部分已经完工了,本来打算投入使用后写几篇说明和各位兄弟探讨,但是现在又发现了WCF Web API,这让我很纠结,不知道该是继续呢还是先研究下Web API。昨天把那本《MongoDB权威指南》算是粗读了一遍,今天晚上闲来无事,又把那个WCF Web API的源码包打开看了看,了解下这个所谓的Web API到底是怎么回事,内容不多,但是由于下周有个项目有新需求要增加,而从下下周开始要休假一段时间,因此有必须把今天看的东西记录下来,以免再过20来天,又不知丢到哪里去了。

要了解一个ASP.NET应用的原理,还是得看Global、HttpHandler、HttpModel,在Web API的示例(ContactManager_Advanced)中,没有发现显示使用HttpHandler和HttpModel,那就只能看Global了:

protected void Application_Start(object sender, EventArgs e)  


{  



// use MEF for providing instances  




var catalog = new AssemblyCatalog(typeof(Global).Assembly);  




var container = new CompositionContainer(catalog);  



var config = HttpHostConfiguration.Create().  


AddFormatters(  



new ContactPngFormatter(),  




new ContactFeedFormatter("http://localhost:9000/Contact"),  




new VCardFormatter(),  




new CalendarFormatter()).  




SetResourceFactory(new MefResourceFactory(container)).  




AddMessageHandlers(typeof (LoggingChannel), typeof (UriFormatExtensionMessageChannel));  



SetMappings();  



RouteTable.Routes.MapServiceRoute<ContactResource>("Contact", config);  




RouteTable.Routes.MapServiceRoute<ContactsResource>("Contacts", config);  



} 

有意义的显然是这段了,

catalog变量是指MEF用于导入的目录,container是组合容器,有了这两个对象实例后,就开始创建一个HttpHostConfiguration的实例,使用一些自定义的Formatter,Formatter是啥用通呢?如果你了解AtomEntry,那就知道,AtomEntry里面实际是一种格式,它定义了一些固定的内容(属性),比如:Id,Title,Summary,Link之类的,对于一个User实体来说,UserName如何表示呢,当能只能去扩展这个AtomEntry了,而这个Formatter就是扩展这个AtomEntry的。SetResourceFactory,这个方法的作用是定义一个资源工厂,啥是资源?在REST中,把用户需要请求操作的服务即称为资源,http://localhost/User,这是一个Url,没错,但是这个Url就代表User服务,它就是个资源,每一个Url就代表一个资源,但是http://localhost/User?id=think8848和http://localhost/User是同一个资源,这其中的道理不难理解,但是设计可访问的资源也是一个比较复杂的话题,这里不做详细说明了,有兴趣的朋友可以参考《RESTful Web Service》一书。

那么在这段代码中,到底是如何设置资源,又是如何使用资源的呢?这里使用M$的MEF,MEF是一个比较复杂的框架,简单的说吧,它有点类似于依赖注入,M$对于它定义如下:“Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。”。也就是说,使用MEF,可以获取某些符合条件(通过特性Attribute检索的)的接口实例。在这里设置一个ResourceFactory,当调用到达时,就会在这个ResourceFactory中去找服务的实例,在我们自已的程序中,可以使用其他方法达到资源工厂的功能,比如Ioc框架。AddMessageHandlers这个名字看起来比较直观,以我现在的观察,之前我们使用HttpRequest好像都变成了HttpRequestMessage了,于是我们姑且把这个Message看成是Request,这样,就可以很清楚的看到,AddRequestHandler就是在添加请求的处理程序。初步猜测在这个处理程序中,应该能做诸如权限控制之类的工作。

最后两句,关键词是MapServiceRoute,这其实是一个扩展方法,就定义在WCF Web API中,方法是为泛型参数类型的服务注册一个UrlRouting的规则,至此,事情就回到了MVC的范畴之类了。

相关推荐