ASP.NET MVC学习之模型绑定(2)

3.手工调用模型绑定

很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了很多过程中的控制,所以我们就需要使用手工的方式进行绑定。下面我们通过一个例子来说明,首先打开Views/Home/Index.cshtml页面,并输入如下代码:

 1 @{
 2     ViewBag.Title = "Index";
 3 }
 4
 5 @if (TempData.ContainsKey("msg"))
 6 {
 7     <h1>
 8         @TempData["msg"].ToString()
 9     </h1>
10 }
11
12 @using (Html.BeginForm())
13 {
14     <input type="text" name="id" />
15     <input type="submit" value="submit" />
16 }

接着打开HomeController并写入如下代码(关于ActionName可以点击这进行参考):

 1 namespace MvcStudy.Controllers
 2 {
 3     public class HomeController : Controller
 4     {
 5         private class TestA
 6         {
 7             public String id { get; set; }
 8         }
 9
10         public ActionResult Index()
11         {
12             return View();
13         }
14
15         [HttpPost]
16         [ActionName("Index")]
17         public ActionResult IndexPost()
18         {
19             TestA ta = new TestA();
20             UpdateModel(ta);
21             TempData["msg"] = ta.id;
22             return View();
23         }
24     }
25 }

这里我们通过UpdateModel进行手动绑定,最终的结果和采用形参的方式相同,读者可以进行测试可以发现输入的值都显示了,但是读者一定会奇怪,因为TestA中的id不仅仅存在于表单,同时还存在与RouteData中以及查询字符串中,我们可以用?id=123来测试这个页面可以发现并不会修改最终结果,而通过手动调用模型绑定的优点之一就是我们可以控制数据来源,比如我们修改HomeController代码如下所示:

1         [HttpPost]
2         [ActionName("Index")]
3         public ActionResult IndexPost()
4         {
5             TestA ta = new TestA();
6             UpdateModel(ta,new FormValueProvider(ControllerContext));
7             TempData["msg"] = ta.id;
8             return View();
9         }

这里我们可以发现我们给UpdateModel传递了第二个参数,FormValueProvider这表示数据源只能来自于表单中,同样我们还可以修改成RouteDataValueProvider或者QueryStringValueProvider,具体的效果读者你自行替换之后,输入http://localhost:1201/Home/Index/123?id=asdsad测试,可以看看最后显示的内容是不是来自于我们指定的来源。再使用形参的方式中我们有时会遇到http流中不存在我们需要的值,并且这个形参的类型不能为null,或者我们不希望它为null,这个时候就会出现异常或者赋值为null,而通过UpdateModel则可以通过try…catch…的形式捕获InvalidOperationException异常从而手动处理,如果读者不希望通过这种方式也可以像下面这种形式来处理:

1             if (TryUpdateModel(ta, new QueryStringValueProvider(ControllerContext)))
2             {
3                 //正确时的操作
4             }
5             else
6             {
7                 //异常时的操作
8             }

这样我们只要通过if判断即可。

4.自定义值提供器

通过上面的我们发现ASP.NET MVC自带的模型绑定器已经提供了很多我们所需要的功能,但是有时候我们想某些值不是来自于http流中而是我们自己来填充的,那么这节知识会让你感兴趣,因为下面我们将要自定义一个值提供器来完成我们的需求。首先介绍需要用的接口和类,首先是IValueProvider接口:

 

其中ContainsPrefix用来判断这个值的前缀是不是我们能够处理的(因为ASP.NET MVC其实自带了很多这种值提供器,最后会通过循环调用的方式调用这些提供器,直到有一个返回值。)然后就是GetValue方法就是返回对应的值了,当然光有这个还不够,还需要一个工厂去创建它,以提供调用,这个类就是ValueProviderFactory,而我们仅仅只需要实现GetValueProvider方法即可,其实就是new一个值提供器并返回,当然你也可以通过这个方法的ControllerContext从而有选择性的返回一个值提供器,下面我们简单的举一个例子来处理ns

首先我们创建一个Provider文件夹,然后新建一个NSValueProvider类并在文件中写入如下代码:

 1 namespace MvcStudy.Provider
 2 {
 3     public class NSValueProvider : IValueProvider
 4     {
 5
 6         public bool ContainsPrefix(string prefix)
 7         {
 8             return String.Compare("ns", prefix, true) == 0;
 9         }
10
11         public ValueProviderResult GetValue(string key)
12         {
13             if (ContainsPrefix(key))
14             {
15                 return new ValueProviderResult("from ns", null, CultureInfo.InvariantCulture);
16             }
17             return null;
18         }
19     }
20
21     public class NSValueProviderFactory : ValueProviderFactory
22     {
23         public override IValueProvider GetValueProvider(ControllerContext controllerContext)
24         {
25             return new NSValueProvider();
26         }
27     }
28 }

最后打开Global.asax将它注册:

1 ValueProviderFactories.Factories.Insert(0, new NSValueProviderFactory());

最后我们需要修改HomeController以便能够看到结果:

1         public ActionResult Index(string ns)
2         {
3             TempData["msg"] = ns;
4             return View();
5         }

重新编译之后刷新页面我们就可以看到如下的结果:

这样我们就完成了一个值提供器了,看到这个读者一定会想模型提供器怎么去自定义呢,其实模型绑定器就是依靠这些值提供器完成的,大家想想就可以明白了。

5.模型绑定器

模型绑定器跟值提供器很相似,只是需要做的工作比较多,因为你要负责将一个类的属性填充,所以比较麻烦。下面是需要实现的接口IModelBinder:

 1 namespace System.Web.Mvc
 2 {
 3     // 摘要:
 4     //     定义模型联编程序所需的方法。
 5     public interface IModelBinder
 6     {
 7         // 摘要:
 8         //     使用指定的控制器上下文和绑定上下文将模型绑定到一个值。
 9         //
10         // 参数:
11         //   controllerContext:
12         //     控制器上下文。
13         //
14         //   bindingContext:
15         //     绑定上下文。
16         //
17         // 返回结果:
18         //     绑定值。
19         object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
20     }
21 }

这里重点是bindingContext参数,里面包含了很多绑定所需要的值和方法,下面我们举一个简单的例子,就是自定义一个模型绑定器负责绑定如下类:

1         public class TestA
2         {
3             public String id { get; set; }
4         }

同时还要规定只能通过namens.id获取值,并不会根据参数的名称去获取,下面就是我们实现接口的代码:

 1 namespace MvcStudy.Provider
 2 {
 3     public class NSModelBinder : IModelBinder
 4     {
 5
 6         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
 7         {
 8             TestA a = (TestA)bindingContext.Model ?? new TestA();
 9             bool isHave = bindingContext.ValueProvider.ContainsPrefix("ns.id");
10             if (isHave)
11             {
12                 a.id = bindingContext.ValueProvider.GetValue("ns.id").AttemptedValue;
13             }
14             else
15             {
16                 a.id = "asd";
17             }
18             return a;
19         }
20     }
21 }

最后一步当然还是需要注册(Global.asax):

1 ModelBinders.Binders.Add(typeof(MvcStudy.Controllers.HomeController.TestA), new NSModelBinder());

然后我们重新编译,并在页面中输入值并提交,可以发现TestAid并不是我们输入的值而是模型绑定器中的值,但是如果我们将Views/Home/Index.cshtml中的文本框的name改成ns.id之后,我们再输入值,最后显示的就是我们输入的值了,由此可以看出来模型绑定器是依赖于值提供器的。

至此关于模型绑定的部分就结束了,下面我们将开始学习模型验证。

转自:http://www.cnblogs.com/yaozhenfa/p/asp_net_mvc_model_bind_2.html

时间: 2024-10-14 11:00:16

ASP.NET MVC学习之模型绑定(2)的相关文章

ASP.NET MVC学习之模型绑定(1)

一.前言 下面我们将开始学习模型绑定,通过下面的知识我们将能够理解ASP.NET MVC模型的模型绑定器是如何将http请求中的数据转换成模型的,其中我们重点讲述的是表单数据. 二.正文 1.简单类型绑定 学过一定ASP.NET MVC都会为这个特点所骄傲,就是能够将表单中与同名的参数映射,这相比操作ASP.NET控件来获取值轻便了许多,但是正如上面所说的那样要同名(大小写不区分),下面我们会讲述如何自己去指定. 首先我们在HomeController(如果不存在则创建)中获取表单中的值并显示:

ASP.NET MVC学习之模型验证篇

一.学习前的一句话 在这里要先感谢那些能够点开我随笔的博友们.慢慢的已经在博客园中度过一年半了,伊始只是将博客园作为自己学习的记录本一样使用,也不敢将自己的随笔发表到博客园首页,生怕自己的技艺不高,反倒成了笑话.但是随着时间的推移,再也按捺不住这种想法,于是就写了一篇随笔发表到博客园首页.让我意想不到的是有许多人都看了,而且也留下了评论.这让我鼓起勇气写了第二.三.四篇.到现在的连载,这里我希望那些从未发表过随笔的人可以尝试去发表,在这里他人不会嘲讽你,而是会给你更好的建议.说了这么多下面我们继

ASP.NET MVC 4 (九) 模型绑定

模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Inde

[转]ASP.NET MVC 4 (九) 模型绑定

本文转自:http://www.cnblogs.com/duanshuiliu/p/3706701.html 模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: n

asp.net mvc 中的模型绑定

在asp.net MVC 应用程序, 表单提交的数据通过模型绑定将数据从View传递到控制器中.使用模型绑定显然比Request.Form["Price"] ,Decimal.Parse(Request.Form["Price"] )还需要手动类型转换要要方便很多. 模型绑定有两种,隐式绑定和显式绑定. 1.隐式模型绑定.先将表单值转化为CLR 类型,然后以表单字段name名称,value值参数传递到Action中.为了防止过度提交,使用Bind(Include)属

ASP.NET MVC 的自定义模型绑定

最近在研究 ASP.NET MVC 模型绑定,发现 DefaultModelBinder 有一个弊端,就是无法实现对浏览器请求参数的自定义,最初的想法是想为实体模型的属性设置特性(Attribute),然后通过取得设置的特性值对属性进行赋值,研究了好久 MVC 源码之后发现可以通过重写 DefaultModelBinder 的 BindProperty 方法可以达到预期的目的. ASP.NET MVC 中有一个自定义模型绑定特性 CustomModelBinderAttribute,打算通过重写

ASP.NET MVC学习之模型模板篇

一.前言 如果你使用ASP.NET MVC制作后台一定会爱上它的EditorForModal.DisplayForModal和LabelForModal方法,因为这些方法可以将模型直接变成对应的标签,省了不少事,但是对于一些苛刻的人来说,一定想自定义,下面我们会先介绍如何使用,然后介绍如何自定义. 二.正文 1.输出模型 首先我们要新建一个Home控制器,对应的还要有一个Index动作,和Index视图,接着我们在Modal下新建一个Address类: 1 namespace MvcStudy.

ASP.NET MVC学习之Ajax(完结)

一.前言 通过上面的一番学习,大家一定收获不少.但是总归会有一个结束的时候,但是这个结束也意味着新的开始. 如果你是从事ASP.NET开发,并且也使用了第三方控件,那么一定会觉得ASP.NET开发ajax十分的简单,而ASP.NET MVC学习到现在页面都是刷新的,所以这节就是ASP.NET MVC的最后一节,通过这节的学习我们将能够实现通过ajax提交表单,下面我们开始继续学习. 二.准备工作 1.首先确保引用了以下js库在_Layout中: 2.新建一个HomeController,然后在其

ASP.NET MVC学习三-数据传递之模型绑定

一:简单的模型绑定 在ASP.NET MVC中是模型绑定来解析客户端传过来的数据的,简单的来说就更近一步来封装了获得数据的手段,让用户更方便的来获取数据了 我们来简单做一个例子 public ActionResult Index() { return View(); } [HttpPost] public ActionResult Index(string username) { ViewData["username"] = username; return View(); } 这里我