27
Apr

Localizing MVC for ASP.NET views and master pages

Microsoft's MVC for ASP.NET is still under serious development but at the moment support for localization is a little weak. Here's one approach that works with the 04/16 source-drop.

LocalizingWebFormViewLocator class

This class helps by trying to identify language-specific versions of views, user controls and master-pages where they exist, falling back to the generic one where necessary.

public class LocalizingWebFormViewLocator : ViewLocator
{
	public LocalizingWebFormViewLocator() : base()
	{
		ViewLocationFormats = new[] { "~/Views/{1}/{0}.{2}aspx", "~/Views/{1}/{0}.{2}ascx",
			"~/Views/Shared/{0}.{2}aspx", "~/Views/Shared/{0}.{2}ascx" };
		MasterLocationFormats = new[] { "~/Views/{1}/{0}.{2}master", "~/Views/Shared/{0}.{2}master" };
	}

	protected override string GetPath(RequestContext requestContext, string[] locationFormats, string name)
	{
		string foundView = FindViewLocation(locationFormats, requestContext, name, CultureInfo.CurrentUICulture.Name + ".");
		if (String.IsNullOrEmpty(foundView))
			foundView = FindViewLocation(locationFormats, requestContext, name, "");
		return foundView;
	}

	protected string FindViewLocation(string[] locationFormats, RequestContext requestContext, string name, string cultureSuffix)
	{
		string controllerName = requestContext.RouteData.GetRequiredString("controller");
		foreach (string locationFormat in locationFormats) {
			string viewFile = string.Format(CultureInfo.InvariantCulture, locationFormat, name, controllerName, cultureSuffix);
			if (HostingEnvironment.VirtualPathProvider.FileExists(viewFile))
				return viewFile;
		}
		return null;
	}
}

Using the class

To use the class you must set the ViewLocator on the WebFormViewEngine to a new instance of LocalizingWebFormViewLocator (either in the constructor or in your common controller subclass) and ensure that any master pages are specified on the RenderView calls to ensure the localized version is detected.

public class HomeController : Controller
{
	public HomeController() {
		((WebFormViewEngine)ViewEngine).ViewLocator = new LocalizingWebFormViewLocator();
	}

	public ActionResult Index() {
		return RenderView("Index", "Site");
	}

	public ActionResult About() {
		return RenderView("About", "Site");
	}
}

You must also ensure the thread's current UI culture is set. The easiest way to do this is to specify the following in your web.config file's system.web section which will pick it up automatically from the user's browser settings via the HTTP language-accept header.

<globalization responseEncoding="UTF-8" requestEncoding="UTF-8" culture="auto" uiCulture ="auto" />

MVC for ASP.NET default page in pseudo-Japanese via the Babelfish
Then all you need to do is create views and master pages that have the culture name appended between the name and .aspx, e.g:

/Views/Home/Index.aspx (common fall-back for this view)
/Views/Home/Index.ja.aspx (Japanese view)
/Views/Home/Index.en-GB.aspx (British English view)

/Views/Shared/Site.Master (common fall-back for this masterpage)
/Views/Shared/Site.ja.Master (Japanese masterpage)

Caveats

There are some limitations to this solution:

Only primary language is attempted

Only the user's primary language specified in their browser is attempted despite browsers having a complete list in order of preference. Ideally we would scan down this entire list before giving up but that would need more code and there is the issue of whether scanning for several languages across several folders could be too much of a performance hit.

Specifying the masterpage on RenderView

It would be nice if you didn't have to specify the masterpage on renderview but if you do not then the ViewLocator never gets called to resolve the actual masterpage address. This may be for backward compatibility within MVC.

Creating files in Visual Studio

Visual Studio 2008 seems to get a little confused if you create a Index.ja.aspx or Site.ja.aspx - whilst the files are created okay the names are not and you will need to adjust the class names to ensure they don't conflict and make sure the opening declaration on the .aspx file points to the right code-behind page and inherits from the correct name.

Of course the beauty of this approach is you can mix-and-match using dedicated views where required and localising labels in the fall-back view when it isn't.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
24
Apr

Boot Camp 2.1, VMware Fusion 1.1.2 and MacBook Pro firmware

Boot Camp 2.1

Apple have released Boot Camp 2.1 which finally includes official 64-bit support on Vista and support for Windows XP Service Pack 3.

This update may mean that 3D games will play without locking up or installing NVidia's own drivers and that the trackpad functions correctly again (broken since Boot Camp 1.x)

MacBook Pro Firmware 1.5.1

Apple's MacBook Pro Firmware Update 1.5.1 applies to all recent MacBook Pro's including the ones with MBP31.0070.B05 firmware that the 1.5 update failed to upgrade leaving 17" owners on MBP31.0070.B07.

The new firmware does not fix a problem where trackpad input would become jerky after suspending/sleeping and turning Airport off would make it even worse.

VMware Fusion 1.1.2

VMware Fusion 1.1.2 is just out and includes a host of fixes and improvements including:

  • Windows XP Service Pack 3
  • Network and USB compatibility
  • Time Machine compatibility

Now that VMware lets Time Machine backup the VM image file and that Time Machine backs up modified files in their entirety you might want to exclude ~/Documents/Virtual Machines it unless you fancy loosing several gigabytes per hour whilst using a VM. Of course if you have your VM running off it's own partition to allow Boot Camp too then that's not an issue.

With any luck VMware will figure out a way of Time Machine backing up changed individual files within the Windows filesystem...

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
18
Apr

WordPress 2.5 notes from the field

It's been a few weeks since I upgraded to WordPress 2.5 and whilst the upgrade went well it hasn't been all plain sailing.

New and changed

Manage files removed

The Manage > Files administration function has been silently removed despite still appearing in the on-line documentation.

If you don't have FTP access this was the only way to modify your .htaccess and other important files without installing additional software. I can understand such a powerful function could be abused but an option to turn it back on or even a warning about its removal in the upgrade notes/read-me would have been useful.

Hopefully somebody will repackage the old functionality into a plug-in.

New look administration

I'm not sold on the new administration theme look but Dean J Robinson has crafted a plug-in called Fluency that refines the styling.

Generally usability in the administration user interface is better, the write post screen makes a lot more sense and the category & tag management is more logical.

Auto update plug-ins

I love this new feature, it shows you when a new version of a plug-in is available and then lets you automatically update. It isn't without issue however, specifically it:
Screen-shot of WordPress 2.5's automatic plug-in upgrade feature

  1. overwrites modified local versions without warning
  2. may go wrong (it "upgraded" my wp-PostViews to wp-DBManager)
  3. does not provide a roll-back or revert facility

Still it's a v1 feature and I'm sure it'll get some refinement in 2.6.

Compatibility

Live search broken (Redoable theme)

The Ajax-enabled live search is broken in Redoable although the normal search works. There have been no signs of an update in quite despite an un-patched HTML injection vulnerability.

Gregarious

This social bookmarking plug-in is broken in 2.5 and the author is too busy to fix it right now and the search for an alternative led me to Joost and his Sociable plug-in.

I'm not 100% happy with the output from Sociable right now but that can wait until my new theme is finished.

Other tweaks

These weren't caused by the 2.5 upgrade but once you start messing with one thing there's always that urge to fix other things you know aren't right.

Google Analytics

Whilst testing my site I found XHTML compliance was broken. It turns out that Joost's Google Analytics for WordPress incorrectly rewrites the hyperlinks when they parent another element such as an image. Putting on my PHP hacking hat I managed to fix it by editing the plug-in and changing the last line of ga_parse_link to:

return '<a ' . $matches[1] . 'href="' . $matches[2] . '//' . $matches[3] . '"' . ' ' . $coolBit . $matches[4] . '>' . $matches[5] . '</a>';

Subscriber counts

My feed subscriber counts have been bugging me for a while as they jump up and down seemingly at random. In fact, it can be traced down to two things:

  1. If you base it on less than 5 days of activity you'll get the weekend dip
    Solution: Count 7 days worth of individual subscribers
  2. Google Reader etc. sometimes stop passing the subscriber count from time to time
    Solution: Use single most recent multi-subscriber header for each service/feed in the last 30 days

If you want to do the same you need to edit the Feed Statistics plug-in and change the how_many_subscribers function to:

$q = "SELECT subscribers, CASE WHEN subscribers = 1 THEN identifier ELSE CONCAT(identifier, feed) END AS ident
	FROM ".$table_prefix."feed_subscribers  WHERE (
			(subscribers = 1 AND
			date > '".date("Y-m-d H:i:s", time() - (60 * 60 * 24 * get_option("feed_statistics_expiration_days")))."' ) OR
			(subscribers = 1 AND LOCATE('###',identifier) != 0 AND
			date > '".date("Y-m-d H:i:s", time() - (60 * 60 * 24 * get_option("feed_statistics_expiration_days") * 3))."' ) OR
			(subscribers > 1 AND date > '".date("Y-m-d H:i:s", time() - (60 * 60 * 24 * 30 * 3))."' ) )
	ORDER BY ident ASC, date DESC";

This should help but it's not ideal with individual readers counted more than once if they change IP and groups counted as one if they are sharing an IP/NAT.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
17
Apr

Four Windows apps for home-sick Mac users

Libra (like Delicious Library)

Delicious Library is a DVD, game and book organisation tool I've been using since my PowerBook G4 and a 2.0 version has been dangling from Wil Shipley's mouth longer than I care to remember.

Windows users however will find Libra a very interesting clone and it features some of the same great features such as bar-code scanning via a web cam, tracking loans, a rendered virtual shelf and fast queries.

Unlike Delicious Library 1.x it also features sharing your library on-line, tweaking the types and rendering and a more advanced query engine and is available free for non-commercial use.

E Text Editor (like TextMate)

TextMate is a programming editor for the Mac that can be extended through the use of Bundles to provide additional syntax highlighting, menu options and command processing. It is fast, feels lightweight and therefore incredibly customisable all of which contribute to it's success.

E Text Editor is a Windows clone of TextMate that doesn't just mimic the user interface but also provides compatibility with TextMate bundles allowing you to take advantage of some of the many great enhancements available and at $34 is almost half the price although it doesn't feel as snappy as it's Mac counterpart.

Digsby (like Adium)

Adium is my instant messaging client of choice allowing me a single app to manage MSN, ICQ and Google Talk (I wish they would get basic Skype support in there too).

Digsby provides similar functionality whilst also throwing social networking (Facebook, Twitter) and email notification (Hotmail, GMail, Yahoo Mail etc.) into the mix.

Dash (like Quicksilver)

QuickSilver provides a quick keyboard-based entry system for performing a wide variety of tasks and selections within Mac OS X and what it doesn't do can often be added with plug-ins.

Dash achieves a similar effect on Windows but I have to admit I'm not really sold on either yet. I think the movement from keyboard to mouse and back every now and then must be a good break for your hands if not for your productivity...

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
14
Apr

More screen-shots of Envy Code R preview #7

Work on my Envy Code R programming font has resumed and I've spent hours playing with the hinting process to ensure it looks good at sizes above and below 10 point:

Screen-shot of Envy Code R PR7 without smoothing on WindowsScreen-shot of Envy Code R PR7 with standard smoothing on WindowsScreen-shot of Envy Code R PR7 with ClearType on Windows

These look great - even more so when you consider there are no embedded bitmaps and very few delta hints.

There is still a lot of work to do - all the foreign characters, symbols and box-drawing characters (another 600 glyphs) require hinting and I should test it on the Mac, Java and Flash font rendering engines to make sure there are no show-stoppers there.

Preview 7 will consist of of just a plain style regular and bold because I need to get this out - it's been too long since the last release. Preview 8 will add back italics and the Visual Studio italics-as-bold hack shortly afterwards.

Check out Talios's shots using Java/Linux and Eddy Young's shots in NetBeans.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
10
Apr

Using LINQ to foreach over an enum in C#

I can't be the only person in the world who wants to foreach over the values of an enum otherwise Enum.GetValues(Type enumType) wouldn't exist in the framework. Alas it didn't get any generics love in .NET 2.0 and unhelpfully returns an array.

Thanks to the power of LINQ you can do this:

foreach(CustomerTypes customerType in Enum.GetValues(typeof(CustomerTypes)).Cast<CustomerTypes>())

That is okay, but this is more concise:

foreach(CustomerTypes customerType in Enums.Get<CustomerTypes>())

The tiny class to achieve that is, of course:

using System.Collections.Generic;
using System.Linq;

public static class Enums {
	public static IEnumerable<T> Get<T>() {
		return System.Enum.GetValues(typeof(T)).Cast<T>();
	}
}

Great.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
07
Apr

Calendar spam, the next nuisance?

Tomorrow morning at 5am where I can enjoy an advanced fee scam! I've had these in email format before but never in my calendar...

Screen-shot of some spam in my calendar

Oddly there are no emails about this in my inbox and I sure didn't tell it to add one to my calendar. As there is no 'Report Spam' link for calendar entries I had to return to calendar view, delete it from there and hope nothing else shows up.

Digital Inspiration also wrote about this and provide a link to Google's spam reporting page.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail
02
Apr

Windows 2008 Server on my MacBook Pro

A troublesome disk (a story for another time) has forced me to reinstall my MacBook Pro and review my Windows partition.

My Boot Camp partition was running Vista Ultimate x86 which felt sluggish, ignored the last 1GB and bugged me with UAC. One Windows update kept failing to install which also prevented SP1 from completing.

Apple's Boot Camp doesn't support 64-bit Windows (except on the Mac Pro) and my 64-bit experiences have been unpleasant so far (no Flash for IE x64, limited 64-bit shell extensions, Live! refusing to install, drivers etc.) The increased x64 memory consumption would also be an issue when running in a 1.5GB virtual machine via Parallels or VMware Fusion.

Windows XP was one option but losing IIS7 and DirectX 10 would see me reinstalling Vista within weeks so I decided to try Windows 2008 Server x86.

Boot Camp happily accepted the 2008 Server x86 CD where I chose the BOOTCAMP partition, formatting it as NTFS and electing for a standard installation. The Boot Camp drivers subsequently installed without complaint, all 4GB of RAM was accessible and there are no 64-bit compatibility issues.

Microsoft are giving away 1 year evaluation copies of Windows 2008 Enterprise Server x86 as part of their Heroes Happen Here launch program for Windows 2008, SQL Server 2008 and Visual Studio 2008 if you don't happen to have an MSDN subscription to hand. There are however a few tweaks you need to do to get a more desktop-like experience:

Install desktop features

Head into Server Manager and Add Features then choose Desktop Experience to install Windows Media Player, Aero etc.

Go into Services and set the Themes service to Automatic and Start it to make themes available and then choose Browse... from the Theme Settings in Personalisation to select %windir%\Resources\Themes\Aero.theme

Install wireless networking

This one had me stumped for a while as I thought my wireless card/drivers weren't working. The reality is that 2008 Server has wireless networking removed by default so head into Server Manager > Add Features > Wireless LAN Service to install it.

Enabling hibernate

Open a command prompt and enter:

powercfg.exe /hibernate on

Remove annoying shutdown

Head into the registry to HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability and change the ShutdownReasonOn DWORD key to 0.

Relaxing local password policy

A controversial change I'm sure but I'd rather choose something complex and unique that will last 90+ days than something memorable every 30. Head into Local Security Policy > Account Policies > Password Policy > Maximum password age and change it to something more reasonable.

Going further

A great guide with screen-shots on additional tweaks for a more workstation-like experience also exists - wish I known about that earlier!

Simone Chiaretta has highlighted the that tap-to-click is absent and there are some Bluetooth issues stemming from missing drivers.

[)amien

Share with others These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • DotNetKicks
  • StumbleUpon
  • DZone
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • Technorati
  • e-mail




Feed subscription

Subjects