找回密码
 立即注册
首页 业界区 业界 用JSON做数据传输格式中的一些问题总结

用JSON做数据传输格式中的一些问题总结

荡俊屯 2025-5-29 16:02:34
Json 凭借其自身的优势,在Web数据处理方面已经占据了一定的位置,这段时间涉及到用Json做为数据传输格式的项目有3个,其中有部分页面就采用了Json 数据传输格式, 这里我总结下这段时间采用这种方式的一些问题总结,
  向客户端提供JSON数据的方式

  一. 用WCF提供Json数据

  用WCF向客户端提供Json数据我们需要注意,
  A. 契约的定义, 在WebInvokeAttribute 或者 WebGetAttribute中的ResponseFormat设置为WebMessageForm.Json,
   
   
  1. [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
复制代码
 
  1. [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "IsExistSSID/{SSID}", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
复制代码
 
B. EndPointBehavior使用WebHttp
  1.         <behavior name="UIAjaxEndpointBehavior">
  2.           <webHttp />
  3.           <PolicyEndPointBehavior />
  4.         </behavior>
复制代码
C. Binding 方式使用webHttpBinding
  1.       <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  2.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  3.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  4.       </service>
复制代码
 
二. 用.Net MVC Action提供 JSON 数据

1. 在ValueProviderFactories.Factories.Add(new JsonValueProviderFactory())中加入 Json 数据的处理, MVC 3默认是加入的, 如果你使用的是 MVC3, 则无需理会这一点.
 
2. 采用JsonResult作为你Action的返回值。
3.返回是使用return Json(XXX); XXX为你要返回的数据,其数据类型必须为可序列化类型.
 
三. 可采用以asmx为后缀名的简单WebService来实现,

四. 使用HttpHandler机制来实现.

 
因为WCF已被微软定义为微软系下的通信平台,而后两种随可以实现,但是是较早的实现方式,所以在此我使用了WCF,直接把所提供的数据,视作系统的数据提供接口.
而在.NET MVC的环境里, 已经直接支持输出 Json 形式的数据,所以在非.NET MVC的环境选择WCF提供, 而在.NET MVC环境直接选择用JSON Action支持.
 
WEB客户端处理

用JQuery Ajax处理

把 dataType设置为 'json' 格式,在接收数据时会自动把result转换为json object格式.
  1.                 $.ajax({      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  2.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  3.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  4.       </service>url: ‘urladdress’      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  5.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  6.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  7.       </service>type: 'GET',      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  8.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  9.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  10.       </service>contentType: 'application/json',      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  11.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  12.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  13.       </service>[b][color=#0000ff]dataType: 'json',[/color][/b]      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  14.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  15.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  16.       </service>cache: false,      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  17.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  18.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  19.       </service>async: false,      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  20.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  21.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  22.       </service>error: JQueryAjaxErrorHandler,      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  23.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  24.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  25.       </service>success: function (result) { }                });
复制代码
异常处理的考虑

  在这里我主要考虑在Web环境下异常的处理, 根据HTTP协议的定义, 每次请求都会返回一个 HTTP Status Code , 不同的Code代表了不同的意义。因此我们的Web应用程序也应该是这样,根据不同的结果返回不同的 HTTP Status Code , 比如200,代表服务端正确的返回,417代表我们期望的服务端异常,404,请求不存在等, 以及301我们的未授权。
  在WCF环境下,我们首先要给每个方法添加 FaultContract, 如下:
     
  1. FaultContract(typeof(WebFaultException<WebErrorDetail>))
复制代码
   
其次我们要对异常做一些处理,让服务端能返回正确的HTTP Status Code.
  1.             try
  2.             {
  3.                  //BussinessCode.....
  4.             }
  5.             catch (DuplicateException ex)
  6.             {
  7.                 throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed);
  8.             }
  9.             catch (NotExistException ex)
  10.             {
  11.                 throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed);
  12.             }
  13.             catch (AppException ex)
  14.             {
  15.                 throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed);
  16.             }
  17.             catch (Exception ex)
  18.             {
  19.                 throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed);
  20.             }
复制代码

其中WebFaultJsonFormatException的签名如下:
  1. [code]    [Serializable, DataContract]    public class WebFaultJsonFormatException : WebFaultException    {        public WebFaultJsonFormatException(T detail, HttpStatusCode statusCode)            : base(detail, statusCode)        {            ErrorDetailTypeValidator(detail);        }        public WebFaultJsonFormatException(T detail, HttpStatusCode statusCode, IEnumerable knownTypes)            : base(detail, statusCode, knownTypes)        {            ErrorDetailTypeValidator(detail);        }        private void ErrorDetailTypeValidator(T detail)        {            foreach (DataContractAttribute item in detail.GetType().GetCustomAttributes(typeof(DataContractAttribute), true))            {                if (item.IsReference)      <service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior">
  2.         <endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior"
  3.           binding="webHttpBinding" contract="DeviceUIServiceContract" />
  4.       </service>throw new WebFaultJsonFormatException(new PureWebErrorDetail("The DataContractAttribute property 'IsReference' which applied on {0} can't be true when the transfer code type is JSON fromat.", typeof(T).FullName), HttpStatusCode.ExpectationFailed);            }        }    }    [Serializable, DataContract(IsReference = false)]    public class PureWebErrorDetail    {        public PureWebErrorDetail(string message, params object[] args)        {            this.Message = string.Format(message, args);        }        [DataMemberAttribute]        public string Message { get; set; }    }
复制代码


[/code]因为我们在JSON做数据传输的时候, DataContract中的IsReference是不可以为true的,其意思是相对于XML来说的,XML是可以支持数据的循环引用, 而JSON是不支持的,所以WebFaultJsonFormatException的作用就在于判断当前我们的JSON数据类型的DataContract的IsReference是否为true, 如果是,则返回一个我们定义好的错误信息. 如果没有采用这个定义,JQUery Ajax因此问题接收到的 HTTP Status Code 是15???的一个错误代码, 但这个错误代码并不是我们正常的 HTTP Status Code 范围.
 
异常处理的一个误区

最早的时候,由于没想到用这个方式处理,也是长久写代码犯下的一个弊病, 给每个方法加了一个固定的泛型返回值类型
  1.     [DataContract]
  2.     public class TmResult
  3.     {
  4.         [DataMember]
  5.         public bool Success { get; set; }
  6.         [DataMember]
  7.         public string ErrorMessage { get; set; }
  8.         [DataMember]
  9.         public string FullMessage { get; set; }
  10.         [DataMember]
  11.         public string CallStack { get; set; }
  12.     }
  13.     [DataContract]
  14.     public class TmResult<T> : TmResult
  15.         where T : class
  16.     {
  17.         [DataMember]
  18.         public T Model { get; set; }
  19.     }
复制代码

每次返回都会有一个Success代表是否成功, ErrorMessage代表错误情况下的错误信息, 这样做的方式其实就是每次返回的 HTTP Status Code 都是200, 后来知道想到上面的解决办法之后,才觉得我们更本不需要搞的这么复杂,既然是Web, 那干吗不把程序写的更符合HTTP协议的定义, 那样岂不更简单。
 
所以在此也体会到各种标准的好处, 熟悉标准,熟悉编程模型及各种API, 我们的开发会更简单,更轻松.

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册