What I wants for HTML Output
<select name="model binding name">
<option value="44" data-object="jsonencoded object">122 front street</option>
<option value="45" data-object="jsonencoded object">123 main street</option>
<select>
The line in my cshtml file will look like
@Html.DropDownFillerFor(model => model.ProfileAddressId,
((ProfileUser)ViewData["ProfileData"]).Addresses,
profileAddress => profileAddress.AddressID.ToString(CultureInfo.InvariantCulture),
profileAddress => profileAddress.House + " " + profileAddress.Street)
The model is something like a store checkout and you have to select the address to use from a collection of address in ProfileData.
My trouble is understanding how ViewData works inside the helpers and I’m reading the MVC 3 source.
My original solution was:
public static MvcHtmlString DropDownFillerFor<TModel, TProperty, T2Model>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<T2Model> objectList,
Expression<Func<T2Model, string>> valueExp,
Expression<Func<T2Model, string>> textExp,
IDictionary<string, object> htmlAttributes = null)
{
var textFunc = textExp.Compile();
var valueFunc = valueExp.Compile();
foreach (var o in objectList)
{
var sli = new SelectListItem {Text = textFunc(o), Value = valueFunc(o)};
selectList.Add(sli);
}
return htmlHelper.DropDownListFor(expression, selectList, null, null);
}
And this was great but lacked the ability to add custom html attributes on a per option basis.
Unfortunately all the the methods that DropDownListFor uses are private so I’m trying to use their code (assuming they know more about this than me). I’m working my way through the code for SelectInternal as found in the SelectExtensions class and I get to the line:
object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
This line seems to get the value from the model so in my case the value of model => model.ProfileAddressId but I can’t find a way to reproduce this in my code.
The function GetModelStateValue basically returns the value in ViewData.ModelState.TryGetValue(key, out modelState). Goin a few more levels up the line I find that it all references an “IViewDataContainer ViewDataContainer”. That gets filled in when htmlhelper is created by “HtmlHelper MakeHtmlHelper(HtmlHelper html, iewDataDictionary viewData)” and I can go up a few more levels but this is where I loose it.
My question is. How do I get my values from the model when writing a extension method?
Edit:
Code for my solution posted at http://pastebin.com/r912xtat It’s been a long time so I don’t remember the details but ask and I can try to help.