Reputation: 6152
What this code is trying to achieve:
I want to create a widget that will generate a container of the latest X reviews of a customer. This widget can be placed on any of my customer's websites, so NOT on my own website. Therefore I think I need to use JSONP to support cross domain calls.
I get an unexpected token error when calling my webservice? The JSON appears to be correct. My callback function is never hit now.
test.aspx
<script type="text/javascript" src="http://www.testsite.com/script/widget/myReviews.js"></script>
<div id="ww-widget-reviews" class="ww-reset ww-reviews-widget"></div>
<script type="text/javascript">
testsite.createReview({ "vendorId": "315", "type": "1", "id": "ww-widget-reviews" });
</script>
relevant functions in myReviews.js
testsite.createReview = function(c) {
testsite.reviewWidgetId = c.id;
console.log('calling service');
var a = "http://www.testsite.com/testservice.svc/getcompanyreviewdetails/?id=" + c.vendorId + "&t=" + c.type + "&callback=testsite.writeReviewsCallback";
};
testsite.writeReviewsCallback = function (b) {
alert('hi in the callback'); //this line is never hit
var a = document.getElementById(testsite.reviewWidgetId);
a.className = "ww-reset ww-reviews-widget";
a.innerHTML = testsite.getReviewWidget(b);
};
Itestservice.vb
<OperationContract()> _
<Web.WebInvoke(Method:="GET", ResponseFormat:=Web.WebMessageFormat.Json, BodyStyle:=Web.WebMessageBodyStyle.Bare, _
UriTemplate:="getcompanyreviewdetails/?id={id}&t={t}")> _
Function getCompanyReviewDetails(ByVal id As Integer, ByVal t As Integer) As Stream
the response of the service is:
{
"responseHeader": {
"status": 0,
"QTime": 0,
"params": {
"facet": "false",
"fl": "id,title,friendlyurl,reviewnickname,reviewtext,overallscore,objecttype,rating,rating_total",
"indent": "off",
"q": "*:*",
"wt": "json",
"fq": "id:315"
}
},
"response": {
"numFound": 1,
"start": 0,
"docs": [
{
"friendlyurl": "beachclub-sunrise",
"id": "315",
"title": "Beachclub Sunrise",
"rating": 8.25,
"rating_total": 8,
"reviewnickname": [
"Van Voorenberghe",
"Echtpaar",
"Spijker",
"Kim Kok",
"TOP feest",
"Carolien en Remco",
"Roel en Ilja",
"Sanne poell"
],
"reviewtext": [
"Wij zijn getrouwd in zaal Bruisend. Een ontzettend mooie witte zaal vol karakteristieke elementen. De prijs was goed en de bediening nog beter. Een echte aanrader! Uitkijk op het water, een terras voor de rokers onder ons en echt sfeervol ingericht.",
"Wij hebben een slechte ervaring met de mensen van de Beachclub.\r\nOnze ceremonie vond plaats op het ponton, gevolgd door een buffet en een feest. \r\nEchter de service was erg slecht. We hadden van te voren afspraken gemaakt, maar daar werd op de dag zelf geen aandacht aan geschonken. \r\nHet is voor ons een bijzondere dag en voor ons en vele gasten zou het een leuke dag moeten zijn. We betalen daar veel geld voor, maar dat heeft voor hen geen waarde. \r\nZe hebben wel excuses aangeboden maar we hebben geen tegemoetkoming in het geld gehad. We hebben dus betaald voor dingen die we niet gekregen hebben. Na afloop bleek het dat zaken duurder waren dan van te voren werd gesuggereerd.",
"Afgelopen augustus zijn wij hier getrouwd. We hadden van tevoren een aantal prettige, vriendelijke gesprekken waarin besproken werd welke zaal, welke consumpties, etc. Er was op een gegeven moment wat miscommunicatie (over welke zaal we gereserveerd hadden) maar dit kon gelukkig nog worden opgelost. Het gekozen diner kon van tevoren worden geproefd.\nOp de dag zelf arriveerden wij laat en liep het diner dus uit, dit is in overleg tussen de keuken/bediening en onze ceremoniemeesters flexibel en zonder problemen verlopen. Het eten heeft een prima prijs-kwaliteit verhouding, hoewel de details van de gerechten verschilden bij het proefeten en het diner op de bruiloft zelf. Vooral de tournedos viel in de smaak :) Het diner hielden we in Bruisend, het mooie openbare restaurant van de locatie. Onze bruiloft viel net buiten het hoogseizoen en ondanks het prachtige weer hebben we geen andere gasten dan onze bruiloftsgasten gezien.\nDe bediening is erg vriendelijk en de sfeer van de feestzaal, Sunset, paste helemaal bij hoe we onze bruiloft wilden: knus, vrolijk, gezellig, zomers. Sunset is exotisch ingericht en vanuit de zaal kun je het terras en eventueel verder het strand oplopen. Voor ons een mooie afsluiter van de dag, we kijken met een tevreden gevoel terug!",
"Eind September 2012 hebben wij onze bruiloft gevierd in beachclub Sunrise, zaal Sunset. We hebben romantische foto's gemaakt op het strand en in het water... een aanrader! Samen met onze daggasten een bijzondere middag gehad en genoten van een heerlijk diner. Service was uitstekend. De avond werd afgesloten met een knalfeest! Na grote twijfels tussen het boeken van een band of dj... hebben we via Aqua Best, dj Harry en saxofonist geboekt, succes gegarandeerd! Vanaf het begin stond de dansvloer helemaal gevuld en er is volop gedanst tot het einde. Nog steeds krijgen we veel complimenten over het personeel en de verzorging van het feest. Het was allemaal top geregeld. De locatie is romantisch, knus en heel sfeervol. Helemaal zoals wij het wilde! Een bijzondere, unieke plek voor een onvergetelijke dag!",
"In september 2010 zijn wij getrouwd en we hebben geborreld, gegeten en gefeest bij Bruisend. Ook hebben we op de pier nog foto's gemaakt. Het was een geweldige dag. Super goede service en eten en drinken in overvloed. Perfect verzorgd allemaal en een SUPER sfeertje. Van te voren hebben we duidelijk onze wensen besproken en bijna alles was mogelijk. Er wordt door ons en onze vrienden/ familie nog geregeld gesproken over dit fantastische feest. Zeker een aanrader dus!",
"wij zijn op 1 juni 2012 getrouwd op Sunrise en hebben er aansluitend gegeten en gefeest. Trouwen deden we op het Ponton, en dat had een heel romantisch sfeertje. daarna hebben we lekker genoten van de BBQ en als klapper een mega groot feest, niemand heeft gezeten iedereen danste!Helemaal geweldig was dat we zelfs op het terras een springkussen mochten plaatsen voor de kids die er overdag waren! we hebben alleen maar leuke en fantastische reacties gehad van vrienden en familie. ze hebben onze dag helemaal tot een om nooit meer te vergeten gemaakt en we hebben samen met ons zoontje echt genoten! beter kan een huwelijk niet beginnen!",
"Sunrise was in een woord FANTASTISCH! Namens ons, maar ook namens alle gasten. Al vanaf het eerste informerende gesprek werd de tijd voor ons genomen, luisterend naar waar we op zoek zijn en bespreken wat er mogelijk is. Vrijblijvend, vriendelijk en relaxt. \nDe dag zelf was ook goed. De bediening was zeer vriendelijk, snel, attent en de hele dag goed aanwezig. Diner was lekker.\nHet waren vooral de finishing details die ons speciaal deden voelen: pro-actief vragen of we wat extra frietjes willen voor onze peuter, altijd een vriendelijke glimlach en interesse voor de gasten, de barman die niet moeilijk doet als een van de daggasten een whisky wil drinken ipv. een mix-drank, prive-bediening voor het bruidspaar: er werd goed op ons gelet, en we hebben de hele dag niet een keer om bediening hoeven vragen.\nWat we erg fijn vonden was de balans van de dag: ‘s middag rustig en relaxt, en ‘s avonds party. Uiteraard ook mogelijk omdat Sunrise verschillende locaties/ zalen heeft, en mooie lounge faciliteiten.\nHet feest was ook super. DJ Harrie was de koning! We hadden een vrij complex gezelschap met alle leeftijdsgroepen aanwezig, maar hij heeft de dansvloer vol gekregen en gehouden tot het einde. Bediening, versiering, verlichting: alles prima!\nWe hebben heel veel positieve feedback ontvangen en ik weet zeker dat Sunrise er weer nieuwe toekomstige klanten bij heeft.\n",
"Wij zijn 14-09-2012 getrouwd op het ponton van sunrise, absoluut een unieke en bijzondere locatie. Wij zijn verder heel de dag op sunrise gebleven dus ook het diner en feestavond daar gehad. En onze trouwdag was meer dan geslaagd. De begeleiding van sunrise met tips en ideeën was super. De service met betrekking tot hapjes en drankjes was super, niemand stond zonder drinken. De huis dj was top, en we hadden een top feest met iedereen op de dansvloer! Kortom ik raad iedereen aan om bij sunrise te trouwen!!"
],
"overallscore": [
10,
1,
8,
9,
9,
10,
9,
10
]
}
]
}
}
UPDATE: wrapping the JSON in the callback function
Based on comments I now have:
testsite.createReview = function(c) {
testsite.reviewWidgetId = c.id;
console.log('calling service');
var a = "http://www.testsite.com/testservice.svc/getcompanyreviewdetails/?id=" + c.vendorId + "&t=" + c.type + "&callback=parseWeddingJSON";
var b = document.createElement("script");
b.setAttribute("type", "text/javascript");
b.setAttribute("src", a);
testsite.headLoc.appendChild(b);
};
function parseWeddingJSON(json) {
console.log('parseWeddingJSON');
console.log(json);
};
But the parseWeddingJSON
function is not executed. Do I need to support this callback
parameter somehow in the configuration of the service itself? Because right now I only have defined 2 parameters id' and
t`.
Upvotes: 0
Views: 2639
Reputation: 16468
In your code you have this:
var a = "http://www.wonderweddings.com/weddingservice.svc/getcompanyreviewdetails/?id=" + c.vendorId + "&t=" + c.type;//+ "&callback=WonderWeddings.writeReviewsCallback";
var b = document.createElement("script");
b.setAttribute("type", "text/javascript");
b.setAttribute("src", a);
WonderWeddings.headLoc.appendChild(b);
But the output of this url is a JSON
and not a javascript
.
To solve it, simply replace
b.setAttribute("type", "text/javascript");
with
b.setAttribute("type", "application/json");
And the error is solved.
You cannot access to the content of script source. Generally you should do an ajax
call in order to get a json from an url.
If you want use the script tag (because crossdomain policies), you should return a valid javascript syntax.
Something like that:
callback({"yourjson":"here"})
and somewhere else in your code, you must define the callback:
function callback(json) {
console.log(json);
}
All this, is a technique called JSONP.
The technique expect that you declare a function via javascript that parse the JSON:
function parseWeddingJSON(json) {
console.log(json);
// ... parse json here
};
attach a script tag appending via get the name of the function declared before:
var src = "http://www.wonderweddings.com/weddingservice.svc/"+
"getcompanyreviewdetails/?id=" + c.vendorId + "&t=" + c.type+
"&callback=parseWeddingJSON"; // <--- see here
// create script with src as source.
The output, generated by server, will be something like this:
parseWeddingJSON({"json":"here"});
(you have to do this manually via VB). that's a valid javascript that simply call the function that parse the JSON data.
Upvotes: 2
Reputation: 1561
Good news, your feed is 100% valid JSON! You just need to finish getting your JSONP set up. You're almost doing it right; you just need your server to wrap your object with the callback function (so, for the request currently in your code [including the callback], the server response would be:
WonderWeddings.writeReviewsCallback({"responseHeader":{...}});
Since your feed is being injected into a <script>
tag, your server needs to prepare it as if it were a .js file, rather than just returning some JSON.
Right now, your string is being executed as JavaScript code, rather than being interpreted as a JavaScript object! It's the difference between
{
var d = 2;
}
and
{
"response":{}
}
In both cases, you can see I'm using {}
tags, but while the first one is valid JS (and invalid JSON), the second one is invalid JS, hence your SyntaxError
: the line "response":{}
doesn't mean anything in JS! Finishing your JSONP will solve this part of the problem, since your object will be inside of the callback()
method and will be interpreted as an object, like you intended.
Added:
Yep, like you thought in your update, your server needs to be updated to support the callback parameter; unless you're using certain frameworks, you won't get it for free.
The server will need to check for the existence of the callback param, and if it exists, the final result it returns should look like
<callbackParam>( {"responseHeader":{...}} );
With JSONP, your server result should actually be a valid JavaScript file that can be run. It's this script that the server generates that will kick off your callback method.
In most cases, this is as simple as just echoing the callback param into your result, and then echoing ()
around your JSON object.
Upvotes: 1
Reputation: 18769
If you look in your reviewtext
, I see this...
verlichting: alles prima!
I suspect the colon in there is breaking the parsing. Try taking this out as a test.
If this isn't the issue, then I think you need to implement this for JSONP
. This suggests you use a callback function, as you have done...
The query parameter of the URI that holds the callback function name is specified as the CallBack property of the behavior
Take a look here on how to use WCF, JSONP and Jquery
.
Upvotes: 0