I use a Google Docs spreadsheet to manage all my domains. It contains a list of all the domain names I own, along with their expiry dates, the name of the registrar the domain is registered with, and some other details. I also wanted to also add a column showing the nameservers, so I could tell which domains were parked vs which domains I'm actively using.

Google Apps Script provides a URLFetchApp.fetch function to perform network requests. We can combine this with Google's DNS-over-HTTPS API to load DNS records for a given domain:

function GetDNSEntries(domain, type) {
  var response = UrlFetchApp.fetch('https://dns.google.com/resolve?name=' + domain + '&type=' + type);
  var data = JSON.parse(response);
  
  var results = data.Answer.map(function(answer) {
    // Remove trailing dot from answer
    return answer.data.replace(/\.$/, '');
  });
  return results.sort().join(', ');
}

We can then use this function in a spreadsheet:

=GetDNSEntries(A1, "NS")

This results in a column listing the DNS servers for each domain, with data that's always kept up-to-date by Google Docs:

One of the most powerful features of ASP.NET MVC is its URL routing engine. The routing engine in ASP.NET MVC is used to route incoming requests to the correct controller action, but it can also generate URLs for you. This is normally done with the URL helper in views:

// Regular ASP.NET MVC:
@Url.Action("View", "Blog", new { id = 123 })
// With T4MVC:
@Url.Action(MVC.Blog.View(123))

This is great, as it means changing your routes will automatically update all the internal URLs throughout your site. If you're using T4MVC (which I strongly suggest), you also get compile time checking on your URLs, which means that it's literally impossible to have broken internal links (any invalid links will throw a compile error).

This is all well and good on the server side, but there's no equivalent on the client side, meaning that people often use one of these approaches:

  • Hard-code URL in JavaScript directly
  • Store the URL in a data attribute on the relevant element (or body)
  • Create a global JavaScript object containing all the URLs the page requires (for example, Jarret Meyer's approach)

Each of these approaches has its downsides. The last one is the most promising, and I had the idea of generalising this approach and making it into a library that can be dropped into any site. There are some existing projects that tackle this problem, the main one being Zack Owens' ASP.NET MVC JavaScript Routing. Zack's library looked good but I had two issues with it:

  • It's unnecessarily tightly coupled with jQuery, meaning you have to load the whole of jQuery just to use it, which is annoying if your site is just vanilla JavaScript or uses a library like PrototypeJS or MooTools instead.
  • It requires you to use a custom routing syntax rather than the standard ASP.NET MVC routing

I decided to write my own library to solve this problem. My library is called RouteJs, and it is available on NuGet. It supports ASP.NET MVC 2, 3 and 4. Basically, RouteJs consists of a small piece of JavaScript to handle building URLs, as well as some information about all the routes you want to expose. All of this is served using an ASP.NET handler, so you don't need to change your build scripts or anything like that. Simply drop it into your site.

Once loaded in your site, RouteJs provides a global Router object, similar to the URL helper that comes with ASP.NET MVC. For example, the same blog view URL can be generated with the following code:

var url = Router.action('Blog', 'View', { id = 123 });

It supports most of the common features of ASP.NET MVC routing, including areas, default values and simple constraints. It does not currently support ASP.NET WebAPI, but I'll definitely add support if someone requests it.

For more information, please see the readme on Github. Please let me know what you think!

Until next time,

— Daniel

Back when IE 9 came out, it was the first major browser to start caching redirects to improve performance. The IE team wrote a detailed blog post about it, but they still got some backlash (mainly from people that didn't set correct no-cache headers on redirects with side effects, like login pages).

The recently released version of Safari for iOS 6 has started caching AJAX POST requests, with no notification to developers at all. Not only is this unexpected, but it goes against the HTTP 1.1 standard, which states:

9.5 POST

...

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields.

This means that if you have something like an edit page that uses AJAX to post the form, the first edit will work, but subsequent edits will return a cached "Success" message instead of sending the request to the server!

This is somewhat similar to Internet Explorer caching AJAX GET requests, except caching GET requests is nowhere near as dangerous. While GET requests are allowed to be cached, POST requests are not idempotent (they can have side effects) so they should never be cached. Sure, IE caches AJAX GET requests more heavily than other browsers, but this is allowed in the HTTP specs:

The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in section 13.

Caching POST requests is horrible. How many times have you added no-cache headers to your POST pages? I'm going to have a guess and say never, since no other browser in the history of the World Wide Web has cached POST requests. This move has essentially broken the functionality of some AJAX-based edit forms, and developers might not notice the breakage initially. I hope this is a bug and not expected functionality, and it gets fixed at some point. Safari used to be a horrible browser with many DOM issues... I hope it's not heading this way again.

The original release of ASP.NET MVC used HTML helpers with a syntax like the following:

@Html.TextArea("Title")

These worked, but if you renamed the property in your model (for example, from “Title” to “Subject”) and forgot to update your view, you wouldn’t catch this error until you actually tried out the page and noticed your model isn’t populating properly. By this time, you might have users using the site and wondering why stuff isn’t working.

ASP.NET MVC 2 introduced the concept of strongly-typed HtmlHelper extensions, and ASP.NET MVC 3 extended this even further. An example of a strongly typed HtmlHelper is the following:

@Html.TextAreaFor(post => post.Title)

These allow you to write more reliable code, as view compilation will fail if you change the field name in your model class but forget to change the field name in the view. If you use precompiled views, this error will be caught before deployment.

Creating your own

The built-in helpers are good, but quite often it’s nice to create your own helpers (for example, if you have your own custom controls like a star rating control or rich-text editor).

Read more ⇒

Modern browsers have support for RGBA colours, allowing you to have semi-transparent background colours. Unfortunately, this only works in awesome browsers (everything except IE 8 and below). However, IE does support a custom gradient filter. Whilst it's commonly used to render gradients (obviously), it supports alpha transparency. If you set the start and end colours to be the same, this has the same effect as setting an alpha value on the colour.

This involves quite a lot of CSS for each alpha colour you want to use. We can automate this tedious code generation through a LESS mixin. If you're still using 'pure' CSS, I'd highly suggest looking into LESS and SASS, they're extremely handy. In any case, I use a mixin similar to the following:

.rgba(@colour, @alpha)
{
	@alphaColour: hsla(hue(@colour), saturation(@colour), lightness(@colour), @alpha);
	@ieAlphaColour: argb(@alphaColour);
	
	background-color: @colour; // Fallback for older browsers
	background-color: @alphaColour; 
	
	// IE hacks
	zoom: 1; // hasLayout
	background-color: transparent\9;
	-ms-filter:  "progid:DXImageTransform.Microsoft.gradient(startColorstr=@{ieAlphaColour}, endColorstr=@{ieAlphaColour})"; // IE 8+
	    filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=@{ieAlphaColour}, endColorstr=@{ieAlphaColour})"; // IE 6 & 7 
	
}

Note that IE requires the element to have layout in order to apply filters to it (hence the zoom: 1 hack), and IE 8 changed the filter syntax to use -ms-filter instead. This LESS mixin can be used as follows:

#blah
{
        .rgba(black, 0.5);
}

This will set the element to a 50% black background. This mixin could be converted to SASS quite easily, too. Ideally I would have liked to apply the IE styles in a better way (like using conditional comments to set classes on the element) but I couldn't get this approach working with LESS.

Hope this helps someone!

Until next time,
— Daniel

Am I the only person that cringes when I see HTML like this?

<div class="h1Title"><div class="spriteicon_img_mini" id="icon-name_mini"></div>Page Title</div>

Or like this?

<!--Start Footer-->
<div id="heading-bottom_bg" class="spriteheading_bg footer">
	<ul class="links footer_ul">
		<li class="footer_li"><a class="footer_li_a bottomlink" href="../index.html">Home</a></li>
		<li class="footer_li"><span class="footer" style="font-size:18px;">&#9642;</span></li>
		...
		<li class="footer_li"><a class="footer_li_a bottomlink" href="/logout/">Log out</a></li>
	</ul>
</div>

Notice the classes on all those elements. Really? A web developer that doesn't know about the

tag or CSS descendant/child selectors? Why do people feel the need to use
tags for everything, when there's other more semantic tags available? It really doesn't make sense to me; some of the first HTML tags I learnt were

and

.

For what it's worth, this is how I'd rewrite those two blocks of HTML:

<h1 class="icon-name">Page Title</h1>
<!--Start Footer-->
<div id="footer">
	<ul>
		<li><a href="../index.html">Home</a> &#9642;</li>
		...
		<li><a href="/logout/">Log out</a></li>
	</ul>
</div>

It's good to keep your HTML and CSS selectors as simple as possible. There's no need for a "footer_li" class when you can just use "#footer li" in your CSS. The "icon-name" CSS class on the

is used for a CSS sprite to display next to the heading. Also, as an alternative, the separator (▪) that was originally in a after all the footer items can easily be added via the :after pseudo selector instead of being in the
  • .

    It's really frustrating that there's so many "web developers" that don't seem to know basic HTML. It's okay if you're just starting to learn, this is fair enough. The HTML I "wrote" when I started web development was horrendous. And by "wrote" I mean "created in FrontPage 98". But it's another thing altogether to be a developer for a number of years and still write ugly HTML like this.

    Ugly JavaScript seems to be way more common, though. But that's a rant for another day.

  • A lot of sites now use OpenID. This is great, as you can use the one account on multiple sites. Unfortunately, Facebook accounts can not yet be used as OpenIDs 😦. However, using Facebook logins isn't too hard, as they support using OAuth 2.0. OpenID and OAuth are fundamentally for different things (OpenID is authentication, OAuth is authorization), but it still works well in this situation.

    Firstly, sign up for a Facebook application at the Facebook developer website. You'll have to correctly set the site URL and site domain. Copy the application ID and application secret as shown on the Web Site section of the settings, as you will need them later.

    Read more ⇒

    I thought I'd give some link love to some of the lesser-known web development blogs I enjoy reading. This post was prompted by a post about my site at GiveUpInternet.com. I didn't expect the link (as I don't think my blog is very good for web development stuff), but I do appreciate it heaps! This blog hasn't really focused too much on web development, perhaps I should post more web development articles 😃

    • GiveUpInternet.com — As it says on the site, "Give Up Internet is a Humor Blog for Internet People and Developers." While it's technically not a web development blog, I love the posts on this site. Unlike a lot of other "humour" sites that post stupid things a lot of the time, it's got actual funny posts. It's one of the only humour blogs that I'm subscribed to.
    • The CSS Ninja by Ryan Seddon— This is a great blog about nice little tricks that can be done in CSS. One of its focuses is doing things that previously required JavaScript, in pure CSS (no JavaScript whatsoever). This includes cross-browser CSS-styled checkboxes, a lightbox in pure CSS, and an easy way to preload images using CSS2.
    • David Walsh's blog — David is one of the core MooTools developers, and as such, he blogs mainly about JavaScript, and occasionally some PHP snippets. While, in my opinon, his posts on PHP are often messy 😛, his posts on JavaScript are excellent.
    • AdequatelyGood.com by Ben Cherry — If you're interested in JavaScript (especially the nitty gritty of its internals), this is by far the best blog on the topic that I've seen. Ben has written detailed articles on a lot of unique features of JavaScript, including scoping and "hoisting", and how it handles object to primitive conversions.
    • Hallvord R. M. Steen's blog and the Opera sitepatching blog — Hallvord is a developer for Opera Software. His blog covers the state of the web as it unfortunately is at the moment - Broken browser sniffer scripts, standards violations, and just general scripting stupidities. Things are definitely improving, but there's a LOT of broken scripts out there. Opera has a file called "browser.js" that contains patches to make these broken sites work correctly in Opera. Hallford's blog (and the Opera site patching blog) detail the things that Opera does to patch these broken sites. There have been some very interesting posts, including the horrible XML and XSLT on the Israeli rail website, how Google Docs used to print documents, and many others.

    That's all for now... I might eventually write another blog post like this. Or a proper blog post 😛 😃

    Until next time,

    — Daniel