Cross-Domain Issue - JSON to the Rescue
About two weeks ago I started out on a little project for one of my web sites that I figured would be rather trivial. All I wanted to do was provide a way for my customers to put a search box on their own web sites and have the search call a “service” hosted on my web site to then display results. This is essentially what Google allows you to do, so I knew it was possible and assumed it wouldn’t be very hard.
I wanted it to be easy for my customers to put the search box on their web pages, so I went down the path of create a Javascript file that they could just reference via a <script src=”…” /> block. Again, this is the same way that Google Adsense and Google Search works. Inside the Javascript code I would create the HTML to display the search box and then have a function that would get called when the search button was clicked. The search function would then use XMLHttpRequest to call a service on my web site that would perform the search and return results that would then be display in a <div> on the web page.
Ah, it all seemed so easy and was working great on my internal development sites. I then made the “mistake” of testing using Firefox and quickly ran into a problem. When I clicked the Search button nothing happened. It took me a little while to track down the issue, but eventually discovered that what I was doing was a cross-domain security issue. You see, it is not allowed having client-side script use XMLHttpRequest to access a file/script/service located on a different domain from the one the web page was served up from. Doh! This really sucked. I searched and searched for ways to resolve the issue. One common approach is to create a “proxy”, but that wasn’t a valid option for me since the web site using my search control wasn’t my own web site. I really didn’t want to force my customers to create or install some proxy file.
After more searching I came across another solution — use JSON (JavaScript Object Notation). Like most things, it’s not quite as simple as just flipping a switch and using JSON. There was some work involved, but it wasn’t that hard and the result is excellent.
For starters, I recommend getting familar with JSON by checking out this Mastering JSON post. It’s brief but covers the key things you need to know about the layout of JSON. The next thing I had to do was change my service so it formatted and returned JSON text instead of HTML/XML like it was doing. The last (and perhaps most important) step was to change my Javascript code to do two things:
1) On the button click I needed to dynamically add a “<script>” block to the HEAD section. The source of the script is my search service. Doing this causes the pages to automatically call the search service.
2) Create a function that will process the JSON data that is returned from the search service.
The real “trick” in all of this is that the text that the search service returns is actually the call to the function that processes the JSON text. (If you’re thoroughly confused at this point don’t worry…so was I…but let me try to make it easier to understand).
Here’s an example that will hopefully bring all of the pieces together for you:
User.html (my customer’s web page)
<html><head></head><body>
<script type=”text/javascript” src=”http://www.MyWebSite.com/Search.js”/>
</body></html>
Search.js (Javascript file stored on my web site)
function process_json_data(jsondata) {
var resultCtrl = document.getElementById(”resultDiv”);
resultCtrl.innerHTML = jsondata.Results[0].Title;
}
function onSearchClick() {
// Add a script to the HEAD which has the Search service as the source
request_script = document.createElement(”script”);
request_script.src=”http://www.MyWebSite.com/search.aspx?kw=abc&jf=process_json_data”;
request_script.setAttribute(”id”, “myscript”);
request_script.setAttribute(”type”, “text/javascript”);
document.getElementsByTagName(”head”)[0].appendChild(request_script);
}
// code that displays the search control…
document.writeln(”<input id=\”searchBtn\” type=\”button\” value=\”Search\” onclick=\”onSearchClick();\” />”);
Search.aspx (my search “service” on my site)
This will perform the search and return JSON formatted data, but also includes the function name:
process_json_data({ “Results” : [ { “Title”:”ABC” }, { “Title”:”XYZ” } ] });
