asp.net mvc (三)

來源:互聯網
上載者:User

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.