Model Binding-模型繫結的方法

 

一、簡單模型繫結

其實就是如何將前端的參數傳遞到後端,並且參數成功地被後端所接收。

Controller為

using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(string myId, string myName)
        {
            ViewBag.MYID = myId;
            ViewBag.MYNAME = myName;
            return View();
        }
    }
}

View為

@{
    ViewBag.Title = "Home Page";
}

<form action="@Url.Action("Index")" method="post">
    <label>ID:</label>
    <input type="text" name="myId" id="myId" value="" />
    <label>NAME:</label>
    <input type="text" name="myName" id="myName" value="" />
    <input type="submit" value="送出" />
</form>

<button>ajax送出</button>

<hr />
<p>@ViewBag.MYID</p>
<br />
<p>@ViewBag.MYNAME</p>

@section scripts{
    <script>
        //jQuery1.10.2
        $("button").on("click", function myfunction() {
            var myId = $("#myId").val();
            var myName = $("#myName").val();
            $.ajax({
                url: "@Url.Action("Index")",
                type: "post",
                data: "myId=" + myId + "&myName=" + myName,
                cache: false,
                async: false,
                dataType: "html",
                success: function (data) {
                    alert("seccess");
                }
            });
        });
    </script>
}

此範例提供了兩種型式的參數傳遞方法,

一種是普遍的form表單傳遞;另一種是ajax方法傳遞,

這兩種都可以成功地把參數傳到後端,差別的是,

「form表單傳遞」可以成功地把資料經由ViewBag送到前端顯示,

而「ajax方法傳遞」卻不行,我認為是用途不同吧,

ajax技術是局部更新,會繞過ASP.NET MVC生命執行週期吧???

所以不會再傳回其他的ActionResult???,ViewBag就算有資料也不會顯示出來。

 

二、FormCollection

也可以使用FormCollection類別來取得資料,

承上例改寫Controller內容如下

using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(FormCollection form)
        {
            ViewBag.MYID = form["myId"];
            ViewBag.MYNAME = form["myName"];
            return View();
        }
    }
}

 

三、複雜模型繫結

也是一樣繼承先前例子的View,但我在model新增一個名為Person類別

namespace WebApplication1.Models
{
    public class Person
    {
        public int myId { get; set; }
        public string myName { get; set; }
    }
}

而Controller改成如下

using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Person form)
        {
            ViewBag.MYID = form.myId;
            ViewBag.MYNAME = form.myName;
            return View();
        }
    }
}

這樣也是可以從前端成功傳遞資料到後端的,

但特別要注意person的myId與myName屬性一定要對好View的myId與myName輸入欄位(name屬性),

<form action="@Url.Action("Index")" method="post">
    <label>ID:</label>
    <input type="text" name="myId" id="myId" value="" />
    <label>NAME:</label>
    <input type="text" name="myName" id="myName" value="" />
    <input type="submit" value="送出" />
</form>

否則參數將傳遞失敗。

 

四、多個複雜模型繫結

model繼承先前例子,Controller改為

using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Person form1, Person form2)
        {
            ViewBag.MYID = form1.myId;
            ViewBag.MYNAME = form1.myName;

            ViewBag.MYID2 = form2.myId;
            ViewBag.MYNAME2 = form2.myName;
            return View();
        }
    }
}

View改為

@{
    ViewBag.Title = "Home Page";
}

<form action="@Url.Action("Index")" method="post">
    <fieldset>
        <label>ID:</label>
        <input type="text" name="form1.myId" id="myId" value="" />
        <label>NAME:</label>
        <input type="text" name="form1.myName" id="myName" value="" />
    </fieldset>

    <fieldset>
        <label>ID:</label>
        <input type="text" name="form2.myId" value="" />
        <label>NAME:</label>
        <input type="text" name="form2.myName" value="" />
    </fieldset>
    <input type="submit" value="送出" />
</form>

<hr />
<p>@ViewBag.MYID</p>
<br />
<p>@ViewBag.MYNAME</p>
<hr />
<p>@ViewBag.MYID2</p>
<br />
<p>@ViewBag.MYNAME2</p>

這樣也是可以從前端成功傳遞資料到後端的

 

五、UpdateModel與tryUpdateModel

使用UpdateModel與tryUpdateModel技術也是可以從前端成功傳遞資料到後端的,

使用UpdateModel可以不用在Action輸入參數,

而tryUpdateModel除了有UpdateModel的特性外,

當繫結失敗時將避免「例外狀況」發生。

 

六、使用Bind屬性限制可被更新的資料模型屬性

可用Exclude、Include來排除或包括屬性

public ActionResult Create([Bind(Exclude = "ID")] News n)
{
}

 

七、ModelState

當Controller在模型繫結完成後,會得到一個完整的ModelState物件,用途如下。

1、判斷模型繫結的驗證結果ModelState.IsValid為true代表通過驗證。

2、如果有錯誤時ModelState.Count會大於零

3、模型繫結驗證失敗的錯誤詳細資料ModelState["name"].Error

4、清空模型繫結狀態ModelState.Clear()

 

參考資料:

BindAttribute 類別

ModelStateDictionary 類別

ModelState 類別