现在的位置: 首页 > 综合 > 正文

WCF学习杂记-AJAX

2012年12月14日 ⁄ 综合 ⁄ 共 5968字 ⁄ 字号 评论关闭

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 }

 

返回基于XML格式的WCF服务
首先分析的还是服务端脚本:
1. 最重要的下面这段,使用的是WebServiceHostFactory而不是WebScriptServiceHostFactory
1 %@ServiceHost language="c#" Debug="true" Service="Microsoft.Samples.XmlAjaxService.CalculatorService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %
2. 相对应的,config里面是webHttpEndPoint而不是webScriptEndPoint
代码
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<!-- Use this element to configure the endpoint -->
<standardEndpoint name="" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>

 

3. 微软提供的Sample有一个对比,可以很清晰的看到对返回Json和XML的区别
  
1 [WebInvoke(ResponseFormat=WebMessageFormat.Json, BodyStyle=WebMessageBodyStyle.Wrapped)]
2 MathResult DoMathJson(double n1, double n2);
3
4 [WebInvoke(ResponseFormat=WebMessageFormat.Xml, BodyStyle=WebMessageBodyStyle.Wrapped)]
5 MathResult DoMathXml(double n1, double n2);

 

客户端的脚本变化比较大,通过XML请求来做
1 <script type="text/javascript">
2 function makeCall(operation){
3 var xmlHttp;
4 try{
5 xmlHttp = new XMLHttpRequest();
6 }catch(e){
7 try{
8 xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
9 }catch(e){
10 try{
11 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
12 }catch(e){
13 alert("This sample only works in browsers with AJAX support");
14 return false;
15 }
16 }
17 }
18
19 //Create result handler
20   xmlHttp.onreadystatechange=function(){
21 if(xmlHttp.readyState == 4){
22 document.getElementById("result").value = xmlHttp.responseText;
23 }
24 }
25
26 var url = "service.svc/";
27 url = url + operation;
28
29 //Build the body of the JSON message
30 var body = '{"n1":';
31 body = body + document.getElementById("num1").value + ',"n2":';
32 body = body + document.getElementById("num2").value + '}';
33
34 //Send the HTTP request
35 xmlHttp.open('POST', url, true);
36 xmlHttp.setRequestHeader("Content-type", "application/json");
37 xmlHttp.send(body);
38 }
39 </script>

 

DataContractJsonSerializer
 
叉开谈一下这个类用来序列化当前的数据成JSON的格式和利用JSON格式的数据实例化类,没有过多需要说明的,一切都在代码里:
1 using System;
2  using System.IO;
3  using System.Runtime.Serializatin;
4  using System.Runtime.Serialization.Json;
5
6  namespace Microsoft.samples.JsonSerialization
7 {
8 class Sample{
9 static void Main(){
10 Person p = new Person();
11 p.name = "John";
12 p.age = 42;
13
14 MemoryStream stream1 = new MemoryStream();
15 //Serialize the Person object to a memory stream using DataContractJsonSerializer;
16 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
17 ser.WriteObject(stream1, p);
18
19 //Show the JSON outpu.
20 stream1.Position = 0;
21 StreamReader sr = new StreamReader(stream1);
22 Console.Write("JSON form of Person object: ");
23 Console.WriteLine(sr.ReadToEnd());
24
25 //Deserialize the JSON back into a new Person object.
26 stream1.Position = 0;
27 Person p2 = (Person)ser.ReadObject(stream1);
28
29 //Show the results.
30 Console.Write("Deserialized back, got name=");
31 Console.Write(p2.name);
32 Console.Write(",age=");
33 Console.WriteLine(p2.age);
34
35 Console.WriteLine("Press <ENTER> to terminate the program.");
36 Console.ReadLine();
37 }
38 }
39
40 [DataContract]
41 class Person{
42 [DataMember]
43 internal string name;
44
45 [DataMember]
46 internal int age;
47 }
48
49
50 }

 

抱歉!评论已关闭.