I am on Twitter

So those persuasive alt.net guys finally nudged me to get a twitter account.  Last conference I came home and started a blog, this time its twitter.  As long as its not naked jazz they can persuade me to do just about anything.  They almost got me to get rid of my RDBMS.

alt.net part II

So better late than never. Alt.Net Seattle was awesome! Last October, Austin set the bar high and Seattle blew it away. The best part was all the new faces at the conference. The community has really grown and evolved since Austin which made the experience all the more refreshing and interesting.

It was great to get a chance to see guys I haven’t seen in a while like: Roy, Chris, Dru, Jason, Jeremy, Dave, and that crazy posse known as the “Eleutian Guys“. I also had the opportunity to meet tons of new people including Adam Dymitruk, Chris Sutton, Scott Reynolds, Tim Barcz, and Greg Young. (If I left your name out I blame Greg as he overloaded my brain with this double double d stuff).

Listening to Greg and Udi talk about distributed messaging was fascinating. The idea of using asynchronous messaging and moving away from traditional request / response style of programming is something that I want to learn and work into my applications. I am not quite ready throw out my RDBMS but thinking about it as just “Dead Object Storage” is much more fun. I need to engage Adam Dymitruk to talk more about how his team made the transition to asynchronous messaging. He said with some of Greg’s help it was pretty painless and the benefits the team has seen are huge.

I made sure I left time to hang out after the conference was over this time. A number of people hung around for a while as well, of course the conversations continued through lunch, over to the book store, and back to the hotel. By 8pm on Sunday I was dead, I could only imagine what the guys who went to both the MVP Summit and alt.net felt like. Thanks to Roy, and TypeMock the stragglers got treated to one final meal where yes, more geek speak was spoken. Doc and I had a chance to talk for a while at dinner, he did another amazing job facilitating the conference.

So what’s next…

Scott Bellware spoke of organizing another alt.net like conference in Austin around October 10th or so.

Scott Hanselman posted a nice piece about the alt.net community in general.

Last night here in Chicago we had our 3rd alt.net meeting. Derik has a summary of the meeting on the yahoo group. If you are interested in writing better software, getting rid of some of that daily developer pain, or just knocking back a couple beers with some local devs I encourage you come to the next meeting.

Thanks again Dave and the rest the organizers for putting this one together. And a special thanks to the sponsors, Digipen, InfoQ, Microsoft P&P, ThoughtWorks, and VersionOne.

Tags: ,

Eleutian Vim Screencast Episode #1

After Aaron’s teaser on vim, I have been waiting for him to start the series. Episode #1 of Aaron’s Vim screencast series is up. Its a basic intro for opening and saving documents as well as learning to use some simple navigation. The use of keyboard jedi is very nice for seeing everything that is going on. Nice work Aaron! If you are unfamiliar with vim I highly recommend subscribing to Eleutian’s blog and following the series. The productivity boost you will gain down the road is priceless.

Ms MVC at CNUG

Yesterday at the Chicago .Net User Group meeting Nermin Dibek presented on the new ms mvc framework.  Several people were interested in a follow up session.  If you are one of those people and have stumbled onto this blog, or if you are local to Chicago and want to see some more stuff, feel free to ping me or email me and we can try and set something up.

Here is a list of links to get you started with Ms MVC.

Tags: ,

MS MVC: Blocks Refactored

In my last post I talked about adding blocks to ms mvc to capture output.  Our solution used an ugly hack with reflection, type caching, and lwg.  Thanks to Jeremy Skinner and Phil who both pointed out you can use a response output filter to do the same thing.  So here is an update to our capturing class.

/// <summary>Renders the action and returns a string.</summary>
/// <param name=”viewRenderer”>The delegate to render.</param>
/// <returns>The rendered text.</returns>
public string Capture(Action viewRenderer)
{
  IHttpResponse resp = _httpContext.Response;
  Stream originalFilter = null;
  CapturingResponseFilter innerFilter;
  string capturedHtml = ““;

  if (viewRenderer != null)
  {
    try
    {
      resp.Flush();
      originalFilter = resp.Filter;
      innerFilter = new CapturingResponseFilter(resp.Filter);
      resp.Filter = innerFilter;
      viewRenderer();
      resp.Flush();
      capturedHtml = innerFilter.GetContents(resp.ContentEncoding);
    }
    finally
    {
      if (originalFilter != null)
      {
        resp.Filter = originalFilter;
      }
    }
  }
  return capturedHtml;
}

The only thing to remember is to flush current response before and after you capture the text.  The CapturingResponseFilter just inherits from Stream and is using a MemoryStream internally.  The call to GetContents just dumps the memory stream to a string using the current encoding of the response.

What do you think… much simpler :)

Thanks Jeremy and Phil.

MS MVC Gets Blocks From Rails

Updated 2008-01-16:

Check out the refactored version which drops the reflection and uses a straight response filter.


Sergio Pereira and I started writing some stories today for Javascript helpers in Mvc Contrib.  During our talk we had to deal with rendering html elements with inner html and javascript blocks ensuring they all got closed but still allowing the ultimate in flexibility for the developer.MvcToolkit goes about this with a using(…) pattern on their FormHelper.  The one disadvantage of this is that the using block will be limited to only a single block.  What happens when you need to render a block for onSuccess and onFailure?

Sergio brought up how powerful ruby blocks are and how cool it would be if we could use lambdas to do something similar.

Sergio proposed being able to do something like this.

<% Ajax.Tag(”div“,  “/controller/action/123“,
new {CssClass=”bigSquare“}, myDiv =>
{ %>
Some Html here
Some helper: <%= Html.Link(”Click me“, “/other/non-ajax/url“) %>
}) %>

What is myDiv?  myDiv is the blocks outer HtmlElement object so inside of your lambda you can manipulate its attributes and perform some other cool stuff we are still cooking up.  While the lambda executes we capture the output and defer rendering to the response until after the lambda is finished.  This allows us to render the HtmlElement with any modifications you made.

So how do we do this, well, we needed a pretty big hack because our delegate is being called from another anonymous delegate which has the HtmlTextWriter as a local variable.  This means that we cannot use IHttpContext.SwitchWriter to capture our output.

Any way to get a fix for this MS?

So in reflector I noticed my anonymous type for my delegate had a public field __w which was the HtmlTextWriter.  Using some reflection I was able to code up my own SwitchWriter which took care of everything.

The helper code is pretty simple.

public static void FromTag(this AjaxHelper helper
  ,string tag
  ,string url
  ,object options,
  Action<Element> innerHtml)
{
  Element element = new Element(tag);
  HtmlTextWriter responseWriter = null;

  if(innerHtml != null)
  {
      try
      {
        using(StringWriter innerWriter = new StringWriter())
        using (HtmlTextWriter innerHtmlWriter =
          new HtmlTextWriter(innerWriter))
        {
          responseWriter = SwitchWriter(innerHtml, innerHtmlWriter);
          innerHtml(element);
          innerHtmlWriter.Flush();
          element.InnerHtml = innerWriter.ToString();
        }
      }
      finally
      {
        if(responseWriter != null)
        {
          SwitchWriter(innerHtml, responseWriter);
        }
      }
  }
  RenderElement(new HtmlTextWriter(
    helper.ViewContext.HttpContext.Response.Output), element);
}

The switch writer is pretty basic, it was tracking it down that took a little bit of time.

public static HtmlTextWriter SwitchWriter(object obj
  , HtmlTextWriter newWriter)
{
  Type actionType = obj.GetType();

  object target = actionType.GetField(”_target“,
    BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(obj);

  Type targetType = target.GetType();

  HtmlTextWriter response = targetType.GetField(”__w“)
    .GetValue(target) as HtmlTextWriter;

  targetType.GetField(”__w“).SetValue(target, newWriter);

  return response;
}

With the above in place I can call it with something like this.

<% Ajax.FromTag("div“, “/Home/About“,
  new object(),
  myDiv => { myDiv.Id = “Justice“; %><h6>
      <%=Html.ActionLink(”Where is Justice?“, “About“)%>
   </h6>
<% }); %>

And it renders something like this… no we didn’t spike any ajax stuff yet.

<div id=“Justice”>
 <h6><a href=“/Home/About”>Where is Justice?</a></h6>
</div>

You may wonder why we do not return a string from our helper.  Asp.Net currently can’t handle that.  It thinks its a block and not a simple expression so using the regular <%= %> will not work.  Instead of having you call <%Response.Write(…);%> we thought it would be easier if the helper just rendered it for you.

This got me excited about some the cool things we can really start to do.  I like getting an instance of Element to set properties on, this can help reduce the abuse that anonymous types are taking in mvc right now.  It would be great if there could be patch so we do not have to resort to reflection to switch writers, but I quote Sergio

how do you feel about that __w hack? For me it looks prettier by the minute

Let me know what you think,

Cheers

Browser Wars are Heating Up

Looks like IE8 can render the acid2 face test. Nice work IE team, maybe we will start seeing more releases out of Microsoft with some higher quality. Today, Jeff talks about the javascript showdown between browsers. I agree with him, competition is a good thing.

Now if I could only get a FF 2.0 and FF 3.0 side by side install going.

Tags: ,

Haml Comes to MS MVC

Andrew Peter has created NHaml, a new view engine for MS MVC based on the ruby Haml dsl. Sweet!! Maybe we can get Andrew to drop this in the MVC Contrib project.

The community support for MS MVC has been awesome so far.

Tags: ,

MS MVC: Routing - The Good, The Bad, The RESTful

After playing with MS MVC for a little bit, and looking at routing extensively I have compiled a list of good things and things that need some improvement. The team has already said they will be doing work with routing, I am looking forward to seeing what they come up with.

What’s Good with MS MVC Routing?

Not Bound Explicitly To Controllers and Actions

An innovative approach to routing was not forcing the controller and action to be bound to the route. Instead they introduced two special parameters [controller] and [action] to indirectly bind the request. This drastically reduces the number of routes your application needs and means you do not have to register a route for every new controller.

Validation

Validation separates the url from matching on the parameters. It allows for full blown regular expressions without dirtying up the url and making it more difficult to generate urls from the routes. Hammett ran into this issue with his new routing module for monorail when he offered a straight regex rule. There was no way to pull parameters out of it.

Route Handlers

A very simple way to extend route resolution on incoming requests. Its not complicated and it gives you access to everything you need to do custom matching. I wish we could get something like that for generating urls.

Restful

Not much more to say hear that hasn’t already been said. This engine does make writing restful urls a breeze.

Testing

Thank you for making my routes so easy to test. I now have confidence that everything is working without having to fire up IIS and a browser to test by hand.

What’s Not So Good with MS MVC Routing?

No Duplicate Controller Names?

I can’t have two controllers in different namespaces with the same name?

Solution

Phil said they are fixing this. I would hope I could specify a Controller parameter either as a Type or a String where the string could be the full name of the controller. I would also maybe like this to be addressed with Areas… maybe.

Areas Where Are You?

There is no out of the box support for Areas. An area is simply a partition for your application. The most common one I can think of is http://localhost/admin/[controller] for separating all of your admin stuff from regular url’s.

Another scenario would be dropping in secondary applications, like a forum, blog, photo gallery, etc. Those will probably need to be defined under some Area.

Workarounds

RouteTable.Routes.Add(new Route
{
 Url = “admin/[controller]/[action]“,
 Defaults = new
 {
  Controller = “Admin“,
  Action = “Index”
 },
 Validation = new
 {
  Controller = “Admin|Users|Categories”
 },
 RouteHandler = typeof(MvcRouteHandler)
});

What we did above is hard code are “admin” area and then set a Validation regular expression on Controller. Now only the controllers listed will be accessible via those urls, and when generating a url it will have the correct prefix of “admin/” in the path.

What sucks about that? Every time I add a new controller that should be an admin controller I have to modify the regular expression. BTW, that regex is not case insensitive like the url.

Potential Solutions

  1. Allow a convention where the namespace dictates the area.
  2. Add an AreaAttribute similar to Monorail.

I like having the option of number 1, but I don’t want to be forced to this. It makes my urls feel to tightly coupled to my code. Its not a bad default convention as I am sure it will work the vast majority of the time.

Number 2 just doesn’t sit right with me but it seems like a decent option as well. The area has to come from somewhere, right?

One thing is for sure, there needs to be some type of Area parameter that is respected by the RouteCollection and based on the current implementation it looks like it would be very difficult for it to support areas deeper than 1 level. By default it is splitting on the “/” so an area covering “admin/maintenance” would be difficult to use with a single Area parameter.

Maybe it could support arrays which could get interesting…

[area]/[area]/[area]/[controller]/[action]
Defaults = new { Area = "admin/maintenance/daily" }
Validation = new { Area = "admin/maintenance/daily" }

Are We Really Blocking and Locking?

Reflecting over the code of the RouteCollection we can see that when an operation is performed like GetRouteData or GetUrl then the routes are locked until the proper route is matched. Every request coming into your application is going to call GetRouteData and every link you render in your views is going to call GetUrl. What does this mean. It means when a request comes in it locks the routes searching for a match. When a new request comes in on a separate thread it calls GetRouteData too and sits and waits until the first request found a match before it can proceed. And all the blocking happens for every link that you are rendering in your views too. Most pages will have 10 - 20 links, that’s lot of blocking, idle time, and context switches for the OS.

Solution

Don’t lock, period. Adding routes should go into a temp route collection. Add explicit methods for Build() or Rebuild() which can perform an atomic assignment operation on the temp routes to the routes in use. Can some kind of error happen if routes are switch in the middle of processing a request? Yes. What are the odds? Slim. If dynamically altering routes is something that my application requires, without restarting it, then let me handle that. Its an edge case.

If you have to lock, think about using a lock free collection, or use Reader/Writer locks as the number of reads is going to demolish the number of writes. Locking is just way too expensive to do on every request and every link render.

Why is Validation Case Sensitive?

Urls should be case insensitive. If I want to validate parameters using a regular expression those should be case insensitive to. Please don’t make me write Validation expression like: @”[eE][dD][iI][tT]” to match any combination of the string “Edit”.

Why is Validation Not Compiled?

Every request coming in is going to call GetRouteData, does it not make sense to compile my Validation expressions so they do not need to parsed every time they are evaluated?

Solution

if (!Regex.IsMatch(input, pattern))
{
 return false;
}

to

foreach(Regex validator in route.Validators)
{
 //…
 if(!validator.IsMatch(input))
 {
  return false;
 }
 //…
}

Where is the Extensibility?

No, not this extensibility, well maybe, give me the option please.

There are a number of edge cases popping up on blogs, comments, and forum posts.

  • What do I do if I need a different sub/domain?
  • What do I do if I need to redirect to a secure url from an insecure one?
  • What do I do if I need an absolute url instead of a relative one?
  • What do I do if I need to redirect to a non-standard port for https?

While the MVCRouteHandler is extendable the Route is not, nor is the RouteCollection. We need a way to override the matching AND url generating for specific rules.

Potential Solution

The RouteCollection looks a little heavy. I think it can delegate some of its responsibility to other services whose implementations can be swapped out. I also think it would be prudent to give us some interfaces and factories. Just overriding the GetRouteData and GetUrl is not enough. It would be great to have the ability to create our own RouteCollection so we could implement different algorithms for collecting and enumerating the routes to find a match?

Summary

All in all I am very pleased with routing in the first CTP. IMHO it is better than Monorail routing right now. It does need some pieces re-thought, re-factored, and de-debugged, but if it were perfect it wouldn’t be CTP and I wouldn’t be writing this.

Please let me know what I am missing and how crazy some of my solutions are.

+1 To the MS-MVC team, they are off to a great start.

Tags: , ,

Vim Screencast Teaser

Aaron just posted a kick ass teaser about using vim. I want the whole series on dvd now.

Tags: ,

Next Page »