If you’ve purposefully been ignoring the announcements out of PDC, I don’t blame you one bit. Everybody knew it would be the unveiling of Microsoft’s “cloud computing” initiative, and just about the only thing we didn’t know was the official name of it: Windows Azure. And of course I pronounce it wrong every time (I say “ah-jour”, as in “soup-de-jour”). It’s hard to call it “initiative” when they’re the 3rd one to bring a product to the table. ;)

One thing I was looking forward to was hearing about the ASP.NET MVC story on Azure. So color me surprised when I found out there wasn’t one. Since ASP.NET MVC is bin-deployable it shouldn’t be impossible, and doing some quick searches didn’t retrieve any results showing anybody else having tried this. Of course later I discovered that Phil and Eilon had whipped up a sample app that ran ASP.NET MVC on Azure, but was pleased to find out that the downloadable sample app didn’t work. In fact, it seemed to just be MVC stuff slapped into a WebRole project. (I’m guessing something got “lost in translation” since it wasn’t Phil or Eilon that posted the code.)

Anyway, here’s how you can get ASP.NET MVC up and running on Azure. I’ve created a Visual Studio template for this to make it easy to set up - download it here. To avoid distributing code that isn’t my own (i.e. Windows Azure SDK Samples) there are a few steps you’ll have to take. I’m presuming that you’ve already installed the Windows Azure SDK and the Azure Visual Studio tools.

One thing that running a web application “in the cloud” means is that you can instantly scale higher by adding more “instances”. This means the leaky-as-a-sieve abstraction of “session state” isn’t immediately available (finally!) since any given HTTP request could be going to a different server. The default session state provider for ASP.NET is an in-memory provider. This assumes that every request comes to the same physical machine. Session state providers have varied in their reliability and handling of scalability, but the other built-in providers include an out-of-proc provider (still same machine, but more resilient to IIS going up and down) and a SQL Server provider. None of these are enabled on the Azure platform, for good reason.

The limitation of zero session state wouldn’t matter except that ASP.NET MVC includes the concept of “Temp Data”, which is data persisted in one request and made available to the next request only. By default, MVC uses the session to store this data.

Aside: like it does everywhere else, ASP.NET MVC allows you to swap out default implementations for TempData persistence. A better solution than what I have below is to specifically implement a TempDataProvider that uses the Azure data storage capabilities. Look for that soon. ;)

Fortunately for us the Windows Azure SDK includes some “samples”, including full implementations of membership, profile, and session providers built on the Azure data storage platform. So let’s hack those in to fulfill the default requirements of ASP.NET MVC. The only thing that I’ll say about this is that much of this stuff had better be baked into the SDK/platform by the time it goes GA. This is just a CTP, and Microsoft has been doing better at earlier community releases, so I’ll cut them some slack. ;) But this is way to much work to be a reasonable shipped solution.

Unzip the “samples.zip” file in the Azure SDK and build the “AspProviders” application.

They’ve conveniently included “buildme.cmd” batch files, but I built the application using Visual Studio since I like to see more of “what’s going on” (even though I really don’t see more, per se).

Create the required tables in the Azure Development Storage.

Open the Azure SDK command prompt under your start menu, and navigate to the directory containing the AspProviders output. Run the command “devtablegen” passing in the assembly name “AspProviders.dll”. This command creates the appropriate database structures to persist objects that meet certain criteria. Run devtablegen with no parameters for a short description, or check out the documentation for more info as well.

You’ll get a confirmation window that displays progress and shows that the table was created successfully.

Start the Development Storage service.

By now, the storage service should be running, but you’ll need to explicitly enable its endpoints. Open the UI from the system tray icon (), and click “Start”. If you’ve never started it before, it will ask you for the name of the database – select “AspProviders”.

Create a new Cloud Service and add an “ASP.NET MVC Web Role” project.

Download the Visual Studio template I created here. Import the template by copying the downloaded .zip file to “My Documents\Visual Studio 2008\Templates\Project Templates” (or whatever you have specified in Tools – Options – Projects and Solutions – General). Create a new “Blank Cloud Service” project.

 

Add a new “ASP.NET MVC Web Role” project using the installed template.

Your VS solution should now approximate this:

Under the “Cloud Service” project, right-click on the “Roles” folder and select “Add > Web Role Project in solution…” and select the web role project we just added.

Cleanup

Because I can’t distribute the compiled version of the sample app, and because the location of it on your drive depends entirely on your personal preferences, you’ll have to re-add the references manually. From the ASP.NET MVC Web Role project we added, delete the references to AspProviders and StorageClient

and re-add the references pointing to the assemblies we built above.

Press F5, and you’re up and running the default ASP.NET MVC sample app on the Windows Azure platform! From there the sky’s the limit. Or maybe “the cloud’s the limit”?

With much fanfare Apple announced the availability of the iPhone SDK. I downloaded it and someday plan to play around with it, though with the SDK already having gone through 4 or 5 beta releases (each a ~2GB download) I’ll probably wait a long time before cracking it open. However, for web applications the best way to integrate with an iPhone is still through the browser.

Unfortunately Apple didn't provide much help in the form of html or css to make your website "iPhone-y". They provide documentation on elements like iPhone specific events ("onorientationchange") and details about how Safari works on the iPhone in terms of zooming, etc., but nothing that offers guidance on how to make an application look like it belongs on the iPhone.

Enter Joe Hewitt and iUI. iUI takes HTML that follows a simple set of conventions and does all the heavy lifting to enable you to easily build a version of your site that is tailored for the iPhone experience. I first started using iUI before ASP.NET MVC was publicly introduced, and I specifically remember thinking how much iUI was built for "webforms unplugged". Let's take a quick look at an example of how iUI works, and how to use it with ASP.NET MVC.

If you’re the type that likes to get their hands dirty first, download the code here.

CSS Zen Garden

iUI is literally nothing more than some javascript, some css, and a bunch of image assets. It’s how things are supposed to work with HTML and it’s beautiful, like the CSS Zen Garden. It also has some simple conventions that I’ll summarize like so: “write HTML the way it was intended”. <ul> or <ol> for lists, and <div> or <form> for dialogs and pages. Easy enough, right? There’s not a ton to iUI but for this post I’ll start simple. Let’s create a list of products that we want to display like so:

This is the HTML behind the list itself (not including the top toolbar, though the “title” attribute of the list controls the text shown in the center of the toolbar):

<ul id="products" title="Products">
    <li><a href="/products/index/1">Alice Mutton</a></li>
    <li><a href="/products/index/2">Aniseed Syrup</a></li>
    <li><a href="/products/index/3">Boston Crab Meat</a></li>
    <li><a href="/products/index/4">Camembert Pierrot</a></li>
    <li><a href="/products/index/5">Carnarvon Tigers</a></li>
    <li><a href="/products/index/6">Chai</a></li>
    <li><a href="/products/index/7">Chang</a></li>
    <li><a href="/products/index/8">Chartreuse verte</a></li>
</ul>

iUI does the heavy lifting to format the list in the iPhone style, and will dynamically load any linked content using an AJAX call and render it in-place, replacing the current list (“products”). iUI handles sliding in the new content from the right-hand side, just like a native iPhone application.

You could also reference another list defined within the same page, for example if you had a very short list of items and had each list item’s “linked content” also included in the page, like this:

<ul id="products" title="Products">
    <li><a href="#subproduct1">Product 1</a></li>
</ul>

<ul id="subproduct1" title="Related Products">
   <li>Sub Item 1</li>
   <li>Sub Item 2</li>
</ul>

The Root Page

iUI will dynamically render partial content into the current view, but it needs an initial root page describing the main layout. The easiest way to figure out what is needed is to look at one of the examples that iUI includes, but in a nutshell you’ll probably need at least two elements: the toolbar (the heading) and some content. To support the example above of a product list, our entire root page could look like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Northwind Explorer</title>
    <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
    <style type="text/css" media="screen">@import "../../Content/iui/iui.css";</style>
    <script type="application/x-javascript" src="../../Content/iui/iui.js"></script>
</head>
<body>
    <div class="toolbar">
        <h1 id="pageTitle"></h1>
        <a id="backButton" class="button" href="#"></a>
    </div>
    <ul id="products" title="Products" selected="true">
        <li><a href="/products/index/1">Alice Mutton</a></li>
        <li><a href="/products/index/2">Aniseed Syrup</a></li>
        <li><a href="/products/index/3">Boston Crab Meat</a></li>
        <li><a href="/products/index/4">Camembert Pierrot</a></li>
        <li><a href="/products/index/5">Carnarvon Tigers</a></li>
        <li><a href="/products/index/6">Chai</a></li>
        <li><a href="/products/index/7">Chang</a></li>
        <li><a href="/products/index/8">Chartreuse verte</a></li>
    </ul>
</body>
</html>

The site will initially show the list of products, and when the user clicks on a product, the <ul id=”products” title=”Products” selected=”true”>…</ul> element will be wholesale replaced with the content loaded by an AJAX call to “/products/index/[number]”.

Hooking up iUI to MVC

First things first - download the latest iUI assets from the google code repository trunk. You'll get the latest bug fixes and features, which I've found to be helpful. As a side note, you can view some samples directly from the repository itself - like the music example. Put the downloaded files in the Content directory:

Define your main page—the main entry point to the site. I chose /home/index in my example. This is where you’ll reference the iUI javascript and css assets, and define the initial structure of your page.

One big catch that I already mentioned with iUI is that it expects links (whether AJAX-loaded or in-page references) to return HTML fragments. It literally takes the results of an AJAX call to a given URL and sets the innerHTML of the content to replace.

This means that every other page in our application should return partial content. For example, when I click on “Products” this is the only content of the view page that lists the products:

As you can see, it’s simply building the list itself and rendering the partial HTML content as a response.

You can connect with an iPhone on your local network with a wifi connection, but it’s much easier to install and test with Safari for Windows. Both Safari for Windows and the iPhone’s mobile Safari use the WebKit engine so the rendering experience is about as close as you can get. Shrink the browser to approximately the size of the iPhone screen and you’d never know you didn’t spend the $400+ on an iPhone. ;)

You can download the first version of my example project here.

Up Next

In future posts I’ll explore some more of iUI’s features such as adding a product page to view details of a product in a friendly way (I’ve included this in the example project already), rendering partial lists (allowing the user to expand the list incrementally), detecting the user agent and loading iPhone views vs. “normal” views, and more. I’ll update the example project as we go!

The Indy Code Camp's schedule was just published. If you were waiting to register until you could see what kind of content would be available, now is the time! We have 24 sessions with a wide range of topics. It should be a great day! I'm very pleased with the turn out of presenters and topics. When I started thinking about the code camp a while ago, I thought a good event would include six sessions - let's just say my expectations have been exceeded yet again.

We've got room for a maximum of 250 people, and I can tell you that the registration list is filling up - so hurry up and register if you are even thinking about coming.

I'm also working to organize a fairly informal "after party" at the local sports bar - leave a comment here if you would be interested in coming. I need to gauge a general interest level. :)

See you there!

About a month and a half ago Ben Scheirman wrote about testing TempData in ASP.NET MVC. It's good stuff, and aside from changes between Preview 1 and Preview 2, it still works fine. (See Scott Hanselman's post for some Preview 2-friendly mock helpers using Rhino Mocks.)

While I can easily understand what Ben's code is doing, what I couldn't figure out is why it worked. If you reflect over TempDataDictionary (the type of the Controller.TempData property), you'll see that the data type it persists to the session is an internal structure.

Ben's code, however, mocks out the Session to return the expected TempDataDictionary object. By all counts, that should fail, since the TempDataDictionary won't be getting back the values it expects--it expects the internal map structure.

Well, it turns out I was glossing over one very important fact. TempDataDictionary was written to be smart enough that if the underlying session store either didn't work, or didn't provide the right data, TempData will continue to operate as normal--for the current request only. You can see below that if the session data was null or wasn't the right type, it just creates a new internal map.


(image cut off for space)

One of the benefits of TempData is the cross-request persistence via the session. You might not have known it, but when you call RedirectToAction in your controller action, for example, it's actually resulting in a 300-level HTTP redirect, which means an entirely new HttpContext for the next request. It's basically deferring to the browser to perform the redirect.

So, while Ben's code will definitely work, here's an extension method that can help with mocking out the session a little more "correctly":

public static void NullifySessionState(this HttpSessionStateBase session)
{
    SetupResult.For(session[null]).IgnoreArguments().Return(null);
    session[null] = null;
    LastCall.IgnoreArguments();
}

Administrative note: I used to maintain two RSS feeds. One for weblogs.asp.net/aaronlerch, and the other for www.aaronlerch.com/blog. I've decided that's dumb, as the content between the two is nearly exactly the same. So, if you subscribe to my weblogs.asp.net feed, it should be automatically redirected, at which point it'll be like you subscribed to my main site. Again, the content is the same, just a little more of it (a very little more).

Hopefully you have no interruptions--but if you do, let me know in the comments here. If you really really care, for some weird reason, and want them separate (and have a good reason), let me know that too.

Cordially,
The Management 

Tim Heuer announced today the release of "S3 Browser", a plug-in for Windows Live Writer that enables easy inserting of links or images from your S3 storage. See his announcement on his blog, and on the Code Trip's blog.

Like Tim, I've been using S3 to host my images for the blog, and I wholeheartedly agree with him - the workflow for writing a post sucked big time. This plug-in had been on my //TODO list for a long while now. Somehow I mentioned that fact to Tim on Twitter and he sent me a link to a screenshot of his initial version. My response? Sign me up!

He uploaded his source to CodePlex and I immediately started implementing the remaining features. The result is the 0.9 beta release of the S3 Browser Windows Live Writer plug-in. Give it a download and try it out! Please submit any feature ideas or bugs on the codeplex site, or you can leave a comment here as well.

A while ago I mentioned a crazy idea about hosting an Indianapolis-based Code Camp. As I worked out that idea, I needed help. It turns out some others had been thinking about it too, and we joined efforts.

It's my pleasure to announce that the Indy Code Camp is officially scheduled for Saturday, April 26th, 2008.

I'm also happy to announce our call for speakers. We welcome all session proposals, for any technology or language. I know the local Ruby and Java user groups have expressed interest in participating. I'm hoping this will be a very well rounded, very deep technical event. No marketing fluff. Just code. Register to attend, and submit a session proposal!

The number of sessions will depend on the number of proposals we receive, but we have the capacity to handle up to about 4x6 == 24 sessions, each 70-minutes long. That's room for a ton of great content.

I've been working on the CodeCampServer open source ASP.NET MVC project with hopes we'd have something functional ready, but alas it didn't materialize in time. Next year... I'd like to give a shout out to Dave Leininger for getting the current site up and running quickly. And also to the Indy .NET Developer's Association folks for being willing to work with me to make this event a reality.

See you on April 26th!

Technorati Tags: , ,

Frequently in web applications there's a requirement like this: "Every page should display [foo]." Where "foo" can be literally anything: a list of favorites, sponsors, news, or whatever - it's data. In what I'll call "normal, by a long shot" ASP.NET cases, universally displayed data will probably be encapsulated in a user control and put on a master page. The master page includes the user control on all pages, and the user control loads the data and renders it, and it was all declared Good.

The MVC world (ASP.NET "unplugged") turns everything on it's head. Maintaining a clean separation of concerns means the controller is responsible for ensuring the appropriate data is made available to the appropriate view. The view does not load data on it's own, nor does it know or care where the data came from. And the view was declared Dumb.

Views aren't really dumb, of course, they have to render data, and the MVC framework does give them some tools to help. For example, the ViewMasterPage base class exposes helpers for constructing links, accessing the view data, etc.

So what do you do in the ASP.NET MVC world when you've got a "user control" embedded in your master page that needs specific data? Let's say that hypothetically speaking you're working on a CodeCampServer project, and you need to, oh I don't know, display a list of code camp Sponsors (ahem, "Contributors") on every single page?

The way I see it, you've got three options:

1. "Global" data for global display

Data can be loaded at a low level for each and every request. Something like:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    this.Context.Items["FooData"] = new FooData();
}

The pro is that FooData will be available to every view (though not through the standard ViewData). Unfortunately if this data is expensive to compute (or even if it isn't) it'll be loaded for every request, no matter what. Oh, and no one in their right mind would actually do it this way. :) There's that, too.

2. Controller.OnPreAction

The main Controller class exposes a virtual OnPreAction method which offers a hook just before an action is invoked. For global data, all controllers in your application could derive from a common base controller class which loads the necessary data.

protected override bool OnPreAction(string actionName, System.Reflection.MethodInfo methodInfo)
{
    ViewData["FooData"] = new FooData();
    return base.OnPreAction(actionName, methodInfo);
}

Views will be able to access the data via the ViewData property, as normal. With single inheritance in C#, a required base class just for common data can potentially cause problems.

3. Call "RenderAction" from the view

RenderAction is an extension method that allows a view to reference a Controller and Action and have the results be rendered in-place within the view.

The "Tags" controller and "Cloud" action would render a view that generated an HTML fragment that would fit within the current view. This approach has advantages of only loading data when absolutely necessary and changing your view doesn't necessarily require changing the application code to match.

There could be questions about separation of concerns: a view is determining what data to include regardless of what it's controller gave it. But the same is true for the other solutions as well - this is just more dynamic.

Another advantage to this approach is that if you set it up right, with no extra work your "viewlets" (the views that render fragments) can return JSON serialized data for an AJAX call, for example.

I'm pro-RenderAction, but in discussions I've had with people it hasn't been as big a hit with them. What are your thoughts? Am I missing some pros or cons? Are there more options that I didn't include? Is it really just an app-by-app decision, or is there an emerging convention that should be followed?

It's amazing how the process of making an application localizable can be both simple and confusing at the same time. At a basic level, the Visual Studio designer makes it very easy. Set the "Localizable" property on your form to True and you're good to go. It's very convenient.

On the other hand, there are a lot of challenges like poorly named properties, confusing defaults, and possibly unexpected behavior. You really need to understand what's going on under the covers.

For instance, if you've looked into .NET localizability at all, you probably know that by default resources are loaded using the CultureInfo retrieved from the System.Threading.Thread.CurrentThread.CurrentUICulture property. That's why most guidance for manually changing the default application UI language says to set that property to a value of your choice. And well you should - it's the only way to override the default language settings for your Windows Forms.

See, the Windows Forms designer automatically generates all sorts of useful code that you can't (and shouldn't) touch. Here's an example.

image

Notice the ComponentResourceManager? It's a local variable in the InitializeComponent method. The only way to alter it's behavior is to alter the current thread's UI culture information.

So that's great, and even better it's easy. When your application starts, you can load culture/language information from whatever persistence mechanism you prefer, and essentially "set it and forget it", since all Controls should be created on the same thread.

image

But there's one problem with this: it only applies to UI elements (Controls).

It's also common to load objects outside the context of the UI, perhaps with the intention of later presenting them to the user, or persisting to a file, or something else "user visible". For this, you can add an arbitrary number of resx files that contain images, strings, serialized objects, etc.

image

With Visual Studio 2005 and higher, these resources are available as strongly-typed properties, giving you compile-time checking and ease of use.

image

But here's where our problem comes in. Overriding the default UI culture on the main thread applies only to that thread. If you load any resources from a background thread of any kind, they will be the resources for the default windows UI language.

The strongly-typed class ("Resources", in my example) offers us some relief, however, in the form of a static "Culture" property on the auto generated class. If you never touch the property, resources will be loaded using the current thread value. But if you assign your own value, you can explicitly control which resources are loaded.

Consider this debugging example where I'm stopped in the execution of a background thread. I've created a global static "Localization" class with a "CurrentCulture" property that I use to maintain the current UI language for my application. You can compare and contrast the values set for the current thread and the auto generated Resource static class, which my application has initialized. (I'm running the English UI for Windows, by the way.)

image

So, why am I posting this? Because I myself was unsure about how to correctly accomplish the goal of enabling users to select their own UI language until I noticed the auto generated "Culture" property on the Resources class. And it took me embarrassingly long to find it. Hopefully this post keeps somebody else from wasting an evening, or more.

In summary, it's actually simple once you understand all the details. To enable a specific "non-default" language in your application:

  • Set the System.Threading.Thread.CurrentThread.CurrentUICulture property to the appropriate culture, and
  • Initialize all auto generated resource classes (or any custom uses of the ResourceManager class) to the appropriate culture, before loading any resources.

imageVisual Studio 2005 and 2008 have built-in support for refactoring code, including renaming namespaces, classes, variables, and more. Add-ins like Resharper also have support for refactoring by renaming. These tools work great, and have good integration into the Visual Studio IDE, for example being able to preview each change and exclude false positive matches. I know many people swear by Resharper in particular (for more features than the refactoring alone).

Unfortunately all of these tools are restricted in one normally insignificant way: they only operate on the currently loaded project(s). For most software this really is insignificant. The entire application can be loaded into the IDE all at once. Sometimes, though, it is a problem--usually when there's another problem at play: code "bloat" (via Jeff).

If you've ever changed a namespace and wanted to simply push the change into every code file in an entire directory branch, PowerShell comes to our rescue with it's search-and-replace capabilities. I wrote the following "Move-Namespace" function to do just that.

Invoke the function like so: "Move-Namespace *.cs "[current namespace]" "[current class name]" "[new namespace]".

After it completes, any explicit reference will be changed, and any implicit references (using traditional "using [namespace];" statements) will have a new "using [new namespace];" line inserted after the last existing using statement.

Let's hope you don't have a code base that requires this function. :) But if you do, I hope it helps!

Note that this function relies on my "Replace-String" function, found here.

function Move-Namespace(
    $includes = $(throw 'Specify a file filter to use'), 
    $oldNamespace = $(throw 'The namespace to replace - i.e. MyCompany.Product'), 
    $className = $(throw 'The class name to search for - i.e. MyClass'), 
    $newNamespace = $(throw 'The new namespace to add - i.e. MyCompany.Product.Feature'))
{    
    # Look for cases of $className
    # or $oldNamespace.$className
    # and replace as necessary
    
    # First check for assumed "using" statements, and add the using statement
    $results = @{}
    $files = get-childitem -r -i $includes | select-string "(?<!$oldNamespace\.)\b$className\b" -list |% { $_.Path }
    select-string "^using.*;" -path $files | group-object Path | select-object Name, @{Expression={ ($_.Group | measure-object -property LineNumber -max).Maximum }; Name="LastUsingStatement" } |% { $results[$_.Name] = $_.LastUsingStatement }
    foreach ($key in $results.keys)
    {
      $processFile = $true
      $lastUsingIndex = $results[$key]
      $fileContents = get-content $key
      # look for existing using statement and cancel processing this file
      for ($i = 0; $i -lt $lastUsingIndex; $i++)
      {
        if ($fileContents[$i] -match "using $newNamespace;")
        {
          # this file already has the correct using statement, stop processing
          Write-Warning "File $key already has the required using statement, ignoring"
          $processFile = $false
          break;
        }
      }
      
      if ($processFile)
      {
        $newContents = $fileContents[0..($lastUsingIndex-1)] + "using $newNamespace;" + $fileContents[$lastUsingIndex..$fileContents.Length]
        set-content -path $key -value $newContents
        Write-Host "Successfully updated file $key" -foregroundcolor Green
      }
    }
    
    # Next check for explicit references
    replace-string "\b$oldNamespace\.$className\b" "$newNamespace.$className" $includes
}
More Posts Next page »