【C#MVC4】菜单管理和访问权限分配(三)
【C#MVC4】菜单管理和访问权限分配(三)
若坚持反复研究之前的步骤,到了这里,相信你不再对C#MVC懵懵懂懂了。进行到这里也渐渐接触到核心了。不得不停下业务,单开一篇讲述一下我们这个Demo是如何加载菜单,显示到easyui的tree上面的。实现方式有很多种,但是原理基本一致,
获取数据源,绑定数据源,显示(看着很废话,好像什么也没告诉你,其实已经将最本质的告诉了你…)实际上很多控件和技术就是基于这个实现的。大部分东西,只要你到他的数据源在哪,绑定方式是什么,基本没什么东西是难理解的,无非是应用了新的框架或是技术,这个东西网上检索很容易得到解决方案。所以当你遇到一个问题的时候问问自己,数据源在哪。很多问题迎刃而解。(小小程序员的乱语,大牛请自动过滤)。
闲言不语,我们是通过xml文件获取菜单信息,然后读取xml信息,将其拼接成html,然后在easyui的tree控件上,可以直接显示。以我浅薄的知识来看,是比较简单的一种实现方式,并且减轻了服务器上数据库的一些压力,因为大部分用户的菜单很少变更,所以这种实现方式,虽然实现起来颇为麻烦,但是还是有一定优势的。当然最终的数据源是数据库的表了,这里的xml你可以理解为一种缓存机制。
因为我刚刚建的数据库,里面并没有信息,所以我这里自己建立一个xml文件,手动模拟几个菜单,等全部项目写完之后,我会回头将这一块获取菜单的代码重写,那时候你应该会有一种,哦,原来如此 的感觉。
XML文件:
代码:
<UserMenu>
<HderMenu MenuName="Setting" MenuUrl="" MenuIcon="icon-system">
<SubMenu MenuName="Menu Management" MenuUrl="/Admin/MenuList" MenuIcon="icon-system" />
<SubMenu MenuName="Access Management" MenuUrl="/Admin/AssignPermission" MenuIcon="icon-system" />
<SubMenu MenuName="Test" MenuUrl="/Test/Test" MenuIcon="icon-system" />
</HderMenu>
</UserMenu>
我来稍作分析: :父节点(其实不应该这么叫,但是相对于菜单结构,它是父节点,为了避免你们混乱),放置一级菜单节点,一级菜单,没有太多意义,只是对下面的菜单的一个分类。
:子节点,放置二级菜单节点,这个才是真正具有跳转链接的菜单项。用户根据其具有的url属性,点击后跳转到相应的action,返回至相应的视图。
属性:MenuName,菜单名;MenuUrl,链接;MenuIcon,图标信息;
我们了解了程序是根据xml加载数据的,那么如何绑定呢?
这里在common中,抽取了一个解析xml的方法,将xml的信息最终拼接成一段html片段,返回给视图,然后视图进行展示。
public static string LoadMenuXML(string xmlpath)
{
string usermenu = "";
XmlDocument doc = new XmlDocument();
if (!System.IO.File.Exists(xmlpath))
{
return "";
}
doc.Load(xmlpath);
XmlElement root = doc.DocumentElement;
for (int i = 0; i < root.ChildNodes.Count; i++)
{
XmlNode Hnodel = root.ChildNodes.Item(i);
usermenu += string.Format("<li data-options=\"iconCls:'icon-system',state:'closed'\"><span>{0}</span><ul>", Hnodel.Attributes["MenuName"].Value);
for (int j = 0; j < Hnodel.ChildNodes.Count; j++)
{
XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
usermenu += string.Format("<li data-options=\"iconCls:'{0}'\"><a style=\"text-decoration:none;color:black;\" href=\"javascript:addTab('{1}','{2}')\">{3}</a></li>", Cnodel.Attributes["MenuIcon"].Value, Cnodel.Attributes["MenuName"].Value, Cnodel.Attributes["MenuUrl"].Value, Cnodel.Attributes["MenuName"].Value);
}
usermenu += string.Format("</ul></li>");
}
return usermenu;
}
对于没有接触过xml的朋友,这里可以称为一个技术难点吧,我如果说让你们自己网上检索,会不会被喷?,这里我稍作解释:
XmlDocument doc = new XmlDocument();
建立一个xml对象,引入System.XML的dll即可使用。
doc.Load(xmlpath);
根据路径加载xml到对象中,这个路径是一个完整的路径哦,包含文件物理路径和文件名,文件后缀。这里大牛应该看出来了,对这个文件是放在服务器上。这样会对服务器造成一定的压力(当用户过多时),但是相比较那些对数据库使用频繁的系统,可以牺牲内存换取运行速度。
XmlElement root = doc.DocumentElement;
获取根节点,也就是我们上面的节点。然后便利根节点下面的父节点(对于xml文件应该称为子节点)
XmlNode Hnodel = root.ChildNodes.Item(i);
usermenu += string.Format(“
- ”, Hnodel.Attributes[“MenuName”].Value);
获取当前遍历中的菜单父节点,并且遍历该菜单父节点,查询其所属的菜单子节点。 这里用了C#中字符串的Format方法,看一下官方api如何解释:
将指定字符串中的一个或多个格式对象替换为指定对象的字符串表示形式。
Hnodel.Attributes[“MenuName”].Value,将节点中属性为MenuName的值取出来赋给{0},
XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
usermenu += string.Format(“
获取当前遍历的菜单子节点。并将子节点中的菜单信息拼接进li元素中。
最后我们就得到了一个包含所有菜单信息的html的片段,将这个片段直接返回给视图,easyui就可以正常加载了。
看一下controller中的写法:
public ActionResult Home()
{
User_Master userMaster = (User_Master)Session["UserMaster"];
ViewBag.User = userMaster.User_Name;
ViewBag.Date = DateTime.Now;
string userMasterId = userMaster.User_Master_Id.ToString();
string userMenuPath = System.Configuration.ConfigurationManager.AppSettings["UserMenuPath"].ToString().Trim();
string xmlPath = userMenuPath + userMasterId + ".xml";
ViewBag.MenuTreeList = MenuXMLHelper.LoadMenuXML(xmlPath);
return View();
}
那么这个userMenuPath 在哪里设置的呢?是在web下面的config文件中设置:
这样,我们还需在自己本地建立相应为问价夹,将刚刚的xml文件放进去,注意xml的命名哦,是以User_Maser_Id做的名字,这样可以唯一标示该用户的登录菜单。
还要讲我们之前在页面注释的tree放开哦:
最终显示: