• ASP.NET MVC模型绑定的6个建议,徐汇区网站设计 狼人:


    ASP.NET MVC中的Model Binding使用起来非常简单。你的Action方法需要数据,在传入的HTTP请求中携带着你需要的数据,数据可以在请求的表单数据中,还可能在你的URL地址本身中。通过DefaultModelBinder,可以神奇地将表单中的数据和路由中的数据转换到对象中。Model Binder使得你的控制器代码可以干净地从请求以及关联的环境中分离出来。

    这里有一些关于在MVC项目中更好使用Model Binding的建议。

    Tip#1:最好使用Model Binding而不是Request.Form

    如果你的Action像下面这样:

    1. [AcceptVerbs(HttpVerbs.Post)]   
    2.  
    3. public ActionResult Create()   
    4.  
    5. {   
    6.  
    7.     Recipe recipe = new Recipe();   
    8.  
    9.     recipe.Name = Request.Form["Name"];   
    10.  
    11.         
    12.  
    13.     // ...   
    14.  
    15.         
    16.  
    17.     return View();   
    18.  
    19. }   

    就不对了。这些属性使得你的Action很难读而且更难以测试,Model Binder可以帮你从Request和HttpContext中摆脱出来。比如,你可以使用FormCollection类型的参数来代替上面的代码:

    1. public ActionResult Create(FormCollection values)   
    2.  
    3. {   
    4.  
    5.     Recipe recipe = new Recipe();   
    6.  
    7.     recipe.Name = values["Name"];         
    8.  
    9.                 
    10.  
    11.     // ...   
    12.  
    13.                 
    14.  
    15.     return View();   
    16.  
    17. }   

    使用FormCollection你可以不必再深入到Request对象,这样,有时候你就可以使用低层次的控制了。但是,如果你的数据来自Request.Form,或者URL请求参数,你可以通过Model Binding来完成它的魔术。

    1. [AcceptVerbs(HttpVerbs.Post)]   
    2.  
    3. public ActionResult Create(Recipe newRecipe)   
    4.  
    5. {               
    6.  
    7.     // ...   
    8.  
    9.         
    10.  
    11.     return View();   
    12.  
    13. }   

    在这个例子中,Model Binder将会帮你创建newRecipe对象,并且使用从Request中获得获得的数据来填充它,真的是魔术。有许多的途径允许你定制绑定的处理过程,使用白名单,黑名单,前缀,以及接口,更多的控制还允许你通过UpdateModel和TryUpdateModel方法进行,只是要注意无意的绑定。看一看Justin Etheredge的文章Think Before You Bind.

    Tip#2定制Model Binder

    在MVC中,Model Binding也是一个扩展点。如果默认的绑定不合适的话,你可以提供一个自定义的Model Binder,实现自定义的Model Binder你需要实现接口IModelBinder,这是仅有的一个方法,有多难吗?

    1. public interface IModelBinder   
    2.  
    3. {   
    4.  
    5.     object BindModel(ControllerContext controllerContext,   
    6.  
    7.                       ModelBindingContext bindingContext);   
    8.  
    9. }   

    一旦你进入Model Binding,实际上,你将会发现这个简单的IModelBinder接口并没有完全描述在框架中的默认契约和负作用。如果你退回一步看一看,就会发现Model Binder,ModelState以及HtmlHelper。

    Scott Hanselman在他的 “Splitting DateTime – Unit Testing ASP.NET MVC Custom Model Binders”中给出了一个并不是演示版的Model Binder,一个我需要提出来的细节是Scott的DateTime分离器仍然没有通过Request.Form来绑定,在GetA<T> 方法中,你将会看到Scott使用了上下文对象的ValueProvider属性来获得数据,ValueProvier表示混合了表单数据,路由数据,以及请求参数数据的数据。Scott的例子非常棒,但是,少了一个细节:绑定中的错误。

    如果默认的模型绑定器在将数据绑定到你的对象上时出现了问题,它会将错误信息和错误的数据压入到ModelState中,你可以检查ModelState.IsValid来检查绑定中的问题,使用ModelState.AddModelError 方法可以注入你自己的错误信息。

    如果你看看Scott文章的回应,你会看到Sebastien Crocquesel’s 对这个问题的补丁。如果转换失败,Sebastien的代码将会使用ModelState.AddModelError方法来表示错误。Controller和View都会使用ModelState来检查绑定的问题。Controller需要检查ModelState,以便在将数据保存到数据库之前检查错误,而View需要通过ModelState来为用户提供验证的回应。需要注意的一点是HtmlHelper,你需要同时提供一个值,通过ModelState.SetModelValue,并且提供错误信息,通过AddModelError,否则你将会得到一个运行时的空引用异常,下面的代码演示了这个问题。

    1. [AcceptVerbs(HttpVerbs.Post)]   
    2.  
    3. public ActionResult Create(FormCollection Form)   
    4.  
    5. {   
    6.  
    7.     // this is the wrong approach ...   
    8.  
    9.     if (Form["Name"].Trim().Length == 0)   
    10.  
    11.         ModelState.AddModelError("Name", "Name is required");   
    12.  
    13.     
    14.  
    15.     return View();   
    16.  
    17. }   

    上面的代码创建了一个模型的错误信息,但是没有提供值。也有其他的问题,但是,如果你像下面一场呈现视图,那么,就会得到一个异常。

    <%= Html.TextBox("Name", Model.Name) %>

    纵然你为 Model.Name 提供了一个值,HtmlHelper 也会发现错误,然后显示试图的值。如果你没有提供值,就会看到一个空引用异常。

    Tip#3通过继承来自定义Model Binding

    如果你决定实现一个自定义的Model Binder,你可能希望通过从DefaultModelBinder继承来减少部分工作量,其实,最终你会发现不能通过继承DefaultModelBinder 来达到你的目的。例如,假如你希望通过自定义的 ModelBinder来创建某些对象,DefaultModelBinder将会使用Activator.CreateInstance和Model的默认构造函数来创建对象,如果你的模型没有提供默认的构造函数,你可以重写CreateModel方法来解决这个问题。

    Jimmy有一篇关于使用DefaultModelBinder的派生类的帖子“A Better Model Binder”.

    Tip#4使用注解来完成验证

    Brad Wilson在他的文章DataAnnotations and ASP.NET MVC中,完美地演示了一切。

    我建议你仔细读一下Brad Wilson的文章,如果你想快一点,这里总结了一下。

    .NET 3.5 SP1带来了System.ComponentModel.DataAnnotations程序集,通过数据的注解和DataAnnotationModelBinder,你可以处理大部分的服务器端验证问题,只需要简单地标注你的模型

    1. public class Recipe   
    2.  
    3. {   
    4.  
    5.     [Required(ErrorMessage="We need a name for this dish.")]   
    6.  
    7.     [RegularExpression("^Bacon")]    
    8.  
    9.     public string Name { get; set; }   
    10.  
    11.     
    12.  
    13.     // ...   
    14.  
    15. }   

    Tip#5绑定和验证是两个步骤

    绑定是从环境中获得数据,然后赋予模型对象的过程,验证是检查模型对象的数据,确认符合我们的期望。这是完全不同的操作,但是模型绑定模糊了他们的区别。如果你希望在Model Binder中一起完成这两步工作,是可以的,这需要准确地知道DataAnnotationsModelBinder做了什么,你可以看这几个例子。实际上,经常被忽略的一点是DefaultModelBinder如何分离绑定和验证步骤。如果只是简单属性的验证,所有你要做的就是重写DefaultModelBinder的OnProperValidating方法。

    下面的几篇文章可以参考一下:

    Tip#6关于绑定的内容

    前面我说过:Model Binder可以帮你从Request和HttpContext中摆脱出来。从更加广泛的角度来说,并没有限制数据的来源,请求上下文中包含丰富的客户端信息。Scott Hanselman的另外一篇文章演示了将用户的标识绑定到模型上。

    综上所述

    Model Binding是美妙的魔术,所以,尽可能使用内置的奇妙功能。

    文章出自:博客园

    英文出自:6 Tips for ASP.NET MVC Model Binding

  • 相关阅读:
    使用 Istio 进行 JWT 身份验证(充当 API 网关)
    DNS 私有域的选择:internal.xxx.com/lan.xxx.com 还是 xxx.local/xxx.srv?
    「Bug」K8s 节点的 IP 地址泄漏,导致 IP 被耗尽
    Linux网络学习笔记(二):域名解析(DNS)——以 CoreDNS 为例
    Linux 发行版的选用(服务器和个人桌面)
    「Bug」VMware 虚拟机的关机测试中,Ubuntu 明显比 CentOS 慢
    VMware vSphere :服务器虚拟化
    「Bug」ubuntu 使用国内 apt 源构建 docker 时提示 hash 不匹配
    留言板
    Idea 自定义快捷代码输入 如syso => System.out.println()
  • 原文地址:https://www.cnblogs.com/waw/p/2177938.html
Copyright © 2020-2023  润新知