mvc html.dropdownlist,ASP.NET MVC Html.DropDownList SelectedValue

If we don't think this is a bug the team should fix, at lease MSDN should improve the document. The confusing really comes from the poor document of this. In MSDN, it explains the parameters name as,

Type: System.String

The name of the form field to return.

This just means the final html it generates will use that parameter as the name of the select input. But, it actually means more than that.

I guess the designer assumes that user will use a view model to display the dropdownlist, also will use post back to the same view model. But in a lot cases, we don't really follow that assumption.

Use the example above,

public class Person {

public int Id { get; set; }

public string Name { get; set; }

}

If we follow the assumption,we should define a view model for this dropdownlist related view

public class PersonsSelectViewModel{

public string SelectedPersonId,

public List Persons;

}

Because when post back, only the selected value will post back, so it assume it should post back to the model's property SelectedPersonId, which means Html.DropDownList's first parameter name should be 'SelectedPersonId'. So, the designer thinks that when display the model view in the view, the model's property SelectedPersonId should hold the default value of that dropdown list. Even thought your List Persons already set the Selected flag to indicate which one is selected/default, the tml.DropDownList will actually ignore that and rebuild it's own IEnumerable and set the default/selected item based on the name.

Here is the code from asp.net mvc

private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,

string optionLabel, string name, IEnumerable selectList, bool allowMultiple,

IDictionary htmlAttributes)

{

...

bool usedViewData = false;

// If we got a null selectList, try to use ViewData to get the list of items.

if (selectList == null)

{

selectList = htmlHelper.GetSelectData(name);

usedViewData = true;

}

object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));

// If we haven't already used ViewData to get the entire list of items then we need to

// use the ViewData-supplied value before using the parameter-supplied value.

if (defaultValue == null && !String.IsNullOrEmpty(name))

{

if (!usedViewData)

{

defaultValue = htmlHelper.ViewData.Eval(name);

}

else if (metadata != null)

{

defaultValue = metadata.Model;

}

}

if (defaultValue != null)

{

selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);

}

...

return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);

}

So, the code actually went further, it not only try to look up the name in the model, but also in the viewdata, as soon as it finds one, it will rebuild the selectList and ignore your original Selected.

The problem is, in a lot of cases, we don't really use it that way. we just want to throw in a selectList with one/multiple item(s) Selected set true.

Of course the solution is simple, use a name that not in the model nor in the viewdata. When it can not find a match, it will use the original selectList and the original Selected will take affect.

But i still think mvc should improve it by add one more condition

if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))

{

selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);

}

Because, if the original selectList has already had one Selected, why would you ignore that?

Just my thoughts.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值