通常情况下在MVC模式中我们会采用使用controller获取业务数据(model)并将业务数据提交给view,或者由view传递数据给controller,再由controller更新model。在一些简单的页面中可以直接使用Model-->action-->View方式,但如果页面较为复杂包含多个model及多个分部页面时为了实现页面数据的局部刷新就需要使用ajax特性,为此需要学习如何使用JQuery获取页面数据,并通过ajax发送请求后台controller,并返回不同类型的result。
先介绍一个简单的实用实例,实例实现通过访问用户组查看选择的用户组下的所属用户,本实例将建立一个treeview,通过选择节点调用后台数据返回该节点的用户信息。
本实例略过EF过程,先看Controller
[HttpPost]
public JsonResult GetGroup()
{
var result = T_GROUPService.GetT_GROUPAllList();
JsTreeModel rootNode = new JsTreeModel();
PopulateTree(null, (List<T_GROUP>)result.AppendData, rootNode);
return Json(rootNode);
}
public void PopulateTree(string id, List<T_GROUP> list, JsTreeModel node)
{
if (node == null)
node = new JsTreeModel();
foreach(var u in list.Where(p=>Equals(p.PARENTID,id)).OrderBy(o=>o.NORDER))
{
JsTreeModel node1 = new JsTreeModel();
node1.id = u.ID;
node1.grouptype = u.GROUPTYPE;
node1.text = u.GROUPNAME;
node.nodes.Add(node1);
PopulateTree(u.ID, list, node1);
}
}
public class JsTreeModel
{
public string id;
public string grouptype;
public string text;
public List<JsTreeModel> nodes = new List<JsTreeModel>();
}
此方法通过获取group数据生成json格式树返回给view,过程很简单,不多解释,直接看View
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<link href="~/Content/bootstrap-treeview.css" rel="stylesheet" />
<script src="@Url.StaticFile("~/Scripts/jquery-1.10.2.js")"></script>
<script src="@Url.StaticFile("~/Scripts/bootstrap.js")"></script>
<script src="@Url.StaticFile("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
<script src="@Url.StaticFile("~/Scripts/bootstrap-treeview.js")"></script>
</head>
由于用到了bootstrap-treeview,所以先添加相关引用,本实例是简单实例并未使用布局页,bootstrap-treeview数据格式如下
var tree = [
{
text: "Parent 1",
nodes: [
{
text: "Child 1",
nodes: [
{
text: "Grandchild 1"
},
{
text: "Grandchild 2"
}
]
},
{
text: "Child 2"
}
]
},
{
text: "Parent 2"
},
{
text: "Parent 3"
},
{
text: "Parent 4"
},
{
text: "Parent 5"
}
];
由此可以看出此数据格式是一个json格式的一个数组对象,那么对应我们需要提供的数据也必须是json格式的数组对象,这里要注意上面我们的GetGroup方法返回的是一个json格式的对象实例而非数组,我在走了很多弯路才发现居然和bootstrap-treeview要求的类型不一致。再来看看bootstrap-treeview的调用方法。
function getTree() {
// Some logic to retrieve, or generate tree structure
return data;
}
$('#tree').treeview({data: getTree()});
好了,基本的调用方法和数据格式知道了后开始我们的view设计
<div class="row">
<div id="tree" class="col-sm-4">
</div>
<div id="user" class="col-sm-8">
</div>
</div>
定义一个treeview的div和一个显示user的div,下面开始编写脚本,首先看看获取树的方法
function getTree() {
var tree ;
$.ajax({
type: 'POST',
url: "/Auth/GroupManager/GetGroup",
dataType: 'json',
async:false,
success: function (responseData) {
tree= responseData.nodes;
},
error: function (XMLHttpRequest, textStatus, errorThrown) {//请求失败处理函数
console.log("请求失败,无法获取分组数据");
}
});
return tree;
}
$('#tree').treeview({
data: getTree(),
nodeIcon: "glyphicon glyphicon-user",
backColor: "#FFFFFF"
});
$('#tree')获取id为tree的div,然后指定treeview下的各属性 ,其中data属性使用了一个方法getTree进行调用获取数据
在getTree方法中使用ajax调用后台名为 GroupManager的controller下的名为GetGroup的action(即上面的方法注意指定了post标记),数据类型datatype则指定为‘json’类型,此处采用的 是同步模式,即设置async:false。下面是如果调用成功则执行success中指定的回调函数,此函数的参数即是返回的结果,由于我们前面返回的是一个json对象,所以将此对象下的所有节点作为数组返回给treeview。如果调用失败则执行error中指定的回调函数,其中XMLHttpRequest可查看具体的错误信息,供调试使用。
到此一个用户组的树视图即完成,下面将实现点击节点查询节点下的用户,同样是使用jquery的ajax方式发送请求,然后通过加载一个分部视图来替换名为user的div对象。
先看看分部视图
@model IEnumerable<URS.Data.Contract.T_USER>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.SFZHM)
</th>
<th>
@Html.DisplayNameFor(model => model.PASSWORD)
</th>
<th>
@Html.DisplayNameFor(model => model.SSDW)
</th>
<th>
@Html.DisplayNameFor(model => model.XM)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.SFZHM)
</td>
<td>
@Html.DisplayFor(modelItem => item.PASSWORD)
</td>
<td>
@Html.DisplayFor(modelItem => item.SSDW)
</td>
<td>
@Html.DisplayFor(modelItem => item.XM)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
一个很简单的分部视图,Model使用的是列表,再来看看调用该分部视图的action
[HttpPost]
public ActionResult GetUserByGroupID(string groupID)
{
var result = this.T_USERService.T_USERRepository.Entities.Include("Group").Where(p => Equals(p.Group.ID, groupID));
//return Json(result.AppendData);
return PartialView("GetUserList", result);
}
同样也是很简单的一个查询,使用了一个groupID的参数,这样就需要我们在ajax请求时传递一个group的id
$('#tree').on('nodeSelected', function (event, node) {
var guid = node.id;
$.ajax({
type: 'POST',
url: "/Auth/UserManager/GetUserByGroupID",
data:{groupID:guid},
dataType: 'html',
async: false,
success: function (responseData) {
$('#user').html(responseData);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {//请求失败处理函数
console.log("请求失败,无法获取分组数据");
}
});
});
调用方法使用的是jquery方式,事件nodeSelected,绑定的回调函数有两个参数,其中第二个参数即是点击的node对象,可以很容易取得该对象的属性值。下面看看ajax的请求:和上面请求有所不同的是需要加入一个参数,即data属性,同样也是以json格式进行传递,另外由于返回的是分部页面,所以返回的数据类型datatype为html,调用成功回调方法中将实现用返回值替换名为user的div对象。看看结果:
整个应用非常简单,其逻辑也很简单,重点实现了由以jquery方式发送ajax请求到后台的controller来执行,此实例提供了一种发送请求返回Json数据的实现过程,同时提供了一种解决如何传递页面数据到后台并返回页面的解决办法。此方法不同于我们简单的在controller中通过action返回view的方式,个人认为这种方法更据代表性,实现更灵活,同时充分利用了ajax的特性实现了局部数据的刷新。当然microsft也提供了一些ajaxhelper方法实现ajax的调用,今后有空再研究吧。
示例很简单,但却提供我们常用的业务模型的一种解决方案,作为新手如果没接触过jquery,ajax,mvc的话,那么此实例还是很有参考价值。