aspnet, aspnetmvc, code, patterns comments edit

Or, as my recent inbox tells me, you’re not afraid to ask. ;)

A coworker recently asked for some good resources on getting up to speed on the Model View Controller (MVC) pattern. Around the same time, I received another email talking about how people are confused around the difference between MVC and the Model View Presenter (MVP) pattern.

mvcNo better opportunity to apply the DRY principle by answering some of these questions with a blog post.

MVC

The first place to start digging into the MVC pattern is to look at the Wikipedia entry. That’ll get you a nice brief summary of the pattern along with a list of resources.

In MVC, the Model represents the information (the data) of the application and the business rules used to manipulate the data, the View corresponds to elements of the user interface such as text, checkbox items, and so forth, and the Controller manages details involving the communication to the model of user actions such as keystrokes and mouse movements.

trygve If you’re really into it, you can go directly to the source and read the original papers from Trygve Reenskaug, the inventor of the pattern.

There you’ll learn from the original paper (pdf) that the initial name for the pattern was Thing-Model-View-Editor. The pattern was baked via a process of extracting, improving, and articulating existing command and control patterns used in the operation of Norwegian ship yards in order to streamline and improve operations.

MVP

That ought to get you going with the MVC pattern. Now onto Model View Presenter, which was a response to the inadequacies of the MVC pattern when applied to modern component based graphical user interfaces. In modern GUI systems, GUI components themselves handle user input such as mouse movements and clicks, rather than some central controller.

MVP was popularized by Taligent in this paper on the subject (pdf). More recently, Martin Fowler suggested retiring this pattern in favor of two variants: Supervising Controller and Passive View.

The Difference?

So what’s the diff between MVC and MVP? Using GitHub, here it is!

246

Sorry, bad joke but I couldn’t resist.

The two patterns are similar in that they both are concerned with separating concerns and they both contain Models and Views. Many consider the MVP pattern to simply be a variant of the MVC pattern. The key difference is in how both patterns solve the following question: Who handles the user input?

With MVC, it’s always the controller’s responsibility to handle mouse and keyboard events. With MVP, GUI components themselves initially handle the user’s input, but delegate to the interpretation of that input to the presenter. This has often been called “Twisting the Triad”, which refers to rotating the three elements of the MVC triangle and replacing the “C” with “P” in order to get MVP.

What About The Web?

If you were playing close attention, most of these articles focus on rich client applications. Applying these patterns to the web is a very different beast because of the stateless nature of the web.

ASP.NET WebForms, for example, attempts to emulate the rich client development paradigm via the use of ViewState. This is why many attempts to apply patterns to ASP.NET focus on the MVP pattern because the MVP pattern is more appropriate for a rich client application with GUI components. A while back I even tossed my Supervising Controller sample into the ring. The Patterns and Practices group at Microsoft ship an MVP Bundle for ASP.NET.

However, many web platforms embrace the stateless nature of the web and forego attempting to simulate a state-full rich client development environment. In such systems, a tweaked MVC pattern is more applicable.

This pattern has been adjusted for the Web for your application development enjoyment.

AFAIK, Struts, a Java web framework, is one of the first widely used web frameworks employing the MVC pattern, though most people now look at Rails as being the tipping point that really brought MVC to the web and popularized the MVC pattern for web applications.

ASP.NET MVC is a new (in development) alternative framework for ASP.NET developers that makes it easy for developers to follow the MVC pattern. This framework employs the MVC pattern rather than the MVP pattern because it does not attempt to emulate rich client development, and thus the MVC pattern is more appropriate.

More Reading

There’s a lot of good content out there that puts these patterns into historical and categorical perspective. Besides the links already mentioned in this paper, I recommend checking out…

humor comments edit

Photo by lizerixt on stock.xchng
http://www.sxc.hu/photo/1005758 Yesterday, I wrote a post that contained the phrase “BFFs Forever” in the title. Commenters were quick to point out the redundancy of “Forever” in the title.

Nice - BTW, your title is redundant, so your title reads “IronRuby and ASP.NET Best Friends Forever Forever”

Thanks! But I had made the very same point in that post.

And for those that don’t know, BFF is an acronym for Best Friends Forever. Yes, the “Forever” is redundant in the blog title, but it’s just how people use it.

Case in point, how often do you hear the phrase “PIN Number” which expands to “Personal Identification Number Number”. I started looking for other examples of such redundant acronyms and sure enough, there’s a term for them and a wikipedia article describing them.

RAS syndrome stands for “Redundant Acronym Syndrome syndrome,” and refers to the use of one of the words that make up an initialism or acronym as well as the abbreviation itself, thus in effect repeating that word. It is itself a humorous example of a redundant acronym.

And in case you didn’t notice, “RAS Syndrome” is itself humorously a RAS. The Wikipedia article points to other great examples.

  • ATM machine
  • HIV virus
  • ISBN number
  • CSS style sheets
  • Please RSVP
  • CNN Network

The article references another page with a collection of more redundant acronyms.

  • LAN network
  • DAT tape
  • RF frequency
  • UPC code

It’s not surprising that most of these come from the technology field as we tend to be very acronym happy and love our TLAs (Three Letter Acronyms).

So now it is my turn to coin a RAS. I am going to call it PCS syndrome which stands for “Premature Correction Syndrome syndrome.” This describes the condition in one is compelled to interject with a correction without having read through the rest of the contents, especially when the author offers an explanation for the seemingly erroneous item. ;)

I’m only teasing because PCS happens to me a lot. I find that the comments to many of my blog posts tend to focus on some irrelevant miniscule detail rather than the topic at hand. Which I’m not necessarily opposed to because that provides great fodder for future blog posts!

Technorati Tags: humor,acronyms,neology

humor comments edit

Today’s Dilbert described one of the most challenging problems small consulting companies face. I’m sure Jon, Micah, and I remember experiencing this many times when trying to build and expand Veloc-IT (though Micah probably still gets the pleasure of dealing with this as he’s still chugging along).

Click the image to see the full size strip at Dilbert.com.

Interest Free
Loan

Technorati Tags: dilbert,funny,humor,consulting

asp.net mvc, code comments edit

UPDATE: I just posted the working demo here.

I wish I could have been there, but I was celebrating my son’s first birthday (which gives me an opening to gratuitously post a picture of the kid here).

cody-birthday

I’m talking about Tech-Ed 2008 Orlando of course where John Lam presented a demo of IronRuby running on top of ASP.NET MVC.

This demo builds on prototype work I’ve done with defining ASP.NET MVC routes and views using IronRuby.

The final missing piece was defining controllers using IronRuby. Working with members of John’s team, Levi (a dev on the ASP.NET MVC team) made the necessary adjustments to get a prototype IronRuby controller working with ASP.NET MVC.

Disclaimer: This is all a very rough prototype that we’ve been doing in our spare time for fun. We just wanted to prove this could work at all.

Unfortunately, we can’t release the demo yet because it relies on unreleased ASP.NET MVC code. When we deploy our next CodePlex interim release of ASP.NET MVC, the demo that John provided should actually work. :)

And for those that don’t know, BFF is an acronym for Best Friends Forever. Yes, the “Forever” is redundant in the blog title, but it’s just how people use it. As an aside, I found out recently that a good buddy of mine in L.A. is actually working on the set of a new show tentatively titled “Paris Hilton’s My New BFF”, where contestants compete to become Paris Hilton’s new Best Friend.

Technorati Tags: aspnetmvc,ironruby

asp.net mvc, code, asp.net comments edit

My compadre Scott Hunter, another PM on the ASP.NET team, who happens to work on the Dynamic Data feature, recently put together an example of using ASP.NET MVC and Dynamic Data Web Forms together in the same application. Look for the link to MvcDynamicData.zip on this Code Gallery page.

I’ve been working on a post detailing a couple different ways to integrate WebForms and MVC, but life has been really busy for me lately. Hopefully I’ll get that to you soon.

MysteryPersonIn the meanwhile, you can probably learn all you need to know by looking at this example.

By the way, Scott was recently featured on .NET Rocks. We need to get a better picture of him taken. That whole Smoking Man image has got to go.

Technorati Tags: aspnetmvc,dynamic data

asp.net, asp.net mvc, code comments edit

tacoma_narrows The design is never right the first time. Nor is it usually right the second time. This is one of those key lessons you learn over time building real software, and is the source of one of the chief complaints leveled at the Waterfall methodology for building software, which puts heavy emphasis on getting the design right up front.

We have to define “right” in this case. If by “right” you mean perfect, then I don’t think the design is ever right, as I’ve argued in the past that there is no perfect design.

Recently, this lesson was driven home as my feature team (ASP.NET MVC) were hashing out some tricky design issues. Many times, we find ourselves in a tight spot in which we have two different audiences demanding a different approach to a design problem. The tough part is that the solutions we come up with inevitable satisfy one camp at the expense of the other.

Let me be clear, it’s not our goal and intention to try and satisfy everyone as that is a sure means to satisfying nobody. As Bill Cosby once said…

I don’t know the key to success, but the key to failure is to trying to please everybody.

At the same time, I also think it’s a copout to simply give up immediately when a thorny design problem comes up with two disagreeing camps. It’s worth a good faith effort to try and gather ideas you haven’t considered before and see if you can’t just solve the problem in a manner that both camps are happy with. Or at least in a manner that one camp is happy, and the other is merely less happy.

An illustration of this point happened recently at work. After many iterations, I sent out our design meeting notes internally with our solution to a particular issue. ScottGu noticed the write-up and had some questions about the design (questions like WTF?) and called me and Eilon (the lead dev) into his office for a “short” meeting to discuss these recent design changes.

I made sure to call my wife before the meeting to let her know I would be late for dinner. Once we get a talking about MVC, I know it won’t be short. We spent two hours hashing out the design, going over options, shooting them down, trying out other ideas, and so on.

At some point, Scott proposed something my team had rejected earlier due to a major flaw. However this time, as he was proposing the idea, it suddenly occurred to me that there were two different ways to implement this idea. The one we thought of wouldn’t work, but a slight adjustment to the idea, the very one Scott was proposing, would make it workable.

Eilon and I left the meeting happy with the improved design, but now concerned with the fact that we had already implemented another solution, had a bunch of unit tests and automated web functional tests. Not to mention having to deal with explaining it to the team and getting buy in so close to our release deadline.

So we did the cowboy thing (which I generally don’t recommend) and decided instead of telling the rest of the team about it, we’d follow the old maxim: “Show, don’t tell”. So that night, we went and coded the whole implementation, updated all the unit and web tests, and had something to demo in the morning rather than talk about. Since we had updated all the tests, QA was much more amenable to signing off on making this change so close to the deadline.

In retrospect, the part that causes me pain in the missed opportunities sense was just how tantalizingly close we were to having implemented this very idea from the beginning. All that time spent prototyping, app building, etc… we could have saved by getting it right the first time.

But that’s the way design goes. Sometimes, you are so close to a great solution that if the wind blows a certain way, you’ll hit upon it, but if it blows another way, you dismiss your line of thought and move onto other plans. Try as you might, it is very difficult to get the design just right the very first time all of the time.

Luckily for us, our team had the agility to respond to a better design. Our suite of unit and integration tests gave us confidence that the changes we were making were not breaking the framework in other areas. To me, this is a real testament to the benefits of applying lean and agile principles in software development, as well as the benefits of having good unit test coverage.

Tags: design , Software Development

asp.net, asp.net mvc, code comments edit

I updated the template to have the correct assembly references so it should work now out of the box. Sorry about that.

northwindA while ago Scott Hanselman linked to my Northwind sample which itself was spawned from an initial sample that Brad Abrams wrote.

As I like to say (to anyone who will listen)

There ain’t no party like a Northwind Party

So I went and updated my sample to work well with the recently released ASP.NET MVC Preview 3Beta.

Download it here.

asp.net comments edit

A while back I wrote a sample that demonstrated how to use Routing with WebForms.

If you missed it, you can download the code here

With the recent announcement that Routing will be included with .NET 3.5 SP1, you can see why I wanted to put that demo together.

I have since updated that sample to work with the versions of Routing that comes with the April CodePlex build of MVC. This should also work with the SP1 Beta. I’ll verify that when I get a moment.

As part of this update, I added a new feature which allows applying a simple substitution. For example, suppose you want URLs such as /forms/whatever to route to a physical file /forms/whatever.aspx. You can do the following:

routes.Map("forms/{whatever}").To("~/forms/{whatever}.aspx");

One mistake a lot of people make when looking at URL Routing is to think of it as URL Rewriting. The difference is subtle, but important. There is no URL rewriting going on with Routing.

What happens here is when an incoming request URL matches this route (aka the URL pattern on the left), the WebFormRouteHandler will instantiate the physical ASPX Page specified in the virtual path on the right and use that http handler to handle the request (Recall that the Page class implements the IHttpHandler interface). As far as the page is concerned, the URL is /forms/whatever/. For example, this means that the URL rendered by your form will match the current URL, unlike what typically happens with URL rewriting.

This is why the above won’t work if you try to map a route to a virtual path that contains a query string:

//WRONG!!!
routes.Map("forms/{whatever}").To("~/{whatever}.aspx?what={whatever}");

The reason the above route won’t work is that the virtual path on the right isn’t valid. The path needs to specify a page we can instantiate, not a request for an URL.

To save you from having to visit the previous post, here is a link to download the code

Technorati Tags: routing,aspnetmvc

asp.net, asp.net mvc, code comments edit

The news is out, the beta for the Visual Studio 2008 and the .NET Framework 3.5 Service Pack has been released. As it relates to ASP.NET MVC, there are two important points to notice about the SP1 release:

  • ASP.NET MVC is not included
  • URL Routing is included

Now you can see why there’s been so much focus on Routing from the MVC team, as Routing is now part of the Framework and is not out-of-band. This meant that we had to put a lot more effort into Routing to make sure it was production ready.

ASP.NET MVC continues to be an out-of-band release. With the Routing code now effectively complete, you should hopefully start to see a lot more progress in MVC as our development team can focus almost exclusively on MVC.

MVC Preview 2 Apps Are Affected By SP1

Another important thing to note is that installing SP1 Beta installs the System.Web.Routing and System.Web.Abstractions assemblies into the GAC (Global Assembly Cache). These assemblies have the same exact assembly version as the ones we released as part of Preview 2.

What this means is that even though you might have a direct reference to the Preview 2 assemblies, when your app runs, it will still load those assemblies from the GAC.

We’ve posted the workaround for Preview 2 applications at the bottom of the page here in the section entitled Changes for ASP.NET MVC Preview 2.

April CodePlex Apps

If you’re running the April CodePlex app, you should be okay using the version from SP1 Beta. There might be minor behavioral differences in edge cases.

Preview 3

MVC Preview 3 will not be affected by having SP1 installed. Preview 3 will include newer privately versioned bin deployable builds of the Routing and Abstractions DLLs. That way these assemblies will not be affected by the versions in the GAC installed by SP1, because they will have different version numbers.

They don’t call it “Bleeding Edge” for nothing when playing with these previews, but we are sorry for the inconvenience and Preview 3 should make it better.

Technorati Tags: aspnetmvc,aspnet,net35sp1

asp.net, asp.net mvc, code comments edit

In my last post, I walked through a simple example of an ActionResult that you can use to transmit a file to the user’s browser along with a download prompt.

The MVC framework will include several useful action results for common tasks. However, we might not cover all results you might want to return. In this post, I walk through a simple result that will cover all remaining cases. With the DelegatingResult, you simply pass it a delegate. This provides ultimate control. Let’s see it in action.

public ActionResult Hello() {
  return new DelegatingResult(context => {
    context.HttpContext.Response.AddHeader("something", "something");
    context.HttpContext.Response.Write("Hello World!");
  });
}

Notice that we pass in a lambda to the constructor of the action result. This lambda is a delegate of type Action<ControllerContext>. By doing this, the lines of code within that block (Response.AddHeader and Response.Write) are deferred till later.

Here’s the code for this action result.

public class DelegatingResult : ActionResult {
    
  public Action<ControllerContext> Command {
    get;
    private set;
  }
    
  public DelegatingResult(Action<ControllerContext> command) {
    this.Command = command;
  }

  public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
      throw new ArgumentNullException("context");
    }
        
    Command(context);
  }
}

I updated the sample I wrote in my last post to include this demo. Download the source.

Technorati Tags: aspnetmvc,actionresult,lambda

asp.net, asp.net mvc comments edit

NEW UPDATE: There is no longer need for this custom ActionResult because ASP.NET MVC now includes one in the box.

UPDATE: I’ve updated the sample to include a new lambda based action result. This also fixes an issue with the original download in which I included the wrong assembly.

The April CodePlex source drop of ASP.NET MVC introduces the concept of returning an ActionResult instance from action methods. ScottGu wrote about this change on his blog.

In this post, I’ll walk through building a custom action result for downloading files. As you’ll see, they are extremely easy to build. Let’s start at the end and see what the end-user behavior of this new result will be.

Here’s a page that contains a link to an action method named Download.This action method returns this new DownloadResult action result.

File Download
HomePage

Clicking on the link then pops up this dialog, prompting you to download and save the file.

File
Download

The code for this action is pretty simple.

public ActionResult Download() 
{
  return new DownloadResult 
    { VirtualPath="~/content/site.css", FileDownloadName = "TheSiteCss.css" };
}

Notice that you just need to give the result two pieces of information, the virtual path to the file to send to the browser and the default filename to save the file as on the browser.

The virtual path is set via VirtualPath property (surprise surprise!). Note that I could have chosen to make this parameter accept the full file path instead of a virtual path, but I didn’t want to force users of this class to fake out a Server.MapPath call in a unit test. In any case, the change is trivial for those who prefer that approach. I might add overloads that accept a Stream, etc…

The file download name is set via the FileDownloadName property. Notice that this is the filename that the user is prompted with.

If the FileDownloadName property is set, the ExecuteResult method makes sure to add the correct content-disposition header which causes the browser to prompt the user to save the file.

For those familiar with Design Patterns, action results follow the pattern commonly known as the Command Pattern. An action method returns an instance that embodies an command that the framework needs to perform next. This provides a means for delaying the execution of framework/pipeline code until after your action method is complete, rather than from within your action method, which makes unit testing much nicer.

Speaking of unit tests, here’s the unit test for that download action method I wrote. As you can see, it is quite simple.

[TestMethod]
public void DownloadActionSendsCorrectFile() {
  var controller = new HomeController();

  var result = controller.Download() as DownloadResult;

  Assert.AreEqual("TheSiteCss.css", result.FileDownloadName);
  Assert.AreEqual("~/content/site.css", result.VirtualPath);
}

Here’s the code for the DownloadResult class. This is the class that does all the work (not that there is much work to do). I do have unit tests of this class in the included source code which demonstrate how to unit test a custom action result.

public class DownloadResult : ActionResult {

  public DownloadResult() {
  }

  public DownloadResult(string virtualPath) {
    this.VirtualPath = virtualPath;
  }

  public string VirtualPath {
    get;
    set;
  }

  public string FileDownloadName {
    get;
    set;
  }

  public override void ExecuteResult(ControllerContext context) {
    if (!String.IsNullOrEmpty(FileDownloadName)) {
      context.HttpContext.Response.AddHeader("content-disposition", 
        "attachment; filename=" + this.FileDownloadName)
    }

    string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
    context.HttpContext.Response.TransmitFile(filePath);
    }
}

I removed the download since this code is no longer needed nor relevant.

Technorati Tags: aspnetmvc,actionresult

asp.net, asp.net mvc comments edit

A while back I wrote a routing debugger which is useful for testing your routes and seeing which routes would match a given URL. Rob suggested we have something like this for unit tests, so I whipped something simple up.

This is a class that allows you to test multiple different URLs quickly. You simply create the RouteEvaluator giving it a collection of routes and then GetMatches which returns a List<RouteData> containing a RouteData instance for every route that matches, not just the first one.

Here’s a sample of usage.

[Test]
public void CanMatchUsingRouteEvaluator()
{
  var routes = new RouteCollection();
  GlobalApplication.RegisterRoutes(routes);

  var evaluator = new RouteEvaluator(routes);
  var matchingRouteData = evaluator.GetMatches("~/foo/bar");
  Assert.IsTrue(matchingRouteData.Count > 0);
  matchingRouteData = evaluator.GetMatches("~/foo/bar/baz/billy");
  Assert.AreEqual(0, matchingRouteData.Count);
}

And here’s the code. Note that my implementation relies on Moq, but you could easily implement it without using Moq if you wanted to.

public class RouteEvaluator
{
  RouteCollection routes;
    
  public RouteEvaluator(RouteCollection routes)
  {
    this.routes = routes;
  }

  public IList<RouteData> GetMatches(string virtualPath)
  {
    return GetMatches(virtualPath, "GET");
  }

  public IList<RouteData> GetMatches(string virtualPath, string httpMethod)
  {
    List<RouteData> matchingRouteData = new List<RouteData>();

    foreach (var route in this.routes)
    {
      var context = new Mock<HttpContextBase>();
      var request = new Mock<HttpRequestBase>();

      context.Expect(ctx => ctx.Request).Returns(request.Object);
      request.Expect(req => req.PathInfo).Returns(string.Empty);
      request.Expect(req => 
req.AppRelativeCurrentExecutionFilePath).Returns(virtualPath);
      if (!string.IsNullOrEmpty(httpMethod))
      {
        request.Expect(req => req.HttpMethod).Returns(httpMethod);
      }

      RouteData routeData = this.routes.GetRouteData(context.Object);
      if (routeData != null) {
        matchingRouteData.Add(routeData);
      }
    }
    return matchingRouteData;
  }
}

Let me know if this ends up being useful to you.

Technorati Tags: aspnetmvc,ASP.NET,routing

asp.net, asp.net mvc, personal comments edit

I did another interview with those wild and crazy guys, Carl and Richard. My first time (show 261) being on .NET Rocks was back in August of 2007 when I talked about Subtext, Open Source, and my blog.

This time (show 339), the interview focused on my experiences with working at Microsoft and the work I do on the ASP.NET MVC project. Notice that my profile pic hasn’t changed at all. I should do something about that.

I haven’t listened to it yet as I hate hearing myself talk. Even worse is seeing myself on video.

In any case, if you are interested, take a listen to the latest .NET Rocks show.

Oh, and I was also a guest on Hanselminutes recently. That talk was recorded at ALT.NET Open Spaces in Seattle. It’s only a coincidence that these two interviews came out a week apart. They were recorded more than a week apart. Honestly, I’m not a microphone whore. I’m more of a camera whore. ;)

Technorati Tags: dotnetrocks

asp.net, asp.net mvc, code comments edit

Not long ago, my compadre Scott Hanselman related the following story

In a recent MVC design meeting someone said something like “we’ll need a Repeater control” and a powerful and very technical boss-type said:

“We’ve got a repeater control, it’s called a foreach loop.”

I beg to differ. I think we can do better than a foreach loop. A foreach loop doesn’t help you handle alternating items, for example. My response to this story is, “The foreach loop is not our repeater control. Our repeater control is an iterating extension method with lambdas!”. Because who doesn’t love lambdas?

Not many people realize that within an ASPX template, it’s possible to pass sections of the template into a lambda. Here, let me show you the end result of using my Repeater<T> helper method. It’s an extension method of the HtmlHelper class in ASP.NET MVC.

<table>
  <% Html.Repeater<Hobby>("Hobbies", hobby => { %>
  <tr class="row">
    <td><%= hobby.Title %></td>
  </tr>
  <% }, hobbyAlt => { %>
  <tr class="alt-row">
    <td><%= hobbyAlt.Title %></td>
    </tr>
  <% }); %>
</table>

This renders a table with alternating rows. The Repeater method takes in two lambdas, one which represents the item template, and another that represents the alternating item template.

This particular overload of the Repeater method takes in a key to the ViewData dictionary and casts that to an IEnumerable<T>. In this case, it tries to cast ViewData["Hobbies"] to IEnumerable<Hobby>. I’ve included overloads that allow you to explicitly specify the items to repeat over.

This isn’t very remarkable when you think a bout it. What the above template code translates to is the following (roughly speaking)…

Response.Write("<table>");

Html.Repeater<Hobby>("Hobbies", hobby => {
    Response.Write("  <tr class=\"row\">");
    Response.Write("    <td>");
    Response.Write(hobby.Title);
    Response.Write("    </td>");
    Response.Write("  </tr>");
  }, hobbyAlt => { 
    Response.Write("  <tr class=\"alt-row\">");
    Response.Write("    <td>");
    Response.Write(hobbyAlt.Title);
    Response.Write("    </td>");
    Response.Write("  </tr>");
  });

Response.Write("</table>");

The code for the Repeater method is simple, short, and sweet.

public static void Repeater<T>(this HtmlHelper html
  , IEnumerable<T> items
  , Action<T> render
  , Action<T> renderAlt)
{
  if (items == null)
    return;

  int i = 0;
  items.ForEach(item => {
    if(i++ % 2 == 0 ) 
      render(item);
    else
      renderAlt(item); 
  });
}

public static void Repeater<T>(this HtmlHelper html
  , Action<T> render
  , Action<T> renderAlt)
{
  var items = html.ViewContext.ViewData as IEnumerable<T>;
  html.Repeater(items, render, renderAlt);
}

public static void Repeater<T>(this HtmlHelper html
  , string viewDataKey
  , Action<T> render
  , Action<T> renderAlt)
{
  var items = html.ViewContext.ViewData as IEnumerable<T>;
  var viewData = html.ViewContext.ViewData as IDictionary<string,object>;
  if (viewData != null)
  {
    items = viewData[viewDataKey] as IEnumerable<T>;
  }
  else
  {
    items = new ViewData(viewData)[viewDataKey] as IEnumerable<T>;
  }
  html.Repeater(items, render, renderAlt);
}

Some of the ViewData machinations you see here is due to the fact that ViewData might be a dictionary, or it might be an unknown type, in which case we perform the equivalent of a DataBinder.Eval call on it using the supplied view data key.

It turns out that the regular <asp:Repeater /> control works just fine with ASP.NET MVC, so there’s no need for such an ugly method call. I just thought it was fun to try out and provides an alternative approach that doesn’t require databinding.

UPDATE: I wanted to end this post here, but my compadre and others took exception to my implementation. Read on to see my improvement…

As astute readers of my blog noted, the example I used forces me to repeat a lot of template code in the alternative item case. The point of this post was on how to mimic the repeater, not in building a better one. Maybe you want to have a completely different layout in the alternate item case. I was going to build a another one that relied only on one template, but I figured I would leave that to the reader. But noooo, you had to complain. ;)

So the following is an example of a repeater method that follows the most common pattern in an alternating repeater. In this common case, you generally want to simply change the CSS class and nothing else. So with these overloads, you specify two CSS classes - one for items and one for alternating items. Here’s an example of usage.

<table>
  <% Html.Repeater<Hobby>("Hobbies", "row", "row-alt", (hobby, css) => { %>
  <tr class="<%= css %>">
    <td><%= hobby.Title%></td>
  </tr>
  <% }); %>
</table>

And here’s the source for the extra overloads. Note that I refactored the code for getting the enumerable from the ViewData into its own method.

public static void Repeater<T>(this HtmlHelper html
  , IEnumerable<T> items
  , string className
  , string classNameAlt
  , Action<T, string> render)
{
  if (items == null)
    return;

  int i = 0;
  items.ForEach(item =>
  {
    render(item, (i++ % 2 == 0) ? className: classNameAlt
  });
}

public static void Repeater<T>(this HtmlHelper html
  , string viewDataKey
  , string cssClass
  , string altCssClass
  , Action<T, string> render)
{
  var items = GetViewDataAsEnumerable<T>(html, viewDataKey);

  int i = 0;
  items.ForEach(item =>
  {
    render(item, (i++ % 2 == 0) ? cssClass : altCssClass);
  });
}

static IEnumerable<T> GetViewDataAsEnumerable<T>(HtmlHelper html, string viewDataKey)
{
  var items = html.ViewContext.ViewData as IEnumerable<T>;
  var viewData = html.ViewContext.ViewData as IDictionary<string, object>;
  if (viewData != null)
  {
    items = viewData[viewDataKey] as IEnumerable<T>;
  }
  else
  {
    items = new ViewData(viewData)[viewDataKey] 
      as IEnumerable<T>;
  }
  return items;
}

Hopefully that gets some people off my back now. ;)

Technorati Tags: aspnetmvc,asp.net

asp.net mvc, code comments edit

File this one away for the next time your boss comes in and asks,lumberg[1]

Yeaaah, I’m going to need you to make that little change to the code. It’ll only take you a couple hours, right?

Software has this deceptive property in which some changes that seem quite big and challenging to the layman end up being quite trivial, while other changes that seem quite trivial, end up requiring a lot of thought, care, and work.

Often, little changes add up to a lot.

I’m going to walk through a change we made that seemed like a no-brainer but ended up having a lot of interesting consequences that were invisible to most onlookers.

The Setup

I’ll provide just enough context to understand the change. The project I work on, ASP.NET MVC allows you to call methods on a class via the URL.

For example, a request for /product/list might call a method on a class named ProductController with a method named List. Likewise a request for /product/index would call the method named Index. We call these “web callable” methods, Actions. Nothing new here.

There were a couple rules in place for this to happen:

  • The controller class must inherit from the Controller class.
  • The action method must be annotated with the [ControllerAction] attribute applied to it.

We received a lot of feedback on the requirement for having that attribute. There were a lot of good reasons to have it there, but there were also a lot of good reasons to remove it.

Removing that requirement should be pretty simple, right? Just find the line of code that checks for the existence of the attribute and change it to not check at all.

The Consequences

Ahhh, if only it were that easy my friend. There were many consequences to that change. The solutions to these consequences were mostly easy. The hard part was making sure we caught all of them. After all, you don’t know what you don’t know.

Base Classes

So we removed the check for the attribute and the first thing we noticed is “Hey! Now I can make a request for /product/gethashcode, Cool!

Not so cool. Since every object ultimately inherits from System.Object, every object has several public methods: ToString(), GetHashCode(), GetType(), and Equals(), and so on… In fact, our Controller class itself has a few public methods.

The solution here is conceptually easy, we only look at public methods on classes that derive from our Controller class. In other words, we ignore methods on Controller and on Object.

Controller Inheritance

One of the rationales for removing the attribute is that in general, there isn’t much of a reason to have a public method on a controller class that isn’t available from the web. But that isn’t always true. Let’s look at one situation. Suppose you have the following abstract base controller.

public abstract class CoolController : Controller
{
  public virtual void Smokes() {...}

  public virtual void Gambles() {...}

  public virtual void Drinks() {...}
}

It is soooo cool!

You might want to write a controller that uses the CoolController as its base class rather than Controller because CoolController does some cool stuff.

However, you don’t think smoking is cool at all. Too bad, Smokes() is a public method and thus an action, so it is callable. At this point, we realized we need a [NonAction] attribute we can apply to an action to say that even though it is public, it is not an action.

With this attribute, I can do this:

public class MyReallyCoolController : CoolController
{
  [NonAction]
  public override void Smokes()
  {
    throws new NotImplementedException();
  }
}

Now MyReallyCoolController doesn’t smoke, which is really cool.

Interfaces

Another issue that came up is interfaces. Suppose I implement an interface with public methods.  Should those methods by default be callable? A good example is IDisposable. If I implement that interface, suddenly I can call Dispose() via a request for /product/dispose.

Since we already implemented the [NonAction] attribute, we decided that yes, they are callable if you implicitly implement them because they are public methods on your class and you have a means to make them not callable.

We also decided that if you explicitly implement an interface, those methods would not be callable. That would be one way to implement an interface without making every method an action and would not require you to annotate every interface method.

Special Methods

Keep in mind that in C# and VB.NET, property setters and getters are nothing more than syntactic sugar. When compiled to IL, they end up being methods named get_PropertyName() and set_PropertyName(). The constructor is implemented as a method named .ctor(). When you have an indexer on a class, that gets compiled to get_Item().

I’m not saying it was hard to deal with this, but we did have to remember to consider this. We needed to get a list of methods on the controller that are methods in the “typical” sense and not in some funky compiler-generated or specially named sense.

Edge Cases

Now we started to get into various edge cases. For example, what if you inherit a base controller class, but use the new keyword on your action of the same name as an action on the base class? What if you have multiple overloads of the same method? And so on. I won’t bore you with all the details. The point is, it was interesting to see all these consequences bubble up for such a simple change.

Is This Really Going To Help You With Your Boss?

Who am I kidding here? Of course not. :) Well…, maybe.

If your boss is technical, it may be a nice reminder that software is often like an iceberg. It is easy to see the 10% of work necessary, but the other 90% of work doesn’t become apparent till you dig deeper.

If your boss is not technical, we may well be speaking a different language here. I need to find an analogy that a business manager would understand. A situation in their world in which something that seems simple on the surface ends up being a lot of work in actuality. If you have such examples, be a pal and post them in the comments. The goal here is to find common ground and a shared language for describing the realities of software to non-software developers.

Technorati Tags: Software,Software Design,ASP.NET MVC

asp.net, asp.net mvc, code comments edit

In a recent post I expressed a few thoughts on using a DSL instead of an XML config file. I followed that up with a technical look at monkey patching CLR objects using IronRuby, which explores a tiny bit of interop.

These posts were precursors to this post in which I apply these ideas to an implementation that allows me to define ASP.NET MVC Routes using IronRuby. Also included in this download is an incomplete implementation of an IronRuby view engine. I haven’t yet implemented layouts.

IronRubyMvcDemo.zip Download (4.93 MB)

This implementation works with the latest CodePlex drop of MVC.

To use routes written in Ruby, reference the IronRubyMvcLibrary from your MVC Web Application and import the IronRubyMvcLibrary.Routing namespace into your Global.asax code behind file. From there, you can just call an extension method on RouteCollection like so…

public class GlobalApplication : System.Web.HttpApplication
{
  protected void Application_Start()
  {
    RouteTable.Routes.LoadFromRuby();
  }
}

This will look for a Routes.rb file within the webroot and use that file to load routes. Here’s a look at mine:

$routes.map "products/{action}/{id}"
  , {:controller => 'products', :action => 'categories', :id => ''}
$routes.map "{controller}/{action}/{id}", {:id => ''}
$routes.map "{controller}", {:action => 'index'}, {:controller => '[^\.]*'}
$routes.map "default.aspx", {:controller => 'home', :action => 'index'}

That’s it. No other cruft in there. I tried experimenting with lining up each segment using tabs so it looks like an actual table of data, rather than simply code definitions.

Also included in this download is a sample web app that makes use of the IronRubyViewEngine. You can see how I applied Monkey Patching to make referencing view data cleaner. Within an IronRuby view, you can access the view data via a global variable, $model. The nice part is, whether you pass strongly typed data or not to the view, you can always reference view data via $model.property_name.

In the case where the view data is a view data dictionary, this will perform a dictionary lookup using the property name as the key.

Be sure to check out the unit tests which provide over 95% code coverage of my code if you want to understand this code and improve on it. Next stop, Controllers in IronRuby…

Technorati Tags: ironruby,ruby,aspnetmvc,aspnet,dsl

code comments edit

In my last post I set the stage for this post by discussing some of my personal opinions around integrating a dynamic language into a .NET application. Using a DSL written in a dynamic language, such as IronRuby, to set up configuration for a .NET application is an interesting approach to application configuration.

With that in mind, I was playing around with some IronRuby interop with the CLR recently. Ruby has this concept called Monkey Patching. You can read the definition in the Wikipedia link I provided, but in short, it is a way to modify the behavior of a class or instance of a class at runtime without changing the source of that class or instance. Kind of like extension methods in C#, but more powerful. Let me provide a demonstration.

I want to pass a C# object instance that happens to have an indexer to a Ruby script via IronRuby. In C#, you can access an indexer property using square brackets like so:

object value = indexer["key"];

Being able to use braces to access this property is merely syntactic sugar by the C# language. Under the hood, this gets compiled to IL as a method named get_Item.

So when passing this object to IronRuby, I need to do the following:

value = $indexer.get_Item("key");

That’s not soooo bad (ok, maybe it is), but we’re not taking advantage of any of the power of Ruby. So what I did was monkey patch the method_missing method onto my object and used the method name as the key to the dictionary. This method allows you to handle unknown method calls on an object instance. You can read this post for a nice brief explanation.

So this allows me now to access the indexer from within Ruby as if it were a simple property access like so:

value = $indexerObject.key

The code for doing this is the following, based on the latest IronRuby code in RubyForge.

ScriptRuntime runtime = IronRuby.CreateRuntime();
ScriptEngine rubyengine = IronRuby.GetEngine(runtime);
RubyExecutionContext ctx = IronRuby.GetExecutionContext(runtime);

ctx.DefineGlobalVariable("indexer", new Indexer());
string requires = 
@"require 'My.NameSpace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=...'

def $indexer.method_missing(methodname)
  $indexer.get_Item(methodname.to_s)
end
";

//pretend we got the ruby script I really want to run from somewhere else
string rubyScript = GetRubyCode();

string script = requires + rubyScript;
ScriptSource source = rubyengine.CreateScriptSourceFromString(script);
runtime.ExecuteSourceUnit(source);

What’s going on here is that we instantiate the IronRuby runtime and script engine and context (I still need to learn exactly what each of these things are responsible for apart from each other). I then set a global variable and set it to an instance of a CLR object written in C#.

After that, I start constructing a string that contains the beginning of the Ruby script I want to execute. I will pre-append this beginning section with the actual script I want to run.

The beginning of the Ruby script imports the .NET namespace that contains my CLR type to IronRuby (I believe that by default you don’t need to import mscorlib and System).

I then added a missing_method method to that CLR instance within the Ruby code via this snippet.

def $indexer.method_missing(methodname);
  $indexer.get_Item(methodname.to_s)
end

At that point now, when I execute the rest of the ruby script, any calls from within Ruby to this CLR object can take advantage of this new method we patched onto the instance.

Pretty nifty, eh?

In my next post, I will show you the concrete instance of using this and supply source code.

Technorati Tags: DLR,IronRuby,DSL

code comments edit

Disclaimer: My opinions only, not anyone else’s. Nothing official here. I shouldn’t have to say this, but past history suggests I should. P.S. I’m not an expert on DSLs and Dynamic Languages ;)

This week I attended a talk by John Lam on IronRuby in which he trotted out the Uncle Ben line, with great power comes great responsibility. He was of course referring to the power in a dynamic language like Ruby.

Another quip he made stuck with me. He talked about how his brain sometimes gets twisted in a knot reading Ruby code written using metaprogramming techniques for hours at a time. It takes great concentration comprehending code on a meta and meta-meta level in which the code is manipulating and even rewriting code at runtime. Perhaps this is why C# will remain my primary language in the near term while I try and expand my brain to work on a higher level. ;)

However, the type of code I think he is referring to is the code for implementing a DSL itself. Once a DSL is written though, the code on top of that DSL ought to be quite readable. This is the nook where I see myself adopting IronRuby prior to using it as my primary language.I can see myself creating and using mini-DSLs (Domain Specific Languages) here and there as replacement for configuration.

Ahhh… configuration. I sometimes think this is a misnomer. At least in the way that the Java and .NET community have approached config in practice. We’ve had this trend in which we started jamming everything into XML configuration.

So much so, we often get asked to provide XML to configure features I think ought to be set in code along with unit tests. We’ve turned XML into a programming language, and a crappy one at that. Ayende talks about one issue with sweeping piles of XML configuration under a tool. This is not an intractable problem, but it highlights the fact that XML is code, but it is code with a lot of ceremony compared to the amount of essence. To understand what I mean by ceremony vs essence read Ending Legacy Code In Our Lifetime.

With the ASP.NET MVC project, we’ve taken the approach of Code First, Config Second. You can see this with our URL Routing feature. You define routes in code, and we might provide configuration for this feature in a future version.

With this approach, you can write unit tests for your route definitions which is a good thing! Routes basically turn the URL into a method invocation, why wouldn’t you want to have tests for that?

The reason I write about this now is that I’ve been playing around with IronRuby lately and want to post on some of the interesting stuff I’ve been doing in my own time. This post sets the context for why I am looking into this, apart from it just being plain fun and coming from a haacker ethic of wanting to see how things work.

Technorati Tags: DLR,IronRuby,Configuration,DSL

asp.net, asp.net mvc, code comments edit

UPDATE: Just to prove that this is a preview of a preview, we had a signing problem with the initial pre-built VSI download. If you tried building from source, everything should’ve been ok. We apologize for that. Even though this is meant to be a rough preview, we do want to have a high quality bar in that you should be able to try out the code. So if you run into that problem, please do download the VSI again.

It’s no secret that Microsoft can get better at naming non RTM (Release to Manufacturing) releases. We have terms like CTP, Preview, Alpha, Beta, RC (Release Candidate), and so on. On the other hand, at least Microsoft does try to move things along to RTM rather than keeping products in perpetual Beta.

With ASP.NET MVC, we also need to add yet another type of release. For now I’ve been calling this a CodePlex Source Release meaning it’s simply sharing source code that is in progress. ScottGu called it a “Preview of a Preview” in my office one day and that name stuck with me. This is really a preview of an upcoming preview. ;)

Speaking of ScottGu, he posted a detailed description of this release on his blog last night. I recommend taking a look at it because he covers most of the changes in good detail.

One aspect of this latest source release that I’m particularly happy about is that we released our unit tests. As Scott mentioned, we are using MoQ as a mock framework within our tests. Note that this is not some official endorsement of any particular mock framework. Originally we started out trying to port our tests to Rhino Mocks (which I’ve written a lot about). MoQ just happened to have a programming model that was closer to the way our internal mock framework works, so we switched over to MoQ.

I will write more about this release later. But for now, I will leave you with an updated Northwind Demo based on this release because there ain’t no party like a Northwind party.

Technorati Tags: aspnetmvc

personal comments edit

If ever someone was undeserving of having others spend their valuable time translating his blog, it would be me. But hey, some people from the http://blog.joycode.com/ site went ahead and did it anyway. I must admit that I’m very flattered that anyone would put the effort in.

Before this, I learned that Subtext powers MySpace China’s blogs, and now my blog is translated to Chinese. As David Hasselhoff says, “I’m big in China”. (To my Chinese audience, that is a joke. I am quite small.)

david_coleman

Technorati Tags: Chinese,China,Blogging