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

  • 相关阅读:
    vue系列——数据请求
    优化记录
    优化记录
    正则
    跨域问题
    原型链之prototype/__proto__/constructor
    vue系列——组件数据通讯(二)
    vue系列——组件数据通讯(一)
    ES6(一)
    ES5总结
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1542459.html
Copyright © 2011-2022 走看看