ExpandoObject
派生自IEnumerable<KeyValuePair<string, Object>>
,并且当您分配 时,大多数序列化程序会将 a 识别dynamic
为这种类型ExpandoObject
。这就是为什么您会在 javascript 端看到一个带有命名键::值对的数组类型。
ExpandoObject 类 (System.Dynamic) @ MSDN
使用的一种替代方法ExpandoObject
是使用 C# 匿名类型。当序列化为 json 时,这些映射字段按您的预期。
匿名类型(C# 编程指南)@ MSDN
可以从 jQuery 访问使用声明的值dynamic
,但很可能您不会返回View()
带有要使用 jQuery 使用的模型的 MVC,因为任何服务器端视图模板引擎(剃须刀等)已经可以执行相同的操作具有较少开销的模板活动。相反,jQuery 模板更适合与 Ajax 调用一起使用。
下面的代码示例演示了三种情况,其中dynamic
服务器上声明的变量在浏览器中与 jQuery 模板一起使用。
第一个示例对成员字段使用匿名类型SomeValue
,并有一个将其视为成员对象的 jQuery 模板。
第二个示例对成员字段使用匿名类型数组,SomeValue
并具有使用{{each}}
语法枚举项目的模板。请注意,在这种情况下,事情可能会变得很糟糕dynamic
,因为您没有得到强类型支持,并且必须知道正确的类型或在您访问它时发现它。
第三个示例使用ExpandoObject
成员字段SomeValue
,并具有与第一个示例类似的 jQuery 模板(单个成员对象)。请注意,在这种情况下,我们需要使用辅助函数pivotDictionaryMap()
将Key :: Value对转换为对象成员。
从一个空白的 C# MVC3 Web 项目开始,我们需要修改三个文件来演示这些示例。
在_Layout.cshtml中,为 jQuery 模板添加脚本,并在 <head> 元素中添加适当版本的 jQuery。
<script src="@Url.Content("~/Scripts/jquery-1.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.tmpl.js")" type="text/javascript"></script>
在HomeController.cs中,我们将添加一些返回 jsonActionResult
的方法。另外,为简洁起见,我们只SomeModelType
在这里声明一个类;请注意,一个适当的应用程序可能会在其Models中声明此类。
using System.Dynamic; // up top...
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult SomeDataSource(int id)
{
dynamic d = new { innerId = 99, innerLabel = "inside object" };
SomeModelType obj = new SomeModelType(id, "new object");
obj.SomeValue = d;
return Json(obj, "text/plain");
}
public ActionResult SomeDataSourceWithArray(int id)
{
dynamic d1 = new { innerId = 99, innerLabel = "inside object (first array member)" };
dynamic d2 = new { innerId = 100, innerLabel = "inside object (second array member)" };
SomeModelType obj = new SomeModelType(id, "new object");
obj.SomeValue = new object[] {d1, d2};
return Json(obj, "text/plain");
}
public ActionResult SomeDataSourceWithExpando(int id)
{
dynamic d = new ExpandoObject();
d.innerId = 99;
d.innerLabel = "inside object";
SomeModelType obj = new SomeModelType(id, "new object");
obj.SomeValue = d;
return Json(obj, "text/plain");
}
}
public class SomeModelType
{
public SomeModelType(int initId, string initLabel)
{
Id = initId;
Label = initLabel;
}
public int Id { get; set; }
public string Label { get; set; }
public dynamic SomeValue { get; set; }
}
最后,在默认视图中,我们将为模板添加脚本标签以及使用它们所需的 javascript。注意$.post()
and not的使用$.get()
,因为JsonResult
MVC 中的 a 默认不允许 GET 请求(您可以使用属性打开这些请求)。
@{
ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<script id="someDataTemplate" type="text/x-jquery-tmpl">
Item <b>${Id}</b> is labeled "<i>${Label}</i>" and has an inner item with id <b>${SomeValue.innerId}</b> whose label is "<i>${SomeValue.innerLabel}</i>".
</script>
<h3>SomeDataSource Example #1 (Single Item)</h3>
<div id="someData">
</div>
<script id="someDataArrayTemplate" type="text/x-jquery-tmpl">
Item <b>${Id}</b> is labeled "<i>${Label}</i>" and has these inner items:
<ul>
{{each SomeValue}}
<li><b>${innerId}</b> has a label "<i>${innerLabel}</i>".</li>
{{/each}}
</ul>
</script>
<h3>SomeDataSource Example #2 (Array)</h3>
<div id="someArrayData">
</div>
<script id="someDataTemplateFromExpandoObject" type="text/x-jquery-tmpl">
Item <b>${Id}</b> is labeled "<i>${Label}</i>" and has an inner item with id <b>${SomeValue.innerId}</b> whose label is "<i>${SomeValue.innerLabel}</i>".
</script>
<h3>SomeDataSource Example #3 (Single Item, Expando Object)</h3>
<div id="someDataFromExpandoObject">
</div>
<script type="text/javascript">
function pivotDictionaryMap(src)
{
var retval = {};
$.each(src, function(index, item){
retval[item.Key] = item.Value;
});
return retval;
}
</script>
<script type="text/javascript">
$(document).ready(function() {
// Ajax Round-Trip to fill example #1
$.post("/Home/SomeDataSource/5", function(data) {
$("#someDataTemplate").tmpl(data).appendTo("#someData");
}, "json");
// Ajax Round-Trip to fill example #2
$.post("/Home/SomeDataSourceWithArray/67", function(data) {
$("#someDataArrayTemplate").tmpl(data).appendTo("#someArrayData");
}, "json");
// Ajax Round-Trip to fill example #3
$.post("/Home/SomeDataSourceWithExpando/33", function(data) {
data.SomeValue = pivotDictionaryMap(data.SomeValue);
$("#someDataTemplateFromExpandoObject").tmpl(data).appendTo("#someDataFromExpandoObject");
}, "json");
});
</script>