Rock the iPhone with ASP.NET MVC

Posted June 8th @ 7:30 pm by aaron

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!

kick it on DotNetKicks.com

Off to TechEd 2008

Posted June 1st @ 1:27 pm by aaron

I’m leaving tomorrow for TechEd 2008 in Orlando, FL. I’m excited about it since it’s my first developer conference that isn’t targeted at a very specific purpose (like Interact 2008 was). I’m looking forward to attending some good sessions, meeting some people I’ve only ever e-listened to, and spending some relaxing evenings with my wife who’s coming with to enjoy a little R&R away from the kids.

Unfortunately, we’ve been without power at our home since 10PM last Friday night due to storms and tornados. Not only is the power out in our area of the city, but a big tree fell on our specific power lines, ripping everything away from the house. So the weekend has been spent calling utility companies, contractors, waiting, and reading. Our family lives far away, so we’ve really appreciated our friends who have welcomed us into their homes, shared their meals with us, and let us type blog posts from their laptops. ;) (Thanks Shawn!)

If you’re going to TechEd and want to meet up, drop me an email at aaronlerch at gmail or tweet me on twitter. I’ll be at Party with Palermo on Monday night.

See you in Orlando!

First thoughts on ASP.NET MVC Preview 3

Posted May 27th @ 10:57 pm by aaron

I had a chance to play with the latest ASP.NET MVC drop tonight. There’s a few changes (some of which came in Preview 2) but a few items caught my eye fairly quickly.

ActionResult

This change came with Preview 2, but it’s worth mentioning. Instead of controller actions returning void, they now return an ActionResult instance. This increases testability and separates functionality. Testability because now controllers can be tested without mocking out all the requirements for invoking the view, and functionality because the loading and invoking of an action’s view is encapsulated in a class structure apart from the controllers.

JsonResult

Something that is included new in Preview 3 is JsonResult (a subclass of ActionResult). It looks like some of my crazy ideas weren’t so crazy after all? A new method on the controller, "Json()", takes a serializable object and returns a JsonResult which uses the obsoleted (whoops??) JavaScriptSerializer to render the object as JSON.

So a controller’s action could look like this:

RedirectToRoute

If a controller action needed to redirect, our only option (until now) has been RedirectToAction which accepts an action name and optional controller name. That’s not bad, but now we have RedirectToRoute which allows us to redirect to a named route, making things more flexible and easier to change (without mass find/replacing all over the place).

And more…

Scott Guthrie has more details, and Scott Hanselman (so many Scotts!) has a few updated screencasts. Be sure to check them out.

Things with MVC are solidifying and starting to look pretty good. Check out the MvcContrib or CodeCampServer projects for some decent reference implementations.

Indy Code Camp This Saturday

Posted April 24th @ 2:56 am by aaron

The Indy Code Camp is this Saturday, April 26th. I’ll post a recap once it’s done, but with 400 people registered and a lot of good sessions given by good speakers, it promises to be a good time.

I’ve put in a reservation with Champps for an after-party. We’ll be going Dutch, and would love to have everybody join us! We’ll be announcing the after-party at the event, so if you’re attending, please RSVP with me at that time so I can call ahead and make sure they can handle the frickin’ huge crowd that will be coming.

Also, I think we’re still in need of a few volunteers to help with registrations in the morning. If you’re willing and able to arrive bright and early at 7AM (-ish), leave a comment here.

See you on Saturday! If I haven’t met you and you’re coming, make sure to find me and say hi.

From Developer to Technical Manager

Posted April 20th @ 6:19 pm by aaron

A long time ago my grandfather worked as a machinist in a factory. He was a damn fine machinist, a true craftsman, and he took great pride and joy in his work. Most of my memories of my grandpa were from after he retired, and I would have loved to have seen him "back in the day". I’ve done some woodworking in my relatively short life, and I understand the euphoric sense of pride and joy that come when you finish a project that you built from scratch.

Grandpa’s skills grew over time and, as it’s a natural thing, he began informally mentoring junior machinists. It wasn’t long at all before management at the factory noticed both his skill and his mentorship and did what any good manager would do. They promoted him to a supervisor.

My dad tells me that my grandfather was never the same.

Being a supervisor sucked the life out of my grandpa. Everything he loved about his job was gone. He no longer worked with peers, he oversaw employees. Reviewing their work, approving their vacation, dealing with "poor performers", and spending less of his time creating.

Grandpa’s managers made an all-too-common mistake. They assumed that because grandpa was good at his job, he’d be good at managing other people doing the same job. Sound familiar? Thought so. By no means is it limited to any one industry, either. I’m pretty sure that eons ago there existed a caveman who was good at killing mammoths, and as a result was promoted to "branch manager", and probably ended up killing his coworkers ’cause that’s all he knew how to do.

A lot has been written about this problem. And it’s definitely a problem.

But it’s not so simple. Managers need a good measure of domain knowledge. There are two ways to get a manager with domain knowledge: hire a "manager" and teach them the domain, or promote a domain expert and teach them to be a manager. Because domain knowledge tends to be more specific and more detailed, and because managing is incorrectly viewed to be "easy", the default is usually to promote a domain expert. Add more mundane logistics like the fact that domain experts tend to already be employees and it makes the decision that much "easier".

In the software world the problem is amplified by the nature of "domain experts". The majority of us can hardly interact with any other human being, not to mention "manage" developers.

Unfortunately, because of wrong assumptions, most organizational structures are set up in a way that assumes a career path from developer to manager. In Code Craft, Pete Goodliffe calls these people "Reluctant Team Leaders".

"This is the organizational classic; a developer who’s been promoted to team leader when there was no further technical route for him to advance. You can plainly see that he is uncomfortable in this role. He doesn’t have the correct skill set, and he struggles to keep up. He is a programmer, and he wants to program. This guy is not a natural organizer or manager of people, and he is a bad communicator."

Organizations with an outdated organizational structure have got to wake up and change before it’s too late. They will either lose or ruin their people. Either way, the company loses because people are the company.

I do think, though, that it is possible for a developer to successfully become a technical manager. There are some developers that have the skills, nay, more like the potential, to be good technical managers. We’re seeing more and more developers with "people skills". Partly because the barriers to entry have lowered. For example, you don’t need to have a secret love affair with bit twiddling 1’s and 0’s in order to write software. Higher level frameworks like Java, .NET, and Ruby/Rails enable more people to create something great than has previously been possible.

So what are the characteristics of a good technical manager?

  1. Communication. Communication is where developers struggle the most. The world with two personalities (1 and 0) is vastly different than the world of billions of personalities. Each personality type communicates in a different way. And as a technical manager, one of the most challenging tasks is to help a group of individuals communicate and work as a team. A developer has a ONE-TO-ONE communication path: developer to their manager. A technical manager has a ONE-TO-MANY communication path: from the manager to every person on the team. Often a technical manager will find themselves proxying the communication between two developers.
  2. Technical savvy. A technical manager has to maintain the respect of their team, and software developers tend to be an elitist group - if you can’t keep up, good luck. You don’t have to be technically "smarter" than your team, not by a long shot (otherwise you should stay a developer), but you should keep up to speed with current trends, best practices, new technologies, etc. In my experience, technical managers can "cherry pick" smaller features, but should never be in the critical path for a project. I’ve been there, it’s not fun. Open source projects are a great way to keep up with both deeper and broader design and implementation techniques.
  3. Organization skills. A normal developer keeps track of many things: bugs, features, ongoing email threads, and of course current designs, implementations, etc. A technical manager must track all of this, but at a higher level and for several people across the team.
  4. Priorities. Your primary job responsibility is no longer writing code. A technical manager has to come to terms with that before accepting the job. But a technical manager’s job also isn’t to dictate or control the team either. A technical manager needs to understand the business, and needs to set a vision for the team, but the primary role of a technical manager should be to clear the path of developers to make them the most productive they can be. Read about the ScrumMaster role in the Scrum project management process. It’s a great description of a technical manager’s priorities.
  5. Humility. Developers have egos. As much as I’ve tried to pretend that’s not true, it is. It’s crucial to understand that for a technical manager to successfully bring a team together, the "I’m the boss of you" attitude can never show it’s face. A manager who assumes they are superior to the people on their team both promotes the wrong assumption that managers are "above" developers (how do you think the wrong organizational structures came to exist in the first place?), and provides a horrible place to work.

In addition to the character traits of technical managers, it’s critical for a developer to have a clear grasp of what the job role will include, in terms of day-to-day activities. Andrew Tokeley has a good write-up of what you can expect. I think most developers considering a move to a managerial role force themselves to believe delusions like "I can still write a lot of code" in order to make the move more palatable. I’d argue that, depending on your company culture, you’ll probably write less code than even Andrew indicates in his charts.

Over a year ago I took the plunge from developer to team lead. It’s been an interesting ride. Frustrating, rewarding, educational, and enlightening. For the right type of person, it’s a good move, if you’re ready for it. For the wrong type of person, you’ll never be ready for it, so avoid it like the plague. If your company forces you to become a manager to "move up", either be satisfied staying put, or find a new company that has a clear technical career path. But overall, do what you enjoy, and do it well.

kick it on DotNetKicks.com

Automatic formatting of inline ASP.NET tags

Posted April 8th @ 1:26 am by aaron

I don’t know whether it’s Resharper and/or Visual Studio 2008 that messes up the auto-formatting of inline ASP.NET tags, but it sucks. I usually start "prettying" it up, but usually give up halfway through, because every time I add anything else, the formatting is shot again. Is it just me? Is there a setting I’m missing?

Indy Code Camp: Schedule announced

Posted March 26th @ 12:43 pm by aaron

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!

Indy Code Camp: Call for speakers ending soon

Posted March 18th @ 11:52 am by aaron

Just a reminder that you have until Saturday, March 22nd to submit a session proposal for the Indy Code Camp before we make the final session schedule.

We’ve had a lot of good submissions already. This promises to be a good event full of great content. And don’t forget the door prizes! :)

Sign up to present, or just register to attend and support the local community of software developers! See you there.

Are Twitter Clients the new Hello World app?

Posted March 13th @ 11:48 am by aaron

There’s been a bit of talk on Twitter recently about the various twitter clients that exist, with more being created practically every day. One view was that everybody is trying to create the ultimate twitter client.

Maybe.

Certainly there are a lot of new twitter client apps being made, some with lofty aspirations, but more importantly I see a twitter client as the new "Hello World" for desktop applications. And I think it’s a great choice. The days of a Hello World application consisting of a Console.WriteLine are long past. To dig in and learn something new, you have to implement something with at least a little substance to it.

A twitter client has the key components one needs when learning a new technology:

Simple

In terms of base functionality, a twitter client has a very simple task. Heck, Twitter itself is built around the simple premise of asking "What are you doing right now?" and letting you answer. A twitter client, at it’s core, needs to do two things: display your timeline and let you update your "status". Simple as that.

Easy and intuitive API

Twitter’s API is easy. Really easy. When you’re writing a real-world Hello World application, you want to focus on what you’re trying to learn, which is the technology, and not a complex API or other things that simply distract.

Options

Like most applications that have a user interface (and even those that don’t), there’s always room for choices. Depending on what you’re trying to learn (I’m a UI guy) you have different approaches you can take. If you’re learning WinForms or WPF, you can play with different presentation models, learning how to accomplish what you want. If you’re learning deeper back-end programming, you could play with the windows services APIs, or WCF, or whatever. It’s flexible.

Room for expansion

A twitter client can move beyond the basics I mentioned above and incorporate more features, with the limit practically being your imagination. Just look at twittervision.

BitterMy friend Mike has been diving head first into .NET (he’s an MFC guru), and decided to create a great twitter client (Bitter) not to create the ultimate one, but to learn the technology. Which is good, because an ultimate twitter client has already been created. It’s called Twitterific. :)

Testing TempData, and Mocking SessionState

Posted March 12th @ 8:07 pm by aaron

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();
}

kick it on DotNetKicks.com

Options:

Size

Colors