WCF学习杂记-AJAX

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 }

 

你可能感兴趣的:(Ajax)