十五天精通WCF——第十三天 用WCF来玩Rest
在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换,
牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议,而是采用json格式的字符串,是不是有一点颠覆你对wcf的认识的???
从传统意义上说,wcf是非常重量级的,很明白的一个例子就是太多太多的配置,尤其是Behavior的配置,而且behavior对wcf来说又是重
中之重,它对wcf的扩展和性能又是最重要的,可恨的是wcf在binding,behavior,contract之中的配置又是非常非常的保守,可以说用
wcf来玩分布式,这些默认配置是完全做不到的,就比如说basicbinding的基类HttpBindingBase。

抱怨的话我也不说了,可能微软也觉得这个问题是个不小的问题,然后就有了轻量级的 asp.net web api,你可以看到它和wcf比起来精
简多了,也许让我们这些码农更加的专注于业务吧,既然wcf带了这玩意,我也得必须约谈一下。
一:UriTemplate
要说rest,还得先说UriTemplate,因为wcf用UriTemplate来做rest中的uri模板匹配,然后用WebInvoke这个OperationBehavior
插入到wcf的心脏中,说的玄乎一点,这个就有点像mvc中的路由匹配机制,下面我举个例子:
1. 用UriTemplate来告知可以监视的完整Url
从下面的图中,可以看到三个元素:服务地址,模板,入参(这里面的”1“),这三个元素组合在一起,就构成了完整的remote url,
然后这个完整的url就是我模板(/User/{id})监视的对象。

2. 通过UriTemplate来解析url中的参数。
既然可以构建url,那当然可以解析url啦,对吧,下面这张图可以很清晰的告知你,当外来的url=http://127.0.1:1920/HomeService
/User/1过来的时候应该被哪个uriTemplate所接收。

正是因为UriTemplate具有这样的url构建和解析能力,所以wcf就把UriTemplate作为WebInvoke和WebGet这两个属性的参数来动态
解析外来的url,然后根据这个url分配到具体的服务方法上,下面我们具体看一看。
二:WebGet,WebInvoke的使用
刚才也说了,WebGet和WebInvoke正是用了UriTemplate,才具有了路由转向的功能,还有就是默认返回的是xml,这里就用json
值作为服务返回的格式
[ServiceContract]
public interface IHomeService
{
[OperationContract]
[WebGet(UriTemplate = "Get/{id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Student Get(string id); [OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Add", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string Add(Student stu);
}
对了,Rest推荐使用Http协议中的Get,Post,Delete,Put来作为CURD的状态机制,然后就是你如果看懂了UriTemplate,那你现在应
该知道这个Template在监视什么类型的url。做完了上面的coding,下面我们需要在webconfig中通过behavior来指定启动“web编程模型”,
就比如下面这样。
<?xml version="1.0" encoding="utf-8"?>
<configuration> <system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="ActivityTracing">
<listeners>
<add name="mylisteners" type="System.Diagnostics.XmlWriterTraceListener" initializeData="E:\1.txt" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="ActivityTracing">
<listeners>
<add name="messagelogging" type="System.Diagnostics.XmlWriterTraceListener" initializeData="E:\2.txt"/>
</listeners>
</source>
</sources>
<trace autoflush="true"/>
</system.diagnostics> <system.serviceModel> <diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics> <behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
33 <endpointBehaviors>
34 <behavior name="webbehavior">
35 <webHttp />
36 </behavior>
37 </endpointBehaviors>
</behaviors> <services>
<service name="MyService.HomeService">
<endpoint address="HomeService" binding="webHttpBinding" behaviorConfiguration="webbehavior"
contract="MyService.IHomeService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:1920" />
</baseAddresses>
</host>
</service>
</services> </system.serviceModel> </configuration>
其实呢?也就是代码中的WebHttpBehavior类

好了,我现在服务地址也出来了:http://127.0.0.1:1920 ,然后服务方法的template也指定了。只要http.sys监控到了template
匹配的url,服务方法就会被执行,比如我现在在浏览器里面输入:http://127.0.0.1:1920/HomeService/Get/1 来测试下Get操作。

可以看到,get方法成功了,也正确的匹配了我的服务方法Get。
public class HomeService : IHomeService
{
public Student Get(string id)
{
return new Student() { ID = Convert.ToInt32(id), Name = "hxc", SNS = "" };
} public string Add(Student stu)
{
return "hello";
}
}
然后我们看看Add方法,我在HttpWebRequest中模拟测试如下。
class Program
{
static void Main(string[] args)
{
Run();
} /// <summary>
/// 报告系统错误
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
public static void Run()
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://127.0.0.1:1920/HomeService/Add");
Encoding encoding = Encoding.UTF8; string param = new JavaScriptSerializer().Serialize(new { ID = "", Name = "hxc", SNS = "" });
byte[] bs = Encoding.ASCII.GetBytes(param); string responseData = String.Empty;
req.Method = "POST";
req.ContentType = "application/json";
req.ContentLength = bs.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(bs, , bs.Length);
reqStream.Close();
}
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
{
responseData = reader.ReadToEnd().ToString();
}
}
}
}

好了,大概就说这么多了,如果说你不嫌麻烦,你可以用WCF Rest,还有就是不要忘了很多的默认配置,如果你觉得太繁琐,
可以用用asp.net web api。

十五天精通WCF——第十三天 用WCF来玩Rest的更多相关文章
- [转]十五天精通WCF——第十三天 用WCF来玩Rest
在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换, 牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议, ...
- 十五天精通WCF——第一天 三种Binding让你KO80%的业务
转眼wcf技术已经出现很多年了,也在.net界混的风生水起,同时.net也是一个高度封装的框架,作为在wcf食物链最顶端的我们所能做的任务已经简单的不能再简单了, 再简单的话马路上的大妈也能写wcf了 ...
- 十五天精通WCF——第十四天 一起聊聊FaultException
我们在玩web编程的时候,可能你会不经意的见到一些http500的错误,我想你应该不会陌生的,原因你应该也知道,服务器异常嘛, 这时候clr会把这个未处理的异常抛给iis并且包装成http500的错 ...
- [转]十五天精通WCF——第十四天 一起聊聊FaultException
我们在玩web编程的时候,可能你会不经意的见到一些http500的错误,我想你应该不会陌生的,原因你应该也知道,服务器异常嘛, 这时候clr会把这个未处理的异常抛给iis并且包装成http500的错 ...
- [转]十五天精通WCF——第一天 三种Binding让你KO80%的业务
转眼wcf技术已经出现很多年了,也在.net界混的风生水起,同时.net也是一个高度封装的框架,作为在wcf食物链最顶端的我们所能做的任务已经简单的不能再简单了, 再简单的话马路上的大妈也能写wcf了 ...
- 十五天精通WCF——终结篇 那些你需要注意的坑
终于一路走来,到了本系列的最后一篇了,这一篇也没什么好说的,整体知识框架已经在前面的系列文章中讲完了,wcf的配置众多,如果 不加一些指定配置,你可能会遇到一些灾难性的后果,快来一睹为快吧. 一: 第 ...
- 十五天精通WCF——第十二天 说说wcf中的那几种序列化
我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的过程,也就是将参数序列化为message,这篇 我们就来说说这里的序列化,蛮有意思的,可能初学者也明白,在wcf ...
- 十五天精通WCF——第十一天 如何对wcf进行全程监控
说点题外话,我们在玩asp.net的时候,都知道有一个叼毛玩意叫做“生命周期”,我们可以用httpmodule在先于页面的page_load中 做一些拦截,这样做的好处有很多,比如记录日志,参数过滤, ...
- 十五天精通WCF——第十天 学会用SvcConfigEditor来简化配置
我们在玩wcf项目的时候,都是自己手工编写system.serviceModel下面的配置,虽然在webconfig中做wcf的服务配置的时候,vs提供大多 数的代码提示,但对于不太熟悉服务配置的小鸟 ...
随机推荐
- 基于TCP和多线程实现无线鼠标键盘-GestureDetector
为了实现无线鼠标,需要识别出用户在手机屏幕上的滑动动作,这就需要用到GestureDetector类. 首先是activity_main.xml: <LinearLayout xmlns:and ...
- 2015暑假多校联合---Cake(深搜)
题目链接:HDU 5355 http://acm.split.hdu.edu.cn/showproblem.php?pid=5355 Problem Description There are m s ...
- NYOJ 737---石子归并(GarsiaWachs算法)
原题链接 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求 ...
- Intellij Idea上传本地项目到Git
方法一:选择菜单VCS-Import into Version Control - Share project on Github,填写仓库名和github账户之后,点击"Share&quo ...
- 由select * from table where 1=1中的1=1说开数据库
众多网站都有select * from table where 1=1此类语句的介绍,并且,针对该类语句,讲得实在是让人越看越迷茫(一个抄袭一个的,简直不像话),不知道是在说什么,导致很多新手不得要领 ...
- php学习5-时间和日期
如果时间时区不对,使用时间是要先设定时区,使用date_default_timezone_set() 设置新时区 date_default_timezone_set('Asia/Shanghai'); ...
- React入门--------组件的生命周期
Mounting/组件挂载相关: componentWillMount componentDidMount Updating/组件更新相关: componentWillReceiveProps sho ...
- php代码美化/格式化 还原 -问题
使用某个PHP代码格式化的工具.源代码: if ($this->_standardize_newlines == TRUE) { if (strpos($str, "\r") ...
- [deviceone开发]-HeaderView和FooterView的示例
一.简介 这个是利用do_ListView组件实现下拉和上拉刷新功能的例子,除了do_ListView,其它比如do_Webview,do_ScrollView都有这个个功能.对应的BBS里的帖子详细 ...
- 定制Eclipse IDE之界面篇
为什么要定制IDE? 在工作时候,当公司有了自己的框架,给自己开放人员用,甚至是可以卖的时候,我们可以做成一个产品,而这个产品将包括框架本身.文档.工具.教程等等.工具之中最重要的莫过于开发 ...