SocialNetworkInc.com - SEO Tips and Tricks
view blog
Subscribe to socialnetworkinc.com on FriendFeedFollow socialnetworkinc.com on Twitter

Latest Site News

Social Network Inc. - Launching Soon.

Related Links

Encosia
http://encosia.com
ASP.NET and AJAX code, ideas, and examples.
Targeting WebKit is not like targeting IE6
source: http://feeds.encosia.com/~r/Encosia/~3/Ffz6E7YV-HI/

There’s been a bit of controversy lately concerning the rising dominance of WebKit-based browsers (e.g. Chrome, Safari, and Mobile Safari) and the potential that we’re repeating past mistakes:

Not so long ago, IE6 was the over-dominant browser on the Web. Technically, the Web was full of works-only-in-IE6 web sites and the other browsers, the users were crying. IE6 is dead, this time is gone, and all browsers vendors including Microsoft itself rejoice. Gone? Not entirely… IE6 is gone, the problem is back.

However, I believe there’s one gigantic difference between IE6 then and WebKit now that’s being overlooked.

Microsoft put the brakes on Internet Explorer development after IE6 because they realized that they were helping build the runtime for their own competition. If Internet Explorer releases had continued at the same pace, most everyone would probably be using IE15 today and IE6 would be as memorable as Chrome 4 or Firefox 7.

Conversely, Google has a vested interest in Chrome’s ongoing success (and WebKit’s success by extension). Instead of threatening Google’s primary revenue stream, WebKit and Chrome serve to enhance Google’s golden goose. So, unlike the past situation with Microsoft, Netscape, and IE6, Google has no motivation whatsoever to shutter active development on Chrome and WebKit if it overtakes Internet Explorer and Firefox.

Does that make vendor prefixes and targeting experimental features a great idea? Maybe not. Frankly, I’m not qualified to speak intelligently about cutting edge CSS features.

What I do know is that just because the current climate seems similar to the one ten years ago, that doesn’t mean it’s reasonable to assume history is repeating.

Related posts:

  1. Sometimes, even jQuery can’t save you from yourself
  2. Improving jQuery’s JSON performance and security
  3. Cripple the Google CDN’s caching with a single character


You've been reading Targeting WebKit is not like targeting IE6, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Web API is now part of ASP.NET (and you can get it today)
source: http://feeds.encosia.com/~r/Encosia/~3/6IGIz9uWbVE/

One of the hardest parts of being privy to NDA information is keeping my mouth shut about new developments that I wish I could share with you immediately, often for months at a time.

Recent developments around ASP.NET Web API (formerly WCF Web API) are a perfect example of that conundrum. As development on WCF Web API seemingly stagnated on CodePlex, Microsoft had actually rolled the project into ASP.NET itself. The project was in no danger whatsoever, but (frustratingly) I wasn’t able to tell you that.

So, it’s a relief that today’s today’s ASP.NET MVC 4 Beta release has made that news public:

Top Features

  • ASP.NET Web API
  • Refreshed and modernized default project templates
  • New mobile project template
  • Many new features to support mobile apps
  • Recipes to customize code generation
  • Enhanced support for asynchronous methods
Note: It’s not entirely clear, but installing the MVC 4 beta allows you to use Web API in WebForms projects too.

Though Web API isn’t necessarily a gigantic step forward from using MVC’s controllers as a makeshift API for simple scenarios, it’s great that ASP.NET now has common mechanism for creating these endpoints that works the same way on both WebForms and MVC.

I’ve long held out against pressure to move from ASMX to WCF in WebForms projects, because accepting WCF’s complexity primarily only rewarded me with less flexible JSON serialization. By contrast, I’ve begun converting some of my projects from ASMX to Web API, and have been pleased with how easily Web API replaces ASMX.

I believe Microsoft has finally found a good balance between ASMX’s simplicity and WCF’s power with Web API.

Since it was built with jQuery in mind from the very start, I’m finding that Web API is perfect for the sort of work that I usually write about here. It even automatically responses to requests from jQuery with JSON, even if you use simple URL encoded parameters with the request, so adding an endpoint for AJAX interaction in either WebForms or MVC is a breeze now.

I’ll be writing more about actually using Web API here in the future, but I wanted to get this post published right away to help spread the news that Web API isn’t dead.

To learn more about what exactly Web API is and does, have a look at its section in the release notes. To get up and running quickly with some example code, take a look at the new Web API material on the ASP.NET site.

No related posts.


You've been reading Web API is now part of ASP.NET (and you can get it today), originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Read my interview with The Code Project
source: http://feeds.encosia.com/~r/Encosia/~3/CDCE30Pf-Ls/

I took part in The Code Project’s A Coder Interview series recently, and the result was published there yesterday. Terrence happened to send the questions at a rare moment when I wasn’t running in five directions at once, which led to me accidentally writing quite a bit.

Part of it touches on something important to me that I plan to write more about eventually:

What advice would you offer to an up-and-coming programmer?

Write about programming. Start a blog, answer questions on The Code Project or Stack Overflow, or whatever else suits you, but find some way to write about programming.

I can’t count how many times I began writing about something I thought I knew thoroughly, only to find that I had to fill in several important gaps in my knowledge to write about it competently. Just as important, you have to learn topics more comprehensively to distill and teach them in simple terms. The combination of writing about programming and making that writing as clear and simple as you can is a powerful exercise.

[…]

The interview also exposes my shameful stance on tabs vs. spaces, but you’ll have to go there to read that part…

Click here to read the full interview at The Code Project

Related posts:

  1. Learn from my Express.js HTTP status code blunder
  2. Review: The best JavaScript book I’ve read
  3. How I Got Started in Software Development


You've been reading Read my interview with The Code Project, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


The ASUS Zenbook UX31: Initial impressions
source: http://feeds.encosia.com/~r/Encosia/~3/vF4J2LEzkFw/

For over a year now, I’ve been using a 13” MacBook Air as my only laptop. Though it’s a bit underpowered and I prefer Windows to OS X, I was ultimately unable to resist Apple’s build quality compared to the Dell I had used previously.

However, I never fully resigned myself to accepting a dichotomy between quality construction and operating system. Thankfully, the recent proliferation of Windows-based Ultrabook™ machines seems to be rapidly bridging that divide.

Given my already-growing desire to find an alternative, when I was contacted about reviewing the ASUS’ Zenbook UX31 Ultrabook™, I decided to give it a go. I know I’m not alone in having been frustrated with a choice between machines that run Windows well and quality hardware, so I hope that you’ll find my experience of trying to move back from the MacBook hardware useful.

Disclaimer: Up front, I want you to know that I’m receiving a complementary UX31 in return for evaluating it and writing a few posts about that experience. I’ll give you my honest assessment of it and only recommend it if it meets my own standards, but I also think it’s important to be transparent and not potentially abuse your trust.

Unboxing

Lurking Inside the cardboard box that Amazon delivered it in, highly polished packaging awaited. ASUS did a great job with the unboxing experience, from overall presentation to ease of unpacking. It definitely reminded me of opening a high-end Apple product.

The UX31 comes encased in a protective plastic casing to keep the brushed aluminum’s finish pristine until you open the box, and its accessories are neatly packaged up with a canvas carrying pouch:

Along with its power adapter, the UX31 comes with a USB Ethernet adapter and VGA adapter that attaches to its mini-HDMI port. Nothing terribly unique, but both are nice to have right from the beginning (especially the ability to use a wired network connection for all the downloads that accompany initial setup of a machine that may be used for development).

Initial impressions

The first thing you notice about the Zenbook is the distinctive top cover of its lid. None of the photos I’ve seen online do it justice, but we tried with this one:

When I saw the radial pattern in photos online, I worried that it might look overdone or gaudy, but it looks great in person. Color me pleasantly surprised.

Quality construction

Removing it from the packaging, the Zenbook immediately impressed me with its rock-solid construction. One of my favorite things about the MacBook Air is that its unibody case feels solid, and my opinion is that the Zenbook bests the Air in that category, with an even more rigid case.

Superficial or not, that attribute is a significant part of how I judge the quality of a laptop’s construction. A laptop case that flexes or creaks when I lift it from a corner annoys me to no end. Holding the Zenbook with one hand, even from the front corners, there’s not hint of flex in its chassis.

Contrasting with the rest of the case’s angular design, the lid’s convex curvature makes the machine feel more comfortable in my hand than my MacBook Air does when both are closed.

Also worth noting, I felt no flex in the lid when I squeezed it to lift and carry. That lid-flex is something I’ve always found unsettling about my Air (and the Dell before it).

Windows 7, now with Bing Bar?

It only took a few minutes to uninstall later, but having a required Bing toolbar installation at the OS level didn’t feel very zen to me. I understand that preinstalled software helps subsidize the machine, but this isn’t a $200 netbook.

The exterior of the machine sets a high bar, and it’s important that the interior hardware and software live up to that high expectation. Thankfully, the remainder of the UX31′s preinstalled software was more tasteful.

Fantastic sound

I’m listening to music on the laptop’s built-in speakers as I write this post, which is something I’d never bother with on the Air (or any laptop I’ve ever used, for that matter). But, since the Bang & Olufsen audio is something touted right on the case itself, I figured I ought to give it a try.

From the first note that played, I was astonished by the quality of sound that the UX31’s sound system produces. Of course, it’s no rival for a proper set of external speakers, but it’s amazing for concealed, self-contained speakers.

Keyboard concerns

I’ve struggled a bit while typing this entire post on the UX31. The keyboard itself looks and feels very nice, with a setup that’s similar to the “chicklet” layout you’ll see on many modern keyboards:

Unfortunately, there’s something about how the keys respond to quick, light touch typing that I’m having a difficult time acclimating to. I’ve had adjustment periods with other keyboards in the past, so I’m hoping time will improve my ability to coax the desired result out of this one too.

More to come

This post has outlined my very initial impressions of using the UX31 for a few hours. I’ll be continuing to use it over the next couple of months and will publish another post after a few weeks and then a final review after a full two months of use. I hope that the end result is that I’ll be able to shelve my MacBook Air, but I’ll let you know how it turns out one way or the other.

How about those photos?

Those photos of the UX31 looked great, didn’t they? Almost… Professional. Well, that’s because they are. My good friends at 35 Atlanta came over, set up studio in my house, and took 55 amazing photos of the UX31 for me to use in these posts. If you need photos of just about any kind, check them out.

No related posts.


You've been reading The ASUS Zenbook UX31: Initial impressions, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Adding your own callbacks to existing JavaScript functions
source: http://feeds.encosia.com/~r/Encosia/~3/mZ6gyCZJm28/

Hey Dave, is there a way to create an event handler so when .tmpl() is done it will fire a function? I’m trying to make it global, so I was hoping I could say, when ANY template gets done, do this…

The question of how to retroactively add hooks before and/or after a pre-existing JavaScript function executes is one that comes up from time to time. Whether it’s a simple method like tmpl(), a server-generated script artifact, or a function in a third-party script, sometimes it’s desirable to alter a JavaScript function without access to change the original declaration of the function.

One of the handy things about JavaScript is that you can combine its functional and dynamic aspects to make surprisingly quick work of tasks like this one. Doing so is fairly straightforward, but it involves an approach you might not consider if you’re more familiar with languages that lack JavaScript’s unique features.

In this post, I’ll briefly cover a few examples of how to “patch” existing JavaScript functions with callbacks. We’ll begin with simple examples, then address an issue that stems from applying this approach to jQuery plugins, and finish with a more elegant way to handle the problem of patching functions that accept parameters.

A simple() example

Let’s start with the simplest possible example, a function that accepts no arguments and returns nothing:

function simple() {
  // I am a black box.
}

Maybe that function is pre-defined and emitted by server-side code. Maybe it’s part of a script you’re referencing from a public CDN. For whatever reason, assume that this function is part of your page, but that you don’t have the ability to directly change its code.

If you need to run some of your own code before and/or after any time the simple() function is called, you can use a technique called monkey patching to achieve that without access to the original function declaration.

// Get a reference to the previously defined simple() function.
var oldSimple = simple;
 
function simple() {
  // Code that runs before any call to simple() here.
 
  // Make a call to the old/previous simple() function.
  oldSimple();
 
  // Code that runs after any call to simple() here.
}

Since functions are just like any other variable in JavaScript, it’s that simple.

Without touching the original simple() function declaration, this snippet has effectively redefined it anyway. Calls to the original function will also execute our before and after code now, unaware that anything has changed.

Parameters and external “event” handlers

If you want to apply this technique to a function that accepts parameters, you’ll also need to capture and relay those parameters.

Take this more complex function, for example:

function complex(foo, bar, baz) {
  // An assortment of black boxes.
}

You could patch in a “before” event, parameters unimpeded, like this:

var oldComplex = complex;
 
// Capture the parameters that the original complex()
//  function expects.
function complex(foo, bar, baz) {
  // Call onBeforeComplex() if it's defined when this runs, and
  //  pass a copy of the parameters that complex() was called with.
  if (typeof onBeforeComplex === 'function')
    onBeforeComplex(foo, bar, baz);
 
  // Call the original function, parameters included.
  oldComplex(foo, bar, baz);
}

Using a separate onBeforeComplex() function instead of inline code isn’t necessary, but I prefer that approach. Now, you can drop this code into a script include anywhere after complex() is defined and then declare the “handler” function anywhere on the page (or not at all).

Passing foo, bar, and baz to onBeforeComplex() is optional, of course, but it’s usually helpful to know something about what sort of call triggered the event.

Applying this to jQuery plugins

Now let’s apply this technique to the real-world problem of updating tmpl(). Doing that isn’t much more difficult than the previous example, but we do need to identify the method’s signature first so that we can apply the patch.

Digging into the last version of jQuery.tmpl.js on GitHub, the function we’ll need to override can be found beginning on line 80:

So, the function we’ll need to patch is jQuery.fn.tmpl. Given the previous examples, you might thing it would be as easy as this:

var oldTmpl = jQuery.fn.tmpl;
 
jQuery.fn.tmpl = function(data, options, parentItem) {
  if (typeof onBeforeTmpl === 'function')
    onBeforeTmpl(data, options, parentItem);
 
  oldTmpl(data, options, parentItem);
}

Unfortunately, that will break tmpl() (in two separate ways, no less).

jQuery plugins make “this” more complicated

Applying the monkey patching approach to functions that operate on and return jQuery collection objects, such as the tmpl() plugin that led to this post, requires extra consideration. The crux of jQuery’s fluent API is that chainable jQuery methods both operate upon and return an instance of the jQuery object.

Now that we’re interjecting an additional level of abstraction, we need to be sure to maintain the scope of this down into the original jQuery plugin method and preserve the original function’s return value. Otherwise, our intermediary function will break jQuery’s chaining.

Using apply() to call the original function allows us to control its this value:

var oldTmpl = jQuery.fn.tmpl;
 
// Note: the parameters don't need to be named the same as in the
//  original. This could just as well be function(a, b, c).
jQuery.fn.tmpl = function(data, options, parentItem) {
  if (typeof onBeforeTmpl === 'function')
    onBeforeTmpl.apply(this, [data, options, parentItem]);
 
  // Make a call to the old tmpl() function, maintaining the value 
  //  of "this" and its expected function arguments.
  var tmplResult = oldTmpl.apply(this, [data, options, parentItem]);
 
  if (typeof onAfterTmpl === 'function')
    onAfterTmpl.apply(this, [data, options, parentItem]);
 
  // Returning the result of tmpl() back so that it's actually 
  //  useful, but also to preserve jQuery's chaining.
  return tmplResult;
};

By capturing the return value of the original tmpl() function and returning that back to the original caller, chaining is preserved at that previous level. That’s particularly important in this specific example because that return value is the rendered template.

Better argument handling

If you’re like me, explicitly capturing and passing each individual function parameter doesn’t feel great. Not only is it extra work to determine how many parameters a method accepts, but our patched version of tmpl() would stop working correctly if the original were updated to begin accepting additional parameters.

We can improve this situation easily enough by taking advantage of JavaScript’s built-in way to capture all of the parameters that were passed to a function. Aptly named arguments, this so-called array-like object is perfect for eliminating the explicit plumbing code to pass parameters between the patched function and the original.

Even better, arguments will capture all the parameters passed into a function even if that function’s declaration doesn’t accept parameters at all. So, now there’s no need to worry about matching the original’s function signature:

var oldTmpl = jQuery.fn.tmpl;
 
jQuery.fn.tmpl = function() {
  if (typeof onBeforeTmpl === 'function')
    onBeforeTmpl.apply(this, arguments);
 
  var tmplResult = oldTmpl.apply(this, arguments);
 
  if (typeof onAfterTmpl === 'function')
    onAfterTmpl.apply(this, arguments);
 
  return tmplResult;
};

Throw that code on a page, anywhere after the reference to jquery.tmpl.js, and then all existing usages of tmpl() will begin triggering the before and after “events”.

Conclusion

We took a circuitous route to get here, but I hope you agree that it was worthwhile to build the solution up step by step. Even if you don’t need to patch an event into tmpl(), you might be surprised how often this technique comes in handy once you’re keeping the possibility in mind.

Related posts:

  1. How to easily enhance your existing tables with simple CSS
  2. Using external templates with jQuery Templates
  3. Composition with jQuery Templates: Why and How


You've been reading Adding your own callbacks to existing JavaScript functions, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Five years of Encosia
source: http://feeds.encosia.com/~r/Encosia/~3/S148V2sKjcI/

As I ponder the title of this post, I’m conflicted.

I clearly remember writing last year’s post and thinking that it didn’t seem like four years could have possibly passed since I started publishing here. As I write this one, I find myself feeling like it’s surely been much longer than five years.

I guess you could say 2011 has been a long year?

Relativity aside, this week saw the fifth anniversary of the night that I hastily threw this site together and published my first post. So, I guess it’s that time again.

Site stats

Page views are far from a perfect metric for measuring the progress of a site like this one, but it’s one of the few consistent, long-term metrics I have. Aggregators come and go, RSS is giving way to Twitter, and social media has decentralized the conversation that would have taken place in a post’s comments years ago (A change for the worse, in my opinion). So, I measure what I can.

Pleasantly enough, the stats have continued to be encouraging.

Since last year’s post, traffic has grown by a healthy 28%. That’s just over 1.6 million page views since this time last year. Insignificant compared to some sites, but I find it truly humbling to think that my little corner of the Internet has been visited 1.2 million times in the last year. Maybe even more incredible to me is that nearly 400,000 of those visits were apparently return visits. Frankly, I have a hard time rationalizing that number.

Interestingly enough, I seem to have benefited from Google’s recent algorithm tweaks aimed at content farms. I saw two distinct, sustained bumps in search traffic this year. I won’t complain…

The Best Posts of 2011

I considered omitting this section this year (and the year-end post itself for that matter). I figured that I probably care more about this than you do and there’s no point wasting everyone’s time, but Joe Brinkman disagrees.

If at least one person finds it useful to have a quick reference of the year’s most popular posts, then who I am to argue?

In JavaScript, curly brace placement matters: An example – This post received the most traffic, primarily due to spending some time on the front page of Hacker News and the JavaScript subreddit. Frankly, I didn’t intend for it to capture the level of attention that it did at all. It was targeted at developers less experienced with JavaScript, but it ended up igniting a light-to-medium religious war around the Allman vs. K&R debate among more seasoned developers instead.

Next year I should post about tabs vs. spaces.

jQuery 1.6.2 syntax error? You may be the victim of SEO. – Similarly, this post did well in the stats simply because it spent some time at the top of Hacker News. Though I did have to endure the predictable abuse from the denizens of Hacker News, exposure there was enough to get some attention focused on the issue and ultimately get it resolved. I’d say that was worth suffering the “Well, Actually” crowd for a couple days.

Cripple the Google CDN’s caching with a single character – Yet another post in this lineup by virtue of the time it spent on the front page of Hacker News. Astute readers correctly pointed out that the Google CDN’s HTTPS assets are served with a header that allows them to be cached. Unfortunately, too many people got stuck on that inaccuracy and missed the larger point.

Since HTTP-delivered scripts aren’t eligible for use as cache hits for HTTPS references to the same script (and vice versa), using the HTTPS reference isolates the potential cross-site caching benefit to only users who have the HTTPS-served script cached. With the vast majority of jQuery CDN references being of the HTTP variety, it’s important to understand that and not use the HTTPS reference unless you actually need it.

Even better, use the protocol-less reference and never worry about it again.

ASP.NET web services mistake: manual JSON serialization – This is one that I felt strongly about. I had been seeing more and more code floating around that used JavaScriptSerializer or DataContractJsonSerializer to manually handle the encoding to and from JSON in ASP.NET services that were automatically doing that anyway. The result being nasty double-serialization of the data, and/or sending values in and out of methods as strings instead of using the strongly-typed objects that the data was usually based on ultimately anyway.

Fun fact: I wrote and published this post, from start to finish, while attending MIX11.

Use jQuery to extract data from HTML lists and tables – This post was somewhat niche, but I‘m a fan of the general approach of using list comprehension methods against the DOM. Particularly, map() is fantastically well-suited to dealing with HTML and the DOM. I’ve subsequently linked to this post to help explain the solutions to all sorts of tangentially related problems. I hope that many of the people who read this post were able to extrapolate the more general usefulness of map() and specifically jQuery’s implementation of it for dealing with selections of HTML elements.

What I expect from 2012

JavaScript is going to continue exploding in popularity. If you’re a web developer and haven’t taken a serious look at Node.js yet, now’s the time. JavaScript is not without flaws, but I think full-stack JavaScript is the future for a lot of platforms and web development in particular.

As new developers begin learning about development, who would choose a platform that requires learning a different client-side and server-side language if a solid platform using a single language from start to finish existed?

Of course, that was part of the promise of failed technologies like Java applets and Silverlight, but JavaScript has the luxury of already being pervasive, native, and well-integrated in every user’s browser. Compared to conquering that client-side morass, ironing out the server-side platform wrinkles and maturing a web framework or two is nothing.

Mobile and touch will change how we approach web development. It’s hard to believe that designing for touch was an obscure niche when I started this site five years ago. More than just avoiding hover menus and making click targets large enough for fat fingers, I think there’s still undiscovered potential for touch and gesture based UIs that we’re going to see begin making its way onto the web as touch input becomes more ubiquitous on a wide range of devices.

Of course, you can’t touch what you can’t see. Making sites work on a wide variety of screen sizes is more important now than ever. Using CSS media queries to build responsive layouts takes a bit of acclimation, but the results are absolutely worthwhile. While responsive layouts aren’t new, I think they will become much more mainstream in the next year. Sites not taking advantage of media queries will probably seem as quaint as sites currently using table layouts soon.

Windows 8 is going to be huge. I don’t know if it’ll be a huge success or a huge flop, but I think it’s safe to say there’s not much middle ground between the two outcomes. It’s certainly a bold move.

As an iPhone, iPad, and MacBook Air owner, I would be overjoyed if I could migrate from those devices to Windows-based devices of comparable quality. I’m rooting for Microsoft to pull this one off.

Thanks

As always, thank you for lending me your eyeballs for a few minutes.

If you’re reading this paragraph, there’s a decent chance that I owe you a bit of gratitude for your support over the past year, be it pointing someone here to solve a problem, a retweet or two, or just sparing me your attention.

Thanks.

And you?

How was your 2011? What technologies helped you succeed or presented challenges for you this year? What do you think’s going to be most important in 2012?

I’m interested to hear what you think. Leave a comment or leave a link to your own year-end post if you’d like.

Related posts:

  1. 3 years of Encosia, the best of 2009, and my gratitude
  2. 4 years of Encosia, and the best of 2010
  3. Announcing the 2010 Encosia Holiday Giveaway


You've been reading Five years of Encosia, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Using CORS to access ASP.NET services across domains
source: http://feeds.encosia.com/~r/Encosia/~3/8NqtWwXnjFY/

Successfully completing a cross-domain request to an ASMX service using CORS

Work on client-side applications long enough and it’s just about inevitable that you’ll eventually want to make an AJAX request that breaches the browser’s XMLHttpRequest security restrictions. Limitations on cross-domain requests are great when they’re preventing malicious sites from malfeasing, but are a thorn in the side when they complicate your legitimate applications.

Traditionally, direct communication across the same-origin boundary required using a rickety (though clever) workaround called JSONP. JSONP is a reasonable compromise if all you need to do is make blind requests to a third-party API like Twitter, but comes up short if you need to use any HTTP verb other than GET. Of course, that’s a deal-breaking issue when you’re working with ASMX ScriptServices or ASPX page methods.

Luckily, a relatively new feature has been making its way into browsers which provides a robust solution to the cross-domain AJAX problem: CORS.

In this post, I’m going to show you how to recognize exactly which requests are cross-origin, how to enable CORS for your ASP.NET site, and the extra configuration necessary when you’re working with ASP.NET’s JSON-enabled services.

Before we get started, I want to emphasize that this approach won’t work with any version of IE prior to IE10. If supporting older versions of IE is a requirement in your target environment, you’re stuck with something like JSONP or a server-side proxy. This will work in any version of IE if Chrome Frame is installed and enabled by your site/server though.

Understanding what constitutes a different “origin”

When it comes to making cross-origin AJAX requests, it’s helpful to understand which requests actually are cross-origin. Of course, a request from a page served under one domain to a resource on an entirely different one definitely falls under the umbrella of cross-origin:

However, the common moniker for these requests, cross-domain, tends to be misleading. While a request from one domain to another is obviously cross-origin, browsers are much more picky than that.

For example, a request from foo.domain.com to bar.domain.com is just as much cross-origin request as one to abc.com. That’s not quite as intuitive as the traditional cross-domain scenario, but requires the same consideration.

A less obvious troublemaker is making a request from localhost:8080 to localhost:8081, which XMLHttpRequest’s security restrictions will also deny you from making. That’s a particularly troublesome scenario for ASP.NET developers since Visual Studio is all too happy to help you spin up a separate services/API project almost transparently hosted at its own separate port.

The easiest way to determine whether a particular request will fall under the umbrella of cross origin resource sharing is to compare the portion of both addresses appearing before the first forward slash. Any difference before the first forward slash, including the port, protocol (HTTP vs. HTTPS), and sub-domain, will thwart a traditional XHR-based AJAX request.

Enabling CORS for an ASP.NET site

Though the conventional wisdom about cross-domain or cross-origin requests has long been JSONP or nothing, a solution called Cross-Origin Resource Sharing has gained broad support in modern browsers over the past couple years. This standard defines a set of HTTP headers that a server can use to instruct browsers that it’s okay for certain XMLHttpRequest requests to that server to cross the same-origin boundary.

In the broadest case, enabling CORS for an ASP.NET site is simple. The enable-cors.org site has handy list of concise examples of how to configure a variety of servers for CORS, including IIS. For sites hosted on IIS7.0+ and Integrated Pipeline, enabling CORS is as simple as adding this to the site’s web.config:

<system.webserver>
 <httpprotocol>
  <customheaders>
   <add name="Access-Control-Allow-Origin" value="*" />
  </customheaders>
 </httpprotocol>
</system.webserver>

That simple change gets you half way there. A regular GET request for an ASPX page’s HTML would work now, for example. Unfortunately, the Content-Type necessary for working with ASMX ScriptServices throws a new wrench in the works:

A partially successful CORS request to an ASMX ScriptService

As it turns out, requests to ASP.NET’s JSON-enabled endpoints require one last configuration step to allow the request to go through unimpeded.

Access-Control-Allow-Headers

Sending the Access-Control-Allow-Origin header allows basic cross-origin access, but calling ASP.NET services like ASMX ScriptServices, ASPX page methods, and WCF services with AspNetCompatibilityRequirements enabled requires jumping through a few more hoops. Namely, sending a specific Content-Type header of application/json.

One of the security precautions that the CORS specification includes is that browsers must tightly control what’s sent along with these cross-origin requests. Among the items that must be explicitly allowed: any but the most basic HTTP headers, including Content-Type.

In order for CORS requests to specify their Content-Type, your site needs to respond with one additional CORS header: Access-Control-Allow-Headers

That brings the web.config modifications necessary to this:

<system.webserver>
 <httpprotocol>
  <customheaders>
   <add name="Access-Control-Allow-Origin" value="*" />
   <add name="Access-Control-Allow-Headers" value="Content-Type" />
  </customheaders>
 </httpprotocol>
</system.webserver>

And finally, it’s possible to use the same, familiar jQuery $.ajax() syntax to request our service from same- and cross-domain origins alike:

A successful CORS request to an ASMX service with jQuery

Conclusion

Even as we’re teetering at the precipice of 2012, CORS is still a fairly new feature and lacks ubiquitous support. IE10 should support CORS as fully as Chrome and Firefox already do, but the XDomainRequest implementation in earlier versions of IE does not (to my knowledge) support Access-Control-Allow-Headers, which makes it all but useless in this scenario.

If you’re comfortable leaving the comfy confines of XMLHttpRequest and jQuery’s $.ajax, a more cross-browser friendly solution does exist: easyXDM. I haven’t personally used easyXDM beyond a bit of experimentation, but the approach it takes in older browsers is one that has been proven to be solid by similar libraries like Socket.IO.

However, if you’re working in an environment where you can mandate Chrome (or Chrome Frame in IE9-) and/or Firefox as the browser of choice, CORS is an invaluable addition to your bag of tricks (I feel like I’ve typed that phrase in another post recently…). I hope this post will help you get your feet wet with this new technology which seems to get more lip service than actual usage.

Get the source

If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.

Browse on GitHubDownload the ZIP

Related posts:

  1. Save yourself some typing when you call ASP.NET services
  2. ASMX and JSON – Common mistakes and misconceptions
  3. Using jQuery to Consume ASP.NET JSON Web Services


You've been reading Using CORS to access ASP.NET services across domains, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Help me organize my posts about using jQuery with ASP.NET
source: http://feeds.encosia.com/~r/Encosia/~3/TIeTEaNW6uc/

Image by OZinOH on Flickr

One of the longest running themes here has been the compelling intersection between ASP.NET and jQuery. Beginning with my post about using jQuery to circumvent ASP.NET AJAX’s client-side apparatus for calling ASMX services, I’ve been writing about using ASP.NET and jQuery since the Spring of 2008.

As these related posts have accumulated over the years, I’ve made an effort to weave a thread of cross-links between them posts where appropriate. However, it’s nearly impossible to anticipate every possible entry point and subsequent path that someone might find themselves following here.

So, I’ve decided to finally do what I should have done a year or two ago: Create a top-level index to organize and improve the accessibility of my content for ASP.NET developers interested in integrating jQuery into their sites.

You can see my first draft of that here: jQuery for the ASP.NET Developer

Unlike the other content here, I’m publishing this one long before it’s “finished”. My hope is that I can solicit early feedback to help better construct a useful narrative while the document is still in its formative stages. So, if you have any feedback on the current page or what you think should ultimately be there, please leave me a comment on either this post or that page, contact me directly, or even @mention it my way on Twitter.

Related posts:

  1. Best of 2008: 5 most popular posts
  2. Best of 2007: 5 most popular posts (and contest winners)
  3. 3 mistakes to avoid when using jQuery with ASP.NET AJAX


You've been reading Help me organize my posts about using jQuery with ASP.NET, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Learn from my Express.js HTTP status code blunder
source: http://feeds.encosia.com/~r/Encosia/~3/RUO_mqr85Kw/

Screenshot of the 200 Object] HTTP status code in Firebug

If you’re like me, HTTP status code 200 Object] unknown probably doesn’t ring any bells. Of course, that’s mainly because it doesn’t exist.

So, how did I end up with the screenshot above? I’ve been running with scissors again. It was one of the more popular web frameworks for Node.js that I cut myself with this time: Express.js

Unfortunately, a malformed status code like 200 Object] will cause some browsers (including the version of Chrome I was using at the time) to refuse loading the page at all. That quickly elevated the importance of my strange status code from a trivial oddity to an annoying thorn in the side.

As it turns out, my code was running up against a documented Express feature and the remedy was simple enough.

Status code: RTFM

The site I was working on at the time is simple enough, built from a handful of views and a few supporting scripts that act as “models”. Unfortunately for me, the topic of this particular site led me to pass one of those models into a view using an object property named status:

app.get('/', function(req, res) {
  Models.getIndexViewModel(function(model) {
    res.render('index', { status: model });
  });
});

You can probably guess where my bizarre HTTP status code came from now, and a quick search through the relevant Express documentation confirms:

This options object is also considered an “options” object. For example when you pass the status local, it’s not only available to the view, it sets the response status to this number. This is also useful if a template engine accepts specific options, such as debug, or compress. Below is an example of how one might render an error page, passing the status for display, as well as it setting res.statusCode.

Head, meet desk.

Instead an HTTP status code, I was passing a JavaScript object to Express and it was trying to interpret the string representation of that object as an HTTP status code to apply to the response. In JavaScript, objects evaluate to a string value of [object Object], which is how Object] ended up being sent down instead.

I didn’t take the time to dive into Express’ source to determine why the [object Object] string ended up being split on the whitespace, with only the second half showing up in the actual response. The net takeaway is the same regardless of why: don’t pass status into your Express views unless you understand what that actually does.

Everything’s easy in hindsight…

In retrospect, it may seem painfully obvious that my choice of property names was the culprit, but I didn’t benefit from this post’s narrow context at the time.

I didn’t end up finding the issue until days after writing the code that caused the problem. Since the odd status code didn’t break anything while I was testing in Firefox, it wasn’t readily apparent that I had introduced a bug at all. By the time I tested in a browser that choked on the invalid status code, I was far removed from the relevant code, and it wasn’t as easy to debug as it might seem now.

I almost decided against posting this for fear of looking like a dunce, but I can’t be the only person that will run into this problem. So, I hope this post saves at least one person from running into the same self-inflicted injury that I did.

Related posts:

  1. Easy incremental status updates for long requests
  2. Updated: See how I used Firebug to learn jQuery
  3. 4 ASP.NET AJAX JavaScript UI methods you should learn


You've been reading Learn from my Express.js HTTP status code blunder, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Why PhoneGap 1.1.0 broke jQuery Mobile’s back button
source: http://feeds.encosia.com/~r/Encosia/~3/DcbbICL5x-o/

For the past week, I’ve been neck-deep in a challenging project that combines jQuery Mobile and PhoneGap to do some relatively heavy lifting. Though I’ve used both jQuery Mobile and PhoneGap in the past, this recent exercise left me with a few morsels of newly-hard-earned knowledge. Among that education was learning that PhoneGap 1.1.0 breaks jQuery Mobile’s back button on Android devices.

Being able to use a web-based framework like jQuery Mobile to create a “native” mobile app is one of PhoneGap’s most appealing propositions. So, you can imagine my dismay when wrapping this latest project in PhoneGap broke its navigation. Worse yet, even closing jQuery Mobile’s dialog windows stopped working under PhoneGap 1.1.0.

Luckily, the problem ended up being a minor one with a simple fix. In this post, I’ll briefly show you why PhoneGap 1.1.0 caused jQuery Mobile’s back buttons to stop working and how you can fix that problem in your own app.

Getting back() to basics

If you’ve ever navigated through a jQuery Mobile app with the document’s address visible, you’ve probably noticed that jQuery Mobile makes heavy use of the browser’s history API to maintain state and facilitate navigation. Whether using its recently added pushState support or the more traditional hash-based history management, even something as simple as opening a dialog window creates a new history entry.

Conversely, moving back to previous states is then as simple as executing a quick history.back() in the browser. And, that’s exactly how jQuery Mobile’s built-in back buttons and dialog close buttons work. Surprisingly, that’s even what initially happens when you make a call to $.dialog('close').

Finding the problem

Knowing that the problem I faced was related to the browser’s history.back() API helped narrow it down quite a bit. The first thing I did was use Remy Sharp‘s invaluable JsConsole to establish a console session linked to the embedded browser window in my PhoneGap app. Using that interface to poke around at the browser’s history object made the problem clear:

PhoneGap’s client-side library had replaced the history.back() function with one of its own (app-native Java code, no less). Digging into the Android version of phonegap-1.1.0.js, the culprit can be found beginning at line 1,277:

PhoneGap.addConstructor(function() {
    navigator.app = new App();
    navigator.app.origHistoryBack = window.history.back;
    window.history.back = navigator.app.backHistory;
});

JavaScript’s incredible flexibility is usually a strength, but it is a bit like running with scissors at times. The latter couple lines of that function stores a reference to the browser’s native history.back function and then monkey patches it with PhoneGap’s implementation instead.

The fix

Fixing the issue could have been accomplished (at least) two different ways. Either jQuery Mobile needed to use navigator.app.origHistoryBack if it existed, or PhoneGap’s interloping needed to be curtailed. Since reverting PhoneGap’s history.back monkey patch was much simpler, I was already leaning that direction.

Then, when I saw this recent commit on GitHub, the choice was an easy one.

Presumably, this change will be included in the next PhoneGap release since it was committed to the master branch. In the meantime, you can easily apply the change to your own copy of phonegap-1.1.0.js by finding this code (beginning at line 1,277):

PhoneGap.addConstructor(function() {
    navigator.app = new App();
    navigator.app.origHistoryBack = window.history.back;
    window.history.back = navigator.app.backHistory;
});

And changing it to this:

PhoneGap.addConstructor(function() {
    navigator.app = new App();
});

As I mentioned earlier, this only impacts the Android version of PhoneGap (to my knowledge). So, don’t go digging through versions of phonegap-1.1.0.js for other platforms looking to remove this monkey patch – it isn’t there.

Related posts:

  1. Disable a button control during postback.
  2. A few thoughts on jQuery templating with jQuery.tmpl
  3. jQuery 1.6.2 syntax error? You may be the victim of SEO.


You've been reading Why PhoneGap 1.1.0 broke jQuery Mobile’s back button, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Resolving an iisnode “The service is unavailable” 503 error
source: http://feeds.encosia.com/~r/Encosia/~3/1jzSfCnFMfE/

I’ve been experimenting with Tomasz Janczuk’s awesome iisnode project lately, in hopes of hosting some of my Node.js sites on IIS. Those sites are running well enough on an Ubuntu VPS currently, but the features that iisnode offers are compelling (and I have unused capacity on one of my Windows servers).

Along the way, I ran into one issue that isn’t addressed in the current iisnode documentation or examples very well. If you try to set up a standalone Node.js website in IIS you’re likely to be greeted with this error when you load it up for the first time:

iisnode 503 error screen

Remotely, you’ll see the dreaded “The service is unavailable.” error:

Those nondescript errors don’t exactly make resolving the problem very straightforward. So, I want to recap what I found to be the underlying problem in my case and a few solutions, in hopes of helping anyone else that ends up with the same issue.

The problem

The problem boils down to the default application pool identity account not having sufficient permission to carry out iisnode’s work. Part of the IIS error message does somewhat cryptically hint at what’s wrong:

An invalid identity in the application pool could cause this error.

That’s not very actionable though.

In the specific case of a barebones Node.js site running under iisnode’s default configuration, this occurs due to iisnode attempting to create its log file when your application is accessed for the first time.

If you’ve run iisnode locally, you’ve probably seen the script-name.js.logs folder that appears after first run. Unfortunately for iisnode, creating this folder (and the log file(s) inside it) is beyond the default application pool identity’s abilities and that results in our 503 error.

The nuclear solution (don’t do this)

The most straightforward way to eliminate the 503 error and get back to work is to change your site’s application pool identity from the default ApplicationPoolIdentity to LocalSystem:

That works well enough if you’re just playing around on a development machine and security isn’t a concern.

However, elevating the application pool’s privileges that high is not something you should do in production. If an attacker finds a hole in your Node.js code, running the site under LocalSystem means they will gain unfettered access to your entire web server. Not good.

Avoiding the problem altogether

Before changing any permissions whatsoever, ask yourself whether or not you care about iisnode’s logging to begin with. It’s enabled by default, but easy enough to disable by tweaking your site’s web.config:

<configuration>
  <system.webServer>
    <iisnode loggingEnabled="false" />
  </system.webServer>
</configuration>

With that small change, iisnode won’t attempt to create a log directory at all, and the file system permissions issue is moot.

If your Node.js code doesn’t attempt to write to disk otherwise and you don’t care about iisnode’s logging feature, this is probably the best solution since it requires no privilege elevation at all.

A more limited escalation

Instead of giving your application pool the keys to the kingdom, a better solution is to grant ApplicationPoolIdentity elevated privileges only on the specific location where your Node.js application resides.

You can grant those permissions via either the Windows GUI interface or the command line, depending on your preference.

Graphical approach

Assuming you have access to the server’s desktop, you can give IIS write access through the usual Properties > Security > Edit… dialogs. In a default installation, the IIS_IUSRS group is what you need to grant write access to:

You might notice that I’m only granting elevated privileges to app.js.logs above, not the entire site structure.

It’s often the case that a single file, like my site’s app.js, will be the exclusive entry point to an entire site. When that’s the case, there will only be a single iisnode logging folder and it’s a good idea to even further isolate write access to the corresponding .logs folder.

Command line approach

Using the Windows GUI to set file permissions is okay, but it can be a bit cumbersome to dig through the file system and then navigate through the dialog windows. More importantly, you may need to script this as part of an unattended deployment process.

Windows also includes a command line utility to handle this: icacls. Here’s an example of how you could grant the IIS user (and iisnode) write access to an entire site structure from the command line:

icacls c:\path\to\your\site /grant IIS_IUSRS:(OI)(CI)W

Running that on my specific example of MySite.com looked like this:

Limiting access specifically to the logging folder, as shown in the GUI approach above, is simple enough too:

icacls c:\path\to\your\site\app.js.logs /grant IIS_IUSRS:(OI)(CI)W

If you’re curious about the syntax of the command, it’s less complicated than it looks. The path and /grant are self-explanatory, but the rest is a bit terse.

IIS_IUSRS:(OI)(CI) means that the change should apply to any objects and containers within the IIS_IUSRS group.

The W at the end determines what type of permission should be granted. We could also have used M to give both write and modify permissions to iisnode, or F to grant full control.

This applies to more than logging

Of course, hitting a permissions error trying to write logs is just one possible reason you might encounter this error. Since this particular cause is one that everyone will probably run into when setting up a standalone site under iisnode, I decided that it’s worth singling out individually though.

If your Node.js code itself needs access to write to the file system, you’ll need to grant the correct permissions in those areas of your site’s structure too (following the same approach as above, but altering the path appropriately).

Related posts:

  1. Use jQuery to catch and display ASP.NET AJAX service errors
  2. How to improve ASP.NET AJAX error handling
  3. ASP.NET page methods are only as secure as you make them


You've been reading Resolving an iisnode “The service is unavailable” 503 error, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Guidance on building real-world HTML and JavaScript apps
source: http://feeds.encosia.com/~r/Encosia/~3/1O6g7His2sI/

Over the past several months, I’ve been participating as an adviser to an interesting Microsoft patterns & practices effort named Project Silk. I don’t publish posts here about every project I’m tangentially involved in, but I think Project Silk is worth a look if you’re building modern, JavaScript-heavy web applications.

The project itself is comprised of a complete reference application and an extensive set of documentation describing how the app works and the process behind the design decisions that the team made along the way. Think of it as the NerdDinner sample (and accompanying book chatper), but focused almost entirely on client-side development rather than the server-side MVC component.

One of the most valuable aspects of the project is that it takes aim at the almost intractable topic of building large, maintainable JavaScript applications. You can see how seriously they took that goal by the time you get to just the second paragraph of the project summary:

An intentional design indicates that deliberate attention was paid to the modularity of the JavaScript code, and the usability of the application was an explicit focus. [...] Modularity is important when building highly interactive web applications because they often require a significant amount of JavaScript code. This guidance aims to help you understand how to write maintainable JavaScript code that reaps the many benefits of a modular design.

Large, maintainable JavaScript is one of those topics that desperately needs a commensurately large real-world sample. Patterns like pub/sub and modular decomposition seem to add unnecessary complexity to small examples, but become invaluable as your codebase grows. It’s great to see a sample application that’s large enough to demonstrate how these problems arise and that attempts to tackle them head-on.

Have a look at the following locations to learn more about the project, download the sample application, and read the accompanying documentation:

Or, if you don’t want to build the sample project yourself just to see how the Mileage Stats application works, you might prefer this demo of it in action:

Related posts:

  1. Use jQuery to extract data from HTML lists and tables
  2. Review: The best JavaScript book I’ve read
  3. Display data updates in real-time with AJAX


You've been reading Guidance on building real-world HTML and JavaScript apps, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


ASP.NET page methods are only as secure as you make them
source: http://feeds.encosia.com/~r/Encosia/~3/BtmvIYGIf7w/

One of the most persistent misconceptions about ASP.NET’s page methods is the notion that they have some intrinsic protection against requests that don’t originate from the page where they’re defined. Since a page method’s code resides within a page’s code-behind file, it’s intuitive to assume that those methods benefit from some form of inherent security.

Unfortunately, that is not the case.

Exploiting your page’s insecurities

In case it’s hard to believe these code-behind methods truly are so easily accessible, let’s take a look at a quick example. Let’s say you have a page method that returns sensitive business information, like so:

[WebMethod]
public static int SecretFormula() {
  return 42;
}

Assuming that method is defined in a Default.aspx file’s code-behind, located in a folder named TopSecret, here’s a bit of jQuery you could use to request the secret formula from any page on the site:

$.ajax({
  url: '/TopSecret/Default.aspx/SecretFormula',
  type: 'POST',
  contentType: 'application/json',
  data: '{}',
  success: function(result) {
    alert(result.d);
  }
});

In fact, you can even make that request from a plain HTML file. In this example, I’m making the request right from a simple HTML file named index.htm:

Not only is the request not originating from the ASPX file that contains the page method, that request wasn’t originating from an ASPX file at all!

Is this really a problem?

You might be asking yourself if this is really a problem to begin with. After all, you aren’t very likely to write client-side code that requests sensitive data unless you actually need that data, regardless of whether you write that code on an ASPX page, HTML page, or anywhere else.

The trouble is, a villain could land on any of your site’s pages, open up Firebug, and start probing for weaknesses like this one. In this case, the obscurity of the exact location of the page method might lead you to a false sense of security, but if an attacker has any knowledge of your system’s architecture then the door is wide open.

Even more troubling, as long as an attacker uses POST requests with an application/json Content-Type, they could use a tool as simple as Fiddler to interrogate your site’s services remotely. A few lines of server-side code, and your competition could set up a site driven by the page method APIs on your site that you thought were private!

A fixable problem

Page methods aren’t indefensible against the shenanigans of external interlopers though. You can secure them with ASP.NET’s built-in authorization mechanism, just as you would any other ASPX page (or ASMX service). In fact, if you secure an ASPX page with ASP.NET authorization, page methods defined in its code-behind are automatically equally secure.

To deny unauthenticated access to methods in our TopSecret folder, adding an authorization entry to the web.config in that folder is all that’s necessary:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
</configuration>

Now, an unauthenticated user trying to access the SecretFormula method from index.htm (or anywhere else, without authenticating first) is denied access:

Attempting to request the same page method with jQuery after securing it.

Of course, there are a variety of ways to control access to these methods. You might test to see which role a user’s in and respond accordingly, or you might only need to verify some token stored in the Session.

Regardless of the particular mechanism, the key is to remember that none of this is automatic and that you must be mindful of regulating access to your page methods.

Related posts:

  1. Using jQuery to directly call ASP.NET AJAX page methods
  2. Why do ASP.NET AJAX page methods have to be static?
  3. Using complex types to make calling services less… complex


You've been reading ASP.NET page methods are only as secure as you make them, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Use ASP.NET’s HttpHandler to bridge the cross-domain gap
source: http://feeds.encosia.com/~r/Encosia/~3/YdLACsHJ79k/

When you’re developing client-side applications, a problem you’ll almost inevitably have to deal with is how to work with services that reside outside your website’s domain. Though many modern APIs do support JSONP, which is a clever workaround to somewhat mitigate the cross-domain problem, JSONP has its own problems.

Worse, if you encounter an API with no JSONP support, the cross-domain barrier can quickly become a formidable one. CORS is slowly becoming a viable alternative, but it requires that the remote service support it via special HTTP headers and browser support for CORS is still not ubiquitous.

Until CORS is more broadly supported, an alternative solution is to bounce cross-domain requests through the web server that hosts your website. In ASP.NET, the best tool for implementing that sort of middleman endpoint is the HttpHandler.

In this post, I’ll show you how to create an HttpHandler to service cross-domain requests, how to use jQuery to communicate with the handler, and an example of one improvement that this approach makes possible.

An example remote API

To focus on an example that’s already familiar to many, I’m going to use Twitter. Twitter’s API does support JSONP, which is a viable alternative for consuming it across domains. In fact, the Twitter status that you see in my sidebar to the right was retrieved from Twitter’s API via JSONP.

However, not every service supports JSONP, its third-party script injection mechanism is sometimes problematic, and using JSONP robs us of niceties like local caching. So, for the sake of a good example, let’s find a way to use the Twitter API on the client-side without resorting to JSONP.

Specifically, I’m interested in querying the service for my last few status updates. The Twitter API request to accomplish that looks like this:

http://api.twitter.com/1/statuses/user_timeline.json?id=Encosia

Twitter will respond to that with a JSON array of objects representing my (or your) last 20 tweets, which is exactly what we’re after.

The best tool for the job: HttpHandler

If you’re accustomed to using ASP.NET’s page methods and ScriptServices to facilitate communication between client and server, those tools begin to look like a hammer that matches every JSON-shaped nail in sight. However, when simply relaying an external API’s JSON through to the client, they often add unnecessary overhead and complexity.

Rather, a lower-level tool is more appropriate in this case.

HttpHandlers are one of ASP.NET’s most under-utilized tools. They’re simple to implement and allow you to handle requests closer to the metal than WebForms pages or MVC controller actions.

One place in particular where HttpHandlers shine is where you would otherwise consider writing Response.Write statements in a WebForms page’s code-behind. This anti-pattern of using ASPX’s code-behind to get closer to the metal looks similar to approaches that you’ll see on some other platforms, such as PHP, but is not equivalent.

Unfortunately, even if you don’t use WebForms controls or ASPX markup at all, executing that low-level code from an ASPX page’s code-behind requires that every request filter through the full page life cycle. That means even the simplest request still has to percolate all the way from PreInit to Unload, adding needless overhead.

Instead, the HttpHandler is where you should write that sort of code that ultimately boils down to Response.Write calls.

Choosing the right handler type

A tricky issue when you’re writing your first HttpHandler is that Visual Studio presents you with two templates, “ASP.NET Handler” and “Generic Handler”:

The add item dialog presents two choices of HttpHandler templates

Both are similar, but the “ASP.NET Handler” template’s approach requires modifying your web.config to configure which URL your handler accepts requests at. Mucking around in the web.config isn’t terribly difficult, but it’s extra friction which makes the process less approachable.

In the spirit of keeping things simple, let’s stick with the more traditionally file-based “Generic Handler”.

Getting started with your first HttpHandler

After choosing that template, specifying a name, and adding the new file to your site, you’ll end up with a bit of boilerplate code that includes this method:

public void ProcessRequest(HttpContext context) {
  context.Response.ContentType = "text/plain";
  context.Response.Write("Hello World");
}

If you start the site up in Visual Studio and then request your newly-created HttpHandler in a browser, Handler1.ashx if you accept the default name, you will see “Hello World” as you might expect.

That’s not very impressive yet, but the response you saw made its way to your browser without touching WebForms’ page life cycle or filtering through ASP.NET MVC’s routing engine and action filters. While those things are worthwhile niceties for the majority of your application, they’re unwanted overhead when all you need is to efficiently relay some content through the server.

Bouncing a request to Twitter through the HttpHandler

To adapt an HttpHandler for relaying requests to the Twitter API, we can use .NET’s handy WebClient class to make the request to Twitter’s API, and then return the result back through as the handler’s response:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  // The base URL for Twitter API requests.
  string baseUrl = "http://api.twitter.com/1/";
 
  // The specific API call that we're interested in.
  string request = "statuses/user_timeline.json?id=Encosia";
 
  // Make a request to the API and capture its result.
  string response = twitter.DownloadString(baseUrl + request);
 
  // Set the content-type so that libraries like jQuery can 
  //  automatically parse the result.
  context.Response.ContentType = "application/json";
 
  // Relay the API response back down to the client.
  context.Response.Write(response);
}

That code simply makes an HTTP request to the Twitter API and blindly bounces the result back through as the HttpHandler’s response. For the time being, everything is hard-coded, but we’ll improve on that soon enough.

Using the handler proxy on the client-side

With our web server doing the heavy lifting, using this server-side proxy to make a remote request is trivial:

$.getJSON('TwitterProxy.ashx', function(tweets) {
  // Call a magical function that does all the presentational work.
  displayTweets(tweets);
});

The jQuery code here is actually identical what you’d use when requesting the API via JSONP. Whether that response is truly being fulfilled by the specified URL or it’s being relayed through our HttpHandler, it’s all the same to the jQuery code on the client-side.

As you’ll see when we add caching, this can easily be exploited for good.

Mixing things up with QueryString parameters

The hard-coded approach works well enough, but what if we wanted to be able to query any Twitter account’s recent updates instead of being limited to just that boring Encosia character?

Since HttpHandlers receive an instance of the current HttpContext as the parameter to their ProcessRequest method, it’s easy to access QueryString parameters and react accordingly. For example, this would allow us to request any Twitter account’s timeline by via an id parameter on the QueryString:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  string baseUrl = "http://api.twitter.com/1/";
 
  // Extract the desired account ID from the QueryString.
  string id = context.Request.QueryString["id"];
 
  // Make a request to the API for the specified id.
  string request = "statuses/user_timeline.json?id=" + id;
 
  // Same as before, from here on out:
  string response = twitter.DownloadString(baseUrl + request);
 
  context.Response.ContentType = "application/json";
  context.Response.Write(response);
}

Now it works exactly the same way as before, but we can choose which Twitter account’s timeline is requested. For example, this URL would request Scott Guthrie‘s latest tweets:

TwitterProxy.ashx?id=ScottGu

Supplying parameters with $.getJSON

To pass this new parameter in from the client-side, you could handcraft the entire URL including the appropriate QueryString. Even better though, $.getJSON has an optional “data” argument that accepts a JavaScript object and converts it to QueryString parameters:

$.getJSON('TwitterProxy.ashx', { id: 'ScottGu' }, function(tweets) {
  displayTweets(tweets);
});

jQuery will automatically URLEncode the parameters you specify in the “data” argument and properly assemble them into the final URL to be requested:

Screenshot of the HttpHandler request generated by the jQuery code above.

Which is exactly what we need it to do.

Using a configuration object like this is cleaner than manually concatenating a string together and makes it easier to vary the parameter at runtime.

Improving performance with server-side caching

An advantage the HttpHandler proxy has over CORS and JSONP is that you can perform any arbitrary server-side processing that you wish, both before and after the remote service repsonds. A great way to take advantage of that is adding a server-side caching layer.

Server-side caching will reduce how often requests actually trigger API calls and can significantly improve performance for requests that are already cached. A caching middleman like this is especially valuable when dealing with rate-limited APIs like Twitter’s.

Let’s say that we wanted to cache Twitter responses for up to five minutes, for example:

public void ProcessRequest(HttpContext context) {
  // This will be the case whether there's a cache hit or not.
  context.Response.ContentType = "application/json";
 
  // Check to see if the twitter status is already cached,
  //   then retrieve and return the cached value if so.
  // 8/3/11: Updated with more robust test, thanks to ctolkien.
  object tweetsCache = context.Cache["tweets-" + id];
 
  if (tweetsCache != null) {
    string cachedTweets = tweetsCache.ToString();
 
    context.Response.Write(cachedTweets);
 
    // We're done here.
    return;
  }
 
  WebClient twitter = new WebClient();
 
  // Move along; nothing to see here. The concatenation is just
  //  to avoid horizontal scrolling within the meager 492
  //  pixels I have to work with here.
  string url = "http://api.twitter.com/1/statuses/" +
               "user_timeline.json?id=Encosia";
 
  string tweets = twitter.DownloadString(url);
 
  // This monstrosity essentially just caches the WebClient result
  //  with a maximum lifetime of 5 minutes from now.
  // If you don't care about the expiration, this can be a simple
  //  context.Cache["tweets"] = tweets; instead.
  context.Cache.Add("tweets", tweets,
    null, DateTime.Now.AddMinutes(5), 
    System.Web.Caching.Cache.NoSlidingExpiration,
    System.Web.Caching.CacheItemPriority.Normal, 
    null);
 
  context.Response.Write(tweets);
}

Adding the intermediate cache results in a tremendous performance improvement after the first request:

Screenshot of an initial uncached request to Twitter and then the subsequent, cached requests

With the server able to immediately serve requests within the five minute caching window, subsequent $.getJSON requests are an order of magnitude faster!

Perhaps even more importantly in the case of Twitter, these four refreshes only counted as one API call against my hourly rate-limit.

Conclusion

Using HttpHandlers as server-side proxies turns out to be a simple way to solve the pesky cross-domain restrictions that we’ve all run into from time to time. All said and done, using an HttpHandler to proxy third-party requests takes few lines of code, but offers nearly unlimited flexibility.

In addition to the obvious benefit of getting around the cross-domain restriction, bouncing requests through your own server potentially has a range of other benefits, including:

  • Error handling – This approach not only passes unhandled exceptions on the WebClient request back through to the client-side, but it also gives you the ability to enhance the error handling with your own sanity checks and constraints.
  • Caching – As shown in this post’s final example, you can very easily interject your own caching layer for requests passing through the HttpHandler proxy. That’s especially useful when working against rate limited or potentially slow/flaky APIs (like Twitter’s).
  • Security – When you’re accustomed to server-side programming, the revealing nature of client-side JavaScript can be unnerving. Learning to appropriately partition sensitive algorithms and data between client and server is key to mitigating that issue. Along those lines, moving the remote request to code running on your server is one way to keep sensitive information like API keys and passwords safely hidden from view-source and client-side developer tools.
  • Reliability – One of JSONP’s less obvious drawbacks is the fact that it relies on injecting a third-party script. However, your users may be using something like NoScript to purposely block third-party scripts, effectively shutting down your ability to use JSONP. Even if you prefer JSONP in most cases, a local server-side proxy can be helpful as a fallback in case of unexpected JSONP failures.

That’s not to say that there’s no downsides to this approach. When you’re using an HttpHandler proxy, it’s important to keep in mind that it can be slower since you’re making a series of two connections instead of a single, direct one. You also lose the ability to request content with the user’s third-party cookies attached to the request, which is helpful in some cases.

Overall, using server-side proxies is a very useful item to have in your toolbox. I hope this post has served to introduce you to the approach and/or given you better insight into how you can use HttpHandlers to your advantage.

Get the source

If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.

HttpHandler-Proxy on GitHubHttpHandler-Proxy.zip

Related posts:

  1. AJAX, file downloads, and IFRAMEs
  2. The easiest way to break ASP.NET AJAX pages
  3. Why ASP.NET AJAX UpdatePanels are dangerous


You've been reading Use ASP.NET’s HttpHandler to bridge the cross-domain gap, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


Highslide JS .NET and PostBack Ritalin open-sourced
source: http://feeds.encosia.com/~r/Encosia/~3/mTJMLHycdWU/

They aren’t the most glamorous projects, but thousands of developers have integrated my Highslide JS .NET and PostBack Ritalin controls into their sites and applications over the years. PostBack Ritalin was even included in Subtext at one point. It’s definitely a great feeling to see your work put to good use (in fact, this motivator can be even more powerful than monetary gain).

As jQuery has risen in popularity among the ASP.NET community, both controls seem somewhat superfluous to me, yet they have surprisingly remained very much in-demand. As long as people are using them, keeping them working and bug-free(ish) is something that I’ll continue to pursue.

I wouldn’t mind some help though.

Over the years, I didn’t keep the source code for these controls closed due to any illusions of ever turning them into commercial products. Rather, they were the first server controls I had built for general consumption and the quality of their code is not great. For the same sort of reasons that developers “go dark”, I always preferred to keep that code hidden in my junk drawer.

At this point though, keeping their source hidden just to protect my delicate programmer-pride is counterproductive, so I’ve open-sourced both controls on GitHub. Go forth and fork them – pull requests are welcomed.

Fork PostBackRitalin on GitHub

Fork Highslide JS .NET on GitHub

Related posts:

  1. PostBack Ritalin Updated (v0.10)
  2. PostBack Ritalin v1.0
  3. Postback Ritalin Update (v0.2)


You've been reading Highslide JS .NET and PostBack Ritalin open-sourced, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you've got any feedback, please click through and leave a comment; I'd love to hear from you. You can click here to jump directly to the comment section of this post.


What's Shakin' on SNI

Popular Communities

» Drug and Alcohol Addiction (293)  » Loans (230)  » Domains (169)  » Drug Rehab Centers (55)  » Entertainment (35)  » Automobiles (15)  » News and Newspapers (12)  » Stocks and Bonds (10)  » Politics (8)  » Restaurants (7)  » Health and Wellness (7)  » General (6)  » Sports - Golf (5)  » Business (5)  » Health (5)  » Real Estate (5)  » Travel (5)  » Home Improvement (4)  » Technology (3)  » Gambling (3)  » Hotels (3)  » Music (2)  » Mortgage (2)  » Food (2)  » Finance and Banking (2)  » Adult (2)  » Dentistry (2)  » Business Services (2)  » Information Technology (2)  » Vacation Destinations (2)  » Shopping (2)  » Cash Advances (2)  » News (2)  » Drug Abuse and Addiction (1)  » Internet - SEO (Search Engine Optimization) (1)  » Stock Trading (1)  » Travel Tours and Groups (1)  » Special Events (1)  » Sports - Football (1)  » Marketing (1)  » Magazines (1)  » Jobs and Training (1)  » Hobbies (1)  » Garden (1)  » Farming (1)  » Education (1)  » Cruises (1)  » Coupons (1)  » Beauty & Fashion (1)  » Auctions (1)  

Copyright ©2012 SocialNetworkinc.com. All Rights Reserved.

Sitemap · RSS Feed · Cloud Vision · Contact · Privacy Policy · Disclaimer/Terms & Conditions · CSS and XHTML