Recently I’ve been working on a project, built in backbone.js, that is required to call a remote web service for its data. It also needs to work in Chrome, Firefox, and IE back to at least IE8.
I was sure this issue had been solved already. As it turns out, there are plenty of hacks out there to get it to work. There’s a great post on StackOverflow with some of your options:
http://stackoverflow.com/questions/3385404/ie8-xss-jquery-problem
Initially I implemented the flxhr option. Simple to get started - just drop some scripts on your page, check for jQuery.support.cors, and if the browser doesn’t support it, initialize the flxhr hack. This of course requires the user has Flash installed, but that’s not a huge deal. Ultimately I went looking for another option however because users were reporting some issues with things hanging in IE, and although I couldn’t pin it to the Flash proxy, it seemed possible it was causing it.
Instead of trying to implement another hack, I decided instead to try the native XDomainRequest support in Internet Explorer. This is what IE decided to use in IE8 and IE9 instead of XMLHttpRequest. I found this little script that overrides a function in jQuery to check for XDomainRequest support, and use that instead in those browsers.
https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js
Once again things were looking good. That is, until there was a server error and backbone showed a 404 not found error to the user instead of the proper error message. Looking at the code you’ll see on line 24 that if there’s an error in the ajax request, it has a hardcoded 404 error that it sends back to the jQuery callback. Well, surely I can fix that I thought. Maybe even patch it on Github. Unfortunately, as the Microsoft page on XDomainRequest says, “The document can respond to the error, but there is no way to determine the cause or nature of the error.” Sure enough, after plenty of testing, nothing I could do would give me a proper HTTP response from the server. Finally, the workaround:
https://gist.github.com/2655118
I took the same xdr.js code, but modified it slightly. Unfortunately, I also had to modify the server-side code. What I do now is always return a 200 response to XDomainRequests from the server, but if there is an error, I send a JSON response back containing the true HTTP Status Code (400, 500, etc), and a Message field with the error. Lines 24-30 are what I changed to detect whether the response contains a JSON object with a StatusCode and Message field. If so, it overrides the actual status code and response sent back to jQuery.
This feels like a horrible hack, but the experience seems to have improved, I can continue using my REST routes, and we’re not relying on Flash anymore.
I’m working on a small project within a bigger web application where an all-javascript solution made the most sense. In the past I’ve used Knockout.JS and had a lot of fun with it. It was simple to learn and easily added some robust javascript functionality on top of a .NET MVC project that would have been much more difficult in straight jQuery.
For this project, however, Backbone.js made more sense because we wanted all the logic to be built without having to add any server-side code. All data access would be done though a separate set of web services.
The problem is:
I ended up giving up on trying to implement REST with the correct HTTP PUT AND DELETE methods. Several searches and attempts pointed possibly to WebDAV interfering. I also found other sites (like the IIS Express FAQ) that said PUT and DELETE just needed to be allowed in the applicationHost.config file. Nothing worked. But more importantly, even if I had it working in a local dev environment within Visual Studio, it didn’t look like things would be easy to deploy. Instead I took advantage of the fact that MVC 3 and Backbone.js support X-HTTP-Method-Override. Just set Backbone.emulateHTTP = true; and you can use REST-like attributes like [HttpPut] on your controller actions.
Now for the cross domain part….
When making a cross domain connection, jQuery will do the following:
Here is and ActionFilterAttribute I use to accomplish that:
https://gist.github.com/1854201
The problem, however, is that even with that in place, you won’t necessarily have anything setup to respond to a request with an HTTP OPTIONS method. In my case, I setup a route and controller action to specifically handle that. It doesn’t do anything other than return the correct headers from the ActionFilterAttribute. There’s probably a better way to handle this, but it’s working nicely for me right now.
And finally, change the jQuery setting to turn CORS on:
$.support.cors = true;
I work on both Ubuntu and Windows, and just recently switched to the Sublime Text 2 editor, which is a nice cross between TextMate and vim, and runs cross platform. Everything runs as expected on Ubuntu, not so much on Windows. Here’s what you need to do to get CoffeeScript highlighting and building:
{
"shell" : true,
"cmd": ["coffee","-c","$file"],
"file_regex": "^(...*?):([0-9]*):?([0-9]*)",
"selector": "source.coffee"
}
Essentially you need to remove the “path” variable that’s there and add in the “shell” variable set to true so it runs from cmd.exe.
I just finished my first non-trivial web app that leverages Knockout, a framework that helps you build better javascript front-end applications. While Knockout isn’t nearly as popular as Backbone.js is, I think it serves a different purpose, even though they’re typically lumped together. There’s a great set of answers on Backbone vs Knockout on StackOverflow about this, but the fact that a post like that exists proves the point.
For me, I picked it because:
I wanted to improve the performance of a search page. Essentially the functionality allows users to search for products from a number of vendors based on the location of that vendor. So, for example, “Show me all instructors offering tennis lessons in the Boston area.” The results page would then be broken down by instructor, and a list of their offerings in that category.
Here’s what I implemented in Knockout:
Two things worth pointing out that helped me:
Ok, its tough not to laugh at this post from Ayende. He’s going through the process of trying to hire someone for his team, and asks those who apply to complete some simple programming tasks. I’m sure he’s glad he does.
But how did this happen? How did someone write code this bad?
Let’s make some assumptions. I think Ayende wouldn’t have wasted this person’s time as well as his own if the person didn’t pass at least an initial resume review. That means they probably have a base level set of experience:
This should give them every opportunity to become a valuable contributor as a programmer.
From looking at the code, however, we can tell they really only know:
In other words, just enough to squeeze by if no one ever looks at your code.
Compile this application and put it up for your (non-technical) manager or client to review and everything works fine. No one tells you it’s bad, so the next time you have to build something similar, you do the same thing again. It’s all you know. Without code reviews, I imagine a developer could go years thinking they’re building up their resume, only to be disappointed the first time someone actually does dive deep into their work.
Now, this might be a blatant example, but there are more subtle ones everyday. If you’re a programmer, do yourself a favor find a coding buddy if you haven’t already.