3.手工调用模型绑定

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

 @{
ViewBag.Title = "Index";
} @if (TempData.ContainsKey("msg"))
{
<h1>
@TempData["msg"].ToString()
</h1>
} @using (Html.BeginForm())
{
<input type="text" name="id" />
<input type="submit" value="submit" />
}

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

 namespace MvcStudy.Controllers
{
public class HomeController : Controller
{
private class TestA
{
public String id { get; set; }
} public ActionResult Index()
{
return View();
} [HttpPost]
[ActionName("Index")]
public ActionResult IndexPost()
{
TestA ta = new TestA();
UpdateModel(ta);
TempData["msg"] = ta.id;
return View();
}
}
}

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

         [HttpPost]
[ActionName("Index")]
public ActionResult IndexPost()
{
TestA ta = new TestA();
UpdateModel(ta,new FormValueProvider(ControllerContext));
TempData["msg"] = ta.id;
return View();
}

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

             if (TryUpdateModel(ta, new QueryStringValueProvider(ControllerContext)))
{
//正确时的操作
}
else
{
//异常时的操作
}

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

4.自定义值提供器

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

 namespace System.Web.Mvc
{
// 摘要:
// 定义 ASP.NET MVC 中的值提供程序所需的方法。
public interface IValueProvider
{
// 摘要:
// 确定集合是否包含指定的前缀。
//
// 参数:
// prefix:
// 要搜索的前缀。
//
// 返回结果:
// 如果集合包含指定的前缀,则为 true;否则为 false。
bool ContainsPrefix(string prefix);
//
// 摘要:
// 使用指定键来检索值对象。
//
// 参数:
// key:
// 要检索的值对象的键。
//
// 返回结果:
// 指定的键的值对象。
ValueProviderResult GetValue(string key);
}
}

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

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

 namespace MvcStudy.Provider
{
public class NSValueProvider : IValueProvider
{ public bool ContainsPrefix(string prefix)
{
return String.Compare("ns", prefix, true) == ;
} public ValueProviderResult GetValue(string key)
{
if (ContainsPrefix(key))
{
return new ValueProviderResult("from ns", null, CultureInfo.InvariantCulture);
}
return null;
}
} public class NSValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
return new NSValueProvider();
}
}
}

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

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

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

         public ActionResult Index(string ns)
{
TempData["msg"] = ns;
return View();
}

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

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

5.模型绑定器

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

 namespace System.Web.Mvc
{
// 摘要:
// 定义模型联编程序所需的方法。
public interface IModelBinder
{
// 摘要:
// 使用指定的控制器上下文和绑定上下文将模型绑定到一个值。
//
// 参数:
// controllerContext:
// 控制器上下文。
//
// bindingContext:
// 绑定上下文。
//
// 返回结果:
// 绑定值。
object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
}
}

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

         public class TestA
{
public String id { get; set; }
}

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

 namespace MvcStudy.Provider
{
public class NSModelBinder : IModelBinder
{ public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
TestA a = (TestA)bindingContext.Model ?? new TestA();
bool isHave = bindingContext.ValueProvider.ContainsPrefix("ns.id");
if (isHave)
{
a.id = bindingContext.ValueProvider.GetValue("ns.id").AttemptedValue;
}
else
{
a.id = "asd";
}
return a;
}
}
}

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

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

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

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

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

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

    一.前言 下面我们将开始学习模型绑定,通过下面的知识我们将能够理解ASP.NET MVC模型的模型绑定器是如何将http请求中的数据转换成模型的,其中我们重点讲述的是表单数据. 二.正文 1.简单类型 ...

  2. .NET MVC学习之模型绑定

    ASP.NET MVC学习之模型绑定(2)   继ASP.NET MVC学习之模型绑定继续 3.手工调用模型绑定 很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了 ...

  3. ASP.NET MVC学习之模型验证详解

    ASP.NET MVC学习之模型验证篇 2014-05-28 11:36 by y-z-f, 6722 阅读, 13 评论, 收藏, 编辑 一.学习前的一句话 在这里要先感谢那些能够点开我随笔的博友们 ...

  4. Asp.net Mvc 中的模型绑定

    asp.net mvc中的模型绑定可以在提交http请求的时候,进行数据的映射. 1.没有模型绑定的时候 public ActionResult Example0() { ) { string id ...

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

    本文转自:http://www.cnblogs.com/duanshuiliu/p/3706701.html 模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C ...

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

    模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: ...

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

    一.学习前的一句话 在这里要先感谢那些能够点开我随笔的博友们.慢慢的已经在博客园中度过一年半了,伊始只是将博客园作为自己学习的记录本一样使用,也不敢将自己的随笔发表到博客园首页,生怕自己的技艺不高,反 ...

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

    一.前言 如果你使用ASP.NET MVC制作后台一定会爱上它的EditorForModal.DisplayForModal和LabelForModal方法,因为这些方法可以将模型直接变成对应的标签, ...

  9. ASP.NET MVC中的模型绑定

    模型绑定的本质   任何控制器方法的执行都受action invoker组件(下文用invoker代替)控制.对于每个Action方法的参数,这个invoker组件都会获取一个Model Binder ...

随机推荐

  1. 使用虚幻引擎中的C++导论(二-UE4基类)

    使用虚幻引擎中的C++导论(二) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如果有不 ...

  2. 使用jna调用dll,jdk位数和dll位数的关系

    最近在学习jna,发现dll文件能能否成功调用取决于jdk位数. 32位jdk只能使用32位的dll,64位jdk只能使用64位的dll,否则位数不对应的话报的错是 "Exception i ...

  3. tomcat7.0 处理问题

    修改tomcat的用户密码 打开tomcat的conf/tomcat-users.xml 将<user username="admin" password="123 ...

  4. app.js ejs 转换为html

    var express = require('express');var path = require('path');var favicon = require('serve-favicon');v ...

  5. Android源代码结构分析

    Google提供的Android包含了:Android源代码,工具链,基础C库,仿真环境,开发环境等,完整的一套.第一级别的目录和文件如下所示:----------------├── Makefile ...

  6. VC++模态对话框和非模态对话框

    MFC中有两种类型的对话框:模态对话框和非模态对话框.  模态对话框是指当其显示时,程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中其他任务.非模态对话框是指当其显示时,允许转而执行程序中 ...

  7. WebView加载本地Html文件并实现点击效果

    Webview是用来与前端交互的纽,可以加载本地Html文件,和网页并实现交互的功能. WebView通过WebSetting可以使用Android原生的JavascriptInterface来进行j ...

  8. 记一次 Ubuntu 使用 arptables 抵御局域网 ARP 攻击

    . . . . . 前段时间大概有一个月左右,租房的网络每天都断一次,每次断大概一两分钟左右就恢复了,所以没太在意.直到有一天晚上,LZ 正在写博客,但是网络频繁中断又重新连上再中断.待 LZ 好不容 ...

  9. C/C++语言的一些精简归纳

    前言:本想直接写个关于OC语言,但觉得还是要说下C先. 先语言特性 C是面向过程的,没有类和对象概念,也就没有什么封装(这个?).继承.多态等特性. 而且是是中级语言,其编译过程包括:预编译(incl ...

  10. js中实现字母大小写转换

    js中实现字母大小写转换主要用到了四个js函数: 1.toLocaleUpperCase  2.toUpperCase3.toLocaleLowerCase4.toLowerCase 下面就这四个实现 ...