Jeff and .NET

The .NET musings of Jeff Putz

Sponsors

News

My Sites

Archives

January 2010 - Posts

Variations on a simple repeater in ASP.NET MVC: A table/gallery

There are times where I've decided that I didn't want to get too deep into a mess of markup in my views, which drives me to writing a simple HtmlHelper extension method. It's a convenient and quick way to introduce slightly more robust display logic into the view.

But first off, if I may get up on my soapbox, I'd like to address the criticism around MVC views in general. I keep reading over and over again how some feel this is a step backward. That's nonsense. What we're doing in a view is not spaghetti code. We're not jumping around from place to place with data access and business rules mixed into the mess, like ASP.old. It just ain't the same thing. It's also not any worse/messy than using WebForms controls. Those are full of templates a bazillion properties to set, and you might still not get the HTML rendered that you'd really like.

In any case, let's say that I'm building a table of images. I can't just do a simple foreach loop because there are new rows to start. I could work in similar logic to what I'm about to show you in the view itself, but it won't be reusable, and will look a little messy (though really not that bad). The logic, then, is that we want to build a table, and split the series every so often to start a new row. Ignoring for a moment the markup components of a table and its rows and cells, we fundamentally only need to repeat the individual cells and end/start rows. This is my first stab at just such a helper:

public static void SeriesSplitter<T>(this System.Web.Mvc.HtmlHelper htmlHelper, IEnumerable<T> 
items, int itemsBeforeSplit, Action<T> template, Action seriesSplitter)
{
    if (items == null)
        return;
    var i = 0;
    foreach (var item in items)
    {
        if (i != 0 && i % itemsBeforeSplit == 0)
            seriesSplitter();
        template(item);
        i++;
    }
}

As you can see, there isn't much to it. The first parameter extends the HtmlHelper class (the Html property of a ViewPage), the second takes the enumerable series you want to split up, the third says how many items to display before doing the split, and finally we take some Action objects to render. We're still doing a foreach, but if we get to a number of items that's divisible by the parameter you supplied, we pop in the splitter markup as well. In the view, your markup ends up looking something like this:

<table>
    <tr>
    <% Html.SeriesSplitter(Model.Photos, 4, photo => { %>
        <td><img src="<%=ResolveUrl("~/Thumbnail.ashx?id=" + photo.ID)%>"
alt="<%=Html.Encode(photo.Title)%>" /></td>
    <%}, () => { %></tr><tr><% }); %>
    </tr>
</table>

What's particularly fun is that even the HTML validates right in Visual Studio (I take the small wins. :)). Here you can see we're making a table that does four cells at a time, and if it has to start a new row, it drops in those tr elements. Piece of cake, and still pretty clear to read.

Current technology stack

Every once in awhile, I feel like I've changed enough stuff around the technology that I'm using to take a sort of inventory. Mostly I just want to be able to refer back to it the next time I feel compelled to do so.

In terms of hardware, the last year or so has been full of upgrades. Last March I replaced my laptop with a 17" MacBook Pro, because I desperately wanted more screen resolution. It's not the size that's special, it's the resolution. The 15" model I had for three years at that point was also restricted to 2 gigs of RAM, which was less than ideal.

On the desktop, I just replaced my three-year-old Mac Pro after three years. It's not that it was inadequate in any way at all. In fact, it was still pretty ridiculous in terms of its computing power. I replaced it because I wanted a bigger screen at a higher resolution (see the pattern forming here?), and the new 27" iMacs were the ticket. I was able to sell the old computer and buy the new one for about $400 difference. So for that amount, I gained a giant and bright, high resolution LED-lit screen, a computer newer by three years and only "lost" two CPU cores. On top of that, I still have the old 20" Dell monitor, and it sites next to it. I've got nearly 6 million pixels to spread out multiple instance of Visual Studio, Photoshop, browsers, chat, etc. It's also the best video editing setup I've ever had.

In other more peripheral categories, I have an Iomega 1.5 TB USB drive where I'm storing video, the Time Machine drive on the router is still the 1 TB no-name I got from NewEgg, I still use the gross (thank God it's black) Microsoft ergonomic keyboard that has been out for years (same one at work, used by nearly everyone). Since I couldn't wait to spend money in the company store, I also scored an Explorer Mouse to replace the even more disgusting one I had for five years. It glows blue when you wake it up. :)

The Web server at The Planet, tucked away somewhere in Dallas, is the same one I've had now for over six years. It's a P4 2.4 GHz with a pair of 40 gig hard drives and a gig of RAM. I can't believe it's still running. As traffic has picked up, it has shown some cracks here and there, in part because of my own poor coding, and partly because it's just so ancient. I would like to replace it, but I'm waiting for CoasterDynamix to pick up and move to their new site. I've been toying with the idea of going to SoftLayer, but haven't researched them thoroughly. I haven't had any real issues with The Planet, except for one recently, but I guess I just feel like a change.

Software has changed dramatically over the years. Chief among those changes is that I don't use a physical PC at home. I'm using Parallels 5 to host instances of Windows 7. Dedicating 4 gigs of memory to it has been awesome, and Parallels has gotten to the point where it even supports all of the eye candy and what not within Windows. As much as I hated Vista, 7 is such an enormous improvement. They really spent time thinking about little usability things, like snapping windows to the side to do split screens, for example. I started to toy with it going back as far as to before my interview, but once it came installed on the new box at work, I became a fan.

I'm still using Visual Studio 2008 at this point, not 2010. Even though I could get super new builds, I'm not sure I'd want to commit until ReSharper is updated to support it. I'm just too reliant on ReSharper now to go without.

For Web development, I'm mostly building on top of ASP.NET MVC, and will probably upgrade to the new version once it's released. MouseZoom will be MVC, except of course the forum since I'm certainly not going to rewrite that. I use NUnit for unit testing and Moq for mocking (neither of which I'm doing much of on MouseZoom since it's almost entirely composed of existing components). At work we use xUnit and Moq. For data, we've been experimenting with NHibernate, but for my home projects I've been sticking to LINQ to SQL. On the client side, the big story is still jQuery and its various plug-ins.

For Web browsers, I'm pretty sold on Google Chrome now. After using Firefox for years, it just seems to have become a dog, and I'm not sure why. Maybe it's the history that needs to be cleared out? I dunno, since Chrome is hooked right into Google search, I love that I can start typing something and pretty much get to where I want to go. I still use Firefox for Firebug though, as Google's tool isn't quite as slick. The Mac version still has some quirks (like a bookmark manager that only half-works), but it'll get there.

Adium is my chat client at home. It just works and is updated frequently. At work, when I use something at all, I use the Gmail chat with AIM enabled. Other than checking in with Diana, I don't interact that often with people while at work.

On the video front, I upgraded to the latest version of Final Cut Studio last fall, and I dig it. The latest version of Compressor in particular is impressive, and still super fast even with the dual-core CPU. The ProRes codec is what I've been using to edit with, transcoding the H.264 stuff recorded by my camera. Works exceptionally well in terms of performance and holding on to as many bits as possible.

I've talked plenty about the cameras, so I'll skip that, except to say that I may endeavor to buy a shoulder rig so I can properly shoot video before the baby is born.

When I stop and look at what we have available today, I'm really astounded at how far things have come these days. Cultural implications aside (i.e., real life social behavior), I'm amazed at what an iPhone can do. It's a computer, plain and simple, that can do far more than even a top of the line PC from ten years ago. That's crazy.

ASP.NET MVC: Why your dislikes may be wrong

Wow, so I keep talking about how I want to write more, particularly now that I'm an "insider" working in Redmond, and yet it has been a month since my last post. But hey, I've been here two months and I just finally spent some time in downtown Seattle for the first time last weekend, so get off my case. :)

Anyway, as is typical in the professional world of software development, I've seen a great deal of debate about whether or not ASP.NET MVC is the second coming or a step backward. There are also peripheral discussions about what Microsoft sees as the future, but given the outright declaration of that guy with the red shirt and the fact that we've got new versions of Webforms and MVC on the way this year, I think it's pretty clear that you use whatever the best tool for the job is. Isn't it funny how that comes up with every religious debate about development tools?

In any case, there are a few themes to the online chatter around MVC that don't give it proper credit. I'm not suggesting that these are stupid people, but rather people who don't have the whole picture for one reason or another. This isn't an exhaustive list I'm sure, but it is noise that may prevent you from investigating the framework further, or inspire you to spread misinformation. There's a positive theme that builds up here, as you'll see.

ASP.NET MVC is too primitive.

Generally I think this statement is made in the context of MVC's lack of server controls. Some people don't like generating markup, particularly those who've enjoyed the drag-and-drop RAD nature of ASP.NET. Let's face it, when we first saw demos of ASP.NET v1 prior to its release, it looked a lot like VB6, solving problems around the stateless nature of HTTP and letting us build stuff quickly. Behold the editable DataGrid, right?

The thing is, I would observe that as time went on, people weren't using these features out in the wild, particularly with big, sprawling, public facing apps. (I'd like to see the DataTable class stricken from the .NET Framework.) Personally, I almost always used Repeater controls, or variations on them I wrote myself, so I'd have more control over how the markup was rendered. And I almost never used in-place editing either, partly because I wasn't building Excel on the Web, and partly because getting your head around the event model was sometimes a pain.

So MVC goes minimal on the UI end of things by rendering simple HTML via the HtmlHelpers, and there's a remarkably simple state bag to hold on to your goodies when your server side validation says something isn't right. That you can simply wire up objects to those helpers without all of the "MyTextBox.Text = myObject.Foo" and the reverse nonsense in event handlers is a huge time saver. Give it a try!

MVC is a step backward to ASP.OLD and spaghetti code.

This is a pretty huge perception problem. I have to admit though, the first time I saw it demo'd, I thought the same thing. I remember the horror of ASP and trying to debug it, and this looked the same. That was because I didn't truly appreciate what Model-View-Controller really meant. After reading through a Ruby On Rails tutorial and reading various articles about the MVC pattern, something clicked in my head and I investigated further. Then I drank the Kool-Aid® at various Mix conferences and I was hooked.

But back to the Italian food, the biggest thing that colors your perception is that there are a lot of really bad examples of what a view should look like. That doesn't mean that it's conceptually broken. Remember that the MVC pattern facilitates the famous separation of concerns, meaning a view should not participate in any logic except perhaps some very basic display logic (most often, looping through some enumerable set of data). If you see some example on the Internets of a view that is calculating salaries, or worse, hitting a database, politely post on that site: "MVC: ur doin it wroung."

It's a lot of work deciding how to split everything up.

Again, I think that's only true if you aren't doing it right. Admittedly, it takes some practice to decide where things go, but after awhile it becomes pretty obvious. If you're dealing with a view, ask yourself if it's doing anything more than displaying stuff. If you're dealing with a controller, ask yourself if it's doing anything more than coordinating what to show the user, and shuttling data between the views and the models. If you're dealing with models (which is a pretty nebulous umbrella term in a lot of texts), ask yourself if it's doing any decision making about what to display or how to display it.

Don't be intimidated over the many related subjects around this concern soup. Dependency injection isn't that hard to get down, and like anything it takes practice to fully grasp why you'd want to soak up its awesomeness (see: Loose coupling).

In fact, the "ah ha" moments really may not come until you've forced yourself to sit down and do an end-to-end science project. While I understand that test driven development is a huge leap that's hard to make, unit testing can make your life easier even if it's slightly after the fact. In order to unit test, you have to figure out how to decouple your bits. That subject is too enormous here to cover, so you'll have to take it on faith until you try it.

Ugh, but it takes so long to do everything "right."

Think about how much time you may spend debugging a code-behind or a custom server control. If we share any experience, it's probably around those hours we'll never get back. Now imagine that you have some tight model that just does what it does, probably interacting with a database (or rather an interface that in production happens to be a database). Imagine you have a controller that takes the request, feeds its data to the model, then sends the model's data to a view to be rendered. Each phase of that can be looked at in total isolation. The points of failure are much easier to narrow down. And because it can be looked at in isolation, each part can also be tested in isolation. The speed at which you can debug this arrangement is far greater than what you do in Webforms.

The bottom line is that MVC is just... different. I happen to be a strong advocate of it because it gets back to the basics of what HTTP truly is, without a huge mess of abstraction on top of it to hide the way it works. That's important these days, because we trust the browser to do more work than ever now. The framework also gets us thinking about (but doesn't force us) how to do things in a way that is testable, more maintainable, and ultimately, more simple.

If you don't think you like MVC, but haven't really looked into it, go check out the learning page on ASP.NET/mvc. Read the tutorials, view the video (that Hanselman guy is a trip).

More Posts