Referring Jon Galloway's post, here is my 5-minute-scracth-up-somthing that includes no hacking at all:
The Controller:
public class GourmetController : SmartDispatcherController { [AccessibleThrough(Verb.Get)] public void WineMatch() { PropertyBag["matches"] = FoodAndWineMatchRepository.FindAll(); } [AccessibleThrough(Verb.Post)] public void Update([DataBind("matches")]FoodAndWineMatch[] matches) { FoodAndWineMatchRepository.UpdateAll(matches); RedirectToAction("WineMatch"); } }
The View:
<%@ Page Language="C#" %> <%@ Import Namespace="Gourmet" %> <% FoodAndWineMatch[] matches; %> <% IDictionary @checked = DictHelper.CreateDict("checked='checked'"); %> <form action="Update.aspx" method="post"> <table> <tr> <th>Food Name</th> <th>Cabarnet</th> <th>Zinfandel</th> <th>Pinot</th> </tr> <%int i = 0; %> <%foreach (FoodAndWineMatch match in matches) { %> <tr> <td> <span><%=match.FoodName%></span> <input type="hidden" name="matches[<%=i%>].FoodName" value="<%=matches[i].FoodName%>" /> </td> <td> <%=FormHelper.CheckboxField("matches[" + i + "].MatchesCabarnet", matches[i].MatchesCabarnet?@checked:null)%> </td> <td> <%=FormHelper.CheckboxField("matches[" + i + "].MatchesZinfandel", matches[i].MatchesZinfandel?@checked:null)%> </td> <td> <%=FormHelper.CheckboxField("matches[" + i + "].MatchesPinot", matches[i].MatchesPinot?@checked:null)%> </td> </tr> <%++i; } %> <tr> <td colspan="4"> <input type="submit" value="Save" /> </td> </tr> </table> </form>
And the mocked "domain objects":
public class FoodAndWineMatch { private string foodName; private bool matchesCabarnet; private bool matchesPinot; private bool matchesZinfandel; public FoodAndWineMatch() { } public FoodAndWineMatch(string foodName) : this(foodName, false, false, false) { } public FoodAndWineMatch(string foodName, bool matchesCabarnet, bool matchesPinot, bool matchesZinfandel) { this.foodName = foodName; this.matchesCabarnet = matchesCabarnet; this.matchesZinfandel = matchesZinfandel; } public string FoodName { get { return foodName; } set { foodName = value; } } public bool MatchesCabarnet { get { return matchesCabarnet; } set { matchesCabarnet = value; } } public bool MatchesPinot { get { return matchesPinot; } set { matchesPinot = value; } } public bool MatchesZinfandel { get { return matchesZinfandel; } set { matchesZinfandel = value; } } } public static class FoodAndWineMatchRepository { private static FoodAndWineMatch[] _matches = null; public static FoodAndWineMatch[] FindAll() { if (_matches == null) _matches = new FoodAndWineMatch[] { new FoodAndWineMatch("Salmon"), new FoodAndWineMatch("Steak"), new FoodAndWineMatch("Chicken"), new FoodAndWineMatch("Chocolate") }; return _matches; } public static void UpdateAll(FoodAndWineMatch[] matches) { _matches = matches; } }
No hacking needed. Controller code is short and intuitive.
Oh. No postback for every client click ...
I especially liked one of the comments on Jon's post:
I love ASP.NET because of tricks like this that the developer can use.
Well, I do not like WebForms because it makes me "do tricks" (or hack) instead of bringing business value.
So I do not mean that Jon's "hack" is bad. That's what you have to do when you're WebForm-ing. I just say that there are other web development frameworks (actually, all but WebForms) that are more suited for reasonable html generation and for dealing with the http protocol.