Localize your MVC with ease.

MVC seems all the rage these days. And while there are many good things it brings to the table, it seams it takes us a step back in terms of I18N.

For instance, if you want to use the special aspx attribute meta:resourceKey=”foo”, you won’t always be able to do so.

The following would work fine:

<asp:Label runat="server" ID="_QueryPrompt" Text="Enter Query" meta:resourcekey="_QueryPrompt" />

But we’re out of luck with buttons:

<asp:Button runat="server" ID="btn" Text="Run" meta:resourcekey="_SubmitQuery" />

At runtime, you will get an exception explaining you need a FORM with a runat=”Server”. Ugh. After some spelunking I came across this discussion, which basically suggests creating an extension to the System.Web.Mvc.HtmlHelper class. The discussion is thick with issues, specifically that if a UserControl is used, finding it’s path in order to get to it’s local resource requires all manners of digging around compilation and application with fairly extensive branching and parsing. Ultimately, the extension is complicated by attempting to combine both a resource retrieval, fallback to global from local resource and formatted template substitution in one. A good helper – if the kinks are worked out.

So I wrote my own syntactic sugar to do the same:

public static string Localize(this System.Web.UI.UserControl control, string resourceKey, params object[] args)
{
string resource = (HttpContext.GetLocalResourceObject(control.AppRelativeVirtualPath, resourceKey) ?? string.Empty).ToString();
return mergeTokens(resource, args);
}
public static string Localize(this System.Web.UI.Page page, string resourceKey, params object[] args)
{
string resource = (HttpContext.GetLocalResourceObject(page.AppRelativeVirtualPath, resourceKey) ?? string.Empty).ToString();
return mergeTokens(resource, args);
}
private static string mergeTokens(string resource, object[] args)
{
if (resource != null && args != null && args.Length > 0)
{
return string.Format(resource, args);
}
else
{
return resource;
}
}

It is substantially shorter and defers to a base class. System.Web.MVC.ViewUserControl inherits from System.Web.UI.UserControl, so the call is true to it’s application. I also extend System.Web.UI.Page.

Lastly, there is the issue of a global resource. Since these resources are compiled and accessed at design time using dot notation (MyGlobalRes.MyKey) I felt that providing an extra function would not significantly shorten code or simplify developer’s life. That is, given a resx file in the App_GlobalResources containing the file Zones.resx, containing a key Zone1 one would simply write out

<%= Resources.Zones.Zone1 %>

or – if your resource is a template requiring tokens to be merged:

<%= String.Format(Resources.Zones.Zone1,"foo",11) %>

Happy MVC Internationalization, localization and globalization!

Save The Date: time_t 1234567890

You know you are a geek when things like this seem of any importance.

It may comfort you to know that there are others who are excited about the buzz. It may disturb you. Make of it what you will:

On Friday, February 13th 23:31:30 UTC 2009 the time_t structure would contain the the number 1234567890

The time_t is measures seconds past midnight of January 1 1970 (see Unix Epoc, POSIX time etc)

You might celebrate UTC time - those of you not stuck in traffic in New York or at work in California. Or just do it according to your time zone: raise a toast, save some doughnuts from doughnut-Friday or look at the sky or do triple click an icon or something.

Here’s a little java script to sneak onto your website which shows the time and the countdown:

<script language="javascript" type="text/javascript">
function onTick()
{
var t = Math.floor( ((new Date()).getTime()) /1000);
var remaining = (1234567890 - t);
var display = "Now: " + t + ": " + remaining + " Sec. to 1234567890 (local time zone).";
document.getElementById("_ShowTime").innerHTML = display;
}
setInterval('onTick()', 1000);
</script>

Timing is everything

You know you have a problem when your app behaves badly.

You know you should do something about it when a customer complains

You know you are late when your competitor took away your customer.

Waiting for Pex to release

After seeing Pex in action at PDC 2008 I have caught the fever.

Since then, I gave it a whirle on my own and was pretty impressed. So much so, I chose it as a topic for one of my So-Cal Code Camp talks in January. Got some very good questions and concerns regarding the capabilities and place of Pex in the world of software development and vis-a-vis TDD.

Update: After more than 5 years, Pex technology is now available as an “automatic unit testing” feature in some editions (paid) of Visual Studio 2015

The Flash Myth

Frustrated with square looking web pages, many web designers look to Flash. In addition to freedom of graphic expression, Flash brings interaction and transition effects which are difficult or impossible to duplicate. Why then shouldn’t all websites be Flash laden? Several reasons pop to mind:

  1. Loading speed: Way too often, flash movies load complex graphics, forcing the viewer to stare at some progress bar. For people who want to quickly access information this is a huge turn off. A “skip intro” sometimes viewed as lame.

  2. SEO: Flash based sites rarely are digestible or well ranked by search engines. You use flash - you lose top slots in natural search results. It’s that simple

  3. Form over content: Flash designs - as beautiful and engaging as they may be - all too often sacrifice text and information quantity in order to not disturb the layout or fit within the containing graphics. Again, ranking will suffer (low authority), viewers seeking comprehensive data will navigate away or become frustrated attempting to dig up more details by clicking every button and link in the movie.

  4. Cost: Although many good web designers can produce Flash movies, the good ones are fewer and more expensive. The problem compounds with natural workplace attrition. The ability to modify the original design, extend the site or give the site a “facelift” becomes constrained or expensive. All too often the original design does not lend itself well to rearrangement or extension.

  5. QA: Automated testing of Flash UI sites is difficult or impossible because the results may not be capture-able by testing tools - and that’s in the good case where the inputs are automatable. Unit testing for ActionScript is available by supporting frameworks these days, but finding implementations which include continuous integration is still rare.

  6. Ease of use: Often, the design focus reflects the author’s perspective. As long as the viewer wants to view information the way the designer does, everything flows well. Once the viewer wants to navigate in a different way, all bets are off.

  7. Stickiness: By far, one of the more compelling reasons for having used a Flash based site was to engage the viewer and strengthen the brand. The delivery on the promise is a bit mixed. Although some interaction does increase the stickiness of the site, other designs may suffer from slow load and skimpy content actually detracting from the overall perceived quality.

If while reading the points mentioned above you think to yourself “It seems that many of the points indicate poor design - not a technology limitation” you are right, and I couldn’t agree with you more.

Yet a good amount of sites out there suffer from these issues. Most of these sites would have been better served producing an HTML / DHTML / CSS + Ajax etc. In fact, my motivation for writing this came from a restaurant website I visited today. While scanning through listings and attempting to learn more, I was forced to watch tab after tab of progress bar latency in order to see the menu, the location, the about us etc. That site would have been cheaper to upgrade by anybody, rank higher on search engines, load faster and create less frustrated visitors. The KISS principle does apply. The pictures were beautiful; the layout was very appealing, the information organized - but the experience utterly annoying. Is that the best impression the business owner could impart on a potential customers?

In another instance, I was searching for a specialty product, and found it about 40 miles away. After having spent the time driving there and making a purchase, I discovered a location much closer to my house. What made the different? The far store had a website with full online catalog in HTML. The close by store had a flash only site. Snazzy - but missed a sale.

I have been to some sites that make great use of Flash though, and it would be foolish to discount the technology for its potential pitfalls. On the contrary - its adoption and application should be studied and considered when new design projects com up. There are many sites containing laundry lists of good vs. bad design. This article is no such list. But when is Flash well suited?

  1. Where a custom tool is created for order processing. Photo order sites, custom printing, fashion model virtualization etc. In these cases Flash serves an interactive function and is typically not the whole site.

  2. Where little textual information is required. Walkthroughs, product 360 views, design concept sites targeting highly interested viewers who don’t mind waiting for content and where alternative information sources are not available.

  3. For isolated rich interaction: Games, presentations and doodads that keep the visitor happy watching and engaged - as a single section of the site.

  4. Offline (DVD, CD) or downloadable media presentations, manuals etc.

  5. Anywhere that you can do a better job at winning the mind of the visitor without losing another 3 along the way.

Bottom line - use it wisely. If you suspect that any of the problems mentioned above might harm your online business, consider alternatives. And yes, by all means - do use a flash player to play video clips on the net. It is very well suited for that.

Pex Gotcha - watch your predicate expressions

Just came back from another great SoCal Code Camp. I had some valuable insights and discussions about TDD and the use of Pex. Thank you attendees!

While developing the presentation for Pex, I ran into a situation where the Pex.Assume() did not seem to work at all:

Consider the function

public List<short> MakeList(short baseNum, short count)
{
List<short> result = new List<short>(count);
for (short i = 1; i <= count; i++)
{
result.Add((short)(baseNum * i));
}
return result;
}

Pex correctly identifies a potential flaw where the multiplication (baseNum * i) would result in overflow.

Adding a filter

PexAssume.IsTrue(baseNum * count < short.MaxValue);

Seems like it would do the trick - but it doesn’t.

Several rebuilds, clean solution, shake heads and searches for bugs later I found the issue: The predicate provided to PexAssume.IsTrue(predicate) produced an overflow! So when pex explores it would have tripped the condition I was trying to avoid by evaluating the parameters I tried to filter out.

The fix was to rewrite the filter as:

PexAssume.IsTrue(short.MaxValue / count > baseNum);

Here, the math would not produce an overflow. Combined with PexAssume(count>0) and PexAssume(baseNum>0) my now filters work as (I) expected. The take home is pretty obvious - ensure the predicate does not throw - but identifying it took a bit of head scratching.