Skip to main content
Logo of TeamLink

Blog

Go Search
Blog
Website
  

Blog > Posts > Customizing Menu's in SharePoint
Customizing Menu's in SharePoint

In this blog I'll rant about how and what menu's you can change in SharePoint. The core of this article will be about adding items to the NewMenu.

Okay, so now you know what this article is about, let me make 2 things clear.

There is a difference in Menu's.

First you have the Left Menu called Quick Launch and the Top Menu called Top Navigation. The second kind of Menus are the following: SiteActions, Menu Toolbars, Personal Actions, Edit Control Blocks, ...

To manipulate the first set, you have different ways:

  1. Add links in your custom schema.xml. This will make sure that every site you create has the same links.
  2. Add NavigationNodes to QuickLaunch and TopNavigation collections in the SPWeb object of your site. This is a way to programatically change your menus. You'll find a lot of this on the web.
  3. Make your own SiteMapProvider and change the datasource of those ASP Menu's. I'm really fond of this way, because then I have absolute control about who sees what and I can do a lot more than what SharePoint offers you OOB. If you need more info about this, I can give you some ;)

To manipulate the second set, you have 2 options and they both require CustomAction features:

  1. Use the CustomAction with the UrlAction child element. This lets you define one link to a custom application page, url, ... . The key is that you have 1 element per custom action. There are also a lot of articles about this, so I'll skip this aswell.
  2. Use the CustomAction with ControlClass attribute. This lets you create a custom WebControl that will enable you to control whatever you want. This is what I want !!!!

Now we have more or less all the possibilities summed, I shall now focus on the latter way to have my Menu's behave how I want.

Before I move on I need to give you the following links:

http://msdn.microsoft.com/en-us/library/ms460194.aspx
http://msdn.microsoft.com/en-us/library/bb802730.aspx
http://johnholliday.net/resources/customactions.html

They are great resources about where you can put your links and what the GroupId & Locations are.

Okay now we're ready to start.

I mentioned you can do whatever you want with the ControlClass way, but to give you an Idea these are the things I do:

  • Hide Menus dynamically. Okay you can do a lot with Permissions, but sometimes it's just not that easily.
  • Add SubMenus dynamically. This is what I'll show you.

First you need to understand how the Feature System works.

It all starts with some user control who has a child repeater control who gets dynamically filled with ToolBarButtons, these ToolBarButtons get filled with MenuTemplates, which can be SubMenuTemplates and MenuItemTemplates.

SubMenuTemplates can hold SubMenuTemplates and MenuItemTemplates.

MenuItemTemplates are clickable and perform some action.

When you use the CustomAction feature with the ControlClass, your control gets wrapped around a FeatureMenuTemplate, which is a different kind of MenuTemplate.

So your Location field determines which user control will load your feature and the GroupId where your feature will get loaded.

To filter your can use RegistrationType and RegistrationId attributes. This lets you define on what kind of element your feature will work on.

Back to the ToolBarButtons, those are inherited to form special buttons, examples are NewMenu and ActionsMenu. By inheriting the ToolBarButton they can add special functionality to it. For example the NewMenu behaves very differently with a Survey list. It also fucks up your CustomAction, but I'll explain it in a moment.

Okay, now you should have an idea about how your control fits the puzzle.

So what do we need ?
A feature.xml
A elements.xml
A custom dll with your custom webcontrol.

Because we want our menu to be shown at the NewMenu we have another file aswell, my FixupJavaScript.js.

For those who have written CustomActions with custom WebControls, there is nothing new. Except when they tried to add it to the NewMenu, they should have noticed that nothing gets rendered. I have a solution for this. And for those who saw there control, but it was flickery, I also have a solution. Basicly I can do this:

image

So here's my code:

Feature.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="{DF5009DE-15B7-4397-9933-995727F3E276}"
         Title="New Template Selector"
         Description="Helps chosing templates from the New Document link"
         Version="1.0.0.0"
         Scope="Web"
         Hidden="FALSE"
         xmlns="
http://schemas.microsoft.com/sharepoint/" >
  <ElementManifests>
      <ElementManifest Location="elements.xml" />
  </ElementManifests>
</Feature>

elements.xml:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
    Id="CustomActionNewTemplateSelector"
    RequireSiteAdministrator="FALSE"
    GroupId="NewMenu"
    Location="Microsoft.SharePoint.StandardMenu"
    ControlAssembly="MyDLL"
    ControlClass="MyDLL.CustomTemplateSelector"
    Sequence="10"
    RegistrationType="List"
    RegistrationId="101"
    Title="New Template"
    Description="Use this menu to select a template"
    >
  </CustomAction>
   <!--RegistrationID 101 = Document Library -->
</Elements>

CustomTemplateSelector.cs:

/*
* This control dynamically loads the document templates for the different business units
* There are some extra's added to make it function under the NewMenu
*          - Override of the Render method that explicitly calls the RenderChildren function
*          - Addition of a Fixup Script to fix some javascript in the Core.Js
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.Web.UI;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.HtmlControls;

namespace xxxxx.xxxxxx.Controls
{
    /// <summary>
    /// This class will generate a dynamic Menu, which will allow us to select from the different templates
    /// </summary>
    public class CustomTemplateSelector: WebControl
    {
        #region Control Events
        protected override void OnLoad(EventArgs e)
        {
            // Ensure the control is build
            this.EnsureChildControls();
            base.OnLoad(e);
        }

        protected override void CreateChildControls()
        {
            // Register the improved javascript
            RegisterFixupScript();
            StringBuilder jsText = null;

            // Here is where all the action is.
            // Define the menu under which all the templates will hang
            SubMenuTemplate firstLevelMenuTemplate = new SubMenuTemplate();
            firstLevelMenuTemplate.ID = "CustomActionNewTemplateSelector";
            firstLevelMenuTemplate.Description = "Use this menu to select a template";
            firstLevelMenuTemplate.Text = "New Template";
            firstLevelMenuTemplate.Sequence = 10;
            //firstLevelMenuTemplate.MenuGroupId = 1000;

            // Add Child Menus
            for (int i = 0; i < 3; i++)
            {
                // Fill in your menuItemTemplate Properties
                SubMenuTemplate secondLevelMenuTemplate = new SubMenuTemplate();
                secondLevelMenuTemplate.ID = "menuItem" + i;
                secondLevelMenuTemplate.Text = "Title " + i;
                secondLevelMenuTemplate.Description = "Description " + i;
                secondLevelMenuTemplate.Sequence = i;
                //secondLevelMenuTemplate.MenuGroupId = 1000 + i;

                for (int j = 0; j < 2; j++)
                {
                    // Fill in the necessary properties
                    string strPathTemplate = "http:\u002f\u002flocalhost:33033\u002fShared Documents\u002fForms\u002ftemplate.doc";
                    string strSaveLocation = getSaveLocation();

                    // Build your javascript
                    // This Javascript will open your local application with the correct template
                    jsText = new StringBuilder();
                    jsText.AppendLine(@"createNewDocumentWithProgID('");
                    jsText.AppendLine(strPathTemplate);
                    jsText.AppendLine(@"','");
                    jsText.AppendLine(strSaveLocation);
                    jsText.AppendLine(@"','SharePoint.OpenDocuments', false)");

                    // Fill in your menuItemTemplate Properties
                    MenuItemTemplate thirdLevelItemTemplate = new MenuItemTemplate();
                    thirdLevelItemTemplate.ID = "menuItem" + j + i;
                    thirdLevelItemTemplate.Text = "Title " + j + i;
                    thirdLevelItemTemplate.Description = "Description " + i;
                    thirdLevelItemTemplate.Sequence = i * 10 + j;
                    thirdLevelItemTemplate.ClientOnClickScript = jsText.ToString();
                    thirdLevelItemTemplate.UseShortId = true;
                    //thirdLevelItemTemplate.MenuGroupId = 1000 + i * 10;

                    // Add it to the parent level
                    secondLevelMenuTemplate.Controls.Add(thirdLevelItemTemplate);
                }

                // Add the subMenuItem to your Menu
                firstLevelMenuTemplate.Controls.Add(secondLevelMenuTemplate);
            }

            // Return your menu
            this.Controls.Add(firstLevelMenuTemplate);
        }

        /// <summary>
        /// We need to override this, or else there will be a SPAN object around our <IE:MENUITEM> objects
        /// This SPAN object makes it impossible for the javascript in the core.js to build your menu
        /// </summary>
        /// <param name="output">The HTML Writer</param>
        protected override void Render(System.Web.UI.HtmlTextWriter output)
        {
            RenderChildren(output);
        }

        #endregion

        #region Private helper methods
        /// <summary>
        /// This method registers a deffered javascript that will override a core.js function
        /// </summary>
        private void RegisterFixupScript()
        {
            ((HtmlHead)Page.Header).Controls.Add(new LiteralControl("<script type='text/javascript' src='/_layouts/1033/FixUp.js' defer></script>"));
        }

        /// <summary>
        /// This methods finds out what the save location is of the document
        /// </summary>
        /// <returns>A absolute URL</returns>
        private string getSaveLocation()
        {
            string strSaveLocation;

            string strSiteUrl = SPContext.Current.Web.Url;

            // Check if you are in a Sub Folder
            if (HttpContext.Current.Request.QueryString["RootFolder"] == null)
            {
                // If not, add the RootFolder (= your list itself) it to your URL
                strSaveLocation = strSiteUrl + SPContext.Current.List.RootFolder.ServerRelativeUrl;
            }
            else
            {
                // If so, use the path in the RootFolder parameter
                strSaveLocation = strSiteUrl + HttpContext.Current.Request.QueryString["RootFolder"];
            }

            return strSaveLocation;
        }

        #endregion
    }
}

// If you want to hide whole menu's, add this code to the page_load event
// To Hide the menu button, use this code
// ((ToolBarMenuButton)((TemplateContainer)((FeatureMenuTemplate)this.Parent).Parent).Parent).Visible = false;

FixUp.js (place this in your layouts folder)

function MenuHtcInternal_Show(oMaster, oParent, y, fFlipTop)
{
    var oPopup=oMaster._arrPopup[oMaster._nLevel];   
    var nIndex;                           
    var fTopLevel;                           
    var oInnerDiv;
    if (!oMaster._oContents) PrepContents(oMaster);
    if (!oMaster._oContents || IsOpen(oMaster)) return;
    if (!oPopup && !oMaster._oRoot)
        {
        oMaster._nLevel=0;
        oMaster._oRoot=oMaster._oContents;
        }
    fTopLevel=oMaster._nLevel==0;
    fFlipTop=fFlipTop && fTopLevel;
    if (!oPopup)
    {
        oMaster._arrPopup[oMaster._nLevel]=document.createElement("DIV");
        oPopup=oMaster._arrPopup[oMaster._nLevel];
        oPopup.isMenu=true;
        oPopup.master=oMaster;
        oPopup.level=oMaster._nLevel;
        oInnerDiv=document.createElement("DIV");
        var oTable=document.createElement("table");
        var oTBody=document.createElement("tbody");
        oInnerDiv.isInner=true;
        oPopup.style.position="absolute";
        oInnerDiv.style.overflow="visible";
        oTable.appendChild(oTBody);
        oInnerDiv.appendChild(oTable);
        oPopup.appendChild(oInnerDiv);
        if (oMaster._fIsRtL)
            oPopup.setAttribute("dir", "rtl");
        else
            oPopup.setAttribute("dir", "ltr");
        document.body.appendChild(oPopup);
        FixUpMenuStructure(oMaster);
        var id=0;
        var childNodeLength=oMaster._oRoot.childNodes.length;
        for (nIndex=0; nIndex < childNodeLength; nIndex++)
        {
            var oNode=oMaster._oRoot.childNodes[nIndex];
            if (oNode.nodeType !=1)
                continue;
            if (!FIsIType(oNode, "label"))
            {
                var oItem=CreateMenuItem(oMaster, oNode, MakeID(oMaster, oMaster._nLevel, id));
                if (oItem) oTBody.appendChild(oItem);
                id++;
            }
        }
        oPopup.className="ms-MenuUIPopupBody";
        oTable.className=oMaster._wzMenuStyle;
        oTable.cellSpacing=0;
        oTable.cellPadding=0;
        oPopup.oncontextmenu=kfnDisableEvent;
        oPopup.ondragstart=kfnDisableEvent;
        oPopup.onselectstart=kfnDisableEvent;
        if (oParent._onmouseover==null)
            oParent._onmouseover=oParent.onmouseover;
        if (oParent._onmouseout==null)
            oParent._onmouseout=oParent.onmouseout;
        if (oParent._onmousedown==null)
            oParent._onmousedown=oParent.onmousedown;
        if (oParent._onclick==null)
            oParent._onclick=oParent.onclick;
        if (browseris.nav)
        {
            oPopup.onkeypress=function(e) {return false; };
            oPopup.onkeyup=function(e) {return false; };
            oPopup.onkeydown=function(e) {PopupKeyDown(e); return false; };
            oPopup.onmousedown=function(e) {TrapMenuClick(e); return false; };
            oPopup.onmouseover=function(e) {PopupMouseOver(e); return false; };
            oPopup.onmouseout=function(e) {PopupMouseLeave(e); return false; };
            oPopup.onclick=function(e) {PopupMouseClick(e); TrapMenuClick(e); return false; };
            oParent.onmouseover=function (e) {PopupMouseOverParent(e); return false; };
            oParent.onmouseout=function(e) {PopupMouseLeaveParent(e); return false; };
            oParent.onmousedown=function(e) {TrapMenuClick(e); return false; };
            oParent.onclick=function(e) {TrapMenuClick(e); return false; };
            oParent.oncontextmenu=function(e) {TrapMenuClick(e); return false; };
        }
        else
        {
            oPopup.onkeydown=new Function("PopupKeyDown(event); return false;");
            oPopup.onmousedown=new Function("TrapMenuClick(event); return false;");
            oPopup.onmouseover=new Function("PopupMouseOver(event); return false;");
            oPopup.onmouseout=new Function("PopupMouseLeave(event); return false;");
            oPopup.onclick=new Function("PopupMouseClick(event); TrapMenuClick(event); return false;");
            //oParent.onmouseover=new Function("PopupMouseOverParent(event); return false;");
            //oParent.onmouseout=new Function("PopupMouseLeaveParent(event); return false;");
            oParent.onmousedown=new Function("TrapMenuClick(event); return false;");
            oParent.onclick=new Function("TrapMenuClick(event); return false;");
            //oParent.oncontextmenu=new Function("TrapMenuClick(event); return false;");
        }
        if (fTopLevel)
        {
            var wzOnUnload=oMaster.getAttribute("onunloadtext");
            if (wzOnUnload) oPopup.onunload=new Function(wzOnUnload);
        }
    }
    else
    {
        var oOld=oMaster._arrSelected[oMaster._nLevel];
        if (oOld) UnselectItem(oOld);
    }
    oMaster._arrSelected[oMaster._nLevel]=null;
    var oBackFrame;
    if (browseris.ie)
    {
        var originalScrollLeft=document.body.scrollLeft;
        oBackFrame=document.createElement("iframe");
        AssureId(oBackFrame);
        oBackFrame.src="/_layouts/blank.htm";
        oBackFrame.style.position="absolute";
        oBackFrame.style.display="none";
        oBackFrame.scrolling="no";
        oBackFrame.frameBorder="0";
        document.body.appendChild(oBackFrame);
        oPopup.style.zIndex=103;
        oPopup._backgroundFrameId=oBackFrame.id;
        if (originalScrollLeft !=document.body.scrollLeft)
        {
            document.body.scrollLeft=originalScrollLeft;
        }
    }
    SetMenuPosition(oMaster, oParent, oPopup, oInnerDiv, fFlipTop, fTopLevel);
    if (browseris.ie)
    {
        SetBackFrameSize(null, oPopup);
        oPopup.onresize=new Function("SetBackFrameSize(event, null);");
        oBackFrame.style.display="block";
        oBackFrame.style.zIndex=101;
    }
}

There's more to be said.

Your Menu gets rendered by JavaScript, this javascript is located in the Core.Js. There are some problems with it, namely it doesn't really behave good when hovering on top of your custom menu.

You cannot insert basic javascript blocks to override this functionality, because the Core.Js gets loaded after your page has loaded. They've done this by adding the defer keyword to the script tag. That's why we need to this aswell, so our function gets loaded after the one in the core.js and thus override it.

I couldn't do this with Page.ClientScript. ... methods, because none has the option to add the defer keyword.

 

Have fun with it. If you do have problems with it, post a comment or mail us.

 

Pascal Van Vlaenderen
TeamLink Consultant

Comments

Not Workign

Pascal,

Can you post your source code samples to be downloaded?  I have tried to follow your instructions here to test this out and I cannot get it to work. Nothing ever appears on the NewMenu.

Thanks,

Paul Liebrand
http://liebrand.wordpress.com
at 20/06/2008 18:25

Safe Controls

Have you tried adding your control as Safe control ?
Pascal Van Vlaenderen at 15/07/2008 19:28

Needs to be public

It actually landed up being that my class was not public. Once I changed that everything worked like a charm!
at 15/07/2008 20:58

Great article!

This is a great article, but for some reason the javascript (used to open the document template) isn't being executed when I click an item in the menu...

Any idea why the javascript would not be executed when an item is clicked?
at 25/09/2008 19:55

Changed jsText.AppendLine to jsText.Append

That did the trick...
at 25/09/2008 20:14

Hmmm

I've never noticed any problems with it, but thanks Jack for pointing it out :)

Pascal
Pascal Van Vlaenderen at 30/09/2008 11:12

Add Any Controls (Button, Textbox, Menu,..) aspx

I can add any controls aspx in MenuItemTemplate.

Can you show me your code or introduce the way do.

Thanks
sealight
at 8/10/2008 9:12

Add Any Controls (Button, Textbox, Menu,..) aspx

The MenuItemTemplate is a template control, which means it will render the Child controls in a specific way. Here it does so by rendering a menu.

You can add controls by adding controls (such as Buttons, Textboxes, ... ) to the .Controls Property of the MenuItemTemplate. I tested it by doing the following:
secondLevelMenuTemplate.Controls.Add(new LiteralControl("My Test Text"));

I haven't tested it with controls that require a postback.

I hope this anwsers a bit of your problems, if not please tell us what you want to do and which code you are using.
Pascal Van Vlaenderen at 8/10/2008 9:40

Ask

Do you know the way click on submenutemplate?
at 9/10/2008 9:04

MenuItemTemplate

You don't really need to click on a SubMenuItemTemplate, unless you use a control that emits javascript of some sort.

The easiest way is to use a MenuItemTemplate. This control has several Client click properties.

I emailed you a screenshot
Pascal Van Vlaenderen at 9/10/2008 10:25

MenuItemTemplate

Hi Pascal

Can you show me the way you use a control that emits javascript of some sort.

It's very important for me, because I use List of sharepoint to display on SubMenuTemplate and Items contain url for link


Thanks
sealight
at 9/10/2008 13:44

The way I understand your problem

You want to list all your lists / all items in a list in your menu.
When someone clicks the item, you want the user to go to that page.

You need to add 1 SubMenuItemTemplate to your Controls collection of your custom control.

Then loop all your lists / list items and add MenuItemTemplate controls to your SubMenuItemTemplate control.

For those MenuItemTemplate controls set the ClientOnClickNavigateUrl property to the URL you want.

Pascal
Pascal Van Vlaenderen at 9/10/2008 14:43

Customize List Menu Bar.

Hi Pascal,

I have SharePoint list. On the menu bar I can see
New Upload Actions Settings
When I click on settings I can see

Create Column
Create View
Form Library Settings

Now I want to remove Create Column.
So when I click on settings I want to see only

Create View
Form Library Settings

For achieving this task
In feature.xml I have written
<?xml version="1.0"?>
<Feature Id="8C4DD0CB-5A94-44da-9B7F-E9ED49C2B2DC" Title="Custom Web page"
Description="This simple feature remove create column from settings in the menu bar" Version="1.0.0.0" Scope="Web"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="Module.xml"/>
</ElementManifests>
</Feature>
In module.xml I have written
<?xml version="1.0"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<HideCustomAction GroupId="SettingsMenu" HideActionId="AddColumn"
Id="HideAddColumn" Location="Microsoft.SharePoint.StandardMenu" />
</Elements>
I have installed and activated the feature for a sharepoint site.
But, it is not working.
Please help me.
Thanks for reading this post.
at 20/10/2008 17:04

Hiding Menu's

Hey,

There are some menu's you cannot hide through the use of HideCustomActions. I don't know why, I just know it is.

I've used the javascript technique describes here:
http://techtrainingnotes.blogspot.com/2008/02/sharepoint-hiding-menus-not-using.html

I'm sure this will help you !!

Pascal
Pascal Van Vlaenderen at 20/10/2008 19:01

It doesnt't work for me

Hi, Pascal!

 

I tried Your solution, but it doesn't work for me. :( I have successfully installed and activated fieature. But when I open "New" menu, I see no additional menu item. I also tried some other, lell complex solution -(http://www.wsswiki.com/Adding_a_custom_menu_item_to_the_NewMenu. The result was the same. There are some details:

I named Your assembly "CustomMenu". So, in elements.xml I replaced MyDll with CustomMenu. I am novice to Sharepoint, so I can't understand, what I do wrong. I have a localized (russian
) version of Sharepoint Server 2007. May be, this is the matter? Any Suggestions?

Regards
at 14/11/2008 12:09

I am sorry, the right link is

at 14/11/2008 12:11

Some help

There are a few things that you may have overlooked.

- Is your dll strongly signed ?
- Is it placed in the GAC ?
- Does your feature reference the good fully qualified assembly ?
- Is your control (or namespace) a save control ? (See web.config at C:\inetpub\....) ?

Those are the common mistakes. If you haven't done either of these, please check the log files located at C:\program files\common\microsoft shared\web services extensions\12\logs
If you make a request and somehow the control isn't loaded, then you should see an entry in the logfile for this.

Hope this helps you !
Pascal Van Vlaenderen at 15/11/2008 10:44

It still doesn't work for me

Hi, Pascal!

Thanks a lot for Your answer. Here are some details of my efforts:

My Features.xml file is identical to Yours. The elements.xml file differs from Yours by 2 strings (I renamed the assembly):

    ControlAssembly="CustomMenu"
    ControlClass="CustomMenu.CustomTemplateSelector"

Then I created the project with Your .cs code (CustomTemplateSelector.sc):
Assembly name: CustomMenu
Output Type: Class Library
Default Namespace: xxxxx.xxxxx.Controls (I tried various with the same result)
Etc.

I signed the assembly – strong name key file = CustomTemplateSelector.snk.

Then I built the project and placed assembly to the GAC with the following command:

> …gacutil.exe" -if bin\Debug\CustomMenu.dll
gacutil reports OK.

Then I go to the appropriate virtual directory (for http://localhost:30000/ site) and add the following string to web.config file:

<SafeControl Assembly="CustomMenu, Version=1.0.0.0, Culture=neutral, PublicKeyToken=93bbd…..8b71f" Namespace="xxxxxx.xxxxxx.Controls" TypeName="*" Safe="True" />

I insert it at the end of <SafeControls>  … </SafeControls> section.

Then I install and activate feature with an stsadm:
>stsadm -o installfeature -filename CustomMenu\feature.xml -force

>stsadm -o activatefeature -filename CustomMenu\feature.xml -url http://localhost:30000/

It also reports OK.

Then I run iisreset and open the http://localhost:30000/ page, go to the “common documents”, choose “Create document” and see only standard menu Items  (create new document and create new folder).

In the logs directory I see a lot of files, named as MYSHAREPOINT-200811**-****.log, they contain strings like this:

11/17/2008 12:36:14.13                wsstracing.exe (0x09D8)                             0x0F14  ULS Logging                       Unified Logging Service                 uls1        Monitorable      Tracing Service lost trace events.  Current value 2.

And there no .log files there, containing “CustomMenu” string.

What I do wrong? Any Suggestions?

at 17/11/2008 11:26

Solution

I see that your savecontrol registration isn't correct.
You should set it equal to your fully qualified dll

If you have an error, there most likely be something like: Could not load ...
Pascal Van Vlaenderen at 17/11/2008 12:01

A bit more details, if it is possible.

Hi, Pascal!

Thanks a lot for You answer.

I am sorry, I am novice at SharePoint. Could You explain this thing in details, please. Could You show me the appropriate fragment of Your web.config, if it is possible.

Regards
at 17/11/2008 14:51

A bit more details

Hey,

<SafeControl Assembly="YourNamespace.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9c954ca1ba0da856" Namespace="YourNamespace.Controls" TypeName="*" Safe="True" />

SharePoint will only load controls/webparts/code if an administrator allows this. You do this by adding an safecontrol entry for the piece of code you want to run.

Usually the web.config for your test site will be located at C:\inetpub\wwwroot\wss\VirtualDirectories\80

You should see a lot of SafeControl entries there, do a search for <SafeControl Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint" TypeName="*" Safe="True" AllowRemoteDesigner="True" />

And then add your entry there.

Be sure to check the name (it is case sensitive) and the publickeytoken as those are always different.

Hope this helps you out a bit
Pascal Van Vlaenderen at 17/11/2008 15:07

I still can't make it work

Hi, Pascal.
Thanks a lot for Your answer.

I tried a various variants, but none of them works.

You wrote:
-----------------------------------------
<SafeControl Assembly="YourNamespace.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9c954ca1ba0da856" Namespace="YourNamespace.Controls" TypeName="*" Safe="True" />
-----------------------------------------

I think, this is not the case. "Assembly" attribute value must be equal to the assembly name in the GAC and "Namespace" attribute value must be equal to one namespace in the assembly - we can see it with .net Reflector utility. I checked this fact for most <SafeControl ...> elements in the web.config file. You mentioned the following case:

-----------------------------------------
<SafeControl Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint" TypeName="*" Safe="True" AllowRemoteDesigner="True" />
-----------------------------------------

When we go to the GAC (c:\windows\assembly), we can find Microsoft.SharePoint assembly there, and when we open it with .net Reflector, we can see the namespace with the same name there.

One more example: I created in VS2005 a simplest "helloword" webpart:


-----------------------------------------
namespace HelloWordNameSpace
{
    [Guid("cc9a8fad-11f1-498f-be4a-e0230858df55")]
    public class HelloWord : System.Web.UI.WebControls.WebParts.WebPart
    {
        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("Hello from Sharepoint WebPart!");
        }
    }
}
-----------------------------------------

I have buit and  deployed it and it works. Then I go web.config file and can see there the following:

-----------------------------------------
<SafeControl Assembly="HelloWordWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" Namespace="HelloWordNameSpace" TypeName="*" Safe="True" />
-----------------------------------------

There no "fully qualified dll" there, but this simple example works.

Maybe, I have to do some additional things explicitly? The problem is still open.

Regards
at 20/11/2008 13:34

Re: Customizing Menu's in SharePoint

Yes there is a fully qualified dll :), otherwise you don't have a publickeytoken. Visual Studio automaticly registers this.

You should try to debug the application. I recommend you google that :)
Pascal Van Vlaenderen at 20/11/2008 19:14

I've made it work

Hi!

The problem was located in the elements.xml file: the ControlAssembly attribute value must be equal to assembly name from the GAC. Not the "CustomMenu", but "CustomMenu, Version=... ets.". Now it works fine. Thanks a lot!

Regards.
at 1/12/2008 14:11

share point

All the steps are clearly mentioned. Thanks
at 1/01/2009 10:23

Works like a charm :)

I was experiencing the aforementioned 'flickering menu' issue with my nested menu in a document library toolbar and your JavaScript has saved the day!

Btw, I did not need to override the Render method. The menu was rendered as expected, it just collapsed at certain mouse positions, making it user unfriendly.

Thanks for the fix!
at 18/05/2009 13:57