本範例展示如何透過jQuery.post傳送string[]參數給ASP.NET MVC。
情境模擬訊息發送操作,提供網頁介面供使用者挑選接收者(採用複選式下拉選單)、輸入發送內容後按鈕傳送訊息給指定對象。
ASP.NET MVC Controller如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Mvc.Controllers
{
publicclass HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public ActionResult SendMessage(string[] users, string message)
{
//假裝發通知給指定的使用者, 此處省略
return Content(string.Format("已傳送訊息給{0}",
users == null ? "null" : string.Join(",", users)));
}
}
}
至於前端,輸入欄位借重Knockout幾行搞定,按鈕動作則透過jQuery.post()以AJAX方式呼叫Controller的SendMessage方法,其中的users參數在C#端宣告型別為string[],Client端靠Knockout的下拉選單複選繫結selectedOptions直接取得使用者挑選的字串陣列,依直覺寫成{ users: vm.selUsers() }將字串陣列傳至Server端。
@{
Layout = null;
}
<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width"/>
<title>Test</title>
<scriptsrc="~/Scripts/jquery-2.0.3.js"></script>
<script src="~/Scripts/knockout-3.0.0.debug.js"></script>
</head>
<body>
<div>
<input type="text" data-bind="value: msg" />
<input type="button" data-bind="click: sendMsg" value="Send Message" />
<br />
<select data-bind="options: users, selectedOptions: selUsers" multiple></select>
</div>
<script>
function myViewModel() {
var self = this;
self.msg = ko.observable("Test");
self.users = ko.observableArray(
["Jeffrey", "Darkthread", "Admin", "Guest"]);
self.selUsers = ko.observableArray();
self.sendMsg = function () {
$.post("@Url.Content("~/home/sendmessage")",
{ users: vm.selUsers(), msg: vm.msg() },
function (res) {
alert(res);
});
};
}
var vm = new myViewModel();
ko.applyBindings(vm)
</script>
</body>
</html>
事與願違,ASP.NET MVC端的輸入參數string[]沒接到值,users為null:
用IE Dev Tool檢視傳送內容,可以發現jQuery.post()自動將字串陣列序列化為users[]=...&users[]=...(上圖黃底部分,%5B%5D是"["與"]"的UrlEncode編碼),但ASP.NET MVC卻認不得,所幸,我們離接通只差一小步。
關於陣列參數的序列化形式,傳統採用a=..&a=..格式,後來如PHP、Ruby on Rails等Framework改採a[]=..&a[]=..格式,jQuery從1.4版起便將陣列序列化預設格式改為a[]=..,但仍提供traditional參數可指定採用舊格式。而ASP.NET MVC仍採a=..&a=..格式,所以只需將傳遞參數交給$.param()轉換並指定traditional參數為true: $.param({ users: vm.selUsers(), msg: vm.msg() }, true), 問題就解決囉!
PS: 如對陣列化序列格式有興趣深入了解,可以參考jQuery.param()文件。