Using javascript in the NavigateUrlFormat property of the SPMenuField

by Sven De Bont 14. April 2009 16:39

When you use an SPMenuField in an SPGridView, you can use the NavigateUrlFormat property to specify an url to navigate to when the users clicks the cell. Using the TokenNameAndValueFields and the NavigateUrlFields properties you can specified tokens in the Url that should be replaced with the underlying values from the datasource for each row in the grid. This all works fine, but when you try to use a javascript function in the NavigateUrlFormat property, the javascript function is never rendered.

SPMenuField colMenu = new SPMenuField();

colMenu.HeaderText = "Company";
colMenu.TextFields = "Company";

colMenu.MenuTemplateId = "mnuCompany";
colMenu.TokenNameAndValueFields = "COMPANYID=CompanyId";
colMenu.NavigateUrlFields = "CompanyId";
colMenu.NavigateUrlFormat = "javascript:alert('you have clicked company with id {0}');";
colMenu.SortExpression = "Company";

When you start digging around in the SharePoint libraries using reflector, you’ll see that reason for this is that the code that renders the menu (Microsoft.SharePoint.WebControls.Menu.Render(HtmlTextWriter)) makes a call to ‘SPHttpUtility.HtmlUrlAttributeEncode(string url)’ passing the value of the NavigateUrlFormat (in the SPMenuField class, the value of NavigateUrlFormat is passed to the NavigateUrl property of an internally create Microsoft.SharePoint.WebControls.Menucontrol).

The method SPHttpUtitlity.HtmlUrlAttributeEncode makes a call to SPUrlUtility.IsProtocolAllowedto verify is the requested protocol (javascript: in our case) is allowed. Since the 'javascript' protocal is not in the list, the link will simply not be rendered.

The list of allowed protocols is an hardcoded string array that is initialized in the constructor of SPUrlUtility.

 

static SPUrlUtility()
{
    m_rgstrAllowedProtocols = new string[] { "http://", "https://", "file://", @"file:\\", "ftp://", 
		"mailto:", "msn:", "news:", "nntp:", "pnm://", "mms://", "outlook:" };
}

 

The list of allowed protocols is available through the public AllowedProtocolsproperty, but it is read-only and since it’s an array, it’s not possible to add additional items to it.

As a workaround, I decided to replace one of the values in the AllowedProtocols array before I render my control in the Render event and set the initial value back when the rendering is done.

The downside of this approach is that any links using the protocol that you replace in the array will not be rendered (as it is no longer an allowed protocol). Therefore I chose to ‘replace’ one of the lesser used protocols: ‘pnm://’

As you can imagine, this is not best practice and even not recommended. Although the AllowedProtocols property is public and therefore should always be available (then again, who will stop MS from changing the public interfaces of their classes if they really want to?).

protected override void Render
{
	SPUrlUtility.AllowedProtocols[9] = "javascript:";
	try
	{

		base.Render(writer);
	}
	Finally
	{
    	SPUrlUtility.AllowedProtocols[9] = "pnm://";
	}
}

protected override void CreateChildControls()
{

	SPGridView grid = new SPGridView();

	SPMenuField colMenu = new SPMenuField();

	colMenu.HeaderText = "Company";
	colMenu.TextFields = "Company";

	colMenu.MenuTemplateId = "mnuCompany";
	colMenu.TokenNameAndValueFields = "COMPANYID=CompanyId";
	colMenu.NavigateUrlFields = "CompanyId";
	colMenu.NavigateUrlFormat = "javascript:alert('you have clicked company with id {0}');";
	colMenu.SortExpression = "Company";

	grid.Columns.Add(colMenu);

	this.Controls.Add(grid);

	... (rest of code ommitted)

}

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

Change the language of SharePoint Site(s)

by Sven De Bont 16. March 2009 09:36

Mirjam van Olst of Macaw (http://www.macaw.nl) explains how to update the language of existing SharePoint sites by running a sql statement on the content datbase.

http://www.sharepointblogs.com/mirjam/archive/2008/04/29/changing-the-language-of-an-existing-sharepoint-site.aspx

For changing the language of all sites in the content database to Dutch the query would be:

UPDATE dbo.Webs SET Language = 1043

Changing the language of one site collection can be done with:

UPDATE dbo.Webs SET Language = 1043 WHERE SiteId = [[SiteCollectionId]]

And for changing the language of a single web or subsite you can use:

UPDATE dbo.Webs SET Language = 1043 WHERE Id = [[WebId]]

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

‘Error in the application’ when configuring incoming e-mail on a list

by Sven De Bont 13. March 2009 05:29

When you try to configure incoming email on a list, you might receive the error ‘Error in the application’ when the ‘Central Admin’ application pool user differs from the ‘Web Application’ application pool user.

There might be other causes for the same symptom. For more information, see http://blogs.technet.com/jks/archive/2009/03/04/3209136.aspx

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

SharePoint outgoing e-mail with Exchange 2007

by Sven De Bont 13. March 2009 05:19

Currently rated 2.0 by 1 people

  • Currently 2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

Handling Postbacks using MenuItemTemplate

by Sven De Bont 6. March 2009 09:41

When using a MenuItemTemplate to perform a postback (instead of a navigate), handling the postback can be tricky. If you have several MenuItems, you will end up writing a lot of code to determine the menuitem that caused the postback and parsing the eventargument data.

Patrick Rodgers came up with a subclassed MenuItemTemplate in this post(http://www.thesug.org/blogs/patrickr/Lists/Posts/Post.aspx?ID=18) that targets itself for the postback and raises an event. You simply have to subscribe to the event and handle the postback there.

Here’s Patrick’s code:

using System;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;

namespace Example
{
    public class PostBackEventMenuItem : MenuItemTemplate, IPostBackEventHandler
    {
        public PostBackEventMenuItem()
            : base() { }

        public PostBackEventMenuItem(string text)
            : base(text) { }

        public PostBackEventMenuItem(string text, string imageUrl)
            : base(text, imageUrl) { }

        public PostBackEventMenuItem(string text, string imageUrl, string clientOnClickScript)
            : base(text, imageUrl, clientOnClickScript) { }

        protected override void EnsureChildControls()
        {
            if (!this.ChildControlsCreated)
            {
                base.EnsureChildControls();
                if (string.IsNullOrEmpty(this.ClientOnClickUsingPostBackEvent))
                {
                    this.ClientOnClickUsingPostBackEventFromControl(this);
                }
            }
        }

        #region IPostBackEventHandler Members

        public void RaisePostBackEvent(string eventArgument)
        {
            EventHandler<EventArgs> handler = this.OnPostBackEvent;
            if (handler != null)
            {
                handler(this, new EventArgs());
            }
        }

        #endregion

        public event EventHandler<EventArgs> OnPostBackEvent;
    }
}

To use the control, register it in an aspx page, add the PostbackEventMenuItem and subscribe to the OnPostBackEvent.

<%@ Register TagPrefix="SharePoint" 
	Namespace="Microsoft.SharePoint.WebControls"
    Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, 
	PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" 
	Namespace="Microsoft.SharePoint.Utilities" 
	Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, 
	PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Example" 
	Namespace="Example" Assembly="Example, Version=1.0.0.0, Culture=neutral, 
	PublicKeyToken=2bb7d29b4348a50b" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Control Language="C#" AutoEventWireup="true" 
	ClassName="Welcome" CompilationMode="Always" %>

<script runat="server">

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            this.ExplicitLogout.Visible = true;
        }
        else
        {
            this.ExplicitLogin.Visible = true;
            this.ExplicitLogin.Attributes.CssStyle.Add("display", "block");
        }
    }

    protected void HandlePostback(object sender, EventArgs e)
    {
        //remove all cookies, redirect to login with current page url
        FormsAuthentication.SignOut();

        Response.Redirect(string.Format("/_layouts/Authenticate.aspx?Source={0}", HttpUtility.UrlEncode(HttpContext.Current.Request.Url.AbsoluteUri)));
    }

</script>

<SharePoint:PersonalActions AccessKey="<%$Resources:wss,personalactions_menu_ak%>"
    ToolTip="<%$Resources:wss,open_menu%>" runat="server" 
	ID="ExplicitLogout" Visible="false">
    <CustomTemplate>
        <SharePoint:FeatureMenuTemplate 
			runat="server" FeatureScope="Site" 
			Location="Microsoft.SharePoint.StandardMenu"
            GroupId="PersonalActions" ID="ID_PersonalActionMenu" UseShortId="true">
            <SharePoint:MenuItemTemplate 
				runat="server" ID="ID_PersonalInformation" 
				Text="<%$Resources:wss,personalactions_personalinformation%>"
                Description="<%$Resources:wss,personalactions_personalinformationdescription%>"
                MenuGroupId="100" Sequence="100" ImageUrl="/_layouts/images/menuprofile.gif"
                UseShortId="true" />
            <example:postbackeventmenuitem 
				runat="server" id="Example_LoginAsDifferentUser" 
				text="<%$Resources:wss,personalactions_loginasdifferentuser%>"
                description="<%$Resources:wss,personalactions_loginasdifferentuserdescription%>"
                menugroupid="200" sequence="100" useshortid="true" ononpostbackevent="HandlePostback" />
            <SharePoint:MenuItemTemplate 
				runat="server" ID="ID_RequestAccess" 
				Text="<%$Resources:wss,personalactions_requestaccess%>"
                Description="<%$Resources:wss,personalactions_requestaccessdescription%>" MenuGroupId="200"
                UseShortId="true" Sequence="200" />
            <SharePoint:MenuItemTemplate 
				runat="server" ID="ID_Logout" 
				Text="<%$Resources:wss,personalactions_logout%>"
                Description="<%$Resources:wss,personalactions_logoutdescription%>" MenuGroupId="200"
                Sequence="300" UseShortId="true" Visible="true" />           
            <SharePoint:MenuItemTemplate 
				runat="server" ID="ID_PersonalizePage" 
				Text="<%$Resources:wss,personalactions_personalizepage%>"
                Description="<%$Resources:wss,personalactions_personalizepagedescription%>" ImageUrl="/_layouts/images/menupersonalize.gif"
                ClientOnClickScript="javascript:MSOLayout_ChangeLayoutMode(true);" PermissionsString="AddDelPrivateWebParts,UpdatePersonalWebParts"
                PermissionMode="Any" MenuGroupId="300" Sequence="100" UseShortId="true" />
            <SharePoint:MenuItemTemplate 
				runat="server" ID="ID_SwitchView" MenuGroupId="300"
                Sequence="200" UseShortId="true" />
            <SharePoint:MenuItemTemplate 
				runat="server" ID="MSOMenu_RestoreDefaults" 
				Text="<%$Resources:wss,personalactions_restorepagedefaults%>"
                Description="<%$Resources:wss,personalactions_restorepagedefaultsdescription%>"
                ClientOnClickNavigateUrl="javascript:MSOWebPartPage_RestorePageDefault()" MenuGroupId="300"
                Sequence="300" UseShortId="true" />
        </SharePoint:FeatureMenuTemplate>
    </CustomTemplate>
</SharePoint:PersonalActions>
<SharePoint:ApplicationPageLink runat="server" ID="ExplicitLogin" ApplicationPageFileName="Authenticate.aspx"
    AppendCurrentPageUrl="true" Text="<%$Resources:wss,login_pagetitle%>" Style="display: none"
    Visible="false" />

Currently rated 3.5 by 8 people

  • Currently 3.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

SharePoint log files grow extremely large

by Sven De Bont 17. February 2009 15:50

Today I ran into a strange issue where the SharePoint log files (located in c:\program files\common files\microsoft shared\web server extensions\12\logs) on one of my development VPC’s would rapidly grow in size (5GB+) until I ran out of disk space.

The log file would fill up with the following message (up to 800 occurrences in just 3 thousands of a second!):

02/17/2009 10:57:14.96     OWSTIMER.EXE (0x0DF4)                       0x0E08    Windows SharePoint Services       Timer                             5uuf    Monitorable    The previous instance of the timer job 'Config Refresh', id '{1520A0E0-E8C6-47F8-BA89-5BEBE5774DFD}' for service '{25FB833C-D7DD-4776-AD50-58105B3A46F0}' is still running, so the current instance will be skipped.  Consider increasing the interval between jobs.

After searching the web for a little while, I found the solution was to clear the SharePoint Configuration Cache as described in this post by Joe Rodgers.

  1. Stop the OWSTIMER service on ALL of the MOSS servers in the farm.
  2. On the Index server, navigate to %ALLUSERSPROFILE% \Application Data\Microsoft\SharePoint\Config\<GUID> and delete all the XML files from the directory.
  3. Edit cache.ini and reset the number in the file to 1.
  4. Start the OWSTIMER service on the Index server and wait for XML files to begin to reappear in the directory.
  5. After you see XML files appearing on the Index server, repeat steps 2, 3 & 4 on the query server(s), waiting for XML files to appear before moving to subsequent servers.
  6. After the query servers have all been cleared, proceed to the WFE and Application servers in the farm, following steps 2, 3 & 4. for each server.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

SharePoint

“Value cannot be null” error on postback when using Grouping in SPGridView

by Sven De Bont 19. December 2008 10:26

When you use an SPGridview with grouping enabled, you will receive an exception whenever you perform a postback: Value cannot be null. Parameter name: container.

Patrick Rodgers came up with a solution which you can read here: http://www.thesug.org/blogs/patrickr/Lists/Posts/Post.aspx?ID=2

The solution is to create your own GridView that inherits from SPGridView and override LoadControlState to raise an event whenever the DataSource is null. The page or control that implement the GridView will need to implement an eventhandler and make sure the Grid is bound to it’s datasource.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

SharePoint

Microsoft.SharePoint.WebControls.DateTimeControl ignores regional settings

by Sven De Bont 28. November 2008 09:24

When you use an instance of the Microsoft.SharePoint.WebControls.DateTimeControl in SharePoint (for example in a webpart), the locale will always be set to en-US, even if the web of user have specified a different locale.

To overcome this, you need to explicitly set the LocaleId property of the control to the correct locale.

DateTimeControl dtCtrl =new DateTimeControl();
dtCtrl.ID = "dtCtrl";
dtCtrl.LocaleId = (int)SPContext.Current.RegionalSettings.LocaleId;
this.Controls.Add(dtCtrl);

You should use SPContext.Current.RegionalSettings as this reflects the RegionalSettings for the current user (they might differ from the Web if the user modified this).

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

Sharepoint lookup with picker

by Sven De Bont 19. November 2008 14:39

Microsoft Sharepoint Server 2007 lookup control with element picker for custom list.
This control is useful if you need to choose lookup data from large lists. This control supports single and multi select mode.

http://www.codeplex.com/lookupwithpicker

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

SharePoint

‘Title’ field and property not available on SPItem when using a View to access the SPListItemCollection

by Sven De Bont 16. November 2008 09:47

You can get an SPListItemCollection from a List using a View with the following code:

SPList list = SPContext.Current.Web.Lists["My List"];

SPListItemCollection items = list.GetItems(list.Views["All Items"]);

When then try to access the Title field of any of the individual SPListItem instances in the collection you will receive an ArgumentExecption

//all these statements will throw an Argument Exception
string titleField = item[0]["Title"];
string titleProperty = items[0].Title;
string titleValue = items[0].GetFormattedValue("Title");

As a workaround, you can access the Title field value using the LinkTitle field:

//this will return the correct value
string title = items[0].GetFormattedValue("LinkTitle");

Currently rated 2.0 by 1 people

  • Currently 2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SharePoint

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen