Hanalei, Hawaii 9/2/2010
438 Posts and Counting

ASP.NET MVC Preview: Using The MVC UI Helpers

Wednesday, December 05, 2007 -

For the last month or so I've been working on the MVC UI Helpers (aka the MVC Toolkit) that will help developers work with HTML in their Views. These helper methods are primarily Extension Methods, and are designed to encapsulate UI code in much the same way that Server Controls do with Web Forms.

 

It's All Extension Methods Baby
When you create a View using ASP.NET MVC, you set it to inherit from System.Web.Mvc.ViewPage<>, where the passed-in type is a data class shared between the Controller and ViewPage (read more on this here). At that point it's all up the UI (the HTML View), and we haven't forgotten you :). To that end we've created a set of Extension Methods, currently called the "MVC Tookit", that you can use to push the data from your controller to your screen, wrapped in some nice HTML controls.

The UI Helper library (currently called System.Web.Mvc.Toolkit) extends the HtmlHelper class, which hangs from ViewPage.Html. When you download the MVC bits (later this week), in there will be a binary file which you can add to your project in order to use the new UI bits (this stuff is slated to be combined with the core MVC bits in the next drop). To use it, you simply reference the Toolkit dll, and then in your Web.Config, add a reference to the namespace:

<pages>
    ...
    <namespaces>
        <add namespace="System.Web.Mvc"/>
    </namespaces>
</pages>

Now you're ready to rock!

 

Enough Chatter - Get To The Code!
Accessing the helpers from your view is pretty straightforward once you have the namespace available to your ViewPage:

1

As you can see here, there are an abundance of methods for you to choose from - I'll go over each one here, and show some examples of each. You asked for more code... you got it!

First, however, you might be asking:

If I can't use server controls, and there's no PostBack, why then can't I just use plain old HTML?

... and the answer is that you can. It's up to you as to what you think is more maintainable and easier to work with.

For the samples below, I'll be working with a sample Forums application for context.

 

Anonymous Hash (Queue Midnight Run Soundtrack)
When looking over the Toolkit code you'll see a lot of "object htmlAttributes" as an argument in the method signatures. We have a nice hashing system we're using which allows you to pass in things we haven't thought of in terms of tag attributes. This system works on the concept of Anonymous Types - the ability to declare, as needed, an object type:

object o=new{name="Rob", type="quack"}

We have an Extension Method (which you can use too!) called "ToAttributeList()", which will transform this object into a set of attrbute values:

//This evaluates to "name=\"Rob\" type=\"quack\" "
string myList=o.ToAttributeList()

So with all of the methods below, you can use htmlAttributes to send in whatever extra tags you like using the Anonymous Type declaration.

Note: if your tag is a reserved work, like "class", use the standard "_" reserved word prefix: "_class"

 

User Controls
The first helper method I want to show off is the RenderUserControl() method. This method allows you to dynamically call/render a UserControl to a page as a string. These controls can be simple standalones, or they can share the ViewData with the controller. So to render a basic UserControl, we use:

<%=Html.RenderUserControl("~/UserControls/ForumList.ascx")%>

This will output the rendered control to the page, right where I put the call. But what if there are properties set on the ForumList? Like ForumGroupID for instance (which tells the ForumList.ascx which forums to display)? We can handle that too by using an Anonymous Type, sent in as a Hash, which will apply each setting to the UserControl:

<%=Html.RenderUserControl("~/UserControls/ForumList.ascx", new{GroupID=2})%>

If the UserControl is typed (ViewUserControl<MyControllerData>) then the ViewData from the controller will be passed down to the control.

To take it one step farther, let's pretend we're building a Forums application and we want to create a skinning engine which applies certain styles (or "skins") to our application based on a setting somewhere and for this we've decided to leverage UserControls.

Normally we'd have to jump through some hoops (small ones) with the BuildManager and some reflection to get this to work properly (note that that since we're not using Server Controls, we also can't use the ASP.NET Skinning Engine).

With MVC we simply setup a Themes folder, and inside of that put our Theme directories. We can then define a set of user controls for each "skin" or Theme, and then call them as needed, based on the current theme. But how do we know what that theme is? And how do we call it?

Since we don't want all this logic in our UI (deciding on which theme and how to call it), we create a Helper Class that will decide for us what theme we're using. Helpers are essentially static classes, designed to contain the UI logic that otherwise clutters up your UI. Think of these as UI utilities.

Since Theme logic is application-wide, I'm going to create an AppHelper class (as opposed to a helper specific to my controller), and put it in my Helpers folder, using the Global namespace. In here I can now put shared View Logic:

apphelper

And now I can create a method to help me decide which themed control to use. I'll call it GetThemedControl():

/// <summary>
/// Gets the root of the site we're working with
/// </summary>
/// <returns></returns>
public static string GetSiteRoot() {
    
    string appPath = System.Web.HttpContext.Current.Request.ApplicationPath;
    if (appPath == string.Empty)
        appPath = "/";

    return appPath;
}
/// <summary>
/// Gets a user control based on the current theme
/// </summary>
/// <param name="controlName">The name of the control</param>
/// <returns></returns>
public static string GetThemedControl(string controlName) {
    string appPath = GetSiteRoot();
    if (!controlName.EndsWith(".ascx"))
        controlName += ".ascx";
    
    //all themes are kept in ~/Themes/ThemeNAME
    string result = appPath+"Themes/" + GetTheme() + "/" + controlName;
    return result;
}

One thing you'll notice here is that I can no longer call "Page.ResolveClientUrl()" because, well, we have no Page! I'll show you below how you can get around that with our LinkExtensions class.

The GetTheme() method above can do something as simple as check the Web.Config's appSettings, or it can shoot to the DB to see which theme the user likes - this parts up to you.

So using GetThemedControl(), I can now rewrite the call to be:

<%=Html.RenderUserControl(AppHelper.GetThemedControl("ForumList"),new {GroupID=2})%>

Nice and tight :).

 

Forms
Working with forms takes on a whole new meaning with ASP.NET MVC since we are no longer bound to one form per page. For those of you who have used Web Forms almost explicitly, this might come as a bit of a Strange New Thing.

You can work with many forms on a page - there is no limit - and often it's nice to be able to split things up like this. Each form submits itself to a Controller/Action, and that action is responsible for doing whatever needs done.

The toolkit allows you to create forms in a lot of ways, including the most transparent way (using our Url helper):

<form action="<%=Url.Action(new{controller="Home", action="Index"})%> method=post>

If all of the "new{thing=1}" code is freaking you out - this is new to C# 3.5 and it's anonymous typing. Basically when you see this, know that in the background we're setting properties based on what you send in. This is typical in dynamic languages like Ruby, and you'll see this a lot in the code below (specifically when creating HTML attributes for HTML tags).

The <form> tag above works fine, but it's a tad verbose. It's also worth mentioning at this point that

All you know and think about URLs and ASP.NET is out the window. URLs no longer route to a physical file - they are (essentially) Remote Procedure Calls. Given that, you generally don't want to "hard-code" URLs into a page since it makes your site pretty brittle. Use ViewPage.Url to resolve the URL for you.

You can set routes to your controllers as you see fit, and it's very customizable. You're no longer constrained to folder structure so keep that in mind as you work with MVC - you may decide to change your routes as you develop your application - this might very well break your links if you don't use our helpers (or some of your own).

You can also use a nice, type-safe way to create a form (this was Phil's brain child):

<%using(Html.Form<HomeController>(action=>action.Index()))}%>
...
<%}%>

This is a nice way to create a form control since you can work with intellisense, and have type-safety associated with your form tag. It's also nice because you get a compiler error if you don't close off your Form tag :).

If you don't like all that code, you can also do this:

<%using(Html.Form("Home","Index"))%>
...
<%}%>

If you want to use GET, you can (for either methods):

<%using(Html.Form("Home","Index"), FormExtensions.FormMethod.get)%>
...
<%}%>

To submit the form, you can use:

<%=Html.Submit()%>

or

<%=Html.Submit("Save")%>

or use an image

<%=Html.SubmitImage("~/Images/SaveButton.gif")%>

 

Using Form Data In Your Controller
Once you post your form data back, we have a helper that you can use to gather it from Request.Form. There are two such methods:

Object.UpdateFrom(Request.Form)

and

Controller.ReadFromRequest(string key)

UpdateFrom basically introspects your object and then tries to match your object's properties to the keys passed in from Request.Form - in other words "auto-binding" it. So if you're working with the Northwind.Product class (using any object type - it doesn't matter), you could use:

Product p=new Product();
p.UpdateFrom(Request.Form);

This will bind your object to the values passed-in on the form. If there is a type-conversion error (or other error), we wait until the end of the method, and then throw a PopulateTypeException. This exception gathers all the exceptions into a collection for you to evaluate in your code. The important thing here is that if there is an error - the binding doesn't stop, it continues to "do it's best" and then lets you know there was a problem.

Currently we support 3 naming conventions (i.e. the name for your controls in your HTML page) that UpdateFrom() uses to "sniff out" the passed-in form values for binding:

  • Property Name ("ProductName")
  • Object.PropertyName("Product.ProductName")
  • Object_PropertyName("Product_PropertyName")

Controller.ReadFromRequest() is another extension method that you can call in your controller to pull a value that has been passed in using HTTP GET or POST (or the QueryString):

string myName=this.ReadFromRequest("name");

 

Select, ListBox, CheckBoxList, RadioButtonList
We very much wanted to create an experience with these methods much like you had with their Web Form counterparts.

Each control works in much the same way: you specify a name, a data source, selected values, etc. The dataSource, currently, can be:

  • IEnumerable
  • DataSet
  • DataTable
  • IQueryable (Linq)
  • IDataReader

For CheckBoxList and ListBox, the selectedValues parameter is also IEnumerable.

Samples:

<%
//Sample Data
string [] songs=new string[]{"Robot Rock (Daft Punk)","Stairway to Heaven (Zeppeling)", 
    "New Slang (Shins)"};
string [] movies=new string[]{"Tron","Big Trouble In Little China", 
    "Say Anything"};
string [] zodiac =new string[]{"Aries", "Taurus","Gemini","Cancer","Leo",
    "Virgo","Libra","Scorpio","Sag","Capricorn","Aquarius","Haack"};
%>
Sign:<br />
<%=Html.Select("myZodiac",zodiac) %><br />

Sign (select Haacked):<br />
<%=Html.Select("myZodiac",zodiac,"Haacked") %><br />

        
Favorite Movie:<br />
<%=Html.CheckBoxList("favMovie",movies).ToFormattedList("<li>{0}</li>") %>
<br />

Favorite Movie, List :<br />
<%=Html.ListBox("favMovie",movies,new string[]{"Say Anything"}) %>
<br />

Favorite Movie, List, Long, Mult (select "Say Anything" and "Tron")i:<br />
<%=Html.ListBox("favMovie",movies,20,true,new string[]{"Say Anything", "Tron"}) %>
<br />

Favorite Songs (Select Shins):<br />
<%=Html.CheckBoxList("favSongs",songs,new string[]{"New Slang (Shins)"})
    .ToFormattedList("<li>{0}</li>") %>
<br />

Favorite Songs:<br />
<%=Html.CheckBoxList("favSongs", songs).ToFormattedList("<li>{0}</li>")%>
<br />

Favorite Songs, Radio:<br />
<%=Html.RadioButtonList("favSongs", songs,"Robot Rock (Daft Punk)")
    .ToFormattedList("<li>{0}</li>")%>
<br />

One super-groovy thing to note here is how CheckBoxList() calls "ToFormattedList()". This is another Extension Method that hangs off of "IEnumerable" and allows you to enumerate the values to a list.

CheckBoxList and RadioButtonList return String[] - not strings! Each string is a single <checkbox> or <radio> tag.

The reason we did it this way was to allow you as much freedom as possible in terms of laying out your page, but if you don't want to write a foreach loop each time, we included the ToFormattedList() method to make things easier.

 

TextBox, TextArea, Password, Hiddens
These methods work in the same way as above. Here are some samples:

Name:<br />
<%=Html.TextBox("txtName",20) %><br />
Name, with maxlength:<br />
<%=Html.TextBox("txtName","My Value",20,20) %><br />

Thoughts:<br />
<%=Html.TextArea("txtBlob","Lorem Ipsum la la la") %><br />

Thoughts, with maxlength, rows, cols:<br />
<%=Html.TextArea("txtBlob","Lorem Ipsum la la la",20,10,40) %><br />

Password<br />
<%=Html.Password("myPassword",50)%><br />
With size, value
<%=Html.Password("myPassword",50,"My Password")%><br />
With size, value, style attribute
<%=Html.Password("myPassword", 50,"",new { style = "width:100px" })%><br />

Links, Buttons, and Navigation
We augmented the Url.Action() method to include a nice, type-safe way of navigating between controllers and actions on your site:

<%=Html.ActionLink<HomeController>(x=>x.Index(),"Home, using Action<T>") %>

Notice that in the linkText argument (second position, after the Lambda) that I'm outputting <T>? It's worth mentioning that we scrub the settable text bits using Html.Encode (another extension method).

You can also navigate between controllers using Button<>():

<%=Html.Button<HomeController>(x=>x.Index(),"cmdNav2","Home") %>

You can also navigate around the internets using NavigateButton():

<%=Html.NavigateButton("cmdNav","GoTo MSN","http://www.msn.com") %>

If you have some custom javascript to run, you can do that with Button():

<%=Html.Button("cmdJS","Click Me","DoTheClickThang()")%>

If you like using Images as buttons, you can do that too, using ImageButton():

<%=Html.Button("cmdJS","~/Images/Clicky.png","DoTheClickThang()")%>

Note: with this method we make sure the cursor hand appears when hovering to denote a clickable element.

 

Images, ResolveUrl, and MailTo
We really want to make things as easy as can be for you with the new MVC Toolkit. So we've also thrown in an Image method:

A nice picture of a wave:
<%=Html.Image("~/Images/bigwave.jpg") %><br />

Set the name and width
<%=Html.Image("~/Images/bigwave.jpg", "myWave", new { width = "30px" })%><br />

Since you're ViewPage no longer has access to Page proper, we've included a method to help you resolve URLs on your page:

<%=Html.ResolveUrl("~/HALP!")%>

If you want to embed an email link, you can do so using MailTo():

Simple Email:
<%=Html.MailTo("robcon@microsoft.com","Email Me!") %>

With Subject and Body
<%=Html.MailTo("robcon@microsoft.com","Email Me!","Sending you a note"
    ,"Hey - wanted to say hi!") %>

MailTo() contains all the overloads needed to send subject, body, cc, bcc, to the client's email program.

 

Summary
Long, long post - but I thought it was worth it to get as much out there as possible. The CTP will be landing very soon, and with it will be the MVC Toolkit. We've tried to pack as much UI help in there as possible - and please know that these things will likely change as we keep building and tweaking.

As always - would love to hear your thoughts!

PS: YES, there is lots of room for SubSonic here, and I've already started putting together the UI "Sugar" that we're going to offer on top of MVC. Look for that in the next post :).

Related


Gravatar
Dave Savage - Wednesday, December 05, 2007 - All I want for Christmas is my MVC!!
Gravatar
Luke Foust - Wednesday, December 05, 2007 - I am so jealous you get to work on this! It looks like fun coming up with ways make it easier to output html. Great job so far.
Gravatar
Murad - Wednesday, December 05, 2007 - Hi Rob, I see you use Macbook pro for your development, do you do dual boot or use software like Parallel desktop. If you use VM, did you find any performance issues? specially using VS 2005 and how is your experience so far?, Thanks
Gravatar
Jake Scott - Wednesday, December 05, 2007 - Hi Rob, I noticed your note about the Html.Button "we make sure the cursor hand appears when hovering to denote a clickable element" surely this would be something that you would worry about in your css and not inline in your html. Are you setting default inline css styles??
Gravatar
Rob Conery - Wednesday, December 05, 2007 - Jake: you surely can set this in CSS if you want and use a normal image, etc. This is a convenience method that uses "onmouseover" to set the style.

If you wanted to do this with an image, you could:
<%=Html.Image("myimage",new{_class="cssImageButton", onclick="myOnClick()"})%>

Of particular note is that there are many different ways of doing this, including the tried and true:

< img src="myimage" onclick=... class=... >
Gravatar
Eric Hexter - Wednesday, December 05, 2007 - Great to see this work being done, Cant wait till I can get my hands on it!

I would like to see a little more support around the typed UserControls being rendered from type Pages. In this case the Page would be typed and the UserControl would be a different type.

I would like to see something like this


Is that supported ?


On another note. I dislike the guidance about have a call to web.config or to a database in the GetTheme() sample. I feel this is going against the entire point of the separation of concerns, and this is a huge benefit of the MVC framework. To have helper methods in the view make calls out to external resources is work that the controller should be performing and passing into the view.
Gravatar
Eric Hexter - Wednesday, December 05, 2007 - So I do not know how to encode comments properly.. here is the example I wanted to show...

Gravatar
Eric Hexter - Wednesday, December 05, 2007 - one more try..

%lt; %=Html.RenderUserControl("~/UserControls/ForumList.ascx", new{GroupID=this.ViewData.ForumCollection })% >
Gravatar
Microsoft MVC HTML Helper Insanity! at Lost In Tangent - Thursday, December 06, 2007 - [...] lately around the forthcoming release of Microsoft’s MVC framework. Rob Conery just wrote a bounteous post, covering a slew of the available HTML helper methods that will make developing MVC apps possible. [...]
Gravatar
Rob Conery - Thursday, December 06, 2007 - @Eric - RE the UserControl - this is precisely how it works - no type is required (it's just an added bonus). In terms of the "guidance" RE the skinning thing - sure you can send it down from the Controller - but this IS indeed UI logic and the Controller is biz logic so I set it up that way. Having said that - it's wide open to pass in as you need. Helpers are all about the UI and should know nothing of the controller.
Gravatar
Ibleif - Thursday, December 06, 2007 - As long as you don't mess with my precious Web Forms! :-)
Gravatar
mike - Thursday, December 06, 2007 - I kind of like to refer to user controls by name: That's why we can register them in web.config right? Also, that prevents us from having to search/replace in multiple files if we change the name of location of a user control. Please consider, thanks! Reading this, it feels like we can't use webcontrols at all, it's all methods now. Is that true? If so, I'm a bit sad, because I love to declare controls using the HTML-like syntax.
Gravatar
Trevor - Thursday, December 06, 2007 - Hi Rob, If I have the tried and true
Gravatar
Ben - Thursday, December 06, 2007 - Great stuff. I hadn't seen anything like the Monorail binder in the MVC framework until now.
Gravatar
Torkel - Thursday, December 06, 2007 - Nice, a CTP is released soon? =) I hope that all this usage of extension methods is not going to make unit testing harder.
Gravatar
Dave Neeley - Thursday, December 06, 2007 - I probably just haven't been developing in .NET long enough, but why MVC is so exciting in comparison to the existing ASP.NET stuff is just not obvious to me yet. Any good resources on that front?
Gravatar
Vijay Santhanam - Thursday, December 06, 2007 - It's looking nice Rob. There's some very elegant extension methods. Are postback declarative controls completely dead in MVC? I would like to see postback declarative controls modified to keep drag n drop goodness. I guess they could stay if you could pass them URL building delegates for postback URLs.
Gravatar
Podge - Thursday, December 06, 2007 - A couple of questions,
How is client side validation done? do you just use the old classic asp way of validation (ie onclick method for the submit button), or is there a helper method for validation.

Is caching implemented or do you have to do your own caching? Like a databound listbox or even the page.

You mention user controls, how are their postbacks handled, do wrap them up in there own form tag?

Final one
are the databound controls supported, such as grids, viewlists etc.

thanks
Gravatar
Eric - Thursday, December 06, 2007 - Hooray!!!

Death to the VS.NET designer!

So, originally... it seems like Microsoft went the declarative route (with server and HTML controls) in order to enable the use of a WYSIWYG designer and drag-and-drop, but now we are going back (full circle?) to a designerless, code-view only way of doing things. I personally couldn't care less about the designer. I hated it since day one (and the absolute positioning of controls), I just wonder how the masses are going to react when they figure this out? Oh well... they can continue to use WebForms, can't they?

Could we get an optimized version of VS.NET with the designer turned off?

Unless... I'm totally wrong about this and the designer will still be valid in the MVC bits, but I just cannot imagine it. The designer would have to substitute place holders for all the method calls, or it would have to execute the method and spit out the result. That would make the designer even slower than it is today. I guess that is still a possibility (because that is what the designer is essential doing, calling the Render method of each server or UserControl to get it's HTML markup)...???
Gravatar
The Daily Find #12 - TechToolBlog - Thursday, December 06, 2007 - [...] Preview of MVC Toolkit - I’m sure the name will change just to throw is off [...]
Gravatar
Ian - Thursday, December 06, 2007 - @Eric: I can't remember the last time I saw the designer in Visual Studio. I am not sure what you mean by absolute positioning of controls either. I believe Scott Guthrie has been depicting MVC as "another option", rather than a replacement for the Web Form model. Either way I do not think designer is required ever.
Gravatar
mike - Thursday, December 06, 2007 - Wait, what is this designer you are talking about... Just kidding of course, I know it's there, I just never (never ever) use it.
Gravatar
Rob Conery » ASP.NET MVC: Using RESTful Architecture - Thursday, December 06, 2007 - [...] Using the MVC Toolkit - I go over all the neat UI methods you can use with the forthcoming CTP of MVC. [...]
Gravatar
Rob Conery - Thursday, December 06, 2007 - @mike: this is where you could use a Helper to get you the control you wanted. You don't want static file references in your app - the architecture is such that URLs can change easily - your app shouldn't break if they do. @Torkel - why would extensions make TDD harder? @Dave - see my next post. Unit Tests are the primary reason, but a clean approach is the other. @Vijay: No, controls aren't dead - but PostBack is. See Scott's post today on using a Reader. In terms of Drag N Drop goodness - it doesn't have to be a server control for that :). @Podge: CSV is done by you :). Or you can put it on the model and serve it back up. Currently we don't have this built in. You can cache the page just like you could before. In terms of PostBack - there is no PostBack so UserControls should really be called "Partials" if you ask me. Yes - databound controls are still supported. @Eric: Microsoft isn't "coming full circle" - this is just an option that some will like, others may not (a lot people like their designer - I'm not one of em - but they're out there).
Gravatar
ASP.NET MVC Preview: Using The MVC UI Helpers · Skin Cancer Information - Thursday, December 06, 2007 - [...] Original post by Rob Conery [...]
Gravatar
Jake Scott - Friday, December 07, 2007 - Hi Rob, So.. do methods such as Html.Button Html.Image pump out javascript "onclick" and "onmouseover" attributes by default? I prefer to use unobtrusive javascript to attach click and mouseover events to elements. So by default can we leave these "convenience" attributes out, and if you MUST use this technique then you still can by doing Word up though, this is going to dominate RoR! Jake
Gravatar
Rob Conery - Friday, December 07, 2007 - @Jake: they do indeed - and as I mention these are just for convenience. If you prefer to use javascript you can always just use good ol HTML (with ID's that YOU define :) and jQuery if you want to wire up some code. If you do this with navigation, you'll want to be sure to use Url.Action() if you nav to another controller (don't hard-code /MyController/ActionName)
Gravatar
Dmitriy Nagirnyak - Friday, December 07, 2007 - Object.UpdateFrom(Request.Form) What if Object has some secure but public properties, like User.HashedPassword? It means that everybody who can update ONE field of User with Object.UpdateFrom(Request.Form) can also update all its properties. It seems such automatic-databinding is unsafe. Just add another hidden field to HTTP request from client and that's all. No way to control it (or is?). As far as I can see - at the end - it will be needed to set object properties manually querying Form, QueryString etc. Workarounds I can see: 1. Give list of properties that *are allowed* to be updated (like in MonoRail). 2. Wrap business objects with their clone-proxies and expose needed binding properties. 3. Set object properties manually. 4. Set some .NET attributes for properties of business objects to recognise it secure prop or not. Disadvantages: 1. If a property is changed, new secure one added etc, it cannot be found at compile time exposing bugs and/or security issues. 2. Too much cloned code. 3. Lots of code to set/convert values. 4. Just a horrible solution. Business objects should never know where they are going to be used. Also secure properties on one page might be allowed to update on the other. Thoughts? Also what about following things (out of the box) in MS MVC: * Caching. * Validation (Client and server). * Handling unhandled exceptions (like Rescues in MonoRail). * Available control suites (like grids with filtering, grouping, paging). Any plans to support ExtJS? Probably answer is NO because of license issues. But just curious. Regards, Dmitriy.
Gravatar
Rob Conery - Friday, December 07, 2007 - @Dmitry: What's unsafe is exposing a user password :). Although I see what you mean - there are times when you want to protect your data on your objects from "spoofing". I would say if you're worried about this scenario - you can set the properties "by hand" using ReadFromRequest(). The other thing is to make these properties ReadOnly (which in the case of a password should be the norm). These helper methods are for you to use when applicable. Caching works as always Validation is up to you, as always. Scott has a great post RE LinqToSql and Validation (server-side). SubSonic has this built into it (you can't save something that violates your DB logic). Currently we don't have client-side validators built in, but this may change. We don't intercept any exceptions - that's up to you (I'm not familiar with MonoRail's Rescue). No "control suites" yet - though I think it's pretty simple to setup paging/sorting using MVC. I'll try to put together some posts on this at a later time.
Gravatar
Vijay Santhanam - Friday, December 07, 2007 - Why are you using the underscore to prefix C# keywords that are also html attributes? Doesn't C# use @ for that? like @class, @new, @public? What did you mean by the Scott's "Reader" w.r.t. postback controls? Scott demoed the use of PagedList and other useful paging classes in his MVC demo. What other useful paging/sorting helpers are we going to see?
Gravatar
Matt Blodgett - Friday, December 07, 2007 - Rob, When did "Haack" become part of the zodiac? Or should I say, the zodiHAACK? ;)
Gravatar
Josh - Friday, December 07, 2007 - So... how about you guys push me out some MVC so I can waste my weekend playing with it. :) :)
Gravatar
Peter - Saturday, December 08, 2007 - Hi there, Great article. I would definately like to see some MVC style control methods. In a smilar fashion to server controls. i.e
Gravatar
David Fauber - Sunday, December 09, 2007 - "If I can't use server controls, and there's no PostBack, why then can't I just use plain old HTML?" Whenever I've had to write methods that return html, I've been tempted to abstract the html elements into an object model. This is one of those things I've gone back and forth on, but have always ended up deciding against doing it. I figured that whoever had to maintain it would probably be someone fluent in html and the abstraction would actually slow them down, even though it seems more correct. Anyway, as geeky as it sounds, I've often wondered how others would handle that situation, so this is really interesting stuff to me.
Gravatar
ASP.NET MVC preview available » DamienG - Sunday, December 09, 2007 - [...] Using user interface (HTML) helpers [...]
Gravatar
Microsoft Releases First CTP of their MVC Framework « Accidental Technologist - Sunday, December 09, 2007 - [...] ASP.NET MVC Preview: Using The MVC UI Helpers [...]
Gravatar
Rob Conery » ASP.NET MVC Is Here (CTP) - Monday, December 10, 2007 - [...] Learn more about the HTML Helpers: ASP.NET MVC Preview: Using The MVC UI Helpers [...]
Gravatar
ASP.NET 3.5 Extensions Cee Teep Pee! at Lost In Tangent - Monday, December 10, 2007 - [...] ASP.NET MVC UI Helpers [...]
Gravatar
Liviu - Monday, December 10, 2007 - Hi Rob,

Could you please shed some light on a component issue:

Let's say i have an ViewUserControl, i would like that logic (and postback ) to be handled in a method of ViewUserControl. Is this possible?

Normally i would say that i need a ViewUserController...
Gravatar
Liviu - Monday, December 10, 2007 - Hi Rob,

Another thought? Are many of these extension helpers not useless? I mean what is the gain of not having design view for your pages? This was a thing i hated in monorail, and i never used this feature.
Gravatar
David Fauber - Monday, December 10, 2007 - "I mean what is the gain of not having design view for your pages? This was a thing i hated in monorail, and i never used this feature." There will be division on this one, personally I feel the opposite way although I know many of my coworkers feel the same way you do. I can't stand designer views in general, including the VS html designer. In fact, I scream like I stubbed my toe on something if I accidentally click the "designer" instead of "source" view.
Gravatar
Bob - Monday, December 10, 2007 - I've referenced MVCToolkit.dll in to my project, completed the build and tried
Gravatar
rascunho » Blog Archive » links for 2007-12-11 - Tuesday, December 11, 2007 - [...] Rob Conery » ASP.NET MVC Preview: Using The MVC UI Helpers These helper methods are primarily Extension Methods, and are designed to encapsulate UI code in much the same way that Server Controls do with Web Forms. (tags: blog.wekeroad.com 2007 mes11 dia11 MVC ASP.NET Extension_Methods blog_post) [...]
Gravatar
Stephen - Tuesday, December 11, 2007 - In terms of these anon types used as 'dictionarys', I kind of like the idea but I feel a little dirty naming propertys with underscores and not being cased correctly.. I guess it doesn't matter at all since the only thing that will ever receive it is the method being called, and it will simply reflect it and build a string..

But aren't attributes suposed to be lower case? couldn't you just ensure that:

new { Class = "myclass" };

Came out as class="myclass"

??

Or am I confused and the lower case thing is just an XHTML specific thing regarding elements and attribute case?
Gravatar
Rob Conery - Tuesday, December 11, 2007 - @Stephen - don't want to make you feel dirty :). Just updated the source so that all attributes are ToLower() :).
Gravatar
ASP.Net MVC Framework made public « - Wednesday, December 12, 2007 - [...] example, check out this post from Rob Conery. He demonstrates an extension method which allows you to create a list of [...]
Gravatar
Stephen - Wednesday, December 12, 2007 - Hey great! but now everyone knows who to blame! ;)

I need to get the MVC installed and checked out more, I've been wondering the last few days how much the designer (even the html source one) is tied in to the concept of web forms (such as being anal about it generating its own ids for elements)..

I mean, I'm interested in trying to create a lightweight control library that is specific to the MVC concept (i.e. not stateful).. I know I could use the webforms ones, but I think they would have more overhead on processing data that isn't useful.. and are designed in a way to take advantage of stateful considerations etc, making them appear somewhat 'odd' in an MVC world..

Not saying the control idea is the way to go, but I think its worth a test.. I was just wondering how low I can get in terms of my own control base, while having the designer based functionality I want, vs what I don't want..

I get the feeling that asp.net is tied into the webforms control system too much, such as the tag registration and such..
Gravatar
Matthew - Tuesday, December 18, 2007 - I can't wait to actually use this. ASP.NET is something I have used for a few years but it hasn't been something I was really excited about until now. Big thanks to all the ASP.NET MVC team.
Gravatar
Santos Ray Victorero, II - Saturday, December 22, 2007 - I was taking the MVC Framework for a test drive this weekend and I found a little problem with the TextBox extension method of the MVC UI Helpers. (I apologize if someone already reported this)

If the ViewData has any null values it will give an "object not found exception".

for example if you pass:


and ViewData.DBA is null it will raise the exception.

I modified the code to workaround the problem: (See the MODIFIED line below)


///
/// Creates a text box for form input
///
/// The name and ID of the control
/// The text for the control
/// The size of the textbox
/// The maximum characters allowed in the textbox
/// Any attributes you want set on the tag. Use anonymous-type declaration for this: new{class=cssclass}
public static string TextBox(this HtmlHelper helper, string htmlName, object value, int size, int maxlength, object htmlAttributes) {
string textBoxFormat = "";

string atts = string.Empty;
if (htmlAttributes != null)
atts = htmlAttributes.ToAttributeList();

if (maxlength > 0) {
atts = "maxlength=\"" maxlength.ToString() "\"";
}

// MODIFIED 12/22/2007 @ 6:30pm
value = value==null ? string.Empty : value.ToString();

return string.Format(textBoxFormat, htmlName, size.ToString(), atts, value);

}


Regards,

Santos
Gravatar
MSDN Blog Postings » How To Create an HTML Helper for ASP.NET MVC - Monday, December 24, 2007 - [...] for rendering common HTML. You can get it here (look for it in the ASP.NET MVC section) and can read more about it at Rob Conery’s ‘blog. Simply reference MVCToolkit and now you can do this in [...]
Gravatar
jeff - Thursday, December 27, 2007 - "Currently we support 3 naming conventions..." * Property Name ("ProductName") * Object.PropertyName("Product.ProductName") * Object_PropertyName("Product_PropertyName") What about multi-part naming, like "OrderDetail.Order.Customer.CustomerName"?
Gravatar
jrnail23 - Saturday, December 29, 2007 - Hi Rob,
Great work on all this stuff... I'm really looking forward to seeing the MVC framework mature into something special.
One thing, though... one of the commenters above mentioned casing of HTML attributes and XHTML compliance -- please keep XHTML compliance in mind with these helper methods. I noticed on one of my form tags generated by the helper methods that the form method was rendered as method=post (instead of the XHTML compliant method="post" -- with quotes). One of the big knocks on MS's web technologies has been a lack of adherence to standards, and I'd love to see you guys shed that reputation.
Enough whining now, you guys are really doing some impressive work with this MVC product.
Gravatar
Bruce Mcleod - Monday, December 31, 2007 - Hang On,

I'm going to simply state this once.

This approach will never take off if you walk away from Web Controls.

UIPAB does not require such an horrific deprecation of user interface functionality and as a result is a better implementation of MVC.

It also has a considerable user base which listened to Microsoft evangelists urging adoption of an MVC standard.

Where did that get us? :-)

Dont go back to .asp!!!!
Gravatar
Dragan Panjkov - Monday, December 31, 2007 - Hi, Rob... I am trying to reproduce steps from Scottgu's first part in MVC series... I encountered some problems with Html.ActionLink, I.E. When I use it to render link, it is not converting value returned from Eval to string, for example Html.ActionLink(Eval("CategoryName"), new {action="List", category= Eval("CategoryName")}) will not implicitly cast returned values in eval from object to string, but I need to Explicitly call ToString() on them... Is this feature or bug? Thanks!
Gravatar
Rob Conery - Friday, January 04, 2008 - >>>This approach will never take off if you walk away from Web Controls. UIPAB does not require such an horrific deprecation of user interface functionality and as a result is a better implementation of MVC.<<< There are many who believe ASP is not used on many "Web 2.0" - y sites (like Social Networking) because of the abstraction of the UI bits and how "formy" it's all become.
Gravatar
Angus McDonald - Tuesday, January 08, 2008 - Rob,

I've followed your samples and have one minor problem ... my VS2008 does not seem to want to recognise the
Gravatar
Angus McDonald - Tuesday, January 08, 2008 - Ugh ... I was meaning to say that it did not recognise the "Html." section of Html.ActionLink, despite my web.config being properly updated. In fact when I compare my code to MvcApplication5 (one of the sample apps) it looks almost identical, but in that project Html. is recognised although intellisense still does not work.

I've checked global.asax, web.config and my references and they all seem the same as the sample project. One difference is that I am using VB.NET. Is there anything else I should be looking at?

Thanks,
Angus
Gravatar
raffaeu - Wednesday, January 09, 2008 - Hi everyone, you forgot an important tips into the installation steps. You can build an MVC application with NET Framework 2 runtime and stay alive with your old DataModel but if you want to work with the cool ToolKit you must convert the web app in NET 3.5 runtime ... Why don't you build also a Toolkit version for the 2 Framework?
Gravatar
UIPScrewed - Monday, January 14, 2008 - >>>
UIPAB does not require such an horrific deprecation of user interface functionality and as a result is a better implementation of MVC.

It also has a considerable user base which listened to Microsoft evangelists urging adoption of an MVC standard
Gravatar
Mio - Wednesday, January 16, 2008 - Hi Rob,
great job with the toolkit.

I had only a short time to give it a spin and although it looks really good I did notice a few problems.

The drop down list example trying to select Phil

Html.Select("myZodiac", zodiac, "Haacked")

does not work [ and it's not Phil's fault :) ].

The problem is the method signature (expecting object not a string), and since there is already a method with the same signature as in your example, it gets invoked and nothing gets selected. To get an item selected in a dropdown using current implementation one needs to call it as following:

Html.Select("myZodiac", zodiac, (object)"Haacked")

Although the above works it doesn't really look nice, so maybe method signatures need a bit of adjusting.

I also noticed that CheckBoxList and RadioButtonList render input tags only, no labels, so selecting items in those lists means chasing small boxes and circles with the mouse. To enable selection also by clicking on the text they should be rendered with 'label for' afterwards and this yields unique IDs for the inputs being rendered.

Hope this was helpful.
Cheers,
Mio
Gravatar
Jeff Handley - Thursday, January 17, 2008 - I am having a slight problem with the CheckBoxList method. I am trying to hand it an IList (or a List) as its data source, and it barfs on me saying "Parameter Count Mismatch". Here's the detail:

Parameter count mismatch.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Reflection.TargetParameterCountException: Parameter count mismatch.


If I use a string[] instead of a List, it works fine. Any ideas?

Great stuff though -- thanks for the help,
Jeff Handley
Gravatar
mio - Friday, January 18, 2008 - @Jeff - this is due to reflection used in System.Web.Mvc.MvcControlDataBinder when PropertyInfo.GetValue is called on indexed properties without the index. Example of indexed default properties is String.Chars. Rob, please correct me if I am wrong here.

So if you do have something like IList and you want to pass it to the Html.CheckBoxList just cast it to array:

IList _myList = new List { "first", "second", "third" };
Html.CheckBoxList("places", _myList.ToArray())

The following works just fine with passing IList (no need to cast it to an array)

IList _theList = new List { new {id="1", value="first value"}, new {id="2", value="second value"} };
Html.RadioButtonList("myFavSongs", _theList, "value", "id")

The same of course applies for RadioButtonList.

Cheers,
m.
Gravatar
Nathan - Friday, January 18, 2008 - I'm using Html.Select, but I need to change the text displayed & value (it's picking up the wrong one by default).

I'm passing in the table through ViewData ala ScottGu's tutorial. How do I specify different columns for the textField & valueField?

I have this:
Html.Select("actvty_typ", ViewData.WorkoutTypes, ViewData.WorkoutTypes.Select(wt => wt.descr), ViewData.WorkoutTypes.Select(wt => wt.actvty_typ).ToString())

And I receive a NullReferenceException. I know there's some kind of LINQy goodness I'm missing... can anyone help?

Thanks.
Gravatar
mio - Friday, January 18, 2008 - @Nathan

You should just pass the names of the text and value columns. Try this:

Html.Select("actvty_typ", ViewData.WorkoutTypes, "descr", "actvty_typ")


Cheers,
m.
Gravatar
Nathan - Friday, January 18, 2008 - When I do that, I get a duplicate name error like the original poster received. This happens even when I use "asdlkjgsalgkjg".
Gravatar
mio - Sunday, January 20, 2008 - @Nathan

That's just plain weird. Could you provide some more info on that ViewData you're passing in (when you say 'Table' I assume you're talking about System.Data.Linq.Table, right?).

I made a small experiment using the blog website that comes with the MVCToolkit, just to try to repro your problem. Nothing happened, it worked just fine. What I did is:

1. added a class for passing the data (ala ScottGu, as you say):
public class HomeViewData
{
public System.Data.Linq.Table Comments { get; set; }
}

2. in the HomeController I edited the Index action to pass the HomeViewData to the view. HomeViewData's 'Comments' property gets populated with the comments table from the datacontext:

[ControllerAction]
public void Index()
{
BlogDataContext _blogDB = new BlogDataContext();
HomeViewData _homeViewData = new HomeViewData();
_homeViewData.Comments = _blogDB.Comments;

RenderView("Index", _homeViewData);
}

3. In the code behind of the Index view I changed the class declaration to be

public partial class Index : ViewPage

and the in the Index.aspx I just added:



Works like a charm. When I run this thing I get a drop-down with comment titles as text and with comment ids as values.

Cheers,
m.
Gravatar
mio - Sunday, January 20, 2008 - Sorrty, forgot the tags get stripped, 3. should've read:

3. In the code behind of the Index view I changed the class declaration to be

public partial class Index : ViewPage<HomeViewData>

and the in the Index.aspx I just added:

Html.Select("comments", ViewData.Comments, "Title", "ID")

Works like a charm. When I run this thing I get a drop-down with comment titles as text and with comment ids as values
Gravatar
Nathan - Tuesday, January 22, 2008 - Thanks everyone. I rebooted and everything worked. I must have had something cached that shouldn't have been.
Gravatar
Juergen - Wednesday, January 30, 2008 - I created a project on codeplex.com, called "Validator Toolkit for ASP.NET". It's a solution to validate a form on client and server-side. You may check out the source code to see if this helps you. http://www.codeplex.com/MvcValidatorToolkit

Juergen
Gravatar
southwo8 - Tuesday, February 05, 2008 - I've got the latest 3.5 Extensions and the MVCToolkit downloaded, but I'm having issues with the generic version of ActionLink The method signature pops up ok in my intellisense, sort of, when I start typing my lambda expression though it can't figure out the type and I get errors when I run the page. Using a Northwind example: Html.ActionLink(p=>p.Edit(p.ProductID), "edit") doesn't work for me, visual studio can't figure out what type "p" is, it just shows "T" as the type in the intellisense popup instead of "ProductsController" so when I type "p." I don't see any of the controller action methods that I have defined....
Gravatar
southwo8 - Tuesday, February 05, 2008 - ok, the angle brackets didn't come through on my comment, but i'm using the generic Html.ActionLink< > method signature
Gravatar
southwo8 - Tuesday, February 05, 2008 - as in Html.ActionLink<ProductsController>(p=>p.Edit(p.ProductID), "edit product") where the "ProductsController" class has a method "public void Edit(int productId)"
Gravatar
Andrei Rinea - Saturday, February 09, 2008 - I like the MVC Toolkit but there are things I hate about the checkbox generator :

1. The text is rendered directly at the right of the checkbox not within a label for="id". This really sucks from a usability point of view.

2. The checked attribute's value is rendered WITHOUT quoutes (or double quotes) !!! this makes the output not XHTML compliant!

It really spoils the joy of the toolkit.
Gravatar
Rob Conery - Saturday, February 09, 2008 - @Andrei - the checkbox bits have been fixed in terms of using a label - thanks for the feedback. I also created a XHTML Validation Test for making sure the tags are compliant so this is fixed for the next drop. There are a few other issues (see the forums) that we've also dealt with (I forgot to quote up the form method and close off some text inputs), and more that I found when I started running XHTML validations. Point is - this is a CTP and we've listened to the feedback and it's in there :)
Gravatar
Andrei Rinea - Sunday, February 10, 2008 - I'm happy to hear that our feedback is useful. :)

Any ideea of a date of a next version (preRelease or release)?
Gravatar
Jorgas - Tuesday, February 12, 2008 - I have a general "question" about type safe c# code in the views. I know that both type safe code, using helper methods, as well as pure html works fine. And that it's up to any developer to choose their own flavor (I probably will use a lot of helper methods for instance).

But, in terms of best practices and total project performance in larger projects (where often some people have responsibility for interface design solely), isn't it a bit like fighting part of the purpose of dividing a page into a model, a view and a controller when using a lot of c# code in the aspx-view? I mean, if a developer needs to go over whatever html he receives from an interface designer, and replace pure html with helper methods every time, it seems to me like a lot of time will be added into the project?

Or, is there going to be a tool-kit available where html can be converted into type safe code in the views?

But again, I do think it's a great thing that you guys give us developers the best of two worlds. :-)

Regards,
Gravatar
Jorgas - Wednesday, February 13, 2008 - Another little "observation", or whish perhaps.

When using the helper methods, like for example Html.Form, the action attribute value will always be written out with in the same casing as the corresponding controller and action are named. I think the same goes for Html.ActionLink.

Well, a lot of people seems to think that really pretty url's should be in lower case, always. So my question, or whish, is that there will be some configuration setting available in the MVC toolkit or in the standard MVC distribution, that says "lowerCaseUrls=true|false" or something similar.

Or, perhaps I have missed some already available setting or way of using the helper methods for this?

Regards,
Gravatar
Rob Conery - Wednesday, February 13, 2008 - @Jorgas: I've honestly never heard anyone argue for a cased URL. It used to be common practise to make sure your page file names were always lowered because in the good old days the web servers were case sensitive (and some still are).
Gravatar
steve - Wednesday, February 13, 2008 - Hi, I have a CheckboxList decendent, where I take over the Render method (the base method is not called). For whatever reasons, after selecting some checkboxes and then counting them in code (item.selected = true), I always get zero. Any help would be appreciated. Thanks
Gravatar
1 Links Today (2008-02-16) - Saturday, February 16, 2008 - [...] Rob Conery » ASP.NET MVC Preview: Using The MVC UI Helpers [...]
Gravatar
Mohammad Azam - Saturday, February 16, 2008 - Hi Rob, What about if I only wanted to create a list of items using the "li" tag? I don't see an option to that.
Gravatar
Rob Conery - Saturday, February 16, 2008 - There is an extension method in there for List and Array called "ToFormattedList()". To use it for list tags, you could: MyList.ToFormattedList("< li >{0} < /li >")
Gravatar
Mohammad Azam - Monday, February 18, 2008 - Thanks!
Gravatar
Shawn Oster - Tuesday, February 19, 2008 - Hey Rob is there a version of the Html.Form that makes it easy to tack on the needed arguments needed by the controller? My Update controller method needs the id of the record I'm updating and I can't seem to find a clean way to do that using this pattern:


.


I'm sure the type-safe method might be able to get to it but man is it ever butt-ass ugly and I'm trying to avoid calls that look like keyboard train-wrecks as much as possible :)
Gravatar
Rob Conery - Tuesday, February 19, 2008 - @Shawn: You can pass the args right in the lambda. It only looks whacky cause you may not be used to it :) but i I know what you mean... < % using(Html.Form< MyController >(x => x.Update(myID))){% > ...
Gravatar
John - Friday, February 22, 2008 - Hi, I'm sorry if someone posted it already, but I didn't find it anywhere. I'm trying to pass htmlAttributes to Html.Select method. There are plenty of different attributes in the output except mines. I think there is problem with this line: Hashtable setHash = HtmlExtensionUtility.GetPropertyHash(htmlAttributes); because calling ToAttributeList on setHash gets different output then calling it on htmlAttributes. Am I missing something or this is a real problem?
Gravatar
Mohammad Azam - Sunday, February 24, 2008 - I think there is some problem with the ToFormattedList. It does not take a datasource or anything so how can I create just the {0} items. I tried using the following: {0} ") %> But it creates a radiobuttonlist.
Gravatar
Jorgas - Monday, February 25, 2008 - Hi again Rob.

I'm not sure if I explained myself well enough.

I know that most browsers are case insensitive in terms of URL's. What I want is some way of overriding the default behavior of the rendering of Html.Form actions, and Html.ActionLink url's so that they do not use the convention used in the Controllers and Action names. Since those are classes and method names our convention is to use CamelCasing (or PascalCasing) which means that the url's and actions written to the output are also CamelCasing. I would prefer to have some configuration setting available so that the output is written in lowercase always, regardless of what convention individual controllers and action names follow.

Best regards,
Gravatar
Ozan BAYRAM - Thursday, February 28, 2008 - I want to create an select with Html.Select. It has 6 overloads. Only the last one has the object htmlAttributes... How can i give css class="abc" for this : Also i dont how to use this htmlAttributes object. I now its a anonymous type but i dont know how to pass class attribute... e.g. new {_class="abc"} Thanks...
Gravatar
Bill - Monday, March 03, 2008 - Thinking DRY, we protect our database with constraints and properties (length, default value, etc.), thus we have entered our validation rules. If an API could be generated from this meta data, it could be used for both server-side (rcp) and client-side validation (xhr). A helper to generate all the required code for both validators would then be really something. No duplication of rules anywhere.
Gravatar
Per Zimmerman - Tuesday, March 04, 2008 - I just glanced through the code and noticed an error when a textarea rendered in TextInputExtensions.cs line 95: ...textarea id=\"{0}\"name=\"{0}\" ... It should be a space between id attribute value and attribute name. Haven't had the time to try the extension yet, but it looks promising.
Gravatar
Jeff Handley - Saturday, March 08, 2008 - Rob,

I've been working on an article series on my blog related to MVC and the Html Helpers. Don't be upset, but I have found some drawbacks to using the Html Helpers. I'd really love for you to read through the articles (3 posted so far) and let me know what you think about what I'm illustrating as an alternative.

Here's the beginning of the series, which has links to the other articles that have been posted:

http://blog.jeffhandley.com/archive/2008/02/13/custom-controls-everywhere-and-asp.net-mvc-part-0.aspx

Thanks,
Jeff Handley
Gravatar
ASP.NET MVC Framework Preview 2 - Changes for the Better « Accidental Technologist - Monday, March 17, 2008 - [...] These were the HTML helper methods developed by Rob Conery. [...]
Gravatar
rai - Tuesday, March 18, 2008 - Rob, I can't find the ImageButton() method. In your example you write "using ImageButton()" and you actually use the Button() method. Thanks for any clarifications, RAi
Gravatar
Exploring the ASP.NET MVC Preview 2 - First Glance « Ramblings of the Sleepy… - Friday, March 21, 2008 - [...] ‘MVCToolkit’ that Rob Conery had developed is now integrated into System.Web.Mvc as [...]
Gravatar
Damian Powell - Tuesday, March 25, 2008 - Hi Rob,

First, let me apologise for raising this issue on your blog - I'm not sure where else I should raise it.

I've been using ASP.NET MVC Preview 2 and I noticed something odd with CheckBoxes and BindingHelperExtensions.UpdateFrom(...)

The logic is slightly wrong, I think. If a box is checked, then the HTML form will send a value back (albeit an empty one). If the box is *not* checked, then the HTML form will *not* send back a value at all. So your logic falls down because it attempts to parse the value (which will *never* be a valid boolean) and so the value can not be retrieved.

I changed the code (as shown below) which works for me but presumably, this is not the intended behaviour.

---

if (values[httpKey] == null) {
httpKey = objName "_" property.Name;
}

object thisValue = values[httpKey];

if (property.PropertyType == typeof(bool)) {
bool thisBool = (null != thisValue);
property.SetValue(value, thisBool, null);
}

else if (values[httpKey] != null) {
TypeConverter conv = TypeDescriptor.GetConverter(property.PropertyType);

---

Also, I notice that there's quite a bit of difference between your stuff that's in ASP.NET MVC Preview 2, and the MVCToolkit. Which is the most up-to-date? I can't find .ToFormattedList(...) in the Preview 2 stuff which is somewhat tricky for radio and check box lists.

Thanks for the great work, Rob.


TTFN,
Damian.
Gravatar
Rob Conery - Tuesday, March 25, 2008 - @Damian - We had this discussion internally and I'm with you on this - it's not straightforward what to do when a checkbox isn't checked (and is, therefore, empty). One could argue that the absense of a boolean value is NULL, others could say that it's intentionally unchecked. It's hard to know if the checkbox was even present given the way that HTML works. That said - the team is working on a way around this. I know Monorail dealt with this very same issue and we have some ideas on how to handle. The latest is Preview 2. Many methods were omitted by the ASP team and I think they want to target putting them back in at some point. You can always post to our forums (link above) if you have questions as well.
Gravatar
Zhaph - Thursday, May 21, 2009 - Hi Rob, rather belated comment, I know, but I've just come across the problem with reserved words in the HTML Attributes - I found that using your method:

Note: if your tag is a reserved work, like “class”, use the standard “_” reserved word prefix: “_class”

Resulted in the html having an _ infront of the attribute. Using the @ symbol worked a treat:

Html.ActionLink&lt;MvcTest.Controllers.NewsController&gt;(c =&gt; c.Comment(), "Comment", new {@class = "comment"})
Gravatar
Oskar Austegard - Friday, August 21, 2009 - So I realize with you leaving MS this is no longer under your area of responsibility, but I for one would love to see an updated version of this post for MVC 1 (or maybe wait for MVC 2?).

Thanks!
Gravatar
Venkatesh - Friday, August 21, 2009 - Hi,

I'm new to ASP.NET MVC and i'm working on unit test using .NET 2008 -- VB.NET


Can you please help to resolve this problem! In order to work with session object in unit test project i've created fake session object which is working fine, now what i need is i want to set the value which can read in controller durig debug, like let say in controller i've code somthing like....

PageID = Request("hdnPageID")

This "hdnPageID" actually set in .aspx page with hidden field ie

How can i pass it from TestMethod in unit test?

Thanks in advance
Venkatesh
Gravatar
Tom Neville - Friday, October 09, 2009 - Excellent Stuff. Very powerful and leads to very clean code.
Gravatar
Altaf - Tuesday, October 13, 2009 - I love MVC. Very nice framework. Can't wait for future releases of MVC.
Gravatar
Altaf - Wednesday, November 04, 2009 - This article describes about how to handle postback in ASP.NET MVC. Check this out:

http://www.altafkhatri.com/Altaf/How-to-get-Ilist-value-from-ASP-net-mvc-postback/Bind-list-to-ASP-NET-MVC-object/Postback-object-list-binding
Gravatar
rajuyusuf - Friday, November 06, 2009 - There are few nice articles on ASP.NET MVC with very fine details at:
http://www.altafkhatri.com/Technical/How_to_bind_IList_with_MVC_Dropdownlist_box
Gravatar
cubbala - Monday, November 09, 2009 - Hi everyone, you forgot an important tips into the installation steps.
You can build an MVC application with NET Framework 2 runtime and stay alive with your old DataModel but if you want to work with the cool ToolKit you must convert the web app in NET 3.5 runtime …
Why don’t you build also a Toolkit version for the 2 Framework?