MVC項目小結:動態菜單


     是近項目中應用到了動態菜單,覺的做的還是不錯的,這里總結出來,也許有一些做的不對的地方,仁者見仁吧。
    
     菜單需求:

     1:支持多語言。

     2:只支持兩級菜單,不需要考慮無限級菜單這種需求。

     3:二級菜單與一級菜單可以動態調整。

         比如我們有一個給用戶授權的功能,網站共有兩個一級菜單:系統管理員以及二級管理員,之前用戶授權的二級菜單出現在系統管理員下來,但后來有人認為應該出現在級 別低點的二級管理員菜單下,這種情況要非常容易的進行調整,這里的容易調整是指不修改任何程序任何配置文件的基礎上完成,完成在網頁上就能完成。

    4: 菜單的顯示需要和登錄用戶權限結合

           比如系統管理員總共有六個二級菜單,每個二次菜單對應一個功能,只要用戶的授權中有其中一項,當用戶登錄系統后就會出現系統管理員的一級菜單,點擊一級菜單,能看到一個自己被授權的二級菜單。
       
     我們采用的是比較傳統的用戶授權模式,這種方式並不一定是最好的,但適用於我們自己的項目。
     1:User,用戶信息。
     2:Role,角色信息。
     3:Function,功能信息,比如數據字典表維護就是一個Function, ControllerName是指mvc程序中Controller路由信息,即去掉Controller后綴的部分,比如HomeController,數據庫中就存Home。Name,是一個程序員能認認識的名稱,不用於菜單顯示,因為我們的菜單需要多語言。
     4:Action,子功能信息,比如數據字典表的查詢就是一個Action,刪除也屬於一個Action。ActionName是指mvc程序中的Action名稱,比如HomeController下面有一個類型為ViewResult的Index方法,此時ActionName就存這個Index。Name,也是一個供 程序員參考的名稱。
     5:RoleAction,角色與子功能的關系,所有權到每一個子功能Action而不是更高一級的Function。
     6:UserRole,用戶與角色的關系。
    
     如何實現二級菜單?
     實現的方式有很多種,但我們選擇的是MvcSiteMap,它允許我們對於展示的樣式進行自定義的控制,而且支持多語言以及動態菜單。
    
     如何實現菜單多語言?
     MvcSiteMap自身就提供了多語言機制,比如我們可以在配置文件中指定如下菜單,通過資源文件的方式來實現。

<mvcSiteMapNode title="$resources:SiteMapResources,Page" controller="PageName" action="Index" roles="Regional Admin"/>


     但這是靜態菜單(要想修改菜單就需要修改這個配置文件),不符合要求,不能寫在配置文件中,因為功能與角色的關系是動態的而非靜態固定的,我們需要采用MvcSiteMap提供的動態菜單,但解決的思想還是采用資源文件。     


      在Function以及Action表中,增加了ResourceKey字段,MvcSiteMap讀取到Function信息時,顯示的名稱根據ResourceKey從指定的資源文件中獲取,而不是取數據庫中的Name字段,從而實現菜單的多語言。


      修改后的sitemap配置文件,配置文件沒有具體指明菜單信息,而只是指定了兩個動態菜單配置節。

 <mvcSiteMapNode title="LevelOne" dynamicNodeProvider="My.Web.Utility.LevelOneDynamicNodeProvider, My.Web">
      <mvcSiteMapNode title="LevelTwo" dynamicNodeProvider="My.Web.Utility.LevelTwoDynamicNodeProvider, My.Web">
      </mvcSiteMapNode>
    </mvcSiteMapNode>


    需要分別完成上圖中的兩個菜單Provider,這里就不貼全部的了,MvcSiteMap源碼中包含了示例,菜單的Provider變成:

DynamicNode node = new DynamicNode();
                var resouceObject = HttpContext.GetGlobalResourceObject("ResourcesMap", menuGroup[j].ResourceKey);
                if (null == resouceObject) continue;
                node.Title = resouceObject.ToString();
                node.Key = menuGroup[j].ResourceKey+"_"+HttpContext.Current.User.Identity.Name;
                result.Add(node);


     如何實現二級菜單與一級菜單動態調整?
    
     1:定義二級菜單:
         我們提到的Function,它對應的是一個大的功能,比如一個表的增刪改查,它有四個功能,但都屬於某某表維護的功能,我這里認為一個Function就是一個二級菜單。
     2:定義一級菜單?
         一級菜單是一大堆二級菜單的匯聚,可以按功能類別來分,比如可以將所有的報表頁面放在一個一級菜單下面,也可以按其它標准。這里我定義了一個MenuGroup的表,任何Function都可以屬於一個MenuGroup,也可以不屬於任何一個MenuGrop,因為有些功能,是不能直接放在菜單上的,它往往需要有前置條件才能導航到這些頁面。既然Function和MenuGroup之間的關系建立起來了,那么一級二級菜單的關系也就解決了。

           例如一個系統包含100個功能,A地區的客戶需要用到其中的50個功能,B地區的客戶需要用到其中的80個功能,通過上面的兩級菜單定義,可以方便的為不同地區的客戶選擇對應的功能,也可以自由的組織一級菜單的分組。
     
      下面是數據庫表關系圖:
           

                
     
     
     
     
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM