ASP.Net MVC的ViewBag一个坑,不要跳进去
如鹏的学习管理系统是使用ASP.net MVC 5开发的,今天一个新版本发布后网站出现一个Bug,学生在下拉列表中选中的项再加载显示的时候发现仍然没被选中。详细一点说吧:
假如有这样一个Action:
public ActionResult Index()
{
List<SelectListItem> persons = new List<SelectListItem>();
persons.Add(new SelectListItem { Text = "腾讯", Value = "qq" });
persons.Add(new SelectListItem { Text = "如鹏", Value = "rupeng", Selected = true });
ViewBag.persons = persons;
return View();
}
Cshtml是这样的:
@Html.DropDownList("persons", (IEnumerable<SelectListItem>)ViewBag.persons)
生成的html是这样的:
<select id="persons" name="persons">
<option value="qq">腾讯</option>
<option value="rupeng">如鹏</option>
</select>
竟然第二项没有处于选中状态,太诡异了吧!
只要把DropDownList第二个参数的"persons"改成和”ViewBag.persons”的persons名字不一样就可以,比如:
@Html.DropDownList("persons1", (IEnumerable<SelectListItem>)ViewBag.persons)
这样就正确生成了:
<select id="persons1" name="persons1">
<option value="qq">腾讯</option>
<option selected="selected" value="rupeng">如鹏</option>
</select>
好诡异!!!
咋办?看源码!
DropDownList是定义在SelectExtensions扩展类中,DropDownList方法最终是调用SelectInternal方法,核心代码是这一段:
if (!flag && obj == null && !string.IsNullOrEmpty(name))
{
obj = htmlHelper.ViewData.Eval(name);
}
if (obj != null)
{
selectList = SelectExtensions.GetSelectListWithDefaultValue(selectList, obj, allowMultiple);
}
这个name参数就是我们传递给DropDownList的第一个参数"persons",上面代码主要逻辑就是:首先到ViewData中查找名字为"persons"的值,我们知道ViewData和ViewBag是一样的,所以htmlHelper.ViewData.Eval(name)取到的值就是我们在Index中定义的List<SelectListItem>()集合。GetSelectListWithDefaultValue方法的代码是:
private static IEnumerable<SelectListItem> GetSelectListWithDefaultValue(IEnumerable<SelectListItem> selectList, object defaultValue, bool allowMultiple)
{
IEnumerable enumerable= new object[]
{
defaultValue
};
IEnumerable<string> collection =
from object value in enumerable
select Convert.ToString(value, CultureInfo.CurrentCulture); HashSet<string> hashSet = new HashSet<string>(collection, StringComparer.OrdinalIgnoreCase);
List<SelectListItem> list = new List<SelectListItem>();
foreach (SelectListItem current in selectList)
{
current.Selected = ((current.Value != null) ? hashSet.Contains(current.Value) : hashSet.Contains(current.Text));
list.Add(current);
}
return list;
}
注意,我们的List<SelectListItem>()集合被当成defaultValue参数传递给GetSelectListWithDefaultValue方法了(why?),在方法内部又把defaultValue给 Convert.ToString()一下,变成了”System.Collections.Generic.List`1[System.Web.Mvc.SelectListItem]”这么一个玩意, GetSelectListWithDefaultValue的主要逻辑就是查找selectList中等于”System.Collections.Generic.List`1[System.Web.Mvc.SelectListItem]”的值,能找到才算见了鬼呢!!!
经过上面的分析我们还可以知道,不能让cshtml中DropDownList的第一个name参数和ViewBag中任何一个属性重名,否则还是会有问题,比如
public ActionResult Index()
{
List<SelectListItem> persons = new List<SelectListItem>();
persons.Add(new SelectListItem { Text = "腾讯", Value = "qq" });
persons.Add(new SelectListItem { Text = "如鹏", Value = "rupeng", Selected = true });
ViewBag.persons = persons;
ViewBag.persons1 = new string[] { };
return View();
}
Cshtml如下:
@Html.DropDownList("persons1", (IEnumerable<SelectListItem>)ViewBag.persons)
生成的html中第二条数据照样不会被selected
不知道微软为什么把DropDownList这么简单的一个东西搞的这么复杂,正验证了这句话“写的越多,错的越多”。当然也许微软会给出理由说我们用错了,说“It’s not a bug,It’s a feature,by design”好吧!谢特!
如鹏网.Net培训班正在报名,有网络的地方就可以参加如鹏网的学习,学完就能高薪就业,点击此处了解
三年前只要懂“三层架构”就可以说“精通分层架构”;现在则需要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值钱;
三年前只要会SQLServer就可以说自己“精通数据库开发”;现在则需还需要掌握MySQL等开源数据库才能说是“.Net开源”时代的程序员;
三年前只要会进行用户上传内容的安全性处理即可;现在则需要熟悉云存储、CDN等才能在云计算时代游刃有余;
三年前只要掌握Lucene.Net就会说自己“熟悉站内搜索引擎开发”;现在大家都用ElasticSearch了,你还用Lucene.Net就太老土了;
三年前发邮件还是用SmtpClient;现在做大型网站发邮件必须用云邮件引擎;
三年前缓存就是Context.Cache;现在则是Redis、Memcached的天下;
如鹏网再次引领.Net社区技术潮流!点击此处了解如鹏网.Net最新课程
ASP.Net MVC的ViewBag一个坑,不要跳进去的更多相关文章
- ASP.NET MVC 5 - 添加一个模型
在本节中,您将添加一些类,这些类用于管理数据库中的电影.这些类是ASP.NET MVC 应用程序中的"模型(Model)". 您将使用.NET Framework 数据访问技术En ...
- ASP.NET MVC掉过的坑_MVC初识及MVC应用程序结构
APS.Net MVC 浅谈[转] 来自MSDN 点击访问 MVC 理论结构 模型-视图-控制器 (MVC) 体系结构模式将应用程序分成三个主要组件:模型.视图和控制器. ASP.NET MVC 框架 ...
- 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截
程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构 .要想在之后的江湖历练中通关,数据结构必不可少. ...
- [转]ASP.NET MVC 5 - 添加一个模型
在本节中,您将添加一些类,这些类用于管理数据库中的电影.这些类是ASP.NET MVC 应用程序中的"模型(Model)". 您将使用.NET Framework 数据访问技术En ...
- 注意!ASP.NET MVC 3 的一个 OutputCache 问题
在用 ASP.NET MVC 3 重写博客园网站首页时,特地留意了一下这个缓存问题,通过这篇博文分享一下. 在 ASP.NET MVC 3 中如果使用了 OutputCache,一定要在 Action ...
- ASP.NET MVC概述及第一个MVC程序
一.ASP.NET 概述 1. .NET Framework 与 ASP.NET .NET Framework包含两个重要组件:.NET Framework ...
- 在ASP.NET MVC下扩展一个带验证的RadioButtonList
在ASP.NET MVC4中,HtmlHelper为我们提供了Html.RadioButton()方法用来显示Radio Button单选按钮.如果想显示一组单选按钮,通常的做法是遍历一个集合把每个单 ...
- ASP.NET MVC 给ViewBag赋值Html格式字符串的显示问题总结
今天再给自己总结一下,关于ViewBag赋值Html格式值,但是在web页显示不正常; 例如,ViewBag.Content = "<p>你好,我现在测试一个东西.</p& ...
- ASP.NET MVC ViewData/ViewBag 简单小结
近期在项目中遇到一个问题,就是用ViewBag.Model存储匿名对象传递给View,但是需要根据条件给匿名对象添加属性,这个可真心不易,Google了一下发现很多方案都是动态编译神马的,感觉好高大上 ...
随机推荐
- three.js 根据png生成heightmap
Three.js: render real world terrain from heightmap using open data By jos.dirksen on Tue, 07/17/2012 ...
- javascript判断变量是不是空值
JavaScript本身没有判断一个变量是不是空值的函数,因为变量有可能是string,object,number,boolean等类型,类型不同,判断方法也不同.所以在文章中写了一个函数,用以判断J ...
- java反射案例
Java反射经典实例 2007-08-29 17:55:25 分类: Java Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射.反射机制是如今很多流行框架的实现 ...
- Three ways to set specific DeviceFamily XAML Views in UWP
Three ways to set specific DeviceFamily XAML Views in UWP http://igrali.com/2015/08/02/three-ways-to ...
- OD使用教程3
reverseMe爆破: 跳转指令 让跳转已实现,把z的1改成0 按F8走,继续把z的1改成0,实现跳转 根据跳转指令,改变s或o,使跳转不实现 指令如上使跳转不实现 继续按f8往下走然后成功
- 【温故Delphi】Win32API之CreateMutex
解决问题 如何让一个软件在一台机器上只能运行一个实例呢?这个问题用专业术语就是进程互斥.这个问题可以通过CreateMutex来解决. 进程互斥的核心思想:进程在启动时首先检查是否存在此进程实例,如果 ...
- C语言小练习二
题目要求: 编程实现功能:将4行4列数组的左下三角设置为下图所示的数据.43 7 2 6 91 5 8 10 程序源码: #include <stdio.h> int main(void) ...
- 理解Java Integer的缓存策略
转载自http://www.importnew.com/18884.html 本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的一个有助于节省内存.提高性能的特性. ...
- java TreeMap用法
转自:http://huchenqiang90.blog.163.com/blog/static/11250080020101025956498/ 最近工作遇到需要按一个model中不同的列进行排序的 ...
- linux下解压被分割的zip文件
形如被分割的一系列文件:linux.z01, linux.z02, linux.z03, linux.zip 直接右键解压是不行的. 首先合并文件:cat linux.* > linux_all ...