一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(4)
现在来完成删除功能。目前的Grid,一次只能选择一行,也就是说,一次只能删除一行,不太方便,因而要设置成使用复选框选择,并允许多选的。在用户视图脚本文件中,添加以下配置项实现这个:
selType: "checkboxmodel",
selModel:{ checkOnly: false, mode: "MULTI" },
打开页面浏览,会看到如图29所示的效果,已经可以在最左边通过复选框进行行选择了。
图29 添加了复选框选择行的Grid
删除用户的方式有2种,一种是先使用remove方法在Store中删除记录,然后调用sync方法同步,一种是提取选择行的id,然后通过Ajax方式提交到服务器进行删除,确认后再在客户端刷新页面。第一种方式必须在proxy的api定义中定义destroy配置项,之前的代码中已经定义了,因而本示例将使用该方式。第二种方式如果也定义了destroy配置项,就千万别用remove删除Store的记录,不然在添加或编辑的时候,调用sync方法进行同步的时候会把删除记录的数据一起提交的。选用那种方法,看喜好吧!呵呵。
现在切换到Users控制器的脚本,为删除按钮绑定单击事件,代码如下:
me.getButtonUserDelete().on("click",me.onDeleteUser, me);
在onDeleteUser方法内,要先从Store的选择模型获取选择的记录。如果有选择记录,则先提示用户是否真的删除用户。确认后,调用remove方法删除记录,并调用sync方法同步数据,如果成功,调用commitChanges方法确认修改,否则调用rejectChanges方法取消修改。具体代码如下:
onDeleteUser: function () {
var me = this,
sm =me.getUserView().getSelectionModel();
if (sm.getCount() > 0){
var rs =sm.getSelection();
content = ["确定删除以下用户?"];
for (var i = 0; ln =rs.length, i < ln; i++) {
content.push(rs[i].data.Username);
}
Ext.Msg.confirm("删除用户", content.join("<br/>"), function (btn) {
if(btn == "yes") {
varme = this,
rs =me.getUserView().getSelectionModel().getSelection()
store = me.getUsersStore();
store.remove(rs);
store.sync({
success: function (e, opt) {
var me = this;
me.getUsersStore().commitChanges();
},
failure: function (e, opt) {
var me = this;
me.getUsersStore().rejectChanges()
Ext.Msg.alert("发生错误", e.exceptions[0].error);
},
scope: me
});
}
}, me)
} else {
Ext.Msg.alert('删除用户', '请选择要删除的用户。');
}
}
代码中,使用了数组content来组合确认信息。当用户确认后,就调用remove方法,并调用sync方法。
现在来完成服务器端代码。因为sync方法提交数据的方式是固定的,因而提取删除数据的方式与添加和编辑操作的一样,需要从data中提取数据,然后使用parse方法转换为JArray。余下的工作就是从JArray中提取出删除数据的JObject,通过id或Username去删除用户了,具体代码如下:
public JObject Delete()
{
string msg = "";
bool success = false;
JArray ja = null;
string data = Request["data"] ?? "";
if (string.IsNullOrEmpty(data))
{
msg = "错误的提交数据。";
}
try
{
ja = JArray.Parse(data);
if(ja.Count > 0)
{
foreach (JObject jo in ja)
{
Membership.DeleteUser((string)jo["Username"]);
}
success = true;
}
else
{
msg = "错误的提交数据。";
}
}
catch (Exception e)
{
msg = e.Message;
}
return MyFunction.WriteJObjectResult(success,0, msg, ja);
}
这里要注意的是,和添加编辑操作一样,尽管success返回true,还是要把删除的数据返回。因为删除不需要改变原有的数据,因而直接将ja返回就行了。
还有2个问题要自己考虑清楚。第1个是删除后是否提示用户已删除记录,如果需要,在sync方法内的回调函数success内加入提示信息就可以了。第2个问题是,因为删除数据后,Grid内的数据会减少,是否需要刷新页面?
最后一个功能重置密码与删除用户差不多,也是从选择模型获取选择记录。不过,这次,不能用sync同步,只能通过提取id,然后使用Ajax方法提交数据了。先为重置密码按钮绑定单击事件,代码如下:
me.getButtonUserResetPassword().on("click",me.onResetPassword, me);
接着完成onResetPassword方法,代码如下:
onResetPassword: function () {
var me = this,
rs = me.getUserView().getSelectionModel().getSelection();
if (rs.length > 0) {
var idList = [];
for (var i = rs.length - 1; i>= 0; i--) {
idList.push(rs[i].data.id);
}
Ext.Ajax.request({
params: { id: idList },
url: '/Users/ResetPassword',
scripts: true,
scope: me,
success: function (response, opt) {
varobj = Ext.JSON.decode(response.responseText);
if(obj) {
if (obj.success) {
Ext.Msg.alert("提示信息", "重置密码成功");
return;
} else {
Ext.Msg.alert("错误",obj.Msg);
}
}
},
failure: function (response, options) {
Ext.Msg.alert("错误", "重置密码失败!<br>错误信息:" + response.responseText);
}
});
}
}
代码中,没有进行确认,如果需要,可自行添加。因为Ajax提交不是根据返回的success值来调用success方法或failure方法的,只要不是页面错误,都会执行回调函数success方法,因而要自己根据返回的数据,调用decode方法将数据转换为对象,然后根据success的值来做处理。
下面,完成服务器端的ResetPassword方法。在这里,有个麻烦,就是ChangePassword方法需要使用旧密码才能修改新买,而ResetPassword方法会随机生成一个密码,都不能直接将密码设置为123456,因而,需要先用ResetPassword方法重置密码后,然后利用这个重置的密码,调用ChangePassword方法将密码修改为123456,具体代码如下:
public JObject ResetPassword()
{
bool success=false;
string msg="";
string idList = Request["id"] ?? "";
try
{
string[] ids = idList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var c in ids)
{
Guid id=Guid.Parse(c);
MembershipUser user = Membership.GetUser(id);
if(user != null)
{
string pwd =user.ResetPassword();
user.ChangePassword(pwd, "123456");
}
}
success=true;
}
catch (Exception e)
{
msg=e.Message;
}
return MyFunction.WriteJObjectResult(success,0, msg, null);
}
用户管理的基本功能就已经全部完成了,不过还有一个问题要解决,就是控制服务器端用户控制器的权限问题。这个在Asp.Net MVC中很容易实现,使用Authorize特性声明方法就能解决了,代码如下:
[Authorize(Roles="系统管理员")]
不过,这里存在的问题,返回的错误信息不是JSON格式的,因而在客户端处理会出问题,因而需要自定义一个返回JSON格式的认证特性。要实现这个不难,从AuthorizeAttribute派生出一个AjaxAuthorizeAttribute类,并重写HandleUnauthorizedRequest方法就可以了。
先在解决方案下添加一个名为Validations的目录。然后在该目录下添加一个名为AjaxAuthorizeAttribute.cs的类文件,生成代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
namespace SimpleCMS.Validations
{
public class AjaxAuthorizeAttribute
{
}
}
先修改类结构,让AjaxAuthorizeAttribute类派生于AuthorizeAttribute,修改后代码如下:
public classAjaxAuthorizeAttribute : AuthorizeAttribute
{
}
这时会提示缺少引用,把以下引用加入就行了:
usingSystem.Web.Mvc;
现在,在类内添加重写HandleUnauthorizedRequest方法的代码,代码如下:
protected override voidHandleUnauthorizedRequest(AuthorizationContext filterContext)
{
}
方法中传入的参数就是要进行验证的上下文。判断上下文中Request对象的IsAjaxRequest方法,就可知道提交的是否Ajax请求,如果是,就构造一个JSON结果返回就行了。具体代码如下:
if(filterContext.HttpContext.Request.IsAjaxRequest())
{
UrlHelperurlHelper = new UrlHelper(filterContext.RequestContext);
filterContext.Result = new JsonResult
{
Data= new
{
success = false,
Msg = "您没有权限访问该页。"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
好了,在控制器内加入对Validations的引用,并在所有方法上添加以下特性:
[AjaxAuthorize(Roles="系统管理员")]
这样,就可以控制访问权限了,要测试是否成功,可以将重置密码的那段Ajax请求复制到Firebug的命令行,把idList修改为1,删除“scope:me”。在运行前,先检查是否已经退出了系统,保证处于没登录状态。单击运行后,就看到如图30所示的结果,在Firebug内,会看到返回的结果,正是在AjaxAuthorizeAttribute类定义的返回结果。
图30 测试权限
至此,用户管理功能就完成了。
源代码:http://download.csdn.net/detail/tianxiaode/4606230