Resource Files and ASP.NET MVC Projects

Thursday, July 16, 2009 by K. Scott Allen
28 comments

If you try some of the traditional ASP.NET approaches to localization and internationalization in an MVC application you’re likely to run into a couple interesting* obstacles.

Resx Files In App_GlobalResources

Using resource files in App_GlobalResources from your controller code will break your unit tests.

When you drop a .resx file in the special App_GlobalResources folder, the IDE uses the GlobalResourceProxyGenerator to generate a strongly typed internal class to wrap the resources inside. The internal class gives any code in the MVC project access to the resources:

var greeting = Resources.Strings.Greeting;

You can also use the resources from a view:

<%= Html.Encode(Resources.Strings.Greeting) %>

The problem is that global resources are not actually embedded into the project’s .dll. Instead it is the ASP.NET runtime that creates an App_GlobalResources assembly with the resources inside. This assembly is referenced by all the view assemblies ASP.NET creates, and is explicitly loaded by the strongly typed wrapper generated by the GlobalResourceProxyGenerator. Since the App_GlobalResources assembly doesn’t exist without an ASP.NET compilation phase, it’s not available when unit tests are running. Controller code under test that tries to access the resources will bomb with an exception.

Note that you’ll also have some Intellisense problems when using the view syntax shown above. I'm guessing this is because the IDE is confused by seeing the resource wrapper in two places (the project assembly, and a wrapper also goes into the App_GlobalResource created by ASP.NET in the Temporary ASP.NET Files folder. ).

There is a way to make resx files in App_GlobalResources work, but the folder isn’t truly necessary in an MVC project (or a web application project, for that matter). I think it’s just as easy to add resx files in a different location, even a separate class library, to avoid any confusion on how App_GlobalResources will behave.

In short: avoid App_GlobalResources and App_LocalResources (which has its own set of problems) in MVC.

Resx Files Outside Of Special Resource Directoriesresx properties in MVC

If you add a resx file to any other folder in an MVC project or class library, the resx is automatically set to be embedded into the project’s output assembly - this is good. The IDE also assigns the resx a custom tool of ResxCodeFileGenerator to generate a strongly typed wrapper - this is good. The generated class is internal by default – this is bad. The assembly created for a view (by ASP.NET) won’t be able to use the internal class because it is in a different assembly – the project assembly compiled in Visual Studio.

Solution

The easy fix is to make sure the custom tool is set to  PublicResXFileCodeGenerator instead of ResXCodeFileGenerator. You can do this in the property window for the file, or in the resource editor that gives you a drop down for “Access Modifer” (the options are Internal, Public, and No Code Generation – choose Public).

You can also set the “Custom Tool Namespace” for the generated wrapper in the properties window. My suggestion is to use a convention like “Resources” for global resources, and “Resources.Controller.View” for resources dedicated to a specific view.

This approach means you can use the resources in unit-testable controller code, and in views, too. The syntax remains the same as above. The ResouceManager used in the wrapper classes can automatically resolve the proper resource to use depending on the current UI culture setting of the thread.

Setting The UI Culture

The easiest approach to having the correct UI culture in effect during web request processing is to use the globalization section of web.config.

<globalization uiCulture="auto" culture="auto"/>

The above will set both the current UI culture and current culture settings for the request. See Dennis Dietrich’s post for a good explanation of the two settings: YACVCP (Yet another CurrentCulture vs. CurrentUICulture post).

If you need to set the culture up according to a user’s preference, or a URL parameter, then the best bet is to write a custom HTTP module or action filter.

* Interesting only if you consider localization and resource files interesting, in which case you might need to take some medication.

Geeky Places to Visit In &amp; Near Maryland

Thursday, July 9, 2009 by scott
3 comments

Maryland has a number of geek attractions inside and around its borders. Here’s a sampling:

National Air & Space Museum

There are two locations to visit. The museum on the National Mall is in the heart of D.C. and features over 20 exhibition galleries that include an Apollo 11 command module, lunar rocks, IMAX theater, and planetarium. For truly colossal exhibits you’ll want to head ~22 miles out of town to the Steven F. Udvar-Hazy Center. Located just off the approach to Dulles airport’s runway 1R, the museum includes the space shuttle Enterprise, and an SR-71 Blackbird. You shouldn’t need any more reasons to go.

National Cryptologic Museumcryptologic museum

Nothing says “hard core geek” more than spending time in a museum dedicated to cryptology. The museum is located within electronic eavesdropping range* of the NSA headquarters on a drab stretch of Route 32. But inside you’ll find many compelling exhibits and intriguing devices, like a Jefferson cipher wheel, an Enigma machine, and a Cray Y-MP supercomputer that could hold 32 GB of memory … in 1993.

You don’t need a password to get in.

Goddard Space Flight Center

It’s a little bit of NASA just outside the D.C. beltway in Greenbelt, MD. Exhibits include a rocket garden, a spherical movie screen,  and a sycamore tree grown from a seed that went to the moon and back with Apollo 14 in 1971. Model rocket launching on the first Sunday of every month!

Maryland Science Center

The MSC sits diagonally across the water from the National Aquarium in Baltimore’s inner harbor. It was voted as one of the 10 best science centers for families by Parents’ magazine and includes interactive exhibits that range from the cells inside us, to the stars around us. The aquarium on the other side of the harbor is top notch, too, with great food and other sights in between.

Western Maryland Scenic Railroad

What’s so geeky about a scenic railroad ride in the mountains? In short: steam power, bridges, tunnels, and turn tables. As a kid I found myself absolutely astounded by the fact that steam (which I thought of then as really hot water), could propel such massive weight. There are also murder mystery trains on the weekends, which is just as geeky as D&D, but without the 20 sided die rolling.

U.S. Army Ordnance Museum

The museum is located on the Aberdeen Proving Ground and contains a formidable number of engineering marvels with German, Soviet, Japanese, American, and Italian tanks and artillery pieces. An exhibit both extraordinary and sobering. The museum is relocating to southern Virginia in 2011.

* This would be them eavesdropping on you, as I wouldn’t recommend the reverse approach.

Event Aggregation with jQuery

Tuesday, July 7, 2009 by scott
3 comments

As the “write less, do more” library, jQuery garners lots of love for its terseness. The terseness, combined with a rich ecosystem of plug-ins, means I can display my OdeToCode twitter feed on a web page using only 10 lines of code (complete with animation and custom loading message)*.

$(function() {
    $("#getTweets").click(function() {
        $("#tweets").getTwitter({
            userName: $("#screenname").val(),
            numTweets: 10,
            loaderText: "Fetching tweets...",
            slideIn: true,
            showHeading: true,
            headingText: "Latest Tweets",
            showProfileLink: true
        });
        return false;
    });
});

When writing with jQuery there is a tendency to use nested functions and collapse as many responsibilities as possible into a single piece of code. For many web pages this approach is entirely suitable.We aren’t building a space shuttle - it’s just a web page. The code above is responsible for locating the DOM element for events, hooking up a click event, fetching tweets, and locating the DOM element to display the tweets.

Composite UIs

In more complex pages, and particularly in composite pages that are made up from independent pieces, the above approach tends to become brittle, and encapsulation breaks down as independent pieces try to peek into each other’s private business. It’s easy to fall into black hole of JavaScript code that swallows all who come near. A step away from the black hole would be to extract some of the common, reusable functionality into different pieces.

For example, you can separate the piece that knows about DOM elements …

$(function() {
    $("#getTweets").click(function() {
        getTweets($("#tweets"), $("#screenname").val());
        return false;
    });
});

… from the piece that knows about Twitter, and include the pieces independently …

function getTweets(element, screenname) {
    $(element).getTwitter({
        userName: screenname,
        numTweets: 10,
        loaderText: "Loading tweets...",
        slideIn: true,
        showHeading: true,
        headingText: "Latest Tweets",
        showProfileLink: true
    });
}

Now we have a bit of separation. At this point some of us would be inclined to raise the battle cry of the object oriented programmer, and run off to a workstation to design  namespaces, prototypes, constructor functions,  properties – blah blah blah**. But we wouldn’t be creating a greater separation between the pieces of code. All we’d really be doing is creating bigger abstractions that are still tied together as closely as they were when they were simple function objects.

Enter The Aggregator

One of the classes I dig in Prism is the EventAggregator. Eventing is pretty much a required approach to managing a composite UI if you want to stay sane. The EventAggregator makes this easy in WPF and SIlverlight, and includes some thread marshalling tricks behind the scenes as a bonus.

Fortunately, you can do something similar in most major JavaScript frameworks, including jQuery. There are jQuery plugins dedicated to event aggregating, but a simple approach would use bind and trigger with custom events, letting the document serve as the aggregator.

Now we can achieve a greater decoupling between the “I need tweets” action …

$(function() {
    $("#getTweets").click(function() {
        $(document).trigger("fetchTweets", [$("#tweets"), $("#screenname").val()]);
        return false;
    });
});

… and the piece (or pieces) that will respond to such an action…

$(document).bind("fetchTweets", function(e, element, screenname) {
    $(element).getTwitter({
        userName: screenname,
        numTweets: 10,
        loaderText: "Loading tweets...",
        slideIn: true,
        showHeading: true,
        headingText: "Latest Tweets",
        showProfileLink: true
    });
});

It’s easy to layer in additional behavior to the “Get Tweets” button click. We could call a web service to save the user’s preferences. We could cache information. We could add some debugging info …

$(document).bind("fetchTweets", function(e, element, screenname) {
    console.log(screenname);
});

All these things could be done by including separate scripts, and without putting any knowledge of these actions inside the click event handler where the aggregated event begins. Of course, to complete the circle, the code should raise an event when the tweets are retrieved, and let someone else deal with the results.

* Most excellent Twitter plug-in is available from @code_za’s blog.

** I’m not saying that bending prototypes to act like classes is bad, it’s just not the solution to every problem.

Pretty Code #1 – Building SelectListItems

Friday, July 3, 2009 by scott
18 comments

In ASP.NET MVC, you can use a collection of SelectListItems to help build an HTML

Tonight, you’ll be the judge in this first contest of charm, grace, and readability.

Contestant #1 hails from the System.Web.Mvc namespace. It likes pina coladas and string literals, but is turned off by tattoos that look like programming symbols. Let me introduce the SelectList class:

var products = GetProducts();
var selectItems = new SelectList(products, "ID", "Name");

Contestant #2 lives in the System.Linq namespace. It likes whips and method chains. Functional programmers call it “map”, but in .NET we call it "Select":

var selectItems = from product in GetProducts()
                  select new SelectListItem 
                  {
                      Text = product.Name,
                      Value = product.ID.ToString()
                  };

… or (from the backside) …
var selectList = GetProducts().Select(product =>
                    new SelectListItem
                    {
                        Value = product.ID.ToString(),
                        Text = product.Name 
                    });

Contestant #3 lives in the MvcContrib project. It’s turned on by pointy things and practices yoga for extensibility. Introducing the ToSelectList method:

var selectItems = GetProducts().ToSelectList(product => product.ID,
                                             product => product.Name);

Personally, I like #2. While the name of #3 makes its purpose obvious, it sometimes takes a moment to be 100% clear about what property becomes Text, and what property becomes Value. In #2 the Text and Value assignments are obvious, even though the code is a little longer. Setting the Selected properties with either approach is trivial.

What do you think?

Three IIS Concepts ASP.NET Developers Should Know

Wednesday, July 1, 2009 by scott
7 comments

It’s possible to do a lot of work with ASP.NET and not know anything about IIS, particularly if you work with a large team where IT specialists keep the riff-raff away from production web applications. Ever since Visual Studio started shipping its own web server1, many people don’t rely on IIS for day to day development work (although many of us still do).

For those of you who are just learning how to deploy in IIS, or those of you who need a refresher, I put together a short and free Pluralsight screen cast on IIS: Web Sites, Applications, and Virtual Directories in IIS

This is one video in a collection of screencasts from Pluralsight.

1) Some people call the web server “Cassini”. Other people call it the “WebDev” server. Still others call it “the web thingy that sits in my system tray”, even though Windows doesn’t have a system tray, but whatever. If you worked with the first release of Visual Studio, you’ll know we’ve come a long way from running as an administrator with Front Page Extensions installed and the IDE trying to force all of our code to live underneath inetpub\wwwroot <shudder />.

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!