Asp.net MVC5 框架是个 开源的,处处可扩展的框架。
蒋先生 在他的这本书里 对如何理解框架,如何扩展框架, 给出了大量的说明和实例。
先上效果图

大部分做传统BS 的同学看到这个页面,脑海里的第一反应 就是一堆HTML 一堆控件 然后 后台绑定什么的吧。
但请看页面的代码。
- 
@model MvcApp.Models.Employee 
 
- 
<html> 
 
- 
<head> 
 
- 
    <title>编辑员工信息</title> 
 
- 
</head> 
 
- 
<body> 
 
- 
    <table> 
 
- 
        <tr> 
 
- 
            <td>@Html.LabelFor(m => m.Name)</td> 
 
- 
            <td> 
 
- 
                @Html.EditorFor(m => m.Name) 
 
- 
            </td> 
 
- 
        </tr> 
 
- 
        <tr> 
 
- 
            <td>@Html.LabelFor(m => m.Gender)</td> 
 
- 
            <td> 
 
- 
                @Html.EditorFor(m => m.Gender) 
 
- 
            </td> 
 
- 
        </tr> 
 
- 
        <tr> 
 
- 
            <td>@Html.LabelFor(m => m.Education)</td> 
 
- 
            <td> 
 
- 
                @Html.EditorFor(m => m.Education) 
 
- 
            </td> 
 
- 
        </tr> 
 
- 
        <tr> 
 
- 
            <td>@Html.LabelFor(m => m.Departments)</td> 
 
- 
            <td> 
 
- 
                @Html.EditorFor(m => m.Departments) 
 
- 
            </td> 
 
- 
        </tr> 
 
- 
        <tr> 
 
- 
            <td>@Html.LabelFor(m => m.Skills)</td> 
 
- 
            <td> 
 
- 
                @Html.EditorFor(m => m.Skills) 
 
- 
            </td> 
 
- 
        </tr> 
 
- 
    </table> 
 
- 
</body> 
 
- 
</html> 
 
怎么做的呢? 这个MvcApp.Models.Employee 又是什么呢?为什么会很神奇的变成一堆 各种各样的 list 控件呢? 
- 
namespace MvcApp.Models 
 
- 
{ 
 
- 
    public class Employee 
 
- 
    { 
 
- 
        [DisplayName("姓名")] 
 
- 
        public string Name { get; set; } 
 
- 
 
 
- 
        [RadioButtonList("Gender")] 
 
- 
        [DisplayName("性别")] 
 
- 
        public string Gender { get; set; } 
 
- 
 
 
- 
        [DropdownList("Education")] 
 
- 
        [DisplayName("学历")] 
 
- 
        public string Education { get; set; } 
 
- 
 
 
- 
        [ListBox("Department")] 
 
- 
        [DisplayName("所在部门")] 
 
- 
        public IEnumerable<string> Departments { get; set; } 
 
- 
 
 
- 
        [CheckBoxList("Skill")] 
 
- 
        [DisplayName("擅长技能")] 
 
- 
        public IEnumerable<string> Skills { get; set; } 
 
- 
    } 
 
- 
} 
 
看到这里对C# 和 .net 熟悉的同学一定心理有点谱了吧,特性!哦原来全是通过特性反射的呀。那又是如何反射的呢?
 

MVC 框架先是通过 TemplateHint 确定了各个特性会对应的子模板,完全是通过名称的映射反射过去的。

然后再在模板中通过代码@Html.DropDownList("", listName, Model) 
去调用对自定义的对HtmlHelper 的扩展方法 DropDownList,然后在这个扩展方法中再去取得需要的列表数据IEnumerable<ListItem>,再根据这个列表数据来构建需要的List<SelectListItem> 
最后再调用已有的htmlHelper.DropDownList(name, selectListItems); 返回了需要的MvcHtmlString
整个扩展到此完毕。
同时还有许多疑点可以深究。
比如@Html.DropDownList("", listName, Model) 这段代码的第一个参数,到底起了什么作用呢?为什么是个空值呢?
通过实际测试我发现在赋空值和非空的情况下生成的HTML 有如下区别。
- 
"" 参数 
 
- 
<tr> 
 
- 
   <td><label for="Education">学历</label></td> 
 
- 
   <td> 
 
- 
     <select id="Education" name="Education"><option value="H">高中</option> 
 
- 
       <option value="B">大学本科</option> 
 
- 
       <option selected="selected" value="M">硕士</option> 
 
- 
       <option value="D">博士</option> 
 
- 
     </select> 
 
- 
   </td> 
 
- 
</tr> 
 
- 
"Test" 参数 
 
- 
<tr> 
 
- 
   <td><label for="Education">学历</label></td> 
 
- 
   <td> 
 
- 
     <select id="Education_test" name="Education.test"><option value="H">高中</option> 
 
- 
     <option value="B">大学本科</option> 
 
- 
     <option selected="selected" value="M">硕士</option> 
 
- 
     <option value="D">博士</option> 
 
- 
     </select> 
 
- 
   </td> 
 
- 
</tr> 
 
具体为何会有如上区别,请去研究代码看书吧。
玩Asp.net MVC 的同学 你真的发挥出 Asp.net MVC 这个框架的强大威力了么?