MVC2 Bug on Data Binding in Listbox?

Seems MVC and MVC 2 don’t realize that there is an issue when binding the data on the view:

Given an extension on HtmlHelper: this extension will generate a list box in view based on the collection “cakes”. (Because I like cake, so I use dessert object as example :)

public static MvcHtmlString MyDropDownList(this HtmlHelper target, string controlName, IQueryable<Cake> cakes, object htmlAttr)
{
if (cakes== null)
return MvcHtmlString.Empty;
var cakesList = new SelectList(cakes, “Id”, “CakesName”);
return target.ListBox(controlName, cakesList, htmlAttr);
}

It is okay, but the main issue is if the when I specify the Model data on control name, it IS SUPPOSED to generate the list box with the data which retrieved from database are selected. Yes.  IT IS SUPPOSED TO BE. But, unfortunately, MVC fail to automatically bind data for us…  The data “cakesList” is showing properly, but with no preselect options. In most of the business logic, it’s not gonna work, because it is no point for user to re-select the options every time before save the data.

In this case, MVC is not gonna auto-bind the data for us, we just need to figure out another way to display and manipulate the data properly. So we will change something on the extension, view and the controller:

1. On the view, don’t specify the name to model’s name, For example, the data which will be weaved to list box is CakeViewData.CakeList, the data related to database is CakeViewData.Dessert.Cakes. Normally, we will use the extension to weave the data:

<%=Html.MyDropDownList(“Dessert.Cakes”, Model.CakeList, new { @class = “multiselect”, size = 5 })%>

Since MVC is not gonna take care of the data binding, The name (on parameter controlName) should and NEED to use other name instead. Change “Cakes” to any other name, for example, change to “MyCakes”:

<%=Html.MyDropDownList(“Dessert.MyCakes”, Model.CakeList, new { @class = “multiselect”, size = 5 })%>

2. Extension is changed to:

public static MvcHtmlString MyListBoxWithSelectedList(this HtmlHelper target, string name, IQueryable<Cake> cakes, List<string> selected, object htmlAttr)
{
if (interests == null)
return MvcHtmlString.Empty;
var cakeList = new MultiSelectList(cakes, “Id”, “CakeName”, selected);
return target.ListBox(name, cakeList, htmlAttr);
}

I just add a parameter “List<string> selected” in the extension which will be used in MultiSelectList object that can be bind to the the items to be selected.

3. In controller, before saving the data, need to use FormCollection or Request["Dessert.MyCakes"] to obtain the data “MyCakes” manually.

string myCakes = Request["Dessert.MyCakes"];
Dessert dessert = new Dessert{Cake = myCakes};

It might not be a bug actually. And in this example you can feel how flexibility that MVC can bring you: the way to manipulate the model or data varies!  :)

Happy programming in MVC 2!

REMIX10 – Share the Web Love, Late Update

I almost forget the interesting 2-day event or you can say “meeting” in Melbourne. The idea of this conference is to show Microsoft developer the latest development kits and to let technical or IT people catch up each other. $300 for joining the meeting but I got it for free. Thanks to my boss to give me such great opportunity to join the great event.

I got 2 souvenirs, such as t-shirt, caps, but all are related to Microsoft stuff. You want to get the t-shirt? well, need to make some efforts. Everyone who attends the meeting will get a magic cube from the host, and need to fix the cube to a designated image. After all, once cubes are fixed, the host sorts them out and put them in a frame, to shape a IE icon:

The Frame of Magic cubes

The Frame of Magic cubes,Everyone is involved

I think the most useful sessions are about how jQuery works peacefully with ASP.NET and VS.NET 2010 new features, and one interesting session talking about the future data representation, and introduce Pivot. Microsoft considers the cooperation with jQuery is a giant step forward, and shows its ambitions to open source community. Microsoft starts to contribute to open source community and make a lot of effort towards it, look forward to seeing its powerful tool released in months to come.

Frankly Speaking - Talk Show in REMIX10

Frankly Speaking - Talk Show in REMIX10

One thing somehow a little bit disappointed me is on this event, Microsoft doesn’t show any thing about HTML5 and CSS3, I think because Microsoft more focuses on sliverlight technology?

Partner of Joomla Development – Part 1 Firefox

Joomla has gained brilliant prestige in open source CMS development. There are heaps of 3rd-party modules and components in Joomla. For Joomla, I would rather say it is an application framework than open source CMS system.

In here, I would like to introduce some useful utilities for Joomla development. Actually the tools are also good for any website development.

Firefox

I don’t want to spend too much time introduce the open source website browser. There are at least 3 must-have plug-ins for Firefox:

1. Firebug

Good for Javascript debug, CSS preview and website structure analysis.

2. Fireshot

Sometimes we got a headache because you need to capture a screen shot of the website which is oversize in height. For a long time, I need to use window painter to join every single pieces of screenshot together to form a integrated website. With Fireshot, just fire it in one shot. Absolutely good tool.

3. Rainbow

This tool is quite useful if you need to get the color from the website (in hex decimal)

Just 3 tools? Hmm, for me, I think they are enough for the development. Of course you might need other tools to help you. In my opinion, not all tools are useful. But at least those 3 tools, especially Firebug could save you a lot of time if you need to deal with many HTML/CSS and javascript stuff.

Use of Lambda Expression to Create Complicated Query

.NET FX introduces a powerful weapon for creating the compact, breezy and elegant code in your project. The weapon’s name is as complicated as the mathematical stuff, called Lambda expression.

As the name implies, the great convenience comes great complication inside. Lambda expression is too important to understand, it is useful and I think it is good to know how it works. Well, it’s not as complicated as we think, just a little bit confusing when using it.

First of all, Lambda is used for 2 purposes. 1 is to simplify delegation, 2 is to create expression tree. In my case, I need to create lambda expression to create dynamic query.

Imagine the following usecase:

In your product table, there is a field called “Tags” and it’s used for storing the CSV (comma separated value) like “car, mazda, suv, luxury”, you have many records:

Product Table: (Table name: ProductTable)

ID    ProductName    Tags
1    Tow bar        car,mazda,suv,luxury
2    Cup holder    car,luxury
3    Phone holder    car,mazda
4    FM Transmitter    car,suv
5    Queens bed    luxury
6    DVD Burner    car,BMW,x5,luxury

When your searching criteria is
“mazda” and “luxury”, the following records would be selected out:

ID    ProductName    Tags
1    Tow bar        car,mazda,suv,luxury
2    Cup holder    car,luxury
3    Phone holder    car,mazda
5    Queens bed    luxury
6    DVD Burner    car,BMW,x5,luxury

In ancient SQL age, you would probably write a SQL like this:

string SQL = “SELECT * FORM ProductTable WHERE Tags LIKE’%mazda%’ OR Tags LIKE ‘%luxury%’”;

It is IMpossible to create SQL like above except the project scope tells you the fixed keywords that would be used, the keywords should flexible. Then the code would be as much as:

string[] tags = new string[]{“mazda”, “luxury”};
string SQL = “SELECT * FROM ProductTable WHERE 1=1″;
foreach(string tag in tags)
{
SQL += string.format(@” AND Tags like ‘%{0}%’”, tag);
}

You must be very exciting that your code supports as many keywrods as it can. (I did before, I mean I would be very exciting when the code filled with logical stuff, LOL, of course, not now, that’s what geek did before~ )

Back to the reality, to the modern age, with the lambda expression, what you need to do is:

(pre-condition: you have created corresponding domain model which mapped to the database.)
The domain object or entity would look like:

[Table("ProductTable")] Class ProductTable{
[Column]public int Id{get; set;}
[Column]public string ProductName{get; set;}
[Column]public string Tags{get; set;}
}

to fullfill the same kind of logic as the stone-aged people do, you just need to

DataContext db = new DataContext(“<connection-string>”);
Table<ProductTable> table = db.GetTable<ProductTable>();
string tag1 = “mazda”;
string tag2 = “luxury”;
var data = table.where(x=>x.Tags.Contains(tag1)).where(x=>x.Tags.Contains(tag2)) select new ProductTable;
return data.AsQueryable();

Since so far, you still feel comfortable with this, but after minute, you would probably wanna go back stone age, how do we dynamically create the query in this case? Unfortunately, there is no short-cut for this, but many people provide lots of solutions on the Internet. We can either download some source codes about dynamically query on Internet or just grab the codes from the blogger’s website.( Most of time, you can’t use all of their codes posted on the blog, the codes are broken and bad structure, remember what Koumei always suggests, absorb the mind from the other coders, do not copy the code they provided. )

But in here, I would rather to use Expression Tree to implement the dynamic query.

First of all, we need to create an expression, because it would be applied to IQueryable.Where(Expression<Func<ProductTable, bool>> expression), so the expression should be defined as:

public static System.Linq.Expressions.Expression<Func<ProductTable, bool>> ApplyTags(IEnumerable<string> tags) //parameter is the collection of tags
{
ParameterExpression c = Expression.Parameter(typeof(ProductTable), “c”); //Get the parameter from Func<ProductTable, bool>, remember? this is the advanced and lazy version of delegation, we need to craete ParameterExpression to hold this
var tagsProperty = Expression.Property(c, typeof(ProductTable).GetProperty(“Tags”)); //Here is the expression for get the Tags value from ProductTable object
Type[] ContainsTypes = new Type[1];
ContainsTypes[0] = typeof(string);
System.Reflection.MethodInfo myContainsInfo = typeof(string).GetMethod(“Contains”, ContainsTypes);
//Create the expression collection (based on the tags collection from parameter)
List<Expression> myTagExpressions = new List<Expression>();
foreach (var t in tags)
{
myTagExpressions.Add(Expression.Call(Expression.Call(tagsProperty, “ToString”, null, null), myContainsInfo, Expression.Constant(t)));
}
Expression OrExpression = null;
foreach (Expression myTagExpression in myTagExpressions)
{
if (OrExpression == null)
{
OrExpression = myTagExpression;
}
else
{
//Need to implement OR relationship among all the expressions
OrExpression = Expression.Or(myTagExpression, OrExpression);
}
}
//This is how Expression would be extracted to expression tree later on.
Expression<Func<ProductTable, bool>> predicate = Expression.Lambda<Func<ProductTable, bool>>(OrExpression, c);
return predicate;
}

Again, you can’t copy the code, since you would NOT have the same object like ProductTable and the same “Tags” property as I do. Luckily, you still can copy the code that I provide later, which is using the magic of template or generic programming. Before that, let us see how to use it:

IQueryable all = table.Where(ApplyTags(new List{“mazda”,”luxury”})).AsQueryable();

Since so far, I am 100% sure you can do it like refactoring, re-structuring to optimize your code. However, I would like to provide the code which can be general used:

public static System.Linq.Expressions.Expression<Func<T, bool>> ApplyFilter<T>(IEnumerable<string> filters, string property)
{
//Get parameter
ParameterExpression c = Expression.Parameter(typeof(T), “c”);
//Get property from <T>
var tagsProperty = Expression.Property(c, typeof(T).GetProperty(property));
Type[] ContainsTypes = new Type[1];
ContainsTypes[0] = typeof(string);
System.Reflection.MethodInfo myContainsInfo = typeof(string).GetMethod(“Contains”, ContainsTypes);
List<Expression> myTagExpressions = new List<Expression>();
foreach (var t in filters)
{
myTagExpressions.Add(Expression.Call(Expression.Call(tagsProperty, “ToString”, null, null), myContainsInfo, Expression.Constant(t)));
}
Expression OrExpression = null;
foreach (Expression myTagExpression in myTagExpressions)
{
if (OrExpression == null)
{
OrExpression = myTagExpression;
}
else
{
OrExpression = Expression.Or(myTagExpression, OrExpression);
}
}
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(OrExpression, c);
return predicate;
}

The usage is similiar:

IQueryable all = table.Where(ApplyFilter<ProductTable>(new List{“mazda”,”luxury”}, “Tags”)).AsQueryable();

Not that hard, right?

Enjoy the powerful weapon, but don’t hurt yourself, bacause the deadline is ahead!

6    DVD Burner    car,BMW,x5,luxury

Giant Hail Storm Hits Melbourne at 2pm Saturday

Never seen this before. In the morning I just plan to go outside, but unfortunately or you may say luckily something wrong with my navigation, I could not turn it on! Then I stay home and try to fix my GPS.  About 2pm, it turns a sudden rain, heavily. Soon I heard some noises from the roof, become louder and louder, even deafening. I think the house is gonna break down! My goodness. It is a big hail storm. Hitting the tree, house and the car outside.

The hailstones are no where!

And the power is cut for about 4 hours.

Here is the abridged news from abc.net.au:

Hailstones the size of golf balls have hit the suburb of Melton, in Melbourne’s west, as a line of storms moved through western Victoria.
……………….
Melton, on Melbourne’s northwest fringe,  was one of the first suburbs to feel the storm’s wrath.
(Tell you what, Melton is the place where I plan to go, roughly 35KM from CBD Melbourne.)

Lucky me! I love my GPS, really love it. Actually I blame it why it stops working when I get into the car. But now I understand, it stops to save me from hitting by the hailstorm! And always give me direction when I am lost.