Monday, September 10, 2007

Using a ControlClass to render an EditControlBlock menu

I found this usefull post on a CustomAction feature for list item context menus, but ran into a problem when I wanted to use ControlClass code rather than a UrlAction. This post details the problem, and it seems it can't be done because context menu items don't appear to be rendered on the server as WebControls. Html is generated that includes the UrlAction, which comes from the feature's xml definition.

If you're determined not to redirect to a different page, it is possible to trap for a postback event in another (2nd) custom action implemented as a WebControl on the StandardMenu. E.g. (in the feature definition):



<UrlAction Url="javascript:__doPostBack(&#39;MyEventTarget&#39;, &#39;{ItemId}&#39;);"/>


In the second menu CustomAction WebControl code:

        protected override void OnLoad(EventArgs e)
        {
            this.EnsureChildControls();
            base.OnLoad(e);
            if (this.Page.Request["__EVENTTARGET"] == "MyEventTarget")
            {
                int itemId = Convert.ToInt32(this.Page.Request["__EVENTARGUMENT"]);
            }
        }

4 comments:

Udalov Alex said...

I was trying to create a project using some of ur ideas but failed. Can u help me? I want to add "Menu items" to ECB directly from pocedure, but every time after the reset of iis i get just one menu item.

CustomAction
Id="ActionsMenuCustomizer"
RegistrationType="List"
RegistrationId="101"
Location="EditControlBlock"
Title="ECB"
Description=""
ShowInLists="TRUE"
ControlAssembly="ECB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0069b41c8e674243"
ControlClass="ECB.ECBWebControl"
UrlAction Url="javascript:__doPostBack('MyEventTarget', {ItemId});"
CustomAction

protected override void OnLoad(EventArgs e)
{
this.EnsureChildControls();
base.OnLoad(e);

if (this.Page.Request["__EVENTTARGET"] == "MyEventTarget")
{
int itemId = Convert.ToInt32(this.Page.Request["__EVENTARGUMENT"]);
}
else { Microsoft.SharePoint.Utilities.SPUtility.Redirect(@"http://www.google.com" , Microsoft.SharePoint.Utilities.SPRedirectFlags.Default, System.Web.HttpContext.Current); }
}

protected override void CreateChildControls()
{
SPListItem _currentItem = SPContext.Current.ListItem;

MenuItemTemplate deleteListItem = new MenuItemTemplate();
deleteListItem.ID = @"deleteListItem";
deleteListItem.Title = @"Delete Item";
deleteListItem.ClientOnClickNavigateUrl = @"www.google.com";
deleteListItem.Sequence = 401;
this.Controls.Add(deleteListItem);

this.Page.Controls.Add(deleteListItem);
base.CreateChildControls();
}

txs8311 said...

If you're unable to debug the control at all, it's likely that the assembly to render your webcontrol is not getting loaded by w3wp.exe in the first place. Try looking in the WSS diagnostic trace log (after first making sure that the event throttling for the General event category is set appropriately low).

Anonymous said...

Hello,

I tried your workaround and it works fine as long as I'm connected with a site collection admin account. Any other type of account (visitor, member, owner) will cause the assembly not to be called by the custom action. I don't find anything in the log files nor in the event log although I've configured the event throttling to catch any kind of event.

Any idea of why this behavior?

txs8311 said...

No, sorry. Try debugging the page on the client browser (e.g. Script Debugger/Break at Next Statement - or change the URL to URL="javascript:debugger;__doPostBack etc) to make sure that the URL is correct and that the post back function is being called with the correct values. On the server, try making sure that the WebControl feature is loading by setting a break point in the OnLoad event - this should fire every time the page is refreshed - something you've probably tried.

The only other thing I could think of is if you've specified specific rights in the Custom action - seems unlikely though.