转自/archive////jsonviewerextjsmvcfiddl
项目的表现层使用MVC+Extjs在开发过程中一旦页面显示不正常第一个需要排查的总是Action是否输出了正确的Json?由于开发人员会日复一日地频繁进行这个操作所以我们的目标是要找到一种方法可以
不用耗费额外的精力随时查看Json输出
不用耗费额外的精力指的是当需要查看Json输出时只要转转眼球(可能至少还需要点两下鼠标恐怕)就能很快找到想看的结果
查看Json输出的方法很多我们所能找的最接近这个目标的方案是Fiddler+JsonViewer插件+自定义Fiddler过滤条件想要查看Json输出时只要先将Fiddler运行起来然后在浏览器里正常操作Web页面就可以在Fiddler里面看到截获的Json输出了效果如下图所示
安装Fiddler+JsonViewer插件
Fiddler是一款老牌Web调试工具下载安装之后通过点击开始|程序|Fiddler或点击IE的菜单工具|Fiddler将其运行起来后它会自动把自己注册成IE的代理服务器从而截获任何经过IE的请求/应答当关闭它时它又会自动把代理服务器配置取消(当年使用Fiddler的时候还得自己添加代理服务器配置很麻烦的说)
JsonViewer是一款查看Json对象的小工具解压后可以看到个子目录
JsonView可独立运行版
VisualizerVS插件
FiddlerFiddler插件
我们接下来要安装JsonViewer的Fiddler插件方法是将Fiddler目录中的所有文件复制到Fiddler的安装目录\Inspectors\然后修改Fiddler的安装目录\nfig如下图所示粗体部分是需要我们添加的配置信息
nfig
<configuration>
<runtime>
<generatePublisherEvidence enabled=false/>
<assemblyBinding xmlns=urn:schemasmicrosoftcom:asmv>
<probing privatePath=Inspectors />
</assemblyBinding>
</runtime>
</configuration>
注意 IE 和 NET Framework 被硬编码成只要是对localhost的请求就不通过代理服务器所以像x这样的请求不会被Fiddler截获解决方法是) 将localhost替换成localhost如x) 将localhost替换成本机IP地址如x
现在让我们把Fiddler运行起来再操作一下页面就可以在Fiddler窗体左侧的Web Sessions列表里看到一大堆请求/应答点击返回Json的那一条再点击进入右侧的InspectorsJsonTab页就可以了只是Fiddler默认会把所有经过IE的任何请求/应答全都显示出来这样一来Web Sessions列表里的东东就嫌太多了能不能把与Json不相干的东东全部过滤掉呢?这个并不难只要在Fiddler的CustomRules里面增加几行代码就可以了
自定义过滤条件
点击Fiddler的菜单Rules|Customize Rules会自动由记事本打开可添加自定义规则的代码文件
在第行增加如下代码目的是在Fiddler的Rules菜单里增加一个只显示Json的菜单项
// jcl
public static RulesOption(只显示 &Json)
var m_ShowJsonOnly: boolean = false;
在OnBeforeResponse事件里增加如下代码意思是如果Rules|只显示Json菜单项被选中了就过滤掉所有ContentType!=application/json; charset=utf的应答
// jcl:
if(m_ShowJsonOnly) {
//MessageBoxShow(oSessionoResponseheadersItem(ContentType)ToString());
if (!oSessionoResponseheadersExistsAndContains(ContentType application/json; charset=utf)) {
oSession[uihide] = hide; // String value not important
}
}
所有源码在此
自定义规则
import System;
import SystemWindowsForms;
import Fiddler;
// GLOBALIZATION NOTE:
// Be sure to save this file with UTF Encoding if using any nonASCII characters
// in strings etc
//
// JScript Reference
//
//
// FiddlerScript Reference
//
//
// FiddlerScript Editor:
//
class Handlers
{
// The following snippet demonstrates a custombound column for the web sessions list
// See for more info
//public static BindUIColumn(Method )
//function FillMethodColumn(oS: Session){
// if ((oSoRequest != null) && (oSoRequestheaders != null))
// return oSoRequestheadersHTTPMethod; else return StringEmpty;
//}
public static RulesOption(Hide s)
var m_Hides: boolean = false;
// Cause Fiddler to override the AcceptLanguage header with one of the defined values
public static RulesOption(Request &Japanese Content)
var m_Japanese: boolean = false;
// Cause Fiddler to override the UserAgent header with one of the defined values
RulesString(&UserAgents true)
RulesStringValue(Netscape & Mozilla/ (Win; I))
RulesStringValue(&IEMobile Mozilla/ (compatible; MSIE ; Windows CE; IEMobile ))
RulesStringValue(&Safari (XP) Mozilla/ (Windows; U; Windows NT ; enUS) AppleWebKit/ (KHTML like Gecko) Version/ Safari/)
RulesStringValue(IE & (XPSP) Mozilla/ (compatible; MSIE ; Windows NT ; SV))
RulesStringValue(IE & (Vista) Mozilla/ (compatible; MSIE ; Windows NT ; SLCC))
RulesStringValue(IE & (Wink x) Mozilla/ (compatible; MSIE ; Windows NT ; WOW; Trident/))
RulesStringValue(IE (Win) Mozilla/ (compatible; MSIE ; Windows NT ; Trident/))
RulesStringValue(IE (IE CompatMode) Mozilla/ (compatible; MSIE ; Windows NT ; Trident/))
RulesStringValue(&Opera Opera/ (Windows NT ; U; en) Presto/ Version/)
RulesStringValue(&Firefox Mozilla/ (Windows; U; Windows NT ; enUS; rv:) Gecko/ Firefox/)
RulesStringValue(&Firefox Mozilla/ (Windows; U; Windows NT ; enUS; rv:) Gecko/ Firefox/)
RulesStringValue(&Firefox (Mac) Mozilla/ (Macintosh; U; Intel Mac OS X ; enUS; rv:) Gecko/ Firefox/)
RulesStringValue(Chrome Mozilla/ (Windows; U; Windows NT ; enUS) AppleWebKit/ (KHTML like Gecko) Chrome/ Safari/)
RulesStringValue(&Custom %CUSTOM%)
public static var sUA: String = null;
// Cause Fiddler to delay HTTP traffic to simulate typical k modem conditions
public static RulesOption(Simulate &Modem speeds Per&formance)
var m_SimulateModem: boolean = false;
// Removes HTTPcaching related headers and specifies nocache on requests and responses
public static RulesOption(&Disable Caching Per&formance)
var m_DisableCaching: boolean = false;
// Show the duration between the start of RequestSend and ResponseCompleted in Milliseconds
public static RulesOption(&Show TimetoLastByte Per&formance)
var m_ShowTTLB: boolean = false;
// Show the time of response completion
public static RulesOption(Show Response &Timestamp Per&formance)
var m_ShowTimestamp: boolean = false;
// Create a new option on the Rules menu Set the default value for the option
public static RulesOption(&UNTITLED)
var m_bUNTITLED: boolean = false;
// Create a new item on the Tools menu
public static ToolsAction(&UNTITLED)
function DoUNTITLED(oSessions: FiddlerSession[]){
// Write your code here
}
// jcl
public static RulesOption(只显示 &Json)
var m_ShowJsonOnly: boolean = false;
// Force a manual reload of the script file Resets all
// RulesOption variables to their defaults
public static ToolsAction(Reset Script)
function DoManualReload(){
FiddlerObjectReloadScript();
}
public static ContextAction(Decode Selected Sessions)
function DoRemoveEncoding(oSessions: Session[]){
for (var x = ; x < oSessionsLength; x++){
oSessions[x]utilDecodeRequest();
oSessions[x]utilDecodeResponse();
}
}
static function OnBoot(){
// MessageBoxShow(Fiddler has finished booting);
// SystemDiagnosticsProcessStart(iexploreexe);
// FiddlerObjectUIActivateRequestInspector(HEADERS);
// FiddlerObjectUIActivateResponseInspector(HEADERS);
}
static function OnShutdown(){
// MessageBoxShow(Fiddler has shutdown);
}
static function OnAttach(){
// MessageBoxShow(Fiddler is now the system proxy);
// SystemDiagnosticsProcessStart(proxycfgexe u); // Notify WinHTTP of proxy change
}
static function OnDetach(){
// MessageBoxShow(Fiddler is no longer the system proxy);
// SystemDiagnosticsProcessStart(proxycfgexe u); // Notify WinHTTP of proxy change
}
static function OnBeforeRequest(oSession: Session)
{
// Sample Rule: Color ASPX requests in RED
// if (oSessionuriContains(aspx)) { oSession[uicolor] = red; }
// Sample Rule: Flag POSTs to in italics
// if (oSessionHostnameIs() && oSessionHTTPMethodIs(POST)) { oSession[uiitalic] = yup; }
// Sample Rule: Break requests for URLs containing /sandbox/
// if (oSessionuriContains(/sandbox/)){
// oSessionoFlags[xbreakrequest] = yup; // Existence of the xbreakrequest flag creates a breakpoint; the yup value is unimportant
// }
if ((null != gs_ReplaceToken) && (oSessionurlindexOf(gs_ReplaceToken)>)){ // Case sensitive
oSessionurl = oSessionurlReplace(gs_ReplaceToken gs_ReplaceTokenWith);
}
if ((null != gs_OverridenHost) && (oSessionhosttoLowerCase() == gs_OverridenHost)){
oSession[xoverridehost] = gs_OverrideHostWith;
}
if ((null!=bpRequestURI) && oSessionuriContains(bpRequestURI)){
oSession[xbreakrequest]=uri;
}
if ((null!=bpMethod) && (oSessionHTTPMethodIs(bpMethod))){
oSession[xbreakrequest]=method;
}
if ((null!=uiBoldURI) && oSessionuriContains(uiBoldURI)){
oSession[uibold]=QuickExec;
}
if (m_SimulateModem){
// Delay sends by ms per KB uploaded
oSession[requesttrickledelay] = ;
}
if (m_DisableCaching){
oSessionoRequestheadersRemove(IfNoneMatch);
oSessionoRequestheadersRemove(IfModifiedSince);
oSessionoRequest[Pragma] = nocache;
}
// UserAgent Overrides
if (null != sUA){
oSessionoRequest[UserAgent] = sUA;
}
if (m_Japanese){
oSessionoRequest[AcceptLanguage] = ja;
}
}
static function OnBeforeResponse(oSession: Session)
{
if (m_SimulateModem){
// Delay receives by ms per KB downloaded
oSession[responsetrickledelay] = ;
}
if (m_DisableCaching){
oSessionoResponseheadersRemove(Expires);
oSessionoResponse[CacheControl] = nocache;
}
if (m_ShowTimestamp){
oSession[uicustomcolumn] = DateTimeNowToString(H:mm:ssffff) + + oSession[uicustomcolumn];
}
if (m_ShowTTLB){
oSession[uicustomcolumn] = oSessionoResponseiTTLB + ms + oSession[uicustomcolumn];
}
if (m_Hides && oSessionresponseCode == ){
oSession[uihide] = true;
}
if ((bpStatus>) && (oSessionresponseCode == bpStatus)){
oSession[xbreakresponse]=status;
}
if ((null!=bpResponseURI) && oSessionuriContains(bpResponseURI)){
oSession[xbreakresponse]=uri;
}
// jcl:
if(m_ShowJsonOnly) {
//MessageBoxShow(oSessionoResponseheadersItem(ContentType)ToString());
if (!oSessionoResponseheadersExistsAndContains(ContentType application/json; charset=utf)) {
oSession[uihide] = hide; // String value not important
}
}
// Uncomment to reduce incidence of unexpected socket closure exceptions in NET code
// Note that you really should also fix your NET code to gracefully handle unexpected connection closure
//
// if (!(((oSessionresponseCode == ) && oSessionoResponse[WWWAuthenticate]Length > ) ||
// ((oSessionresponseCode == ) && oSessionoResponse[ProxyAuthenticate]Length > ))) {
// oSessionoResponse[Connection] = close;
// }
}
static function Main()
{
var today: Date = new Date();
FiddlerObjectStatusText = CustomRulesjs was loaded at: + today;
// Uncomment to add a Server column containing the response Server header if present
// FiddlerObjectUIlvSessionsAddBoundColumn(Server @responseserver);
}
// These static variables are used for simple breakpointing & other QuickExec rules
static var bpRequestURI:String = null;
static var bpResponseURI:String = null;
static var bpStatus:int = ;
static var bpMethod: String = null;
static var uiBoldURI: String = null;
static var gs_ReplaceToken: String = null;
static var gs_ReplaceTokenWith: String = null;
static var gs_OverridenHost: String = null;
static var gs_OverrideHostWith: String = null;
// The OnExecAction function is called by either the QuickExec box in the Fiddler window
// or by the ExecActionexe command line utility
static function OnExecAction(sParams: String[]){
FiddlerObjectStatusText = ExecAction: + sParams[];
var sAction = sParams[]toLowerCase();
switch (sAction){
case bold:
if (sParamsLength<) {uiBoldURI=null; FiddlerObjectStatusText=Bolding cleared; return;}
uiBoldURI = sParams[]; FiddlerObjectStatusText=Bolding requests for + uiBoldURI;
break;
case bp:
FiddlerObjectalert(bpu = breakpoint request for uri\nbpm = breakpoint request method\nbps=breakpoint response status\nbpafter = breakpoint response for URI);
break;
case bps:
if (sParamsLength<) {bpStatus=; FiddlerObjectStatusText=Response Status breakpoint cleared; return;}
bpStatus = parseInt(sParams[]); FiddlerObjectStatusText=Response status breakpoint for + sParams[];
break;
case bpv:
case bpm:
if (sParamsLength<) {bpMethod=null; FiddlerObjectStatusText=Request Method breakpoint cleared; return;}
bpMethod = sParams[]toUpperCase(); FiddlerObjectStatusText=Request Method breakpoint for + bpMethod;
break;
case bpu:
if (sParamsLength<) {bpRequestURI=null; FiddlerObjectStatusText=RequestURI breakpoint cleared; return;}
if (sParams[]toLowerCase()StartsWith(//)){sParams[] = sParams[]Substring();}
bpRequestURI = sParams[];
FiddlerObjectStatusText=RequestURI breakpoint for +sParams[];
break;
case bpafter:
if (sParamsLength<) {bpResponseURI=null; FiddlerObjectStatusText=ResponseURI breakpoint cleared; return;}
if (sParams[]toLowerCase()StartsWith(//)){sParams[] = sParams[]Substring();}
bpResponseURI = sParams[];
FiddlerObjectStatusText=ResponseURI breakpoint for +sParams[];
break;
case overridehost:
if (sParamsLength<) {gs_OverridenHost=null; FiddlerObjectStatusText=Host Override cleared; return;}
gs_OverridenHost = sParams[]toLowerCase();
gs_OverrideHostWith = sParams[];
FiddlerObjectStatusText=Connecting to [ + gs_OverrideHostWith + ] for requests to [ + gs_OverridenHost + ];
break;
case urlreplace:
if (sParamsLength<) {gs_ReplaceToken=null; FiddlerObjectStatusText=URL Replacement cleared; return;}
gs_ReplaceToken = sParams[];
gs_ReplaceTokenWith = sParams[]Replace( %); // Simple helper
FiddlerObjectStatusText=Replacing [ + gs_ReplaceToken + ] in URIs with [ + gs_ReplaceTokenWith + ];
break;
case select:
if (sParamsLength<) { FiddlerObjectStatusText=Please specify ContentType to select; return;}
FiddlerObjectUIactSelectSessionsWithResponseHeaderValue(ContentType sParams[]);
MessageBoxShow(sParams[]);
FiddlerObjectStatusText=Selected sessions returning ContentType: + sParams[] + ;
if (FiddlerObjectUIlvSessionsSelectedItemsCount > ){
FiddlerObjectUIlvSessionsFocus();
}
break;
case allbut:
case keeponly:
if (sParamsLength<) { FiddlerObjectStatusText=Please specify ContentType to retain during wipe; return;}
FiddlerObjectUIactSelectSessionsWithResponseHeaderValue(ContentType sParams[]);
MessageBoxShow(sParams[]);
FiddlerObjectUIactRemoveUnselectedSessions();
FiddlerObjectUIlvSessionsSelectedItemsClear();
FiddlerObjectStatusText=Removed all but ContentType: + sParams[];
break;
case stop:
FiddlerObjectUIactDetachProxy();
break;
case start:
FiddlerObjectUIactAttachProxy();
break;
case cls:
case clear:
FiddlerObjectUIactRemoveAllSessions();
break;
case g:
case go:
FiddlerObjectUIactResumeAllSessions();
break;
case help:
UtilitiesLaunchHyperlink();
break;
case hide:
FiddlerObjectUIactMinimizeToTray();
break;
case nuke:
FiddlerObjectUIactClearWinINETCache();
FiddlerObjectUIactClearWinINETCookies();
break;
case show:
FiddlerObjectUIactRestoreWindow();
break;
case tail:
if (sParamsLength<) { FiddlerObjectStatusText=Please specify # of sessions to trim the session list to; return;}
FiddlerObjectUITrimSessionList(intParse(sParams[]));
break;
case quit:
FiddlerObjectUIactExit();
break;
case dump:
FiddlerObjectUIactSelectAll();
FiddlerObjectUIactSaveSessionsToZip(CONFIGGetPath(Captures) + dumpsaz);
FiddlerObjectUIactRemoveAllSessions();
FiddlerObjectStatusText = Dumped all sessions to + CONFIGGetPath(Captures) + dumpsaz;
break;
default:
if (sActionStartsWith(http) || sActionStartsWith(www)){
SystemDiagnosticsProcessStart(sAction);
}
else
FiddlerObjectStatusText = Requested ExecAction: + sAction + not found Type HELP to learn more;
}
}
}
现在Web Sessions列表已经清爽多了可是如果我们想忙里偷闲去博客园首页逛逛就会发现Web Sessions列表里面多了几条博客园首页的Json输出这是因为Fiddler默认会截获所有经由IE的请求/应答能不能让它只显示本机的请求/应答呢?这个只需要配置一下Fiddler的Filter选项就可以了如下图所示