MSDN的Windows Communication Foundation (WCF) Samples里AJAX部分同样也提供了丰富的例子供学习,第一个是JSONP的例子,这个例子基于JSONP提供WCF REST服务,
首先我们看看WCF服务端的实现,有几点需要mark一下:
1. 例子中的SVC使用WebScriptServiceHostFactory,
<%@ ServiceHost Factory=”System.ServiceModel.Activation.WebScriptServiceHostFactory”%>
WebScriptServiceHostFactory会自动添加一个WebScriptEndPoint到服务里,如果没有其他终结点等配置的需要,<system.ServiceModel>这个节其实可以直接从Web.config里直接移掉
2. 服务的方法通过WebGetAttribute属性来标记,这样可以确保服务响应Http Get请求,并且默认采用JSON格式
例子中的标记如下:
[WebGet(ResponseFormat = WebMessageFormat.Json],但实际上等价于[WebGet]
这个配合web.config里的
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint name="" crossDomainScriptAccessEnabled="true"/>
</webScriptEndpoint>
</standardEndpoints>
</system.serviceModel>
当crossDomainScriptAccessEnabled设置为true并且response format设置为JSON时,WCF将提供REST服务,客户端web page可以通过类似于URL
http://localhost:33695/CustomerService/GetCustomer?callback=Sys._json0来访问
而服务器端的返回值类似于:Sys._json0({"__type":"Customer:#Microsoft.Samples.Jsonp","Address":"1 Example Way","Name":"Bob"});
3. 此例服务端脚本的写法有别于Getting Started的例子,所有的脚本均在service.cs里实现,通过Service来进行标记:
%@ServiceHost Service=”Microsoft.Samples.Jsonp.CustomerService”%>
4. 服务契约标记了命名空间“JsonAjaxService”,这个将是客户端访问时使用的命名空间:
[ServiceContract(Namespace=”JsonAjaxService”)]
回过头来看看客户端的实现,也有几点想mark一下的:
1. 关于javascript defer,这个以前没有接触过,defer的目的在于让脚本等待所有的DOM元素加载完毕后再执行,具体用法如下:
<script type=”text/javascript” defer=”defer”>makeCall();</script>,此处的方法makeCall()会在DOM元素加载完毕后再执行,
这个可以帮助解决经常在代码执行如getElementById方法由于对象DOM还没有加载完毕而失败的问题,而且与onload相比,defer可以延缓脚本的加载,从而提高page的加载速度
关于defer的更多介绍,参看http://www.w3schools.com/tags/att_script_defer.asp,目前仅IE支持,这里有更详细的测试结果。
2. 我们看看具体的javascript脚本实现
function makeCall(){
var proxy = new JsonpAjaxService.CustomerService();
proxy.set_enableJsonp(true);
proxy.GetCustomer(onSuccess, onFail, null);
}
function onSuccess(result){
document.getElementById(“name”).value = result.Name;
document.getElementById(“address”).value = result.Address;
}
function onFail(result){
document.getElementById(“name”).value = “Error”;
document.getElementById(“address”).value = “Error”;
}
注意其中new的对象是JsonpAjaxService.CustomerService,分别是我们标记的命名空间和定义的类
此外,set_enableJsonp指定要支持JSONP.
3. 最后我们再看一点
<asp:ScriptMangager ID=“ScriptManager1” runat=“server”>
<Services>
<asp:ServiceReference Path=” http://localhost:33695/service.svc” />
</Services>
</asp>
此段代码提供了对WCF REST服务的访问引用
PostWCF服务
以上的例子是基于HTTP GET请求,基于HTTP POST请求的代码大同小异
首先,与以上的例子相比,客户端的访问代码不需要任何修改;
其次,服务器端的方法标记上[WebInvoke]就可以了
1 [ServiceContract(Namespace = "PostAjaxService")]
2 public interface ICalculator
3 { [WebInvoke]
4 double Add(double n1, double n2);
5 //Other operations omitted…
6 }
返回对象的WCF服务
只提一点:一切尽在代码中(OnSucess方法里清晰的表明了如何在客户端脚本里访问返回的对象属性值)。但没有直接确认过,返回的内容应该是JSON的格式
1 [DataContract]
2 public class MathResult
3 {
4 [DataMember]
5 public double sum;
6 [DataMember]
7 public double difference;
8 [DataMember]
9 public double product;
10 [DataMember]
11 public double quotient;
12 }
13
14 function onSuccess(mathResult){
15 document.getElementById("sum").value = mathResult.sum;
16 document.getElementById("difference").value = mathResult.difference;
17 document.getElementById("product").value = mathResult.product;
18 document.getElementById("quotient").value = mathResult.quotient;
19 }