簡體   English   中英

應該為每個頁面請求綁定asp菜單項

[英]Should asp menu items be bound for every page request

asp菜單控件位於母版頁中。 它的數據源是一個web.sitemap文件。 該文件最初具有聲明為節點的所有項目/頁面。 用戶登錄后,我已根據用戶權限編寫了此代碼以從菜單中刪除項目。

protected void MyMenu_MenuItemDataBound(object sender, MenuEventArgs e) 
{
  if(Session["MenuLoaded"]==null)
  {
    SiteMapNode node = (SiteMapNode)e.Item.DataItem;
    bool deleteItem = true;
    if(lstRoles.Count==0)
       lstRoles = (List<tblDetail>)Session["sRoles"];
    if(!string.IsNullOrEmpty(node.Description))
     {
       foreach(var item in lstRoles)
        {
          if(Convert.ToInt32(node.Description)==item.FormId)
           {
             deleteItem = false;
             break;
           }
        }
        if(deleteItem)
         {
           if(e.Item.Parent !=null)
            {
              MenuItem mItem = e.Item.Parent;
              mItem.ChildItems.Remove(e.Item);
              if(mItem.ChildItems.Count==0)
                {
                  if(mItem.Parent !=null)
                   {
                     MenuItem Item = mItem.Parent;
                     Item.ChildItems.Remove(mItem);
                   }
                  else
                   {
                     Menu menu = (Menu)sender;
                     menu.Items.Remove(mItem);
                   }
                }
              else
                {
                  Menu menu = (Menu)sender;
                  menu.Items.Remove(e.Item);
                }
            }
         }
     }

  }
}

protected void MyMenu_DataBound(object sender, EventArgs e)
{
  Session["MenuLoaded"]=true;
}

會話變量的原因是-每次刷新/頁面請求單擊都會觸發menuitemdatabound,並且我希望對於用戶會話只加載一次菜單。

問題:

“刪除項目”代碼可以正常工作。 當用戶登錄時,菜單項不會按預期顯示。 但是,當他單擊現有項目以移至另一頁時,所有菜單再次出現在菜單欄中。

為什么會這樣呢? 每次刷新頁面或請求新的URL時,是否應允許menuitemdatabound事件。 那不對。是嗎? 但是還有其他辦法嗎? 或者我可以刪除會話條件。

使用C#

嘗試此:

page_load()
{
  if(Session["sMenuLoaded"]==null)
    lstRoles = (List<tblRoles>)Session["sMenuLoaded"];
  else
    {
      Menu mainMenu = (Menu)Session["sMenuLoaded"];
      mainMenu.DataBind();
    }

}

mymenu_menuitemdatabound()
{
  //  remains the same as above
}

mymenu_databound()
{
  Session["sMenuLoaded"] = (Menu)Page.Master.FindControl("menuBar");
}

如果您使用的是XML網站地圖,則可以使用另一種方法。 Asp.Net具有覆蓋站點地圖邏輯的機制 有基礎SiteMapProvider和默認實現XmlSiteMapProvider 基本SiteMapProvider具有IsAccessibleToUser 您可以這樣創建自己的站點地圖提供程序:

public class MySiteMapProvider : XmlSiteMapProvider 
{
    public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
    {
        var lstRoles = (List<tblDetail>)context.Session["sRoles"];

        // when we are accessing ChildNodes, it will execute the same IsAccessibleToUser method for each of this sub nodes
        var childs = node.ChildNodes;

        var isParentNode = node["isParent"] == "true";
        if (childs.Count == 0 && isParentNode)
        {
            // it means that this is node is parent node, and all it sub nodes are not accessible, so we just return false to remove it
            return false;
        }

        if (string.IsNullOrWhiteSpace(node.Description))
            return true;

        var formId = Convert.ToInt32(node.Description);
        foreach (var item in lstRoles)
        {
            if (item.FormID == formId)
                return true;
        }

        return false;
    }
}

然后,您可以在web.config中指定它:

  <siteMap defaultProvider="myProvider">
      <providers>
          <add name="myProvider" securityTrimmingEnabled="true"  
          type="WebApplication5.MySiteMapProvider"  siteMapFile="web.sitemap" />
      </providers>
  </siteMap>

然后,當Asp.Net將基於站點地圖呈現菜單時,它將每次為每個用戶調用IsAccessibleToUser,以驗證其是否有權訪問它。 如果在該方法中返回false,則該節點及其子節點將被隱藏。

UPDATE1

我更新了代碼以反映綁定的原始思想。 為了測試,我使用了這樣的web.sitemap

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="" title="Root">
    <siteMapNode url="Default.aspx" title="1"  description="1">
        <siteMapNode url="SubDefault.aspx" title="2"  description="11" />
        <siteMapNode url="SubDefault1.aspx" title="3"  description="12" />
    </siteMapNode>
    <siteMapNode url="Default2.aspx" title="2_1" isParent="true">
        <siteMapNode url="Default3.aspx" title="21" description="2"/>
    </siteMapNode>
</siteMapNode>

這是我的測試角色:

Session["sRoles"] = new List<tblDetail>()
                    {
                        new tblDetail() { FormID = 12 }, 
                        new tblDetail() { FormID = 1 }
                    };

還在上面的示例中,將securityTrimmingEnabled =“ true”添加到了web.config中。 現在,當它檢查每個節點時。 如果節點無法從會話中基於tblDetail進行訪問,則IsAccessibleNode返回false,並且該節點和所有子節點都隱藏在UI上。 它將對每個節點執行此方法。 在我的測試案例中,僅顯示Default.aspx和SubDefault1.aspx節點,因為我僅指定了兩個FormID 1、11。因此MySiteMapProvider僅顯示它們。

UPDATE2添加了我使用的aspx UI

<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"></asp:Menu>
<asp:SiteMapDataSource ID="SiteMapDataSource1" Runat="Server" 
     StartFromCurrentNode="False" ShowStartingNode="True" />

更新3

我已經將新屬性添加到web.sitemap-isParent。 如果無法訪問所有子節點,則可以在應隱藏的節點中指定它。 而且我還更新了提供程序的代碼以使用此isParent節點。

成功登錄后,您可以重新綁定菜單

Menu mainMenu=(Menu)Page.Master.FindControl("MyMenu");

if(mainMenu!=null)

{ 
   mainMenu.DataBind();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM