用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 相关文章推荐
jquery 的 $(&quot;#id&quot;).html() 无内容的解决方法
Jun 07 Javascript
ajaxFileUpload.js插件支持多文件上传的方法
Sep 02 Javascript
排序算法的javascript实现与讲解(99js手记)
Sep 28 Javascript
JavaScript中的setMilliseconds()方法使用详解
Jun 11 Javascript
AngularJS自动表单验证
Feb 01 Javascript
vue.js表格分页示例
Oct 18 Javascript
BootStrap框架个人总结(bootstrap框架、导航条、下拉菜单、轮播广告carousel、栅格系统布局、标签页tabs、模态框、菜单定位)
Dec 01 Javascript
JS实现仿饿了么在浏览器标签页失去焦点时网页Title改变
Jun 01 Javascript
vue页面切换到滚动页面显示顶部的实例
Mar 13 Javascript
详解使用angular框架离线你的应用(pwa指南)
Jan 31 Javascript
VUE实现自身整体组件销毁的示例代码
Jan 13 Javascript
Vue data的数据响应式到底是如何实现的
Feb 11 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
德生H-501的评价与改造
2021/03/02 无线电
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
一起来写段JS drag拖动代码
2010/12/09 Javascript
jquery scrollTop方法根据滚动像素显示隐藏顶部导航条
2013/05/27 Javascript
jquery事件与函数的使用介绍
2013/09/29 Javascript
解决jQuery上传插件Uploadify出现Http Error 302错误的方法
2015/12/18 Javascript
浅析Jquery操作select
2016/12/13 Javascript
JavaScript实现二分查找实例代码
2017/02/22 Javascript
Angular获取手机验证码实现移动端登录注册功能
2017/05/17 Javascript
layui文件上传实现代码
2017/05/20 Javascript
Vue中的slot使用插槽分发内容的方法
2018/03/01 Javascript
详解webpack 入门与解析
2018/04/09 Javascript
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
vue中v-show和v-if的异同及v-show用法
2019/06/06 Javascript
通过原生vue添加滚动加载更多功能
2019/11/21 Javascript
在Django的URLconf中使用多个视图前缀的方法
2015/07/18 Python
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
Python对文件和目录进行操作的方法(file对象/os/os.path/shutil 模块)
2017/05/08 Python
python密码错误三次锁定(实例讲解)
2017/11/14 Python
用Python中的turtle模块画图两只小羊方法
2019/04/09 Python
Pytorch DataLoader 变长数据处理方式
2020/01/08 Python
查看keras的默认backend实现方式
2020/06/19 Python
详解Python 函数参数的拆解
2020/09/02 Python
Django与AJAX实现网页动态数据显示的示例代码
2021/02/24 Python
Canal官网:巴西女性时尚品牌
2019/10/16 全球购物
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
初二物理教学反思
2014/01/29 职场文书
《高尔基和他的儿子》教学反思
2014/04/09 职场文书
2014年小学教学工作总结
2014/11/13 职场文书
2014年职称评定工作总结
2014/11/26 职场文书
大学生党课心得体会
2016/01/07 职场文书
公司开业的祝贺语大全(60条)
2019/07/05 职场文书
网络新闻该怎么写?这些写作技巧你都知道吗?
2019/08/26 职场文书
python实现简单的名片管理系统
2021/04/26 Python
Python爬虫实战之爬取携程评论
2021/06/02 Python
win11怎么用快捷键锁屏? windows11锁屏的几种方法
2021/11/21 数码科技