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


Posted in Javascript onDecember 21, 2011

向客户端提供JSON数据的方式
一. 用WCF提供Json数据
用WCF向客户端提供Json数据我们需要注意,
A. 契约的定义, 在WebInvokeAttribute 或者 WebGetAttribute中的ResponseFormat设置为WebMessageForm.Json,

[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] 
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "IsExistSSID/{SSID}", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]

B. EndPointBehavior使用WebHttp
<behavior name="UIAjaxEndpointBehavior"> 
<webHttp /> 
<PolicyEndPointBehavior /> 
</behavior>

C. Binding 方式使用webHttpBinding
<service name="XX.DeviceUIService" behaviorConfiguration="UIAjaxServiceBehavior"> 
<endpoint address="" behaviorConfiguration="UIAjaxEndpointBehavior" 
binding="webHttpBinding" contract="DeviceUIServiceContract" /> 
</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格式.
$.ajax({ 
url: ‘urladdress' 
type: 'GET', 
contentType: 'application/json', 
dataType: 'json', 
cache: false, 
async: false, 
error: JQueryAjaxErrorHandler, 
success: function (result) { } 
});

异常处理的考虑

在这里我主要考虑在Web环境下异常的处理, 根据HTTP协议的定义, 每次请求都会返回一个 HTTP Status Code , 不同的Code代表了不同的意义。因此我们的Web应用程序也应该是这样,根据不同的结果返回不同的 HTTP Status Code , 比如200,代表服务端正确的返回,417代表我们期望的服务端异常,404,请求不存在等, 以及301我们的未授权。

在WCF环境下,我们首先要给每个方法添加 FaultContract, 如下:
FaultContract(typeof(WebFaultException<WebErrorDetail>))
其次我们要对异常做一些处理,让服务端能返回正确的HTTP Status Code.

try 
{ 
//BussinessCode..... 
} 
catch (DuplicateException ex) 
{ 
throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed); 
} 
catch (NotExistException ex) 
{ 
throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed); 
} 
catch (AppException ex) 
{ 
throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed); 
} 
catch (Exception ex) 
{ 
throw new WebFaultJsonFormatException<WebErrorDetail>(new WebErrorDetail(ex.Message, ex), HttpStatusCode.ExpectationFailed); 
} 
其中WebFaultJsonFormatException的签名如下: 
[Serializable, DataContract] 
public class WebFaultJsonFormatException<T> : WebFaultException<T> 
{ 
public WebFaultJsonFormatException(T detail, HttpStatusCode statusCode) 
: base(detail, statusCode) 
{ 
ErrorDetailTypeValidator(detail); 
} 
public WebFaultJsonFormatException(T detail, HttpStatusCode statusCode, IEnumerable<Type> 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) 
throw new WebFaultJsonFormatException<PureWebErrorDetail>(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; } 
}

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

异常处理的一个误区
最早的时候,由于没想到用这个方式处理,也是长久写代码犯下的一个弊病, 给每个方法加了一个固定的泛型返回值类型

[DataContract] 
public class TmResult 
{ 
[DataMember] 
public bool Success { get; set; } [DataMember] 
public string ErrorMessage { get; set; } 
[DataMember] 
public string FullMessage { get; set; } 
[DataMember] 
public string CallStack { get; set; } 
} 
[DataContract] 
public class TmResult<T> : TmResult 
where T : class 
{ 
[DataMember] 
public T Model { get; set; } 
}

每次返回都会有一个Success代表是否成功, ErrorMessage代表错误情况下的错误信息, 这样做的方式其实就是每次返回的 HTTP Status Code 都是200, 后来知道想到上面的解决办法之后,才觉得我们更本不需要搞的这么复杂,既然是Web, 那干吗不把程序写的更符合HTTP协议的定义, 那样岂不更简单。

所以在此也体会到各种标准的好处, 熟悉标准,熟悉编程模型及各种API, 我们的开发会更简单,更轻松.
以上都是按个人理解所写,有不对之处请指正.

Javascript 相关文章推荐
javascript取消文本选定的实现代码
Nov 14 Javascript
js 链式延迟执行DOME
Jan 04 Javascript
javascript查找字符串中出现最多的字符和次数的小例子
Oct 29 Javascript
jQuery中:header选择器用法实例
Dec 29 Javascript
js实现Form栏显示全格式时间时钟效果代码
Aug 19 Javascript
JS实现的适合做faq或menu滑动效果示例
Nov 17 Javascript
webpack打包node.js后端项目的方法
Mar 10 Javascript
vue-quill-editor+plupload富文本编辑器实例详解
Oct 19 Javascript
如何解决.vue文件url引用文件的问题
Jan 18 Javascript
vue倒计时刷新页面不会从头开始的解决方法
Mar 03 Javascript
jQuery 隐藏/显示效果函数用法实例分析
May 20 jQuery
详解Vue3 Teleport 的实践及原理
Dec 02 Vue.js
40款非常有用的 jQuery 插件推荐(系列一)
Dec 21 #Javascript
这段js代码得节约你多少时间
Dec 20 #Javascript
js实现的仿新浪微博完美的时间组件升级版
Dec 20 #Javascript
非主流的textarea自增长实现js代码
Dec 20 #Javascript
javascript之querySelector和querySelectorAll使用介绍
Dec 20 #Javascript
js有关元素内容操作小结
Dec 20 #Javascript
js汉字排序问题 支持中英文混排,兼容各浏览器,包括CHROME
Dec 20 #Javascript
You might like
用Zend Encode编写开发PHP程序
2006/10/09 PHP
PHP 魔术函数使用说明
2010/05/14 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
修改destoon会员公司的伪静态中的com目录的方法
2014/08/21 PHP
php对xml文件的增删改查操作实现方法分析
2017/05/19 PHP
PHP getName()函数讲解
2019/02/03 PHP
详解php反序列化
2020/06/10 PHP
JavaScript中Array 对象相关的几个方法
2006/12/22 Javascript
jqeury eval将字符串转换json的方法
2011/01/20 Javascript
分享20款好玩的jQuery游戏
2011/04/17 Javascript
Angular中的Promise对象($q介绍)
2015/03/03 Javascript
jquery Validation表单验证使用详解
2020/09/12 Javascript
使用Angular.js开发的注意事项
2016/10/19 Javascript
基于JavaScript实现幸运抽奖页面
2020/07/05 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
JavaScript中this用法学习笔记
2019/03/17 Javascript
JavaScript实现简易聊天对话框(加滚动条)
2020/02/10 Javascript
VUE和Antv G6实现在线拓扑图编辑操作
2020/10/28 Javascript
Python原始字符串与Unicode字符串操作符用法实例分析
2017/07/22 Python
tensorflow 中对数组元素的操作方法
2018/07/27 Python
对python判断ip是否可达的实例详解
2019/01/31 Python
Python对象转换为json的方法步骤
2019/04/25 Python
使用python爬取抖音视频列表信息
2019/07/15 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
python3 pillow模块实现简单验证码
2019/10/31 Python
Python 文件数据读写的具体实现
2020/01/24 Python
基于Django signals 信号作用及用法详解
2020/03/28 Python
Python调用JavaScript代码的方法
2020/10/27 Python
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
详解CSS3实现响应式手风琴效果
2020/06/10 HTML / CSS
乌克兰香水和化妆品网站:Notino.ua
2018/03/26 全球购物
房地产管理毕业生自荐信
2013/11/04 职场文书
银行开业庆典方案
2014/02/06 职场文书
先进工作者申报材料
2014/12/23 职场文书
财务负责人岗位职责
2015/02/03 职场文书
《乙女游戏世界对路人角色很不友好》OP主题曲无字幕动画MV公开
2022/04/05 日漫