• Asp.net Ajax WebService 实现循环引用(自定义JavascriptConverter)


    准备技术:
        1.简单的WebService编写;
        2.了解Asp.net Ajax 客户端访问WebService


    内容:
        asp.net ajax框架在去年看过,只是些基本的使用,并没有过多的去研究它的原理。最近在一个项目中要实现客户端访问WebService并返回DataTable类型的数据,当我调用一个返回DataTable的方法时,不能返回成功,在错误的回调函数中告诉我DataTable是一个循环应用类型,不能序列化。当是想过把DataTable替换成其他类型的数据如ArrayList或则Array等,可是有点心不甘,所以查过各个方面的资料,告诉我微软已经提供了一个解决DataTable的JavaScriptConverter的dll文件,当我在web.config中添加了对这个JavascriptConverter引用即可以将DataTable序列化成Json字符串了。
        好了,废话不多说了。下面就自己来做个循环应用的实例,并通过自定义JavascriptConverter来解决循环引用的问题。本文只会简单的介绍下服务器端序列化数据类型到Json的过程,不会太深入。

        首先先来定义两个类,想了半天最好的实例就是一对夫妻,一个老公只有一个老婆,这是婚姻法规定的,所以老公类型跟老婆类型就可以达到实例中的循环引用。看下两个类型的类试图:

    其实两个类里面的内容都很简单,Husband.cs:

    using System;
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.ComponentModel;

    public class Husband
    {
        
    private string _firstName;

        
    public string FirstName
        
    {
            
    get return _firstName; }
            
    set { _firstName = value; }
        }

        
    private string _lastName;

        
    public string LastName
        
    {
            
    get return _lastName; }
            
    set { _lastName = value; }
        }

        
    private Wife _wife;

        
    public Wife Wife
        
    {
            
    get return _wife; }
            
    set { _wife = value; }
        }

    }

    Wife.cs:
    using System;
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.ComponentModel;

    public class Wife
    {
        
    private string _firstName;

        
    public string FirstName
        
    {
            
    get return _firstName; }
            
    set { _firstName = value; }
        }

        
    private string _lastName;

        
    public string LastName
        
    {
            
    get return _lastName; }
            
    set { _lastName = value; }
        }

        
    private Husband _husband;

        
    public Husband Husband
        
    {
            
    get return _husband; }
            
    set { _husband = value; }
        }

    }


    然后我定义了个Webservice类用来提供Client的访问,HusbandService.cs:
    using System;
    using System.Collections;
    using System.Linq;
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml.Linq;
    using System.Web.Script.Services;

    /// <summary>
    /// Husband's Method
    /// </summary>

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo 
    = WsiProfiles.BasicProfile1_1)]
    [ScriptService]
    public class HusbandService : System.Web.Services.WebService {

        
    public HusbandService () {

            
    //Uncomment the following line if using designed components 
            
    //InitializeComponent(); 
        }


        [WebMethod]
        
    public Husband GetHusband()
        
    {
            Husband hansband 
    = new Husband();
            hansband.FirstName 
    = "Henllyee";
            hansband.LastName 
    = "Cui";
            Wife wife 
    = new Wife();
            wife.FirstName 
    = "Throwen";
            wife.LastName 
    = "Yang";

            hansband.Wife 
    = wife;
            wife.Husband 
    = hansband;

            
    return hansband;
        }

        
    }



    我在一个asp.net 页面中通过asp.net ajax对GetHusband()的应用的,JavascriptConverter.aspx:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="JavascriptConverter.aspx.cs" Inherits="_Default" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        
    <title>JavaScriptConverter Demo</title>
    </head>
    <body>
        
    <form id="form1" runat="server">
        
    <div>
            
    <asp:ScriptManager ID="scriptManager" runat="server">
                
    <Services>
                    
    <asp:ServiceReference Path="~/HusbandService.asmx" />
                
    </Services>
            
    </asp:ScriptManager>
            
    <script language="javascript" type="text/javascript">
              function getServiceHasband()
              
    {
                HusbandService.GetHusband(onSuccess,onFailed);
              }

              function onSuccess(result)
              
    {
                alert(result.FirstName);
              }

              function onFailed(error)
              
    {
                alert(error.get_message());
              }

              
              
              window.onload
    =function()
              
    {
                var btnGet 
    = $get("btnGet");
                
    if(btnGet)
                
    {
                    btnGet.onclick
    =getServiceHasband;
                }
      
              }

            
    </script>
            
    <input type="button" id="btnGet" value="Get HusBand" />
        
    </div>
        
    </form>
    </body>
    </html>
    运行后当我们点击按钮是,会弹出出错的信息,告诉我们Husband是一个循环引用类型,不能序列化。这时我们可以通过编写对应的JavascriptConverter来告诉服务器端如何去序列化。

    我们自定的JavascriptConverter必须继承于JavascriptConverter(JavascriptConverter参考文档),然后去重写里面的两个方法跟一个属性:
    1.Deserialize:如何反序列化一个Jason到这个Converter类型;
    2.Serialize:如何序列化支持的对象到一个Jason;
    3.SupportedTypes:这个Converter支持的类型。
    好了下面我们定义下一个Converter来支持循环引用,现在我们先定义如何将去序列化,HusbandConverter.cs:
    using System;
    using System.Data;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml.Linq;
    using System.Web.Script.Serialization;
    using System.Collections.Generic;

    /// <summary>
    /// Husband's Converter
    /// </summary>

    public class HusbandConverter:JavaScriptConverter
    {
        
    public HusbandConverter()
        
    {
            
        }


        
    /// <summary>
        
    /// 
        
    /// </summary>
        
    /// <param name="dictionary"></param>
        
    /// <param name="type"></param>
        
    /// <param name="serializer"></param>
        
    /// <returns></returns>

        public override object Deserialize(IDictionary<stringobject> dictionary, Type type, JavaScriptSerializer serializer)
        
    {
            
    throw new NotImplementedException();
        }

        
        
    /// <summary>
        
    /// Serizlize a json
        
    /// </summary>
        
    /// <param name="obj"></param>
        
    /// <param name="serializer"></param>
        
    /// <returns></returns>

        public override IDictionary<stringobject> Serialize(object obj, JavaScriptSerializer serializer)
        
    {
            Husband husband 
    = (Husband)obj;
            IDictionary
    <string,object> dictionary  = new Dictionary<string,object>();
            husband.Wife.Husband 
    = null;
            dictionary[
    "FirstName"= husband.FirstName;
            dictionary[
    "LastName"= husband.LastName;
            dictionary[
    "Wife"= husband.Wife;

            
    return dictionary;
        }


        
    /// <summary>
        
    /// Support Types
        
    /// </summary>

        public override System.Collections.Generic.IEnumerable<Type> SupportedTypes
        
    {
            
    get
            
    {
                
    yield return typeof(Husband);
            }

        }

    }

    然后我们在web.config中注册这样一段对这个Converter的引用:

    <system.web.extensions>
            
    <scripting>
                
    <webServices>
                    
    <jsonSerialization>
                        
    <converters>
                            
    <add name="HusbandConvert" type="HusbandConverter,App_Code"/>
                        
    </converters>
                    
    </jsonSerialization>
                
    </webServices>
            
    </scripting>
        
    </system.web.extensions>

    这下我们再运行时,去点击按钮就能返回“Henllyee”。
    在上面中我们首先重写了SupportedTypes属性去告诉系统我这个Converter支持那些类型的数据。然后我们去重写了Serialize方法,其实我们在这里只是把husband.Wife.Husband设置为了null,让它不去循环引用了,所以这样就破坏原来的类的本意。但是我们可以在客户端再去完善它,再在客户端设置husband.Wife.Husband=husband即可了。
    下面我们再看如何进行反序列化了。首先我们在webservice中先添加一个方法,来传入Husband对象

     [WebMethod]
        
    public string GetHusbandInfo(Husband hansband)
        
    {
            Debug.Assert(hansband.Wife.Husband 
    == hansband);

            
    return String.Format(
                
    "Husband's :{0}\n Wife:{1}",
                hansband.FirstName 
    + " " + hansband.LastName,
                hansband.Wife.FirstName 
    + " " + hansband.LastName);
        }

    然后我们再去把反序列化实现下:

    public override object Deserialize(IDictionary<stringobject> dictionary, Type type, JavaScriptSerializer serializer)
        
    {
            Husband husband 
    = new Husband();
            husband.FirstName 
    = (string)dictionary["FirstName"];
            husband.LastName 
    = (string)dictionary["LastName"];
            husband.Wife 
    = serializer.ConvertToType<Wife>(dictionary["Wife"]);
            husband.Wife.Husband 
    = husband;
            
    return husband;
        }

    最后我们在客户端进行调用:

      function getHusbandInfo()
              
    {
                var husband 
    = new Object();
                husband.FirstName
    ="Henllyee";
                husband.LastName
    ="Cui";
                var wif 
    = new Object();
                wif.FirstName
    ="Erry";
                wif.LastName
    ="Du";
                husband.Wife
    =wif;
                HusbandService.GetHusbandInfo(husband,onGetInfoSucceded,onFailed);
              }

              
              function onGetInfoSucceded(result)
              
    {
                alert(result);
              }

    具体的前台的脚本就不在给出,通过运行我们会发现反序列化是成功的。
    程序下载地址:https://files.cnblogs.com/henllyee/JavascriptConverter.rar
  • 相关阅读:
    分布式、集群的概念、区别
    Entity Framework学习
    QT入门
    Xcode插件开发
    函数指针
    c创建win窗口
    设置UITableView section间距
    使用谷歌地图时报一堆错的解决方法
    IOS地图及定位使用
    IOS判断手机型号
  • 原文地址:https://www.cnblogs.com/Henllyee/p/1246161.html
Copyright © 2020-2023  润新知