Logo




Subscribe:
RSS 2.0 | Atom 1.0
Categories:

Sign In


[Giagnocavo]Michael::Write()

 Wednesday, August 27, 2008
ASP.NET MVC Begs for Tuples

[Yea, I’m not a web dev, and actively avoid it as much as possible, so I’m late to this party.]

The interesting thing about ASP.NET MVC is that it takes an opposite approach to ASP.NET in general. ASP.NET concepts try to “build up”, so as to shelter us from the evolved idiocy that is HTML, as well as clean up the inherently stateless nature of HTTP. ASP.NET MVC makes no attempt and forces you to deal with reality. Considering ASP.NET’s abstraction isn’t really perfect (example: databinding sucks), MVC’s approach is unfortunately refreshing.

Because of its “raw” nature, you’ll be writing a lot more HTML than you’d do with ASP.NET, and this HTML must line up with code on your server. To make this less of a pain, there are some HTML helper functions. Rob “ type inference” Conery has an overview here.

Here’s the signature for one of the functions:

    public static string CheckBox(this HtmlHelper helper, string htmlName, string text, string value, bool isChecked, object htmlAttributes);

The last parameter confused me. Why would it be an object? Am I supposed to pass in an IDictionary<string,string>? Just a long string? To make it more confusing, other helpers had two overloads:

    public static string TextArea(this HtmlHelper helper, string htmlName, object value, IDictionary<string, object> htmlAttributes);

    public static string TextArea(this HtmlHelper helper, string htmlName, object value, object htmlAttributes);

OK, so they explicitly called out the IDictionary there – THEN WHO WAS OBJECT HTMLATTRIBUTES?

Rob covers in his overview. The idea is that you’re supposed to use anonymous types to hack around the lack of tuples.

<%=Html.Whatever(arg1, bla, …,
                             new { @class=”cssx”, style=”x:f” …}) %>

What a great case of not-having-built-in-tuples-is-lame. It’s so lame, Microsoft’s own developer teams have to resort to weird (but quite creative!) hacks like this so that their syntax won’t completely suck*. Damn.

And now, a duck

For bonus points, there is another C# compiler feature that the MVC team could have [ab]used, and it would arguably have made more sense (although the syntax isn’t as tight). C# supports duck typing on collection initializers! So, they could create a class like this:

    public class HtmlAttributes : System.Collections.IEnumerable

    {

        public System.Collections.IEnumerator GetEnumerator() { ... }

        public void Add(string name, object val) { ... }

    }

And then they can write this:

new HtmlAttributes { { "A", 123} , {"B", "test"} }

No, it’s not as tight as the anonymous type syntax, but it does make a lot more sense.  And tuples still make much more sense than either approach, and have benefits for the rest of the language to boot (death to out parameters!).

 *The only benefit I see in anonymous types is that, at compile time, you'll  know there are no key conflicts - but that is totally trivial in the way they use them, since all the keys are declared right there.

ASP.NET | Code
Wednesday, August 27, 2008 1:12:13 AM UTC  #    Comments [10]  |  Trackback

 Tuesday, August 26, 2008
ASP.NET MVC - Abusing Using (At VB's request?)
Someone on our team started using ASP.NET MVC for a new web interface we're doing. I must say I'm impressed with the level that the MVC team [ab]uses the C# compiler, mostly in a good way. On the plus side, they end up with a bit more compiler time checking than would be possible otherwise (we can only hope WPF will follow suit some day).

But one thing struck me odd was how their helper method for generating an HTML form works. The goal is to generate an HTML form tag with the right action, and they use lambdas as symbolic references to figure out the action. The next problem is making sure that the <form> gets closed with a </form>. The straightforward answer to this is "create a function that takes a function". The C# signature would be: void Form<A>(Expression<Action<A>>, Action). Then your ASPX code would be:

<% Html.Form<FooController>(x => x.Edit(someVar.FieldX), () => { %>
    Some Html <% SomeCode%>
<% }); %>

The code is nicely bracketed and works fine. But ASP.NET MVC doesn't actually do that. Instead, the Form method returns an IDisposable! The code to use it is:

<% using (Html.Form<FooController>(x => x.Edit(someVar.FieldX)) { %>
    Some Html <% SomeCode%>
<% } %>

Why do they use an IDisposable? The rest of the MVC framework seems to assumes people are somewhat familiar with lambdas, closures and what not. The only thing I can think of is that VB doesn't support anonymous methods. So in order to make it VB friendly, they come up with quite a strange use of IDisposable to abuse language support for it. Overall, I'm not sure if this is dumb or cute.

Code | ASP.NET
Tuesday, August 26, 2008 9:19:59 PM UTC  #    Comments [4]  |  Trackback