• 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 }
  • 相关阅读:
    TestNG中DataProvider的用法
    性能调优过程发现的问题
    20170221——接口自动化测试代码提交流程
    svn忽略target文件
    springboot搭建dubbo+zookeeper简单案例
    docker上启动mysql镜像,mysq中记录乱码解决方法
    docker在linux上的安装
    使用jave1.0.2将amr文件转成其他格式报错解决方案
    使用fio命令查看磁盘iops
    解决使用maven clean项目的时候报错,删除target文件夹失败
  • 原文地址:https://www.cnblogs.com/johnsonwong/p/1726790.html
Copyright © 2020-2023  润新知