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

Today I read something where someone was comparing Web Forms to ASP.NET MVC and suggested that Web Forms does a lot more than ASP.NET MVC to protect your site from malicious attacks.

One example cited was that Server controls automatically handled HTML encoding so you don’t have to really think about it. The idea here is that Web Forms automatically protects you from XSS attacks.

My friends, I’m afraid this is just not true. Take a look at the following page code.

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<%
//For demo purposes, we have inline code here.
// Pretend the following userInput came from the database
string userInput = "<script>alert('You’ve been Haacked!');</script>";
label1.Text = userInput;
literal1.Text = userInput;
%>

<html>
<head>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="label1" runat="server" />
        <asp:Literal ID="literal1" runat="server" />
    </div>
    </form>
</body>
</html>

In this page, we simulate taking some some user input we got from somewhere, whether it’s from a form post or from a database, and we place it in a Label control, and in a Literal control.

These are two of the most common controls used to display user input. I’ll save you the suspense of having to actually try it out, and just show you what happens when run this page.

Message from
webpage

Contrary to popular belief, these controls do not automatically HTML encode their output. I don’t see this as some gaping security flaw because it may well be that the intention of these controls, and general usage, is to display HTML markup the developer specifies, not what the user specifies. The potential security flaw lies in using these controls without understanding what they actually do.

The lesson here is that you always have to think about security. There’s no silver bullet. There’s no panacea. Damien Guard has a great post where he lists other signs your ASP.NET application might be succeptible to injection attacks, pointing out various ways that protection is not automatic.

The best approach is to take a more holistic approach. Create a threat model for your website and start attacking your own site as if you were a hacker, looking for flaws. Conduct security reviews and use any automated tools you can find for finding potential flaws. I recommend taking a look at CAT.NET combined with the AntiXss library.

In this particular case, I don’t think Web Forms provides any more automatic security than ASP.NET MVC. With MVC, we’ve swapped server controls with our helper methods, which properly encode output. If you don’t use our helpers, it’s roughly equivalent to not using the server controls.

Interestingly enough, in order to get that particular user input to the page in the first place is tricky. If you were to create a Web Form with a text input and a button, and type that script tag into text box and click the button, you’d be greeted by the following yellow screen of death.

request-validation

By default, ASP.NET has Request Validation turned on, which prevents requests with suspicious looking data such as the one I tried. Note that ASP.NET MVC also has Request Validation turned on by default too. You can turn it off per Controller or Action via the ValidateRequestAttribute like so.

[ValidateInput(false)]
public ActionResult SomeAction(string someInput) {
}

This is not to say that I think ASP.NET MVC provides just as much automatic protection that Web Forms does. This is not exactly the case. There are some cases where Web Forms does provide more automatic protection that ASP.NET MVC leaves to you, the developer.

For example, ASP.NET MVC does not have an automatic equivalent of Event Validation which was introduced in ASP.NET 2.0. Note that event validation is very different from request validation and is very specific in to server controls. For example, as the blog post I linked to mentions, if you add a DropDownList control with three options, and a user posts a non-existent option, you will get an exception. ASP.NET MVC doesn’t have such automatic validation. In some cases, this is a good thing because it makes AJAX scenarios simpler.

What ASP.NET MVC does have is a set of Anti Forgery (CSRF) helpers which require a bit of manual intervention.

To recap, while I do agree that Web Forms does provide a bit more automatic security than ASP.NET MVC, the gap is not as wide as you might think. Server controls are no more nor less secure than using the Helpers with ASP.NET MVC. And all of that is irrelevant because it is still up to the developer’s to take responsibility for the security of his or her site. I’ve heard of many developers who had to turn off Request and Event Validation for various reasons. In those cases, they examined the attack vectors opened up by these changes and provided alternate protections to replace the ones they turned off.

asp.net, asp.net mvc comments edit

Here’s a little known fact about T4 Templates…well besides that they exist in the first place. Visual Studio 2005 had support for T3 templates. T4 is the natural successor to T3. T3 is also the abbreviation used when marketing the movie Terminator 3: Rise of the Machines. I heard that the names are related, but I haven’t confirmed it beyond a doubt, which seems appropriate given the title of the movie. But you didn’t hear that from me, deal?

terminator3 Dude looks ready to write some code!

Although they’ve been around forever, I haven’t really dived into T4 templates until recently as I’ve been using them in Subtext. I’m excited that we’re now incorporating them into ASP.NET MVC.

The Visual Web Developer Team Blog just posted an in-depth look at T4 templates in ASP.NET MVC entitled, T4 Templates: A Quick-Start Guide for ASP.NET MVC Developers.

Be sure to check out their other post covering What’s New for MVC Tools in ASP.NET MVC 1.0 Release Candidate.

asp.net, asp.net mvc comments edit

UPDATE: I have a followup to this post that works for down-level browsers.

In a recent post, Stephen Walther pointed out the dangers of using a link to delete data. Go read it as it provides very good coverage of the issues. The problem is not restricted to delete operations. Any time you allow a GET request to modify data, you’re asking for trouble. Read this story about something that happened to BackPack way back in the day to see what I mean.

The reason that delete operations deserve special attention is that it’s the most common case where you would use a link to change information. If you were editing a product record, for example, you would use a form. But a delete operation typically only needs one piece of information (the id) which is easy to encode in the URL of a GET request.

If you are using jQuery, one simple way to turn any link into a POST link is to add the following onclick attribute value:

$.post(this.href); return false;

For example

<a href="/go/delete/1" onclick="$.post(this.href); return false;">Delete</a>

Will now make a POST request to /go/delete/1 rather than a GET. Of course, you need to enforce this on the server side. This is pretty easy with ASP.NET MVC.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id) {
  //Delete that stuff!
}

The AcceptVerbs attribute specifies that this action method only responds to POST requests, not GET requests.

At this point, you could easily write helpers specifically for delete links. I usually write very specific helper methods such as Html.DeleteProduct or Html.DeleteQuestion. Here’s an example of one I wrote for a sample app I’m building.

public static string DeleteAnswerLink(this HtmlHelper html, string linkText
  , Answer answer) {
    return html.RouteLink(linkText, "answer",
        new { answerId = answer.Id, action = "delete" }, 
        new { onclick="$.post(this.href); return false;" });
}

The nice thing about this approach is that you can leverage the existing helper methods by adding a minimal amount of extra information via the onclick attribute.

I hope the combination of Stephen’s post and this post will lead you to safer deleting.

asp.net mvc, asp.net comments edit

Earlier this morning, I posted on making a simple jQuery delete link which makes it easy to create a delete link that does a form post to a delete action. Commenters pointed out that my solution won’t work for down-level browsers such as some mobile phones, and they were right. I wasn’t really concerned about down-level browsers.

One solution for down-level browsers is to render a proper form with a submit button, and then hide the form with JavaScript. Of course this takes a bit more work. Here’s what I did. I made sure I had the following script in my master template.

<script type="text/javascript">
 $("form.delete-link").css("display", "none");
 $("a.delete-link").show();
 $("a.delete-link").live('click', function(ev) {
    ev.preventDefault(); 
    $("form.delete-link").submit(); 
 });
</script>

When the following HTML is rendered in the page…

<form method="post" action="/go/delete/1" 
  class="delete-link">
  <input type="submit" value="delete" />
  <input name="__RequestVerificationToken" type="hidden" 
  value="Jrcn83M7T...8Z6RkdIfMZIJ5mVb" />
</form>
<a class="delete-link" href="/go/delete/1" 
  style="display:none;">delete</a>

… the jQuery code shown above will hide the form, but display the link (notice the link is hidden by default). When the link is clicked, it posts the form. However, in cases where there is no JavaScript, the form will be displayed, but the link will not be because the JavaScript is the thing that hides the form.

To make this easier to use, I wrote the following helper:

public static string DeleteLink(this HtmlHelper html
  , string linkText
  , string routeName
  , object routeValues) {
  var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
  string url = urlHelper.RouteUrl(routeName, routeValues);

  string format = @"<form method=""post"" action=""{0}"" 
  class=""delete-link"">
<input type=""submit"" value=""{1}"" />
{2}
</form>";

  string form = string.Format(format, html.AttributeEncode(url)
    , html.AttributeEncode(linkText)
    , html.AntiForgeryToken());
  return form + html.RouteLink(linkText, routeName, routeValues
  , new { @class = "delete-link", style = "display:none;" });
}

Notice that we’re using the AntiForgery helpers included with ASP.NET MVC. What this means is that I need to make one small change to my delete method on my controller. I need to add the ValidateAntiForgeryToken attribute to the method.

[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id) {
  //Delete it
}

I’ve left out a bit. For example, I didn’t specify a callback to the jQuery code. So what should happen when this action method returns? I leave that as an exercise to the reader. I may address it in a future follow-up to this blog post. In my code, I’m just being cheesy and doing a full redirect, which works fine.

asp.net mvc, asp.net comments edit

Hello there. :)

On Tuesday, we announced the release candidate for ASP.NET MVC. While there is much new in there to be excited about and many many bug fixes, there were two changes introduced in the RC that broke some scenarios which previously worked in the Beta, as reported by customers.

We’ve updated the Release Candidate with a refresh that addresses these two issues. You can use the recently released Microsoft Web Platform Installer 1.0 to install ASP.NET MVC RC Refresh. It happens to be a handy tool for installing not just ASP.NET MVC, but everything you might need to use ASP.NET MVC such as Visual Web Developer Express 2008 SP1.

The link on the official download page appears to be updated with the new MSI (we pushed it out yesterday), but we’ve experienced some odd proxy caching issues etc where some people were still getting the old MSI.

In order to be safe, you can get the download directly from this download link.I don’t anticipate any problems with that link, but being paranoid, the way to fully ensure you have the refresh is to right click on the downloaded file, select the Digital Signatures tab, and make sure the Time Stamp says Wednesday, January 28 and not Friday, January 23.

msi-props

Don’t forget to fully uninstall the previous RC before installing this one.

Also note that this refresh does not address the Controls Collection Cannot Be Modified issue I reported recently. We will address that soon. The following describes the issues that this refresh does fix.

The first change was that we changed our helper methods that generate URLs and links to now generate relative paths instead of absolute paths. This caused problems with several AJAX scenarios.

The fix to this in the refresh was to roll back that check-in so the behavior went back to the way it was in the Beta. We will not use relative paths, and we have no intention of re-introducing the generation of relative paths. Because we rolled back this change to a known good state, we feel very confident in the current behavior. URL generation should work the same way it did back in the Beta.

The other regression is that in some cases, the RouteUrl (and thus RouteLink) methods return an empty string when you specify a route name, but the route has default parameters which are not parameters in the URL.

For example, if you have the following route:

routes.MapRoute("route-name", 
  "foo/bar", 
  new {controller="Home", action="index"});

Notice that controller has default value, but is not part of the URL. If you then specify:

<%= Url.RouteUrl("route-name") %>

You might expect that it would use that route to render the URL, but it doesn’t. This bug was introduced when we refactored all our url generating helpers to call into a common method. It turns out, however, that our RouteUrl methods (aka non-MVC specific) should have subtly different behavior than the MVC specific methods (such as Action). We added a flag to the common method so that this difference is taken into consideration. This was a fix that did not have a large surface area.

Another thing we did was update all our test cases (both unit tests and automated functional tests) with scenarios reported to us by customers. So now, we have these types of cases well covered.

If you downloaded the Release Candidate before today, you should check the digital signature timestamp as I described earlier and if it’s the old one, I recommend you go and download the refresh via the Web Platform Installer or directly at the URL I mentioned earlier.

As I mentioned before, we are very excited about this release and hope that you are enjoying writing code with it. :)

asp.net mvc, asp.net comments edit

In my last post, I announced the happy news that the Release Candidate for ASP.NET MVC is available. In this post, I say mea culpa for a known bug within this release.

This bug is a consequence of a change we made in our default template. We know have a content placeholder in the <head> section of the Site.master page.

<head runat="server">
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

The benefit here is that it makes it easy to specify view specific scripts, style sheets, and title tags from the specific view, like so.

<asp:Content ID="indexHead" ContentPlaceHolderID="head" runat="server">
    <title>Home Page</title>
    <style type="text/css">
        /* Some style specific to this view */
    </style>
</asp:Content>

Long story short, if the Header control (aka <head runat="server" />) doesn’t see a title tag as a direct child of itself, it renders an empty title tag in order to ensure the page has valid HTML. This results in having two title tags, the one you intended and an empty one.

We put in a fix for this whereby we modify the controls collection of the header control, but the fix itself causes a problem when you have code nuggets within the <head> section. For example, the following causes an exception.

<head runat="server">
    <script src="<%= Url.Content("~/foo.js") %>" type="text/javascript">
    </script>
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

The exception this causes is:

The Controls collection cannot be modified because the control contains code blocks (i.e. <% … %>).

We unfortunately didn’t find this until very recently. The current workaround is simple. Place the script tag within a normal PlaceHolder control.

<head runat="server">
    <asp:PlaceHolder runat="server" id="mainScripts">
        <script src="<%= Url.Content("~/foo.js") %>" type="text/javascript">
        </script>
    </asp:PlaceHolder>
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

We have one simple solution to this we are bouncing around, and are investigating alternative solutions. We apologize for any inconveniences this may cause.

asp.net mvc, asp.net comments edit

At long last I am happy, relieved, excited to announce the release candidate for ASP.NET MVC. Feel free to go download it now. I’ll wait right here patiently.

There have been a lot of improvements made since the Beta release so be sure to read the release notes. I’ve tried very hard to be thorough in the notes so do let me know if anything is lacking. We are also pushing new tutorials up to the ASP.NET MVC Website as I write this.

Also, don’t miss ScottGu’s usual epic blog post describing the many improvements. There’s also a post on the Web Tools team blog covering tooling aspects of this release in detail. As I mentioned when we released the Beta, we didn’t have plans for many new features in the runtime, but we did have a lot of tooling improvements to add. I’ve already described some of these changes in a previous blog post, as did ScottGu in his detailed look.

Our goal with this release was to fix all outstanding bugs which we felt were real showstoppers and try to address specific customer concerns. We worked hard to add a bit of spit and polish to this release.

Unfortunately, a few minor bugs did crop up at the last second, but we decided we could continue with this RC and fix the bugs afterwards as the impact appear to be relatively small and they all have workarounds. I wrote about one particular bug so that you’re aware of it.

For now, I want to share a few highlights. This is not an exhaustive list at all. For that, check out Scott’s post and the release notes.

Ajax

Yes, I do know that jQuery released a new version (1.3.1), and no, it is not in this release. :) We just didn’t have time to include it due to the timing of its release. However, we are performing due diligence right now and plan to include it with the RTM.

We did make some changes to our Ajax helpers to recognize the standard X-Requested-With HTTP header used by the major JavaScript libraries such as Prototype.js, jQuery, and Dojo. Thus the IsMvcAjaxRequest method was renamed to IsAjaxRequest and looks for this header rather than our custom one.

ControllerContext

ControllerContext no longer inherits from RequestContext, which will improve testing and extensibility scenarios. We would have liked to make changes to RequestContext, but it was introduced as part of the .NET Framework in ASP.NET 3.5 SP1. Thus we can’t change it in our out-of-band release.

Anti Forgery Helpers

These helpers were previously released in our “futures” assembly, but we’ve fixed a few bugs and moved them into the core ASP.NET MVC assembly.

These are helpers which help mitigate Cross-Site Request Forgery (CSRF) attacks. For a great description of these helpers, check out Steve Sanderson’s blog post on the topic.

MVC Futures

I added a couple of expression based helpers to the ASP.NET MVC futures assembly, Microsoft.Web.Mvc.dll. These are just samples to demonstrate how one could write such helpers. I’ll add a few more by the time we ship the RTM. Note, if you’re using the old futures assembly, it won’t work with the new RC. You’ll need to update to the new Futures assembly.

In case you missed it the first time,click here for the Download.

asp.net comments edit

A while back on a lark, I posted a prototype demonstrating how one could use Routing within Web Forms. This is something you can do today with ASP.NET 3.5 SP1, because of the work we did to separate Routing from ASP.NET MVC. I would have liked to include Web Form Routing as part of the Routing feature when we were working on SP1, but we didn’t have the time to do so in a robust manner before SP1 was locked down.

Since then, Scott Galloway, who just happens to be my office mate, has taken the reigns and is the PM in change of guiding the Web Form Routing feature to be included in ASP.NET 4.0 in a more integrated fashion.

He wrote a blog post earlier today describing some of the ways that routing will be more deeply integrated into ASP.NET such as new properties of the Page class, cool uses of Expression Builders, etc… That’s just a teaser as he promises to go a little more in depth soon.

Technorati Tags: Routing,ASP.NET

code comments edit

UPDATE: Be sure to read Peli’s post in which he explores all of these implementations using PEX. Apparently I have a lot more unit tests to write in order to define the expected behavior of the code.

I recently wrote a post in which I examined some existing implementations of named format methods and then described the fun I had writing a routine for implementing named formats.

In response to that post, I received two new implementations of the method that are worth calling out.

The first was sent to me by Atif Aziz, who I’ve corresponded with via email regarding Jayrock. He noticed that the slowest format method by James had one obvious performance flaw and fixed it up. He then sent me another version that passed all my unit tests. Here it is in full, and it’s much faster than before.

public static class JamesFormatter
{
  public static string JamesFormat(this string format, object source)
  {
    return FormatWith(format, null, source);
  }

  public static string FormatWith(this string format
      , IFormatProvider provider, object source)
  {
    if (format == null)
      throw new ArgumentNullException("format");

    List<object> values = new List<object>();
    string rewrittenFormat = Regex.Replace(format,
      @"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+",
      delegate(Match m)
      {
        Group startGroup = m.Groups["start"];
        Group propertyGroup = m.Groups["property"];
        Group formatGroup = m.Groups["format"];
        Group endGroup = m.Groups["end"];

        values.Add((propertyGroup.Value == "0")
          ? source
          : Eval(source, propertyGroup.Value));

        int openings = startGroup.Captures.Count;
        int closings = endGroup.Captures.Count;

        return openings > closings || openings % 2 == 0
           ? m.Value
           : new string('{', openings) + (values.Count - 1) 
             + formatGroup.Value
             + new string('}', closings);
      },
      RegexOptions.Compiled 
      | RegexOptions.CultureInvariant 
      | RegexOptions.IgnoreCase);

    return string.Format(provider, rewrittenFormat, values.ToArray());
  }

  private static object Eval(object source, string expression)
  {
    try
    {
      return DataBinder.Eval(source, expression);
    }
    catch (HttpException e)
    {
      throw new FormatException(null, e);
    }
  }
}

The other version I got was from another Microsoftie named Henri Wiechers (no blog) who pointed out that a state machine of the sort that a parser or scanner would use, is well suited for this task. It also makes the code easier to understand if you’re accustomed to state machines.

public static class HenriFormatter
{
  private static string OutExpression(object source, string expression)
  {
    string format = "";

    int colonIndex = expression.IndexOf(':');
    if (colonIndex > 0)
    {
      format = expression.Substring(colonIndex + 1);
      expression = expression.Substring(0, colonIndex);
    }

    try
    {
      if (String.IsNullOrEmpty(format))
      {
        return (DataBinder.Eval(source, expression) ?? "").ToString();
      }
      return DataBinder.Eval(source, expression, "{0:" + format + "}") 
          ?? "";
    }
    catch (HttpException)
    {
      throw new FormatException();
    }
  }

  public static string HenriFormat(this string format, object source)
  {
    if (format == null)
    {
      throw new ArgumentNullException("format");
    }

    StringBuilder result = new StringBuilder(format.Length * 2);      

    using (var reader = new StringReader(format))
    {
      StringBuilder expression = new StringBuilder();
      int @char = -1;

      State state = State.OutsideExpression;
      do
      {
        switch (state)
        {
          case State.OutsideExpression:
            @char = reader.Read();
            switch (@char)
            {
              case -1:
                state = State.End;
                break;
              case '{':
                state = State.OnOpenBracket;
                break;
              case '}':
                state = State.OnCloseBracket;
                break;
              default:
                result.Append((char)@char);
                break;
            }
            break;
          case State.OnOpenBracket:
            @char = reader.Read();
            switch (@char)
            {
              case -1:
                throw new FormatException();
              case '{':
                result.Append('{');
                state = State.OutsideExpression;
                break;
              default:
                expression.Append((char)@char);
                state = State.InsideExpression;
                break;
            }
            break;
          case State.InsideExpression:
            @char = reader.Read();
            switch (@char)
            {
              case -1:
                throw new FormatException();
              case '}':
                result.Append(OutExpression(source, expression.ToString()));
                expression.Length = 0;
                state = State.OutsideExpression;
                break;
              default:
                expression.Append((char)@char);
                break;
            }
            break;
          case State.OnCloseBracket:
            @char = reader.Read();
            switch (@char)
            {
              case '}':
                result.Append('}');
                state = State.OutsideExpression;
                break;
              default:
                throw new FormatException();
            }
            break;
          default:
            throw new InvalidOperationException("Invalid state.");
        }
      } while (state != State.End);
    }

    return result.ToString();
  }

  private enum State
  {
    OutsideExpression,
    OnOpenBracket,
    InsideExpression,
    OnCloseBracket,
    End
  }
}

As before, I wanted to emphasize that this was not a performance contest. I was interested in correctness with reasonable performance.

Now that the JamesFormatter is up to speed, I was able to crank up the number of iterations to 50,000 without testing my patience and tried it again. I also made the format string slightly longer. Here are the new results.

named format perf take
2As you can see, they are all very close, though Henri’s method is the fastest.

I went ahead and updated the solution I had uploaded last time so you can try it yourself by downloading it now.

Tags: format strings , named formats

code comments edit

I’ve been having trouble getting to sleep lately, so I thought last night that I would put that to use and hack on Subtext a bit. While doing so, I ran into an old Asynchronous Fire and Forget helper method written way back by Mike Woodring which allows you to easily call a delegate asynchronously.

On the face of it, it seems like you could simply call BeginInvoke on the delegate and be done with it, Mike’s code addresses a concern with that approach:

Starting with the 1.1 release of the .NET Framework, the SDK docs now carry a caution that mandates calling EndInvoke on delegates you’ve called BeginInvoke on in order to avoid potential leaks. This means you cannot simply “fire-and-forget” a call to BeginInvoke without the risk of running the risk of causing problems.

The mandate he’s referring to, I believe, is this clause in the MSDN docs:

No matter which technique you use, always call EndInvoke to complete your asynchronous call.

Note that it doesn’t explicitly say “or you will get a memory leak”. But a little digging turns up the following comment in the MSDN forums.

The reason that you should call EndInvoke is because the results of the invocation (even if there is no return value) must be cached by .NET until EndInvoke is called.  For example if the invoked code throws an exception then the exception is cached in the invocation data.  Until you call EndInvoke it remains in memory.  After you call EndInvoke the memory can be released.  For this particular case it is possible the memory will remain until the process shuts down because the data is maintained internally by the invocation code.  I guess the GC might eventually collect it but I don’t know how the GC would know that you have abandoned the data vs. just taking a really long time to retrieve it.  I doubt it does.  Hence a memory leak can occur.

The thread continues to have some back and forth and doesn’t appear to be conclusive either way, but this post by Don Box gives a very pragmatic argument.

…the reality is that some implementations rely on the EndXXX call to clean up resources.  Sometimes you can get away with it, but in the general case you can’t.

In other words, why take the chance? In any case, much of this discussion is made redundant with the C# 3.0 Action class combined with ThreadPool.QueueUserWorkItem aka (QUWI)

Here is the code in Subtext for sending email, more or less. I have to define a delegate and then pass that to FireAndForget

// declaration
delegate bool SendEmailDelegate(string to, 
      string from, 
      string subject, 
      string body);

//... in a method body
SendEmailDelegate sendEmail = im.Send;
AsyncHelper.FireAndForget(sendEmail, to, from, subject, body);

This code relies on the FireAndForget method which I show here. Note I am not showing the full code. I just wanted to point out that the arguments to the delegate are not strongly typed. They are simply an array of objects which provide no guidance to how many arguments you need to pass.

public static void FireAndForget(Delegate d, params object[] args)
{
  ThreadPool.QueueUserWorkItem(dynamicInvokeShim, 
    new TargetInfo(d, args));
}

Also notice that this implementation uses QUWI under the hood.

With C# 3.0, there is no need to abstract away the call to QUWI. Just pass in a lambda, which provides the benefit that you’re calling the actual method directly so you get Intellisense for the argumennts etc… So all that code gets replaced with:

ThreadPool.QueueUserWorkItem(callback => im.Send(to, from, subject, body));

Much cleaner and I get to get rid of more code! As I’ve said before, the only thing better than writing code is getting rid of code!

asp.net, asp.net mvc comments edit

Rob pinged me today asking about how to respond to requests using different formats based on the extension in the URL. More specifically, he’d like to respond with HTML if there is no file extension, but with JSON if the URL ended with .json etc…

/home/index –> HTML

/home/index.json –> JSON

The first thing I wanted to tackle was writing a custom action invoker that would decide based on what’s in the route data, how to format the response.

This would allow the developer to simply return an object (the model) from an action method and the invoker would look for the format in the route data and figure out what format to send.

So I wrote a custom action invoker:

public class FormatHandlingActionInvoker : ControllerActionInvoker {
  protected override ActionResult CreateActionResult(
      ControllerContext controllerContext, 
      ActionDescriptor actionDescriptor, 
      object actionReturnValue) {
    if (actionReturnValue == null) {
      return new EmptyResult();
    }

    ActionResult actionResult = actionReturnValue as ActionResult;
    if (actionResult != null) {
      return actionResult;
    }

    string format = (controllerContext.RouteData.Values["format"] 
        ?? "") as string;
      switch (format) {
        case "":
        case "html":
          var result = new ViewResult { 
            ViewData = controllerContext.Controller.ViewData, 
            ViewName = actionDescriptor.ActionName 
          };
          result.ViewData.Model = actionReturnValue;
          return result;
          
        case "rss":
          //TODO: RSS Result
          break;
        case "json":
          return new JsonResult { Data = actionReturnValue };
    }

    return new ContentResult { 
      Content = Convert.ToString(actionReturnValue, 
       CultureInfo.InvariantCulture) 
    };
  }
}

The key thing to note is that I overrode the method CreateActionResult. This method is responsible for examining the result returned from an action method (which can be any type) and figuring out what to do with it. In this case, if the result is already an ActionResult, we just use it. However, if it’s something else, we look at the format in the route data to figure out what to return.

For reference, here’s the code for the HomeController which simply returns an object.

[HandleError]
public class HomeController : Controller {
  public object Index() {
    return new {Title = "HomePage", Message = "Welcome to ASP.NET MVC" };
  }
}

In order to make sure that all my controllers replaced the default invoker with this invoker, I wrote a controller factory that would set this invoker. I won’t show the code here, but I will include it in the download.

So at this point, we have everything in place, except for the fact that I haven’t dealt with how we get the format in the route data in the first place. Unfortunately, it ends up that this isn’t quite so straightforward. Consider the default route:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = "" }
);

Since this route allows for default values at each segment, this single route matches all the following URLs:

  • /home/index/123
  • /home/index
  • /home

So the question becomes, if we want to support optional format extensions in the URL, would we have to support it for every segment? Making up a fictional syntax, maybe it would look like this:

routes.MapRoute(
    "Default",
    "{controller{.format}}/{action{.format}}/{id{.format}}",
    new { controller = "Home", action = "Index", id = "", format = ""}
);

Where the {.format} part would be optional. Of course, we don’t have such a syntax available, so I needed to put on my dirty ugly hacking hat and see what I could come up with. I decided to do something we strongly warn people not to do, inheriting HttpRequestWrapper with my own HttpRequestBase implementation and stripping off the extension before I try and match the routes.

Warning! Don’t do this at home! This is merely experimentation while I mull over a better approach. This approach relies on implementation details I should not be relying upon

public class HttpRequestWithFormat : HttpRequestWrapper
{
  public HttpRequestWithFormat(HttpRequest request) : base(request) { 
  }

  public override string AppRelativeCurrentExecutionFilePath {
    get
    {
      string filePath = base.AppRelativeCurrentExecutionFilePath;
      string extension = System.IO.Path.GetExtension(filePath);
      if (String.IsNullOrEmpty(extension)) {
        return filePath;
      }
      else {
        Format = extension.Substring(1);
        filePath = filePath.Substring(0, filePath.LastIndexOf(extension));
      }
      return filePath;
    }
  }

  public string Format {
    get;
    private set;
  }
}

I also had to write a custom route.

public class FormatRoute : Route
{
  public FormatRoute(Route route) : 
    base(route.Url + ".{format}", route.RouteHandler) {
    _originalRoute = route;
  }

  public override RouteData GetRouteData(HttpContextBase httpContext)
  {
    //HACK! 
    var context = new HttpContextWithFormat(HttpContext.Current);

    var routeData = _originalRoute.GetRouteData(context);
    var request = context.Request as HttpRequestWithFormat;
    if (!string.IsNullOrEmpty(request.Format)) {
      routeData.Values.Add("format", request.Format);
    }

    return routeData;
  }

  public override VirtualPathData GetVirtualPath(
    RequestContext requestContext, RouteValueDictionary values)
  {
    var vpd = base.GetVirtualPath(requestContext, values);
    if (vpd == null) {
      return _originalRoute.GetVirtualPath(requestContext, values);
    }
    
    // Hack! Let's fix up the URL. Since "id" can be empty string,  
    // we want to check for this condition.
    string format = values["format"] as string;
    string funkyEnding = "/." + format as string;
    
    if (vpd.VirtualPath.EndsWith(funkyEnding)) { 
      string virtualPath = vpd.VirtualPath;
      int lastIndex = virtualPath.LastIndexOf(funkyEnding);
      virtualPath = virtualPath.Substring(0, lastIndex) + "." + format;
      vpd.VirtualPath = virtualPath;
    }

    return vpd;
  }

  private Route _originalRoute;
}

When matching incoming requests, this route replaces the HttpContextBase with my faked up one before calling GetRouteData. My faked up context returns a faked up request which strips the format extension from the URL.

Also, when generating URLs, this route deals with the cosmetic issue that the last segment of the URL has a default value of empty string. This makes it so that the URL might end up looking like /home/index/.jsonwhen I really wanted it to look like /home/index.json.

I’ve omitted some code from this blog post, but you can download the project here and try it out. Just navigate to /home/index and then try /home/index.json and you should notice the response format changes.

This is just experimental work. There’d be much more to do to make this useful. For example, would be nice if an action could specify which formats it would respond to. Likewise, it might be nice to respond based on accept headers rather than formats. I just wanted to see how automatic I could make it.

In any case, I was just having fun and didn’t have much time to put this together. The takeaway from this is really the CreateActionResult method of ControllerActionInvoker. That makes it very easy to create interesting default behavior so that your action methods can return whatever they want and you can implement your own conventions by overriding that method.

Download the hacky experiment here**and play with it at your own risk. :)

code, format comments edit

TRIPLE UPDATE! C# now has string interpolation which pretty much makes this post unnecessary and only interesting as a fun coding exercise.

DOUBLE UPDATE! Be sure to read Peli’s post in which he explores all of these implementations using PEX. Apparently I have a lot more unit tests to write in order to define the expected behavior of the code.

UPDATE: By the way, after you read this post, check out the post in which I revisit this topic and add two more implementations to check out.

Recently I found myself in a situation where I wanted to format a string using a named format string, rather than a positional one. Ignore for the moment the issue on whether this is a good idea or not, just trust me that I’ll be responsible with it.

The existing String.Format method, for example, formats values according to position.

string s = string.Format("{0} first, {1} second", 3.14, DateTime.Now);

But what I wanted was to be able to use the name of properties/fields, rather than position like so:

var someObj = new {pi = 3.14, date = DateTime.Now};
string s = NamedFormat("{pi} first, {date} second", someObj);

Looking around the internet, I quickly found three implementations mentioned in this StackOverflow question.

All three implementations are fairly similar in that they all use regular expressions for the parsing. Hanselman’s approach is to write an extension method of object (note that this won’t work in VB.NET until they allow extending object). James and Oskar wrote extension methods of the string class. James takes it a bit further by using DataBinder.Eval on each token, which allows you to have formats such as {foo.bar.baz} where baz is a property of bar which is a property of foo. This is something else I wanted, which the others do not provide.

He also makes good use of the MatchEvaluator delegate argument to the Regex.Replace method, perhaps one of the most underused yet powerful features of the Regex class. This ends up making the code for his method very succinct.

Handling Brace Escaping

I hade a chat about this sort of string parsing with Eilon recently and he mentioned that many developers tend to ignore or get escaping wrong. So I thought I would see how these methods handle a simple test of escaping the braces.

String.Format with the following:

Console.WriteLine(String.Format("{{{0}}}", 123));

produces the output (sans quotes) of “{123}”

So I would expect with each of these methods, that:

Console.WriteLine(NamedFormat("{{{foo}}}", new {foo = 123}));

Would produce the exact same output, “{123}”. However, only James’s method passed this test. But when I expanded the test to the following format, “{{{{{foo}}}}}”, all three failed. That should have produced “{{123}}”.

Certainly this is not such a big deal as this really is an edge case, but you never know when an edge case might bite you as Zune owners learned recently. More importantly, it poses an interesting problem - how do you handle this correctly? I thought it would be fun to try.

This is possible to handle correctly using regular expressions, but it’s challenging. Not only are you dealing with balanced matching, but the matching depends on whether the number of consecutive braces are odd or even.

For example, the following “{0}}” is not valid because the right end brace is escaped. However, “{0}}}” is valid. The expression is closed with the leftmost end brace, which is followed by an even number of consecutive braces, which means they are all escaped sequences.

Performance

As I mentioned earlier, only James’s method handles evaluation of sub-properties/fields via the use of the DataBinder.Eval method. Critics of his blog post point out that this is a performance killer.

Personally, until I’ve measured it in the scenarios in which I plan to use it, I doubt that the performance will really be an issue compared to everything else going on. But I thought I would check it out anyways, writing a simple console app which runs each method over 1000 iterations, and then divides by 1000 to get the number of milliseconds each method takes. Here’s the result:

format
perf

Notice that James’s method is 43 times slower than Hanselman’s. Even so, it only takes 4.4 milliseconds. So if you don’t use it in a tight loop with a lot of iterations, it’s not horrible, but it could be better.

My Implementation

At this point, I thought it would be fun to write my own implementation using manual string parsing rather than regular expressions. I’m not sure my regex-fu is capable of handling the challenges I mentioned before. After implementing my own version, I ran the performance test and saw the following result.

haackformat
perf

Nice! by removing the overhead of using a regular expression in this particular case, my implementation is faster than the other implementations, despite my use of DataBinder.Eval. Hopefully my implementation is correct, because fast and wrong is even worse than slow and right.

One drawback to not using regular expressions is that the code for my implementation is a bit long. I include the entire source here. I’ve also zipped up the code for this solution which includes unit tests as well as the implementations of the other methods I tested, so you can see which tests they pass and which they don’t pass.

The core of the code is in two parts. One is a private method which parses and splits the string into an enumeration of segments represented by the ITextExpression interface. The method you call joins these segments together, evaluating any expressions against a supplied object, and returning the resulting string.

I think we could optimize the code even more by joining these operations into a single method, but I really liked the separation between the parsing and joining logic as it helped me wrap my head around it. Initially, I hoped that I could cache the parsed representation of the format string since strings are immutable thus I could re-use it. But it didn’t end up giving me any real performance gain when I measured it.

public static class HaackFormatter
{
  public static string HaackFormat(this string format, object source)
  {

    if (format == null) {
        throw new ArgumentNullException("format");
    }

    var formattedStrings = (from expression in SplitFormat(format)
                 select expression.Eval(source)).ToArray();
    return String.Join("", formattedStrings);
  }

  private static IEnumerable<ITextExpression> SplitFormat(string format)
  {
    int exprEndIndex = -1;
    int expStartIndex;

    do
    {
      expStartIndex = format.IndexOfExpressionStart(exprEndIndex + 1);
      if (expStartIndex < 0)
      {
        //everything after last end brace index.
        if (exprEndIndex + 1 < format.Length)
        {
          yield return new LiteralFormat(
              format.Substring(exprEndIndex + 1));
        }
        break;
      }

      if (expStartIndex - exprEndIndex - 1 > 0)
      {
        //everything up to next start brace index
        yield return new LiteralFormat(format.Substring(exprEndIndex + 1
          , expStartIndex - exprEndIndex - 1));
      }

      int endBraceIndex = format.IndexOfExpressionEnd(expStartIndex + 1);
      if (endBraceIndex < 0)
      {
        //rest of string, no end brace (could be invalid expression)
        yield return new FormatExpression(format.Substring(expStartIndex));
      }
      else
      {
        exprEndIndex = endBraceIndex;
        //everything from start to end brace.
        yield return new FormatExpression(format.Substring(expStartIndex
          , endBraceIndex - expStartIndex + 1));

      }
    } while (expStartIndex > -1);
  }

  static int IndexOfExpressionStart(this string format, int startIndex) {
    int index = format.IndexOf('{', startIndex);
    if (index == -1) {
      return index;
    }

    //peek ahead.
    if (index + 1 < format.Length) {
      char nextChar = format[index + 1];
      if (nextChar == '{') {
        return IndexOfExpressionStart(format, index + 2);
      }
    }

    return index;
  }

  static int IndexOfExpressionEnd(this string format, int startIndex)
  {
    int endBraceIndex = format.IndexOf('}', startIndex);
    if (endBraceIndex == -1) {
      return endBraceIndex;
    }
    //start peeking ahead until there are no more braces...
    // }}}}
    int braceCount = 0;
    for (int i = endBraceIndex + 1; i < format.Length; i++) {
      if (format[i] == '}') {
        braceCount++;
      }
      else {
        break;
      }
    }
    if (braceCount % 2 == 1) {
      return IndexOfExpressionEnd(format, endBraceIndex + braceCount + 1);
    }

    return endBraceIndex;
  }
}

And the code for the supporting classes

public class FormatExpression : ITextExpression
{
  bool _invalidExpression = false;

  public FormatExpression(string expression) {
    if (!expression.StartsWith("{") || !expression.EndsWith("}")) {
      _invalidExpression = true;
      Expression = expression;
      return;
    }

    string expressionWithoutBraces = expression.Substring(1
        , expression.Length - 2);
    int colonIndex = expressionWithoutBraces.IndexOf(':');
    if (colonIndex < 0) {
      Expression = expressionWithoutBraces;
    }
    else {
      Expression = expressionWithoutBraces.Substring(0, colonIndex);
      Format = expressionWithoutBraces.Substring(colonIndex + 1);
    }
  }

  public string Expression { 
    get; 
    private set; 
  }

  public string Format
  {
    get;
    private set;
  }

  public string Eval(object o) {
    if (_invalidExpression) {
      throw new FormatException("Invalid expression");
    }
    try
    {
      if (String.IsNullOrEmpty(Format))
      {
        return (DataBinder.Eval(o, Expression) ?? string.Empty).ToString();
      }
      return (DataBinder.Eval(o, Expression, "{0:" + Format + "}") ?? 
        string.Empty).ToString();
    }
    catch (ArgumentException) {
      throw new FormatException();
    }
    catch (HttpException) {
      throw new FormatException();
    }
  }
}

public class LiteralFormat : ITextExpression
{
  public LiteralFormat(string literalText) {
    LiteralText = literalText;
  }

  public string LiteralText { 
    get; 
    private set; 
  }

  public string Eval(object o) {
    string literalText = LiteralText
        .Replace("{{", "{")
        .Replace("}}", "}");
    return literalText;
  }
}

I mainly did this for fun, though I plan to use this method in Subtext for email fomatting.

Let me know if you find any situations or edge cases in which my version fails. I’ll probably be adding more test cases as I integrate this into Subtext. As far as I can tell, it handles normal formatting and brace escaping correctly.

personal comments edit

At the end of the year, it’s very common for bloggers to take a look back at their own blog and list their favorite 10 blog posts. I find that somewhat narcissistic, so you know I’m going to do that.

But before I do, I thought it would be great to list the top 10 blog posts by others I read in 2008. The only problem is, I have very bad short-term memory and I can’t seem to remember which ones I read that had a real impact on my thinking. I’ll have to try and keep better track in 2009.

So based on a cursory Google search and look through my Google Reader app, here are some of my favorite blog posts of 2008 by you all, I couldn’t even list 10. Please do comment with your own favorite blog posts, mine or otherwise of 2008.

Favorite Posts I Read

My Top Posts (Using the Ayende Formula)

A while back, Ayende wrote up a weighted query for Subtext to determine the top posts. I updated it to only include mine published in

  1. Here are the top 5.

Milestones Moments

There are some posts that I personally liked because they represent important events that happened to me in 2008.

Ok, so maybe this post is pretty typical and doesn’t live up to the title I gave it. Oh well, I tried.

I’m sure I’m forgetting a whole lot of other important events that happened in 2008. I’m probably neglecting great blog posts that I read. But that’s the great thing about a blog, I’m confident people will point out my shortcomings in the comments to this post, and for that, I’m grateful. You all rock!

And with that, I leave you with this moment of zen, a photo taken near my house.

giant
snowman

asp.net, asp.net mvc comments edit

Dmitry, who’s the PUM for ASP.NET, recently wrote a blog post about an interesting approach he took using VB.NET XML Literals as a view engine for ASP.NET MVC.

Now before you VB haters dismiss this blog post and leave, bear with me for just a second. Dmitry and I had a conversation one day and he noted that there are a lot of similarities between our view engine hierarchy and and normal class hierarchies.

For example, a master page is not unlike a base class. Content placeholders within a master page are similar to abstract methods. Content placeholders with default content are like virtual methods. And so on…

So he thought it would be interesting to have a class be a view rather than a template file, and put together this VB demo. One thing he left out is what the view class actually looks like in Visual Studio, which I think is kinda cool (click on image for larger view).

VB.NET XML Literal
View

Notice that this looks pretty similar to what you get in the default Index.aspx view. One advantage of this approach is that you’re always using VB rather than switching over to writing markup. So if you forget to close a tag, for example, you get immediate compilation errors.

Another advantage is that your “view” is now compiled into the same assembly as the rest of your code. Of course, this could also be a disadvantage depending how you look at it.

code comments edit

I was reading Jeff Atwood’s latest post, Programming: Love it or Leave it when I came across this part, emphasis mine.

Joel implied that good programmers love programming so much they’d do it for no pay at all. I won’t go quite that far, but I will note that the best programmers I’ve known have all had a lifelong passion for what they do. There’s no way a minor economic blip would ever convince them they should do anything else. No way. No how.

Unlike Jeff, I will go that far. I love to code, and I do it for free all the time.

I don’t think Joel meant to imply that programmers would continue to write code for their current employers for free in lieu of any pay. What I think he meant was that programmers who love to code will code for fun as well as profit. They’ll write code outside of their paying jobs.

For example, I took the entire week off last week and spent lots of time with my family, which was wonderful (cue gratuitous picture of kid)! I trained my son in Ninja acrobatics.

cody ninja
acrobatics 

I got my brother completely hooked on Desktop Tower Defense.

brian playing desktop tower
defense

And tried to figure out what sort of mischief my son was involved in, as that face is as guilty as sin.

mischief

However, along with all that family fun, I spent nearly every minute of downtime hacking on Subtext. I went on a huge refactoring binge cleaning up stale code, separating concerns left and right, and replacing the old method of matching requests with ASP.NET Routing.

And it was huge fun!

And I’m not alone. I noticed several streams on Twitter of folks having fun writing code, such as Glenn Block sharing his learning in the open experiences, among others.

Developers I’ve worked with who really love to code, tend to do it for fun, as well as for work. Personally, I don’t think it’s unhealthy as long as it’s not the only thing you do for fun. And I’m not suggesting that if you don’t do it for fun, you don’t love to code. Some people work so much, they don’t have time to do it for fun, but would code for fun if they had copious free time.

As for me, I’ll say it again, I <3 to code.

asp.net, asp.net mvc comments edit

A while ago ScottGu mentioned in his blog that we would try and have an ASP.NET MVC Release Candidate by the end of this year. My team worked very hard at it, but due to various unforeseeable circumstances, I’m afraid that’s not gonna happen. Heck, I couldn’t even get into the office yesterday because the massive dumping of snow. I hope to get in today a little later since I’m taking next week off to be with my family coming in from Alaska.

But do not fret, we’ll have something early next year to release. In the meanwhile, we gave some rough bits to Scott Guthrie to play with and he did not disappoint yet again with a a great detailed post on some upcoming new features both in the runtime and in tooling.

look-ma-no-code-behind Often, it’s the little touches that get me excited, and I want to call one of those out, Views without Code-Behind. This was always possible, of course, but due to some incredible hacking down in the plumbings of ASP.NET , David Ebbo with some assistance from Eilon Lipton, figured out how to get it to work with generic types using your language specific syntax for generic types. If you recall, previously it required using that complex CLR Syntax within the Inherits attribute.

Keep in mind that they had to do this without touching the core ASP.NET bits since ASP.NET MVC is a bin-deployable out-of-band release. David provided some hints on how they did this within his blog in these two posts: ProcessGeneratedCode: A hidden gem for Control Builder writers and Creating a ControlBuilder for the page itself.

 

In the meanwhile, Stephen Walther has been busy putting together a fun new section of the ASP.NET MVC website called the ASP.NET MVC Design Gallery.

In one of my talks about ASP.NET MVC, I mentioned a site that went live with our default drab blue project template (the site has since redesigned its look entirely). The Design Gallery provides a place for the community to upload alternative designs for our default template.

Happy Holidays

Cody Again, I apologize that we don’t have updated bits for you to play with, but we’ll have something next year! In the meanwhile, as the end of this year winds down, I hope it was a good one for you. It certainly was a good one for me. Enjoy your holidays, have a Merry Christmas, Hannukah, Kwanza, Winter Solstice, Over Consumption Day, whatever it is you celebrate or don’t celebrate. ;)

asp.net mvc, asp.net comments edit

ASP.NET Routing is useful in many situations beyond ASP.NET MVC. For example, I often need to run a tiny bit of custom code in response to a specific request URL. Let’s look at how routing can help.

First, let’s do a quick review. When you define a route, you specify an instance of IRouteHandler associated with the route which is given a chance to figure out what to do when that route matches the request. This step is typically hidden from most developers who use the various extension methods such as MapRoute.

Once the route handler makes that decision, it returns an instance of IHttpHandler which ultimately processes the request.

There are many situations in which I just have a tiny bit of code I want to run and I’d rather not have to create both a custom route handler and http handler class.

So I started experimenting with some base handlers that would allow me to pass around delegates.

Warning: the code you are about to see may cause permanent blindness. This was done for fun and I’m not advocating you use the code as-is.

It works, but the readability of all these lambda expressions may cause confusion and insanity.

One common case I need to handle is permanently redirecting a set of URLs to another set of URLs. I wrote a simple extension method of RouteCollection to do just that. In my Global.asax.cs file I can write this:

routes.RedirectPermanently("home/{foo}.aspx", "~/home/{foo}");

This will permanently redirect all requests within the home directory containing the .aspx extension to the same URL without the extension. That’ll come in pretty handy for my blog in the future.

When you define a route, you have to specify an instance of IRouteHandler which handles matching requests. That instance in turn returns an IHttpHandler which ultimately handles the request. Let’s look at the simple implementation of this RedirectPermanently method.

public static Route RedirectPermanently(this RouteCollection routes, 
    string url, string targetUrl) {
  Route route = new Route(url, new RedirectRouteHandler(targetUrl, true));
  routes.Add(route);
  return route;
}

Notice that we simply create a route using the RedirectRouteHandler. As we’ll see, I didn’t even need to do this, but it helped make the code a bit more readable. To make heads or tails of this, we need to look at that handler. Warning: Some funky looking code ahead!

public class RedirectRouteHandler : DelegateRouteHandler {
  public RedirectRouteHandler(string targetUrl) : this(targetUrl, false) { 
  }

  public RedirectRouteHandler(string targetUrl, bool permanently)
    : base(requestContext => {
      if (targetUrl.StartsWith("~/")) {
        string virtualPath = targetUrl.Substring(2);
        Route route = new Route(virtualPath, null);
        var vpd = route.GetVirtualPath(requestContext, 
          requestContext.RouteData.Values);
        if (vpd != null) {
          targetUrl = "~/" + vpd.VirtualPath;
        }
      }
      return new DelegateHttpHandler(httpContext => 
        Redirect(httpContext, targetUrl, permanently), false);
    }) {
    TargetUrl = targetUrl;
  }

  private void Redirect(HttpContext context, string url, bool permanent) {
    if (permanent) {
      context.Response.Status = "301 Moved Permanently";
      context.Response.StatusCode = 301;
      context.Response.AddHeader("Location", url);
    }
    else {
      context.Response.Redirect(url, false);
    }
  }

  public string TargetUrl { get; private set; }
}

I bolded a portion of the code within the constructor. The bolded portion is a delegate (via a lambda expression) being passed to the base constructor. Rather than creating a custom IHttpHandler class, I am telling the base class what code I would want that http handler (if I had written one) to execute in order to process the request. I pass that code as a lambda expression to the base class.

I think in a production system, I’d probably manually implement RedirectRouteHandler. But while I’m having fun, let’s take it further.

Let’s look at the DelegateRouteHandler to understand this better.

public class DelegateRouteHandler : IRouteHandler {
  public DelegateRouteHandler(Func<RequestContext, IHttpHandler> action) {
    HttpHandlerAction = action;
  }

  public Func<RequestContext, IHttpHandler> HttpHandlerAction {
    get;
    private set;
  }

  public IHttpHandler GetHttpHandler(RequestContext requestContext) {
    var action = HttpHandlerAction;
    if (action == null) {
      throw new InvalidOperationException("No action specified");
    }
    
    return action(requestContext);
  }
}

Notice that the first constructor argument is a Func<RequestContext, IHttpHandler>. This is effectively the contract for an IRouteHandler. This alleviates the need to write new IRouteHandler classes, because we can instead just create an instance of DelegateRouteHandler directly passing in the code we would have put in the custom IRouteHandler implementation. Again, in this implementation, to make things clearer, I inherited from DelegateRouteHandler rather than instantiating it directly. To do that would have sent me to the 7^th^ level of Hades immediately. As it stands, I’m only on the 4^th^ level for what I’ve shown here.

The last thing we need to look at is the DelegateHttpHandler.

public class DelegateHttpHandler : IHttpHandler {

  public DelegateHttpHandler(Action<HttpContext> action, bool isReusable) {
    IsReusable = isReusable;
    HttpHandlerAction = action;
  }

  public bool IsReusable {
    get;
    private set;
  }

  public Action<HttpContext> HttpHandlerAction {
    get;
    private set;
  }

  public void ProcessRequest(HttpContext context) {
    var action = HttpHandlerAction;
    if (action != null) {
    action(context);
    }
  }
}

Again, you simply pass this class an Action<HttpContext> within the constructor which fulfills the contract for IHttpHandler.

The point of all this is to show that when you have interfaces with a single methods, they can often be transformed into a delegate by writing a helper implementation of that interface which accepts delegates that fulfill the same contract, or at least are close enough.

This would allow me to quickly hack up a new route handler without adding two new classes to my project. Of course, the syntax to do so is prohibitively dense that for the sake of those who have to read the code, I’d probably recommend just writing the new classes.

In any case, however you implement it, the Redirect and RedirectPermanent extension methods for handling routes is still quite useful.

personal comments edit

UPDATE: There’s a workaround mentioned in the Google Groups. It’s finally resolved.

Ever since I first started using FeedBurner, I was very happy with the service. It was exactly the type of service I like, fire and forget and it just worked. My bandwidth usage went down and I gained access to a lot of interesting stats about my feed.

When I was first considering it, others warned me about losing control over my RSS feed. That led me to pay for the MyBrand PRO feature which enabled me to burn my feed using my own domain name at http://feeds.haacked.com/haacked by simply creating a CNAME from feeds.haacked.com to feeds.feedburner.com.

The idea was that if I ever wanted to reclaim my feed because something happened to FeedBurner or because I simply wanted to change, I could simply remove the CNAME and serve up my feed itself.

That was the idea at least.

This week, I learned the fatal flaw in that plan. When Google bought FeedBurner, nothing really changed immediately, so I was completely fine with it. But recently, they decided to change the domain over to a google domain. I had assumed they would do a CNAME to their own domain for MyBrand users. Instead, I saw that they were redirecting users to their own domain, thus taking control away from me over my own feed and completely nullifying the whole point of the MyBrand service.

That’s right. People who were subscribed via my feeds.haacked.com domain were being redirected to a google domain.

Ok, perhaps I’m somewhat at fault for ignoring the email on November 25 announcing the transition, but I’m a busy guy and that didn’t leave me much time to plan the transition.

And even if I had, I would have still been screwed. I followed the instructions provided and set up a CNAME from feeds.haacked.com to haackedgmail.feedproxy.ghs.google.com and watched the next day as my subscriber count dropped from 11,000 to 827. I’ve since changed the CNAME back to the feedburner.com domain (I tried several variations of the CNAME beforehand) and am resigned to let the redirect happen for now.

In the meanwhile, I’ve set up a CNAME from feeds3.haacked.com to the one they gave me and it still doesn’t work. At the time I write this, http://feeds3.haacked.com/haacked gives a 404 error.

I’m very disappointed in the haphazard manner they’ve made this transition, but I’m willing to give a second chance if they’d only fix the damn MyBrand service.

asp.net mvc, asp.net comments edit

While at PDC, I met Louis DeJardin and we had some lively discussions on various topics around ASP.NET MVC. He kept bugging me about some view engine called Flint? No… Electricity? No… Spark!

I had heard of it, but never got around to actually playing with it until after the conference. And the verdict is, I really like it.

Spark is a view engine for both Monorail and ASP.NET MVC. It supports multiple content area layouts much like master pages, which is one thing that seems to be lacking in many other view engines I’ve seen, which only support a single content area, correct me if I’m wrong. Not only that, but he’s already included IronPython and IronRuby support.

But what I really like about it is the simple way you effectively data bind HTML elements to code. Let’s start with a simple example. Suppose you have an enumeration of products you’re passing to the view from your controller action. Here’s how you might render it in Spark.

<viewdata model="IEnumerable[[Product]]"/>

<ul class="products">
  <li each="var product in ViewData.Model">${product.ProductName}</li>
</ul>

Note the each attribute of the <li> tag contains a code expression. This will repeat the <li> tag once per product. The <viewdata> element there declares the type of the ViewData.Model property.

Spark still supports using code nuggets <% %> when you absolutely need them. For example, when using the BeginForm method, I needed a using block, so I used the code nuggets.

Just for fun, I redid the views of my Northwind sample to replace all the ASPX views with Spark as a demonstartion of using an alternative view engine. Try it out.

UPDATE: Updated to the latest version of ASP.NET MVC and Spark as of ASP.NET MVC 1.0 RC 2.

asp.net mvc, asp.net comments edit

I’m working to try and keep internal release notes up to date so that I don’t have this huge amount of work when we’re finally ready to release. Yeah, I’m always trying something new by giving procrastination a boot today.

These notes were sent to me by Jacques, a developer on the ASP.NET MVC feature team. I only cleaned them up slightly.

The sections below contain descriptions and possible solutions for known issues that may cause the installer to fail. The solutions have proven successful in most cases.

Visual Studio Add-ins

The ASP.NET MVC installer may fail when certain Visual Studio add-ins are already installed. The final steps of the installation installs and configures the MVC templates in Visual Studio. When the installer encounters a problem during these steps, the installation will be aborted and rolled back. MVC can be installed from a command prompt using msiexec to produce a log file as follows:

msiexec /i AspNetMVCBeta-setup.msi /q /l*v mvc.log

If an error occurred the log file will contain an error message similar to the example below.

MSI (s) (C4:40) [20:45:32:977]: Note: 1: 1722 2: VisualStudio_VSSetup_Command 3: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe 4: /setup

MSI (s) (C4:40) [20:45:32:979]: Product: Microsoft ASP.NET MVC Beta – Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action VisualStudio_VSSetup_Command, location: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe, command: /setup

Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action VisualStudio_VSSetup_Command, location: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe, command: /setup

This error is usually accompanied by a corresponding event that will be logged in the Windows Event Viewer:

Faulting application devenv.exe, version 9.0.30729.1, time stamp 0x488f2b50, faulting module unknown, version 0.0.0.0, time stamp 0x00000000, exception code 0xc0000005, fault offset 0x006c0061, process id 0x10e0, application start time 0x01c9355ee383bf70

In most cases, removing the add-ins before installing MVC, and then reinstalling the add-ins, will resolve the problem. ASP.NET MVC installations have been known to run into problems when the following add-ins were already installed.:

  • PowerCommands
  • Clone Detective

Cryptographic Services

In a few isolated cases, the Windows Event Viewer may contain an Error event with event source CAPI2 and event ID 513. The event message will contain the following: Cryptograhpic Services failed while processing the OnIdentity() call in the System Writer Object.

The article at http://technet.microsoft.com/en-us/library/cc734021.aspx describes various steps a user can take to correct the problem, but in some cases simply stopping and restarting the Cryptographic services should allow the installation to proceed.