RESTful WCF

RESTful WCF

自打学编程以来,蠢事干过不少,就“掉进坑里”这事而言,有不小心陷进去的,有心甘情愿跳下去的,还有被别人拉进去的...但是像过去两天一样一步一个坑的...真的是还没有体验过。“避之不得,弃之可惜”,人生最痛苦的事莫过于此。

好吧,“最近”REST很热门...我那么喜欢凑热闹的人,当然也想搞一搞,其实最主要的是SharePoint 2013搜索里面有一种API采用了这种模型,为了“备着用”,也应该了解下...当然这个很大程度上是个借口。百度一下或者谷歌一下教程真不少,全部声称构建支持“CRUD”的REST WCF,但是打开一看,简直就是坑爹啊...要么只实现了查询,要么只实现了服务没有调用示例,要么就是啪用一个模版然后改下代码...最后导航到服务页,声称构建完成。当然...看到几位前辈的文章还是很全面的..只不过是比较旧的方式,节点绑定比较麻烦就没有走那条路。本文“特点”:真正的CRUD全包含以及调用,货真价实童叟无欺;详细记录本人的爬坑史(有些时候我也不知道我怎么爬出来的,so...);收录各种解决方案的链接。

服务

目的是完成一个叫“BookService”的服务,包含基础的增删查改操作。整个可用的解决方案只需要处理4个文件,所以没有必要提供文件下载只需要贴出源码就行。

[数据]为了区分重点,没有必要使用数据库这样的东西,使用代码引用一块内存当数据存储区就够了,先是实体类,代码如下。

 View Code

还是说明下,static Book Clone方法是为了提取部分属性的...后来了解到可以使用dynamic或者ResponseObject;另外需要注意的是,公开的具有get和set访问器的属性才能成功被序列化,本来应该private set的,这里就只能get/set了。
[服务]关于如何从一个空的ASP.NET项目构造一个RESTful WCF服务,请参考这里,非常详细:http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx。当然这样的话就需要引用几个程序集:

  • System.ServiceModel
  • System.Web.Services
  • System.Web.Routing
  • System.ServiceModel.Activation
  • System.ServiceModel.Web

看完上面那篇文章,构建服务是没问题的,像我这么掉坑的人都完成了。以下是源码:

 View Code

可以看到,我在Service的实现里面声明了静态成员用来存储数据。

[坑s]

POST,WebInvokeAttribute有个成员叫BodyStyle,先前我看过一篇文章说在XX情况下应该将BodyStyle置为Wrapped,但是我犯2忽略了别人说的那个前置条件,所以悲剧了。所以目前的情况是,将BodyStyle设置为Bare,也就是不包装,然后在客户端使用不包装的json请求提交就可以了。

PUT(DELETE),就服务配置而言,PUT爬坑花费的时间比较少了...主要是要配置IIS允许的动词(verb),由于我使用的VS2012所以调试的时候使用了IIS Express。关于如何配置IIS Express的动词过滤规则,参考这里:http://geekswithblogs.net/michelotti/archive/2011/05/28/resolve-404-in-iis-express-for-put-and-delete-verbs.aspx。另外,不需要声明请求格式和相应格式(后话)。这里上一张配置config文件的截图:

DELETE,至于为什么要把DELETE单独提出来..那是因为我被深深的坑住了。 [WebInvoke(UriTemplate = "Book/{id}/", Method = "Delete")]我使用这个特性的时候,一直返回405 method not allowed,比对下就知道了..大小写问题啊。我也不清楚是什么情况了..不过我猜测是IIS上面配置的时候使用了大写的delete,所以导致被过滤了。

另外,关于PUT和DELETE,曾经返回过两个错误,一个是404,另外一个是405。现在我已经分不清什么时候返回什么了。网上有些解决方案说要移除WebDAV和WebDAVMoudle,参考这里:http://forums.iis.net/post/1937843.aspx。其实这两个在IIS Express中是已经被注释掉的。所以主要关注点在verb配置上,我的web.config可以证明这点。

 View Code

[Global.asax]

主要是处理路由的:

 View Code

调用

这个花样就更多了,作为一个脚本菜鸟,不想讨论太多。这里涉及一下同域调用和跨域调用。 原理请查看这里:http://www.cnblogs.com/chopper/archive/2012/03/24/2403945.html。因为是使用ajax进行请求,同域调用就确保执行脚本的页面和服务处于同一个端口,跨域就是不同端口(大概是这么一个意思吧)。我们主要处理同域调用。

[同域调用]

先看代码,其实就是一个html文件,然后执行了CRUD这些操作:

 View Code

备注:到此为止,所有的代码提供完毕,在本人的机子上均正常执行。(只能声明到这里了..)

[坑s]

GET,说来惭愧,调用GET方法的时候就已经错误频出了,主要是:1,乱码;2,提示缺少分号(;)。后来我没有使用$.ajax而是使用了$.getJSON,代码短不说,还不出错。

POST,主要是data的格式(不包装),应该是'{"XXX":int,"XX":"string"}'这样;有些文章说应该将processData置为false,但是我发现不声明这一条现在也可以正确执行。

PUT,前面说过不要指明PUT方法的ResponseFormat,因为返回的是void。所以如果在客户端调用的时候指明dataType为“json”,总会触发error事件,尽管返回的是200[OK],这点参考这里:

http://stackoverflow.com/questions/6186770/ajax-request-return-200-ok-but-error-event-is-fired-instead-of-success,另外这个标题中的fired真是着实让我乐了一下,老外真好玩(英语好的人可能觉得这个词很正常吧)。

DELETE,和PUT差不多,主要是dataType的问题。

执行结果如图:

[跨域调用]

这里再引用一篇文章:http://www.cnblogs.com/tom-zhu/archive/2012/10/25/2739202.html(配置)。目前我们是把html文件和service放在同一个解决方案里面,然后在同个端口打开,所以属于同域调用。其实只要把html文件右键使用浏览器打开就是跨域调用的情形了。

至于怎么调用,上个截图就可以一目了然:

$.getJSON调用:

$.ajax调用:

$.ajax({
type:"GET",
dataType:'jsonp',
success:function(e){alert(e.length)}
})

部署

接下来要做的就是这个了,一是将服务部署到IIS上;二是将服务使用控制台托管,看看情况如何。文章就先发布好了,反正修修补补也是可以接受的。

 
 
分类: C#
标签: WCFRESTAJAX

NodeJs:module.filename、__filename、__dirname、process.cwd()和require.main.filename 解惑

 

背景

一直存在一个疑惑,require()坐标路径是啥?fs.readFile()的坐标路径又是啥?总之,需要路径的方法,我总有这样的疑问。今天就实验一下,给弄清楚。

实验

实验素材

app.js

复制代码
 1 //执行 node E:\node_study\file_path_study\app.js
 2 
 3 console.log('*** app start ***');
 4 
 5 console.log('***      module.filename = ' + module.filename + ' ***');
 6 console.log('***           __filename = ' + __filename + ' ***');
 7 console.log('***            __dirname = ' + __dirname + ' ***');
 8 console.log('***        process.cwd() = ' + process.cwd() + ' ***');
 9 console.log('*** require.main.filename= ' + require.main.filename + ' ***');
10 
11 console.log('*** app end ***');
12 
13 console.log('');
14 
15 require('./lib/test');
复制代码

test.js

复制代码
1 console.log('*** app start ***');
2 
3 console.log('***      module.filename = ' + module.filename + ' ***');
4 console.log('***           __filename = ' + __filename + ' ***');
5 console.log('***            __dirname = ' + __dirname + ' ***');
6 console.log('***        process.cwd() = ' + process.cwd() + ' ***');
7 console.log('*** require.main.filename= ' + require.main.filename + ' ***');
8 
9 console.log('*** app end ***');
复制代码

结果

结论

  • module.filename:开发期间,该行代码所在的文件。
  • __filename:始终等于 module.filename。
  • __dirname:开发期间,该行代码所在的目录。
  • process.cwd():运行node的工作目录,可以使用  cd /d 修改工作目录。
  • require.main.filename:用node命令启动的module的filename, 如 node xxx,这里的filename就是这个xxx。

require()方法的坐标路径是:module.filename;fs.readFile()的坐标路径是:process.cwd()。

原文地址:https://www.cnblogs.com/Leo_wl/p/3081654.html