As I continue to work with the new MVC bits with respect to SubSonic, I keep smacking my forehead (and there's a lot to smack) at how much simpler things can be if I stop overthinking them. Getting to know toolsets like jQuery and SubSonic can offer many of these moments. Bundle that with the new MVC stuff and your forehead will be burning...
Last week I wrote a post about how I had to relearn some concepts as I sat noodling over a rather simple problem:
How do I auto-postback an HTML select box and refresh some bits on my page based on the selection?
It's pretty easy with WebForms and takes all of 10 minutes - but I don't have PostBack with MVC and I love a challenge :). I started to get sort of frustrated at first - slignin javascript around - but then it occurred to me that while I've been relying on WebForms to do this kind of thing for me over the last few years, the "other guys" out there have kept on truckin with javascript and HTML and dernit if those kids haven't come up with some very neat stuff! jQuery, as they say, is the bees knees...
Put things like .NET 3.5, jQuery, SubSonic, and the new MVC framework together, and you have something really, really Super Groovy to look forward to.
Extension Methods
This is part of the fun of .NET 3.5. These methods allow you to "add functionality" to a class when needed - sort of like Ruby's mixins but you don't declare these extensions on the class - you simply have to have a "using" statement that declares the extension namespace - thus "attaching them" at the hip during design-time (see Scott's writeup).
So, the first part of my solution was to create an extension method for a Dictionary<string,string> that creates some HTML. These extension methods (or versions of them, after Eric has his way with my coding) will be part of SubSonic in the future:

As you can see, this method will take any Dictionary<string, string> and add a method to it called "ToHtmlSelect()".
At first I was a little hesitant about this. I don't like UI properties and methods hanging off objects - it's muddy. But then as I thought about it - these are extenders! They live separately from the object anyway, and are only present when I "slap them on"- so I think this kind of thing is OK.
Secondly I wasn't too happy seeing HTML in code. It sort of triggers a gag reflex. But as Jon Galloway put it to me:
Dude, HTML's not going to change the way you write select boxes for a long time. I think you're OK here. And you're my hero...
Well he might not have said that last part... but I know he thinks it...
The thing to note here is the third argument in the method: "object attributes". This is ScottGu magic at work and something he shows in his MVC demos. This little bad boy allows you to pass in an anonymous type to declare any extra attributes you might want this select box to have - like "title" or "class" - simply by using new{title="This is my title", _class="MyCSSClass"}.
These attributes are then turned into an Attribute list (a simple hash) by, yep, another Extension method that hangs off the object class (you can see it there in the last line of the method).
I also created another method called "ToHtmlRadioList()" which is an extension of List<string>:
It does the same thing as the first method, above, but this time outputs a bunch of HTML Radio buttons.
Here's the whole Controller method:
A key thing to remember about these methods is that they live in an assembly that's completely reusable at any time and are not part of the class, base class, or interface - so in effect you've bottled up your UI logic far, far away from your view and are "tacking it on" when you need it. This is a good thing, and we've just removed a mess of noodles from the boiling pot.
Notice the last line? Response.Write? Keep that in mind...
Putting It Together
So now that we have these things, I can put the bits together using jQuery and the new MVC bits. The first thing I want to do is create a controller method to serve up some HTML. I can create an view page if I want, but all I need is the radio list so I'm going to go with less code and files, and just serve up the HTML. I can use JSON here - but to keep this example concise I'm going straight for the gut...
On my main view (called "Index"), I create 3 things: my select box, a button to fire the refresh, and a div to hold the results. Notice the simple one-liner for the select box? ViewData is handed off from the controller to the View page, and "Providers" is simply a Dictionary<string,string> property that's been populated in the request. I can now pop this into HTML using the Extension methods above:
Finally, hooking this up is trivial with jQuery. I'll admit I haven't used the library long enough to claim that I'm an expert - or even close. But this took all of 5 minutes to read up on and I was off doing something else!
What I want to do now is hook up my "providerSelect" button to fire a request back to the server, sending it the value in the select box above it (called "providerList"). This is easy with jQuery:
At first glance, jQuery "syntax" can be a bit scarey cause it doesn't look much like the javascript that I remember. But a quick read on the docs and you're off:
Final Thoughts
I like this example because the view is light and nimble, and has ZERO logic in it - not one "if" anywhere and no variables. The UI is handled from a central UI class, which in this case is my Extension methods class in SubSonic.
You may be thinking to yourself
"dude, that's a lot of code for something that would take me ummmmm 5 lines using WebForms"
and that's true. But consider that
I, for one, can't wait until this stuff hit's CTP and I can see what these guys have been up to. Don't get me wrong, this MVC demo code is really solid - but the real stuff, I am sure, will be very fun indeed!
What other kind of SubSonic-y/MVC stuff do you want to see?
And great example of where makes sense to apply extension methods, this shows how it's not needed to abstract in System.Web.UI.Control-derived classes the html form elements, a helper method allows you to work with Dictionary in the server side without mixing your logic with html code.
Good job
Great stuff Rob.
What if SubSonic had controls that rendered the HTML for you without the postbacks and such. It could help the devs who don't use HTML that often use ASP.NET-like controls without the nasty things they do (viewstate, postbacks, etc).
And maybe a jQuery tie into that too? I shall play arround with that idea.
2.@Scott: I'm not sure I'd be as worried about that method declaration, that's not what you'd be typing over and over, it would be the "Providers.ToHtmlSelect("providerList", "", null)" and that actually reads pretty clean. If you want to save yourself from typing the initial method signature then setup a keyboard macro/template for it.
3. Rob, with all your lovely playing with MVC bits what does this mean for your MVC templates that you released awhile back? I'm assuming they'll probably change or go away entirely as SubSonic gets refactored but I'm curious. Each new project I debate whether to use the stock SS or the MVC templates.
4. The thing I'm *most* excited about the new MVC is now people can start using their id's as selectors again! I've noticed a whole breed of ASP.NET developers that don't even know you can style elements using the #id CSS notation vs. the .class selector because of the funky postback id that gets generated.
I would also like an update on the MVC templates as I just ripped out an old custom DAL and used those to replace it.
One thing I really do like about ASP.NET AJAX is that it allows you to work with a debug and release version of your JavaScript. I hope to see this implemented in the MVC framework. If not then someone could potentially create it.
I mean, when I start to write a class and I start to get methods like this, I start to foresee it becoming monolithic.. theres so much interaction that can be done with methods, and then much more by having objects represent a 'builder'.
What would be so wrong with writing a new set of server side controls that are really minimal.. don't use viewstate, but have lots of great features like accessing the object as an element, just as we would in JS on the client side..
I sometimes wonder if some people are moving right back for the sake of it.. while I think webforms has some design flaws from its attempt to abstract state into the web.. I do feel it should be used to teach us something about a MVC implementation..
I know that the MVC will still work with .NET controls, giving that the viewstate functionality is handled by the page, and can be simply 'ignored'..
But it seems to be a lot of these controls are at least considering view state compatible code, meaning their doing that extra bit of work for the sake of something that won't be used.. (hence my idea of writing a new mvc control base and common children).
The term spaghetti code does of course come from mixing server side blocks into blocks of html, regardless of the language.. vbscript might be nothing to c# but I don't think that really matters..
I think its a tad unfair to call it spaghetti code, as ASP days there was a very narrow seperation between major code blocks, such as what will be in code behind now, vs include files back then for example.
But I don't know if I agree with your description of this being all concatenation of strings that is disgustingly hidden away from us..
Surely thats just an ignorant view of the powers of abstraction.. we don't all sit here and write our own OS for each application.. or write our own binary.. or make our own computer..
I wondered what you thought about my concerns with these methods becoming monolithic, having a lot of overloads to achieve something that wasn't originally considered and becoming confusing and non standard..
What is the reason you would rather use these methods? surely we're moving away from a good convience that has invaded into lots of things now, such as xaml, mxml.. etc etc..
Spaghetti code has for a long time referred to how PHP and ASP applications view, regardless of if it is an adaption to the original point.. I can now see your argument for saying 'this is c#', but I'm attempting clarify the OP's point that this is related to mixing in server side code blocks with client side html..
I did also state after this that I think thats a little unfair.. as the only server side code included is that which is directly translated to client side html blocks..
I find it very strange that you become very aggressive about your points, defending them without actually adding any reason..
You end your point stating essentially 'Stick to webforms if you can't understand the concept'..
This of course is ignoring my original points again.. my suggestions aren't at all trying to convert an MVC paradigm into some mangled webforms system..
My suggestion is merely to use structure building objects instead of various string creating method calls..
My point was about abstracting a system from being method based.. to becoming object instance based.. as it is with web forms.. to allow the system to be more adaptable and generic..
It doesn't mean at all that these items are webforms.. webforms isn't dictated by the fact we concept this idea of a 'control'.. its only that implicitly, the default control in webforms is state enabled.. which more describes the difference with webforms to an MVC (the idea that we try and abstract state away from the programmer so they can develop in a more winforms like fashion).
I'm also not stating that a new control base IS better, I'm simply asking you why you selected going back away from this concept, since it seems to be a sensible evolution..
You could essentially see my question as:
Why methods and not object instances for building html..
Isn't one of the ideas of using MVC with ASP.Net that we can test the controllers separately? In this case, I don't want to generate HTML in my controllers.
And even if JQuery is cool, it's just another thing that people have to learn. I like learning new stuff, but not everyone is like me.
Can't we make the MVC thing a lot simpler?
I'm working on my own implementation of Model-View-Controller Presenter with SubSonic as the Model which allows me to test the whole app, and still use WinForms. Perhaps there's room for that too.
The extension methods seem really useful though.
Thanks for your reply, and I agree also that its all code, the repeater is also a strange object, it seems more redundant in an MVC pattern..
When I was thinking of my examples, I was thinking more about controls that map almost directly to html, rather than controls that composite html.
For example, given:
ToHtmlSelect(..)
Vs.
foreach(entry in dictionary)
{
ListBoxMyItems.Items.Add(entry);
}
ListBoxMyItems.Items[selectedEntry].selected = true;
I know the initial example is more verbose, but it does let me easily do things like.. say.. add attributes to the list..
If I wanted to get additional functionality out of the Method version, I may end up needing to overload it, and it could become confusing and bloated..
I do see the beauty in the methods binding being extremely transparent..
I actually hate the generic DataSource and DataBind() part of asp.net, while they have their uses in composite controls, it seems a little 'odd' in a lot of situations..
When are we likely to see some demos (screencasts etc.) for using the latest Subsonic, together with the latest MVC? I have an impending project for which I'm still deciding whether to go Webforms or MVC. It'd be great to see it all in action together?