天天看点

ASP.NET MVC Model绑定(六)ASP.NET MVC Model绑定(六)

前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框架中给我们提供了几种默认的实现类型,在本篇中将会对NameValueCollectionValueProvider类型做一个示例讲解,了解一下MVC框架给我们提供的值提供程序是怎么处理Model值的。

IModelBinder、自定义Model绑定器简单实现

Model绑定器在MVC框架中的位置

MVC中的默认Model绑定器生成过程

IModelBinderProvider的简单应用

IValueProvider在MVC框架中生成的位置以及过程

IValueProvider的应用场景

IValueProvider的实现之NameValueCollectionValueProvider

前面的一篇中我们对IValueProvider的使用作了示例演示,那是一个从控制器方法到视图的一个绑定的过程,大家有没有想过在视图里的数据是怎么在绑定回控制器部分的。视图中的数据类型的不同对应的使用绑定的类型也不同,本篇就为大家示例一个自定义类型的绑定。

代码1-1

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<code>public</code> <code>class</code> <code>Customer</code>

<code>    </code><code>{</code>

<code>        </code><code>[HiddenInput(DisplayValue=</code><code>true</code><code>)]</code>

<code>        </code><code>public</code> <code>string</code> <code>CustomerID { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>[Display(Name=</code><code>"姓名"</code><code>)]</code>

<code>        </code><code>public</code> <code>string</code> <code>Name { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>[DataType(DataType.Date)]</code>

<code>        </code><code>[Display(Name=</code><code>"注册日期"</code><code>)]</code>

<code>        </code><code>public</code> <code>DateTime RegistrationDate{ </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>[UIHint(</code><code>"Address"</code><code>)]</code>

<code>        </code><code>public</code> <code>Address Address { </code><code>get</code><code>; </code><code>set</code><code>; } </code>

<code>    </code><code>}</code>

<code>    </code><code>public</code> <code>class</code> <code>Address</code>

<code>        </code><code>[Display(Name=</code><code>"地址名称"</code><code>)]</code>

<code>        </code><code>[MyCustomMetadataAware]</code>

<code>        </code><code>public</code> <code>string</code> <code>AddressName { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

对的代码1-1中的类型已经出现过很多次了,但是出于对没看过前面篇幅的朋友负责的态度也要加上阿,这是下面示例要用到的示例ViewModel。

首先我们需要数据展示:

代码1-2:

<code>    </code><code>public</code> <code>class</code> <code>ValueProviderCaseController : Controller</code>

<code>        </code><code>public</code> <code>ViewResult Show(Customer customer)</code>

<code>        </code><code>{</code>

<code>            </code><code>return</code> <code>View(customer);</code>

<code>        </code><code>}</code>

代码1-2中定义了个Show()方法,参数类型为代码1-1所示类型。

看下Show()方法对应的视图,当然了这样创建的是强类型视图,代码1-3.

代码1-3

<code>@model ConsoleApplication2.Customer</code>

<code>@{</code>

<code>    </code><code>ViewBag.Title = "Show";  </code>

<code>}</code>

<code>&lt;</code><code>h2</code><code>&gt;</code>

<code>    </code><code>Show&lt;/</code><code>h2</code><code>&gt;</code>

<code>@using (Html.BeginForm("Update", "ValueProviderCase"))</code>

<code>{</code>

<code>    </code><code>&lt;</code><code>p</code><code>&gt;@Html.EditorForModel()&lt;/</code><code>p</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>p</code><code>&gt;@Html.EditorFor(m =&gt; Model.Address)&lt;/</code><code>p</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>br</code> <code>/&gt;</code>

<code>    </code><code>&lt;</code><code>input</code> <code>type</code><code>=</code><code>"submit"</code> <code>value</code><code>=</code><code>"提交"</code> <code>/&gt;</code>

在代码1-3中,我们也看到了,使用了BeginForm()视图辅助器,并且令表单指向ValueProviderCase 控制器的Update()方法,这个后面会说到,暂且带过。现在这个时候我们还运行不了项目,我们需要为代码1-2中的Show()配置一个Model绑定器,代码1-4.

代码1-4

<code> </code><code>public</code> <code>class</code> <code>MyCustomModelBinder : IModelBinder</code>

<code>        </code><code>public</code> <code>object</code> <code>BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)</code>

<code>            </code><code>if</code> <code>(controllerContext.HttpContext.Request.RequestType == </code><code>"GET"</code><code>)</code>

<code>            </code><code>{</code>

<code>                </code><code>return</code> <code>new</code> <code>Customer()</code>

<code>                </code><code>{</code>

<code>                    </code><code>CustomerID = </code><code>"010"</code><code>,</code>

<code>                    </code><code>Name = </code><code>"测试人员"</code><code>,</code>

<code>                    </code><code>RegistrationDate = DateTime.Now,</code>

<code>                    </code><code>Address = </code><code>new</code> <code>Address()</code>

<code>                    </code><code>{</code>

<code>                        </code><code>AddressName = </code><code>"天空之城"</code>

<code>                    </code><code>}</code>

<code>                </code><code>};</code>

<code>            </code><code>}</code>

<code>            </code><code>return</code> <code>null</code><code>;</code>

从代码1-4中,我们可以看到对Model绑定器做了控制,使它在请求类型为Get的时候返回代码1-1所示类型的ViewModel实例。因为后面的示例我们也还会用到这个Model绑定器,所以加了控制。对于Model绑定器的注册这里就不说了,运行结果如图1.

图1

ASP.NET MVC Model绑定(六)ASP.NET MVC Model绑定(六)

如果这个时候我们单击提交按钮会把数据会变成什么样子呢?数据到了当前系统上下文中。

NameValueCollection

为什么要讲到NameValueCollection类型呢,因为NameValueCollectionValueProvider类型中的操作就是针对的NameValueCollection类型的,这里我们来看图1中点击提交后的的数据展示如图2

图2

ASP.NET MVC Model绑定(六)ASP.NET MVC Model绑定(六)

说好了数据呢?大家别急,图2中的是NameValueCollection类型的AllKeys属性中的值,而NameValueCollection类型的实例是通过controllerContext.HttpContext.Request.Form这样获取而来,也就是上面说到的点击&amp;ldquo;提交&amp;rdquo;后所形成的数据类型。而我们的NameValueCollectionValueProvider类型则是对NameValueCollection类型的处理,具体的内部处理细节就不在这详细描述了。

下面我们需要做提交后的操作,就是显示到更新界面,那我们得按照上面代码1-3中的定义的那样,需要个Update()方法,示例代码1-5.

代码1-5

<code>        </code><code>[HttpPost]</code>

<code>        </code><code>public</code> <code>ActionResult Update(Customer customer)</code>

这个时候我们是看不到绑定器内部的实现的,所以我们来模拟一下,修改上面代码1-4中的内容,如示例代码1-6.

代码1-6

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

<code>public</code> <code>class</code> <code>MyCustomModelBinder : IModelBinder</code>

<code>            </code><code>else</code> <code>if</code> <code>(controllerContext.HttpContext.Request.RequestType == </code><code>"POST"</code><code>)</code>

<code>                </code><code>Customer customer = </code><code>new</code> <code>Customer();</code>

<code>                </code><code>customer.Address = </code><code>new</code> <code>Address();</code>

<code>                </code><code>NameValueCollection nameValueCollection =</code>

<code>                    </code><code>controllerContext.HttpContext.Request.Form;</code>

<code>                </code><code>NameValueCollectionValueProvider nameValueCollectionValueProvider =</code>

<code>                    </code><code>new</code> <code>NameValueCollectionValueProvider(</code>

<code>                        </code><code>nameValueCollection,</code>

<code>                        </code><code>System.Globalization.CultureInfo.InstalledUICulture);</code>

<code>                </code><code>customer.CustomerID = GetValue(nameValueCollectionValueProvider, </code><code>"CustomerID"</code><code>);</code>

<code>                </code><code>customer.Name = GetValue(nameValueCollectionValueProvider, </code><code>"Name"</code><code>);</code>

<code>                </code><code>customer.RegistrationDate = DateTime.Parse(GetValue(nameValueCollectionValueProvider, </code><code>"RegistrationDate"</code><code>));</code>

<code>                </code><code>customer.Address.AddressName = GetValue(nameValueCollectionValueProvider, </code><code>"Address.AddressName"</code><code>);</code>

<code>                </code><code>return</code> <code>customer;</code>

<code>        </code><code>private</code> <code>string</code> <code>GetValue(IValueProvider valueProvider, </code><code>string</code> <code>preFix)</code>

<code>            </code><code>return</code> <code>valueProvider.ContainsPrefix(preFix) ? valueProvider.GetValue(preFix).AttemptedValue : </code><code>null</code><code>;</code>

这里忘了说了,可以把NameValueCollection类型想象成一个键值队类型的集合,并且NameValueCollection类型的实例已经包含着所有数据了,可以使用它内部的GetValue方法(并非代码1-6中的GetValue方法)来获取所对应的值,在NameValueCollectionValueProvider类型内部也是使用的这个方法来获取的值。

在代码1-6中我们对Model绑定器修改了太多了,首先是控制器了在请求类型为POST的时候(也就是为了在请求Update()方法时所用)使用这个Model绑定器,随之我们实例化了一个代码1-1中所示的ViewModel实例,后面会对它进行赋值,随后我们通过上下文获取到表单中的数据(NameValueCollection类型的实例)作为NameValueCollectionValueProvider类型构造函数的参数,我们还在Model绑定器中定义了个私有的GetValue()方法,这个的用途就是根据执行的前缀(NameValueCollection类型中的键值,也就是视图元素中的Name属性)从NameValueCollectionValueProvider类型的实例中获取对应的数据。

现在看一下Update()方法所对应的视图代码,示例代码1-7

<code>    </code><code>ViewBag.Title = "Update";</code>

<code>    </code><code>Update&lt;/</code><code>h2</code><code>&gt;</code>

<code>&lt;</code><code>p</code><code>&gt;@Html.EditorForModel()&lt;/</code><code>p</code><code>&gt;</code>

<code>&lt;</code><code>p</code><code>&gt;@Html.EditorFor(m =&gt; Model.Address)&lt;/</code><code>p</code><code>&gt;</code>

这个时候我们可以运行项目,首先看到Show页面后,修改其中的值,然后提交过后会看到修改的值已经更新到了Update的界面中。

     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1434205,如需转载请自行联系原作者