用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下4个跨浏览器必备的函数
Mar 07 Javascript
JavaScript 笔记二 Array和Date对象方法
May 22 Javascript
js展开闭合效果演示代码
Jul 24 Javascript
JavaScript 数组详解
Oct 10 Javascript
JavaScript sub方法入门实例(把字符串显示为下标)
Oct 17 Javascript
JavaScript中的console.time()函数详细介绍
Dec 29 Javascript
详解在Vue中如何使用axios跨域访问数据
Jul 07 Javascript
全新打包工具parcel零配置vue开发脚手架
Jan 11 Javascript
vue input输入框模糊查询的示例代码
May 22 Javascript
微信小程序通过保存图片分享到朋友圈功能
May 24 Javascript
小程序scroll-view安卓机隐藏横向滚动条的实现详解
May 16 Javascript
微信小程序复选框实现多选一功能过程解析
Feb 14 Javascript
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
dedecms中常见问题修改方法总结
2007/03/21 PHP
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
2011/12/19 PHP
免费手机号码归属地API查询接口和PHP使用实例分享
2014/04/10 PHP
调用WordPress函数统计文章访问量及PHP原生计数器的实现
2016/03/21 PHP
php实现登录tplink WR882N获取IP和重启的方法
2016/07/20 PHP
phpcms中的评论样式修改方法
2016/10/21 PHP
PHP中Laravel 关联查询返回错误id的解决方法
2017/04/01 PHP
PHP回调函数与匿名函数实例详解
2017/08/16 PHP
PHP抽象类基本用法示例
2018/12/28 PHP
laravel实现简单用户权限的示例代码
2019/05/28 PHP
让你的网站可编辑的实现js代码
2009/10/19 Javascript
jQuery DOM操作小结与实例
2010/01/07 Javascript
解决Jquery load()加载GB2312页面时出现乱码的两种方案
2013/09/10 Javascript
javascript中parseInt()函数的定义和用法分析
2014/12/20 Javascript
实例讲解JS中pop使用方法
2019/01/27 Javascript
基于Vue+elementUI实现动态表单的校验功能(根据条件动态切换校验格式)
2019/04/04 Javascript
微信小程序swiper组件实现抖音翻页切换视频功能的实例代码
2020/06/24 Javascript
Vue组件生命周期运行原理解析
2020/11/25 Vue.js
详解JavaScript中的链式调用
2020/11/27 Javascript
[03:22]DAC最前线(第二期)—DOTA2亚洲邀请赛主赛场周边及线路探访
2015/01/24 DOTA
[01:16:50]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第一场 3月7日
2021/03/11 DOTA
Python环境变量设置方法
2016/08/28 Python
django使用图片延时加载引起后台404错误
2017/04/18 Python
Linux RedHat下安装Python2.7开发环境
2017/05/20 Python
python中正则表达式与模式匹配
2019/05/07 Python
在keras中获取某一层上的feature map实例
2020/01/24 Python
Python打包工具PyInstaller的安装与pycharm配置支持PyInstaller详细方法
2020/02/27 Python
css3 伪元素和伪类选择器详解
2014/09/04 HTML / CSS
巧克力领导品牌瑞士莲美国官网:Lindt Chocolate美国
2016/08/25 全球购物
美国彩妆品牌:Coastal Scents
2017/04/01 全球购物
医务人员竞聘职务自我评价分享
2013/11/08 职场文书
旅游局领导班子“四风”问题对照检查材料思想汇报
2014/09/29 职场文书
2014年实习期工作总结
2014/11/27 职场文书
家长学校教学计划
2015/01/19 职场文书
团队执行力培训心得体会
2015/08/15 职场文书
HTML静态页面获取url参数和UserAgent的实现
2022/08/05 HTML / CSS