zoukankan      html  css  js  c++  java
  • asp.net mvc (三)

    ModelBinder

         我们在利用asp.net mvc做些服务端操作时,例如增删改等,很多时候都需要和数据库打交道,要想把数据提交给数据库,第一个条件就是获取页面的表单值。在传统的asp.net中,获取值是非常容易的,因为很多都是些服务器端控件,而asp.net mvc中获取值并不是靠服务器控件的属性来获取。我们来看一下用户新增一则留言的处理方式,当然这里为了简单,只是让用户输入标题和内容,其它的略过。

       第一:创建新增留言的partial view,有点类似asp.net中的用户控件。   

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<GuestBook.Common 

    .Models.GuestBookInfo
    >" %>

    <script language ="javascript" type ="text/javascript" src ="http://www.cnblogs.com/Scripts/jquery-1.3.2.min.js"></script>
    <script language ="javascript" type ="text/javascript" >
        function check() {
            var IsOK 
    = false;
            var err 
    = "";
            
    if (jQuery.trim($("#sTitle").val()) == "") {
                err 
    += "请输入留言标题\n";
            }
            
    if (jQuery.trim($("#sContent").val()) == "") {
                err 
    += "请输入留言内容\n";
            }
            
    if (err != "") {
                alert(err);
                
    return false;
             
              }
            
    return true;
            
        }
    </script>
     
    <% using (Html.BeginForm())
           {
    %>
        
    <fieldset>
            
    <p>
                
    <label for="Title">
                    标题:
    </label>
                
    <%= Html.TextBox("sTitle", Model.sTitle)%>
                
            
    </p>
            
    <p>
                
    <label for="EventDate">
                    内容:
    </label>
                
    <%=Html.TextBox("sContent", Model.sContent)%>
               
            
    </p>
            
            
    <p>
                
    <input type="submit" onclick ="return check();" value="Save" />
            
    </p>
        
    </fieldset>
        
    <% }
        
    %>

      
            第二:Controller类的修改。   
                   说明:下面的部分代码可以会让大家迷惑,ViewData["flag"]是啥东西,其实这是我为了保存一个操作处理结果,因为提交留言后往往会转向到另外的View中,例如留言列表页,这时在用户提交操作后,应该反馈给用户执行的结果(成功还是失败),这里有两种情况:
     
                   (1):提交后View不切换,则利用ViewData["flag"]就可以完成,在页面中判断ViewData["flag"]是否存在,如果存在则根据对应的值显示不同的提示语。

                   (2):提交后View切换,例如转到Index.aspx中,此时ViewData就不能胜任了,我只能给GuestBookInfo的基类Message属性赋值,在index.aspx页面判断Message的值,分别做出对应处理。这时有两种方法:

                        1>:利用return View("Index", models);这种方法页面的地址并不会发生变化,当然页面内容会变化。
                        2>:return RedirectToAction("Index");这种方法链接和内容都会变化。这是比第一种方法好的地方。
                   问题: index中的Model由于是一个记录集,为了实现如上的提示语功能,不得不给每个记录对象的Message赋值,如果不这样做,在View中很难知道哪一个对象的Message属性是我们赋的值。不知道大家在面临这种问题时都是如何处理的,请多多指教。
        

     [AcceptVerbs(HttpVerbs.Post)]
           
    public ActionResult Create(GuestBookInfo model)
           {
               
    try
               {
                   inter.Add(model);
                   var  models 
    = inter.FindAllInfo();
                   ViewData[
    "flag"= 1;
                   
    //model.Message = "已经成功创建";
                   foreach (var i in models)
                   {
                       i.Message 
    = "已经成功创建";
                   }
                   
    return View("Index", models);
                   
    //return RedirectToAction("Index");
               }
               
    catch(Exception ex)
               {
                   ModelState.AddModelError(
    "ex",ex);
                   
    return View(model);

               }
           }   

          
            留言列表页的View部分代码:(提示语部分),这里取记录集第一个对象的Message值。

     <% =Html.MessageBox (Model.First ())%>


           在上面代码中代码中,并没有显示的给出model赋值,但实际上程序运行时,会自动把表单的相关值赋给对象。这点看起来特别神奇,MVC 为我们提供了一个自动化的操作,这一切都归功于IModelBinder 接口,系统默认会找它DefaultModelBinder来完成这一神圣的任务。DefaultModelBinder 内部通过大量的反射完成最终的赋值操作,基本上能适应开发所需。至于如何实现大家可以到网上去搜索下资料,既然有默认的,我们也可以自定义ModelBinder。

            1:创建GuestBookBinder,让它继承IModelBinder,并实现其方法。这里我们可以根据实际业务需要,修改方法,这里只是一个简单实现。

    public class GuestBookBinder : IModelBinder
        {
            
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                var info 
    = bindingContext.Model ?? new GuestBookInfo();

                var properties 
    = bindingContext.ModelType.GetProperties();

                
    foreach (var item in properties)
                {
                    
    if (bindingContext.PropertyFilter(item.Name))
                    {
                        var result 
    = bindingContext.ValueProvider[item.Name];
                        
    if (null == result)
                        { 
    break; }
                        var value 
    = result.ConvertTo(item.PropertyType);

                        item.SetValue(info, value, 
    null);
                    }
                }

                
    return info;
            }

        }

        
           2:注册GuestBookBinder,自定义Binder写好后,系统并不会自动识别,需要在应用程序初始化进行注册,ControllerActionInvoker.GetParameterValue 根据 ModelBinders.Binders.GetBinder() 来找对应的 IModelBinder,如没找到则返回默认的 DefaultModelBinder。    

    protected void Application_Start()
            {
                ControllerBuilder.Current.DefaultNamespaces.Add(
    "GuestBook.MVC.Controller");
                ModelBinders.Binders.Add(
    typeof(GuestBookInfo ), new GuestBookBinder ());
                RegisterRoutes(RouteTable.Routes);
            }

        
          3:除了上面的注册方法外,可以直接把 ModelBinderAttribute 用在对应的实体上 ,但不推荐这样做。

    [ModelBinder(typeof(GuestBookBinder))]
    public class GuestBookInfo

        
          4:除了由 ControllerActionInvoker.GetParameterValue() 自动完成 BindModel 操作外,还提供了两个方法:这两个方法唯一的区别在于,TryUpdateModel不会抛异常,前者会。 
            1>:Controller.UpdateModel()
            2>:Controller.TryUpdateModel()

          示例:例如更新一则留言时,我们可以这样写:
         

    [AcceptVerbs(HttpVerbs.Post)]
           
    public ActionResult Edit(int id, FormCollection formValues)
           {
               GuestBookInfo model 
    = new GuestBookInfo();
               model.ID 
    = id;
               model 
    = inter.GetInfo(model);
               UpdateModel(model );
               inter.Edit(model);
               
    return RedirectToAction("Index");
           }


          总结:这篇文章主要总结了些IModelBinder 接口的作用,以及如何自定义Binder类。
          注:本文参考:http://www.rainsts.net/article.asp?id=779

  • 相关阅读:
    Java实现 LeetCode 27 移除元素
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1542459.html
Copyright © 2011-2022 走看看