From be2d5e8425c8af981f6946304eaf5e766e716772 Mon Sep 17 00:00:00 2001 From: Hattan Shobokshi Date: Wed, 20 Feb 2013 16:37:39 -0800 Subject: [PATCH 1/2] Added css for formatted response tab --- .../WebApiTestClient/Areas/HelpPage/TestClient.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/TestClient.css b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/TestClient.css index 6c733af..bbcf039 100644 --- a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/TestClient.css +++ b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/TestClient.css @@ -35,4 +35,15 @@ select { width: 100px; float: left; border: none; +} + +.formattedJson { + white-space: pre; + width:300px; + height:300px; +} + +#formattedResponseTab { + overflow:auto; + height:400px } \ No newline at end of file From 049b9e039b83b3e72be6e46429e49d821e0156a2 Mon Sep 17 00:00:00 2001 From: Hattan Shobokshi Date: Wed, 20 Feb 2013 16:45:23 -0800 Subject: [PATCH 2/2] Added changes to support formatted response Added the option to see formatted responses for xml and json. For other content types the tab is hidden and only the raw content tab is visible. Currently using vkbeautify.js for formatting but this can easily changed. --- .../TestClientDialogs.cshtml.pp | 13 +- .../TestClientReferences.cshtml | 1 + .../Scripts/WebApiTestClient.js | 208 ++++++---- .../WebApiTestClient/Scripts/vkbeautify.js | 358 ++++++++++++++++++ .../WebApiTestClient/WebApiTestClient.csproj | 121 +++--- .../WebApiTestClient/WebApiTestClient.nuspec | 1 + 6 files changed, 558 insertions(+), 144 deletions(-) create mode 100644 WebApiTestClient/WebApiTestClient/Scripts/vkbeautify.js diff --git a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientDialogs.cshtml.pp b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientDialogs.cshtml.pp index f0a4f9d..5981ac1 100644 --- a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientDialogs.cshtml.pp +++ b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientDialogs.cshtml.pp @@ -61,7 +61,18 @@
Body
- +
diff --git a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientReferences.cshtml b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientReferences.cshtml index 4cdd3a0..c61e8ae 100644 --- a/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientReferences.cshtml +++ b/WebApiTestClient/WebApiTestClient/Areas/HelpPage/Views/Help/DisplayTemplates/TestClientReferences.cshtml @@ -7,4 +7,5 @@ { } + \ No newline at end of file diff --git a/WebApiTestClient/WebApiTestClient/Scripts/WebApiTestClient.js b/WebApiTestClient/WebApiTestClient/Scripts/WebApiTestClient.js index e04d68c..933e436 100644 --- a/WebApiTestClient/WebApiTestClient/Scripts/WebApiTestClient.js +++ b/WebApiTestClient/WebApiTestClient/Scripts/WebApiTestClient.js @@ -22,6 +22,128 @@ var emptyTestClientModel = return path; } + function decodeSample(sampleString) { + return unescape(sampleString).replace(/\+/gi, " ").replace(/\r\n/gi, "\n"); + } + + function addOrReplaceHeader(headers, headerName, headerValue) { + var headerList = headers(); + for (var i in headerList) { + if (headerList[i].name.toLowerCase() == headerName) { + headers.replace(headerList[i], { name: headerList[i].name, value: headerValue }); + return; + } + } + headers.push({ name: headerName, value: headerValue }); + } + + function SendRequest(httpMethod, url, requestHeaders, requestBody, handleResponse) { + if (httpMethod.length == 0) { + alert("HTTP Method should not be empty"); + return false; + } + + if (url.length == 0) { + alert("Url should not be empty"); + return false; + } + + var httpRequest = new XMLHttpRequest(); + try { + httpRequest.open(httpMethod, encodeURI(url), false); + } + catch (e) { + alert("Cannot send request. Check the security setting of your browser if you are sending request to a different domain."); + return false; + } + + httpRequest.setRequestHeader("If-Modified-Since", new Date(0)); + try { + for (var i in requestHeaders) { + var header = requestHeaders[i]; + httpRequest.setRequestHeader(header.name, header.value); + } + } catch (e) { + alert("Invalid header."); + return false; + } + + httpRequest.onreadystatechange = function () { + switch (this.readyState) { + case 4: + handleResponse(httpRequest); + break; + default: + break; + } + }; + + httpRequest.ontimeout = function () { + alert("Request timed out."); + }; + + httpRequest.send(requestBody); + + return true; + } + + function getFormattedJson(json) { + var result = vkbeautify.json(json); + return result; + } + + function getFormattedXml(xml) { + var result = vkbeautify.xml(xml); + return result; + } + + var ContentTypes = { + JSON: "application/json", + XML: "text/xml" + }; + + function getFormattedContent(rawResponse, contentType) { + if (contentType.is(ContentTypes.JSON)) { + return getFormattedJson(rawResponse); + } + else if (contentType.is(ContentTypes.XML)) { + return getFormattedXml(rawResponse); + } + + return null; + } + + function getContentType(request) { + var result = function () { + var self = this; + self.value = request.getResponseHeader('content-type'); + self.is = function (expectedContentType) { + return self.value.indexOf(expectedContentType) > -1; + }; + return self; + }; + return new result(); + } + + function getHttpResponse(httpRequest) { + var statusCode = httpRequest.status, + statusText = httpRequest.statusText, + responseHeaders = httpRequest.getAllResponseHeaders(), + rawResponse = httpRequest.responseText, + contentType = getContentType(httpRequest), + formattedResponse = getFormattedContent(rawResponse, contentType); + + // IE - #1450: sometimes returns 1223 when it should be 204 + if (statusCode === 1223) { + statusCode = 204; + statusText = "No Content"; + } + + var responseStatus = statusCode + "/" + statusText; + + return { status: responseStatus, headers: responseHeaders, content: rawResponse, formattedContent: formattedResponse }; + } + function TestClientViewModel(data) { var self = this; self.HttpMethod = ko.observable(data.HttpMethod); @@ -99,7 +221,7 @@ var emptyTestClientModel = open: function () { jQuery('.ui-widget-overlay').bind('click', function () { jQuery('#testClientDialog').dialog('close'); - }) + }); }, buttons: { "Send": function () { @@ -114,9 +236,10 @@ var emptyTestClientModel = width: "550", modal: true, open: function () { + $("#responseTabsLinks").tabs({ selected: 0 }); jQuery('.ui-widget-overlay').bind('click', function () { jQuery('#testClientResponseDialog').dialog('close'); - }) + }); } }); @@ -130,84 +253,3 @@ var emptyTestClientModel = ko.applyBindings(new TestClientViewModel(initialModel)); })(); -function decodeSample(sampleString) { - return unescape(sampleString).replace(/\+/gi, " ").replace(/\r\n/gi, "\n"); -} - -function addOrReplaceHeader(headers, headerName, headerValue) { - var headerList = headers(); - for (var i in headerList) { - if (headerList[i].name.toLowerCase() == headerName) { - headers.replace(headerList[i], { name: headerList[i].name, value: headerValue }); - return; - } - } - headers.push({ name: headerName, value: headerValue }); -} - -function SendRequest(httpMethod, url, requestHeaders, requestBody, handleResponse) { - if (httpMethod.length == 0) { - alert("HTTP Method should not be empty"); - return false; - } - - if (url.length == 0) { - alert("Url should not be empty"); - return false; - } - - var httpRequest = new XMLHttpRequest(); - try { - httpRequest.open(httpMethod, encodeURI(url), false); - } - catch (e) { - alert("Cannot send request. Check the security setting of your browser if you are sending request to a different domain."); - return false; - } - - httpRequest.setRequestHeader("If-Modified-Since", new Date(0)); - try { - for (var i in requestHeaders) { - var header = requestHeaders[i]; - httpRequest.setRequestHeader(header.name, header.value); - } - } catch (e) { - alert("Invalid header."); - return false; - } - - httpRequest.onreadystatechange = function () { - switch (this.readyState) { - case 4: - handleResponse(httpRequest); - break; - default: - break; - } - } - - httpRequest.ontimeout = function () { - alert("Request timed out."); - } - - httpRequest.send(requestBody); - - return true; -} - -function getHttpResponse(httpRequest) { - var statusCode = httpRequest.status; - var statusText = httpRequest.statusText; - var responseHeaders = httpRequest.getAllResponseHeaders(); - var rawResponse = httpRequest.responseText; - - // IE - #1450: sometimes returns 1223 when it should be 204 - if (statusCode === 1223) { - statusCode = 204; - statusText = "No Content"; - } - - var responseStatus = statusCode + "/" + statusText; - - return { status: responseStatus, headers: responseHeaders, content: rawResponse }; -} \ No newline at end of file diff --git a/WebApiTestClient/WebApiTestClient/Scripts/vkbeautify.js b/WebApiTestClient/WebApiTestClient/Scripts/vkbeautify.js new file mode 100644 index 0000000..1c2b496 --- /dev/null +++ b/WebApiTestClient/WebApiTestClient/Scripts/vkbeautify.js @@ -0,0 +1,358 @@ +/** +* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats. +* +* Version - 0.99.00.beta +* Copyright (c) 2012 Vadim Kiryukhin +* vkiryukhin @ gmail.com +* http://www.eslinstructor.net/vkbeautify/ +* +* Dual licensed under the MIT and GPL licenses: +* http://www.opensource.org/licenses/mit-license.php +* http://www.gnu.org/licenses/gpl.html +* +* Pretty print +* +* vkbeautify.xml(text [,indent_pattern]); +* vkbeautify.json(text [,indent_pattern]); +* vkbeautify.css(text [,indent_pattern]); +* vkbeautify.sql(text [,indent_pattern]); +* +* @text - String; text to beatufy; +* @indent_pattern - Integer | String; +* Integer: number of white spaces; +* String: character string to visualize indentation ( can also be a set of white spaces ) +* Minify +* +* vkbeautify.xmlmin(text [,preserve_comments]); +* vkbeautify.jsonmin(text); +* vkbeautify.cssmin(text [,preserve_comments]); +* vkbeautify.sqlmin(text); +* +* @text - String; text to minify; +* @preserve_comments - Bool; [optional]; +* Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. ) +* +* Examples: +* vkbeautify.xml(text); // pretty print XML +* vkbeautify.json(text, 4 ); // pretty print JSON +* vkbeautify.css(text, '. . . .'); // pretty print CSS +* vkbeautify.sql(text, '----'); // pretty print SQL +* +* vkbeautify.xmlmin(text, true);// minify XML, preserve comments +* vkbeautify.jsonmin(text);// minify JSON +* vkbeautify.cssmin(text);// minify CSS, remove comments ( default ) +* vkbeautify.sqlmin(text);// minify SQL +* +*/ + +(function() { + + function createShiftArr(step) { + + var space = ' '; + + if ( isNaN(parseInt(step)) ) { // argument is string + space = step; + } else { // argument is integer + switch(step) { + case 1: space = ' '; break; + case 2: space = ' '; break; + case 3: space = ' '; break; + case 4: space = ' '; break; + case 5: space = ' '; break; + case 6: space = ' '; break; + case 7: space = ' '; break; + case 8: space = ' '; break; + case 9: space = ' '; break; + case 10: space = ' '; break; + case 11: space = ' '; break; + case 12: space = ' '; break; + } + } + + var shift = ['\n']; // array of shifts + for(ix=0;ix<100;ix++){ + shift.push(shift[ix]+space); + } + return shift; + } + + function vkbeautify(){ + this.step = ' '; // 4 spaces + this.shift = createShiftArr(this.step); + }; + + vkbeautify.prototype.xml = function(text,step) { + + var ar = text.replace(/>\s{0,}<") + .replace(/ or -1) { + str += shift[deep]+ar[ix]; + inComment = true; + // end comment or // + if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) { + inComment = false; + } + } else + // end comment or // + if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) { + str += ar[ix]; + inComment = false; + } else + // // + if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) && + /^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) { + str += ar[ix]; + if(!inComment) deep--; + } else + // // + if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) { + str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix]; + } else + // ... // + if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) { + str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix]; + } else + // // + if(ar[ix].search(/<\//) > -1) { + str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix]; + } else + // // + if(ar[ix].search(/\/>/) > -1 ) { + str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix]; + } else + // // + if(ar[ix].search(/<\?/) > -1) { + str += shift[deep]+ar[ix]; + } else + // xmlns // + if( ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) { + str += shift[deep]+ar[ix]; + } + + else { + str += ar[ix]; + } + } + + return (str[0] == '\n') ? str.slice(1) : str; + } + + vkbeautify.prototype.json = function(text,step) { + + var step = step ? step : this.step; + + if (typeof JSON === 'undefined' ) return text; + + if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step); + if ( typeof text === "object" ) return JSON.stringify(text, null, step); + + return text; // text is not string nor object + } + + vkbeautify.prototype.css = function(text, step) { + + var ar = text.replace(/\s{1,}/g,' ') + .replace(/\{/g,"{~::~") + .replace(/\}/g,"~::~}~::~") + .replace(/\;/g,";~::~") + .replace(/\/\*/g,"~::~/*") + .replace(/\*\//g,"*/~::~") + .replace(/~::~\s{0,}~::~/g,"~::~") + .split('~::~'), + len = ar.length, + deep = 0, + str = '', + ix = 0, + shift = step ? createShiftArr(step) : this.shift; + + for(ix=0;ix/g,"") + .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns'); + return str.replace(/>\s{0,}<"); + } + + vkbeautify.prototype.jsonmin = function(text) { + + if (typeof JSON === 'undefined' ) return text; + + return JSON.stringify(JSON.parse(text), null, 0); + + } + + vkbeautify.prototype.cssmin = function(text, preserveComments) { + + var str = preserveComments ? text + : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ; + + return str.replace(/\s{1,}/g,' ') + .replace(/\{\s{1,}/g,"{") + .replace(/\}\s{1,}/g,"}") + .replace(/\;\s{1,}/g,";") + .replace(/\/\*\s{1,}/g,"/*") + .replace(/\*\/\s{1,}/g,"*/"); + } + + vkbeautify.prototype.sqlmin = function(text) { + return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")"); + } + + window.vkbeautify = new vkbeautify(); + +})(); + diff --git a/WebApiTestClient/WebApiTestClient/WebApiTestClient.csproj b/WebApiTestClient/WebApiTestClient/WebApiTestClient.csproj index d7a7855..fdeca43 100644 --- a/WebApiTestClient/WebApiTestClient/WebApiTestClient.csproj +++ b/WebApiTestClient/WebApiTestClient/WebApiTestClient.csproj @@ -1,68 +1,69 @@  - - - Debug - AnyCPU - {55E16CDA-4832-43F8-822E-5BE81A9845C9} - Library - Properties - WebApiTestClient - WebApiTestClient - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - - + + + + + + \ No newline at end of file diff --git a/WebApiTestClient/WebApiTestClient/WebApiTestClient.nuspec b/WebApiTestClient/WebApiTestClient/WebApiTestClient.nuspec index 54804de..53592b0 100644 --- a/WebApiTestClient/WebApiTestClient/WebApiTestClient.nuspec +++ b/WebApiTestClient/WebApiTestClient/WebApiTestClient.nuspec @@ -22,5 +22,6 @@ + \ No newline at end of file