Tuesday, July 21, 2009

June Cumulative Update for Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0

The server-packages of June Cumulative Update for Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 are ready for download. See below:

Download Information

Windows SharePoint Services 3.0 June cumulative update package
http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=971538

Office SharePoint Server 2007 June cumulative update package
http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=971537

Detail Description

Description of the Windows SharePoint Services 3.0 June cumulative update package
http://support.microsoft.com/kb/971538

Description of the Office SharePoint Server 2007 June cumulative update package
http://support.microsoft.com/kb/971537

SharePoint Single Sign-On Error: “User DOMAIN\USERID failed to configure the single sign-on server. The error returned was ERROR NUMBER. Verify this account has sufficient permissions and try again”

When configure SharePoint Single Sign-On (SSO), sometimes you’ll get “You do not have the rights to perform this operation.” error message on the “Manage Settings for Single Sign-On” page and subsequently “User DOMAIN\USERID failed to configure the single sign-on server. The error returned was ERROR NUMBER. Verify this account has sufficient permissions and try again.” error message is displayed in the Windows Event Viewer and SharePoint Log.

To fix this issue, you have to make sure “Single Sign-On Administrator Account” account name to start the Microsoft Single Sign-On Service MUST meet all of the following:

  • Must be a domain user account. It cannot be a group account.
    • The user must be a member of Domain Admins and Domain Users

image

  • Must be an Office SharePoint Server farm account
    • Go to Central Administration > Operations, then click on the “Update farm administrator's group” link to add the user to farm administrator group.
  • Must be a member of the local Administrators group on the encryption-key server
    • The encryption-key server is the first server on which you start SSOSrv
  • Must be a member of the Security Administrators role and Database Creators role on the computer running Microsoft SQL Server.
    • Open SQL Management Studio, go to Security > Server Roles folder, add the user to securityadmin and dbcreator server roles

Also most important setting is to MAKE SURE, the same “Single Sign-On Administrator Account” account name is used at both “Manage Server Settings for Single Sign-On” page and “Service Accounts” page as shown below:

image

Saturday, July 18, 2009

Adding Drop-Down Menu Items to SPGridView Using SPMenuField Control

When displaying custom data through SPGridView you won’t get the same look and feel of the default SharePoint List View. SPMenuField provides a data bound drop-down menu to be used in place of BoundField, TemplateField, or similar controls.

The following describe steps required to add drop-down menu items to a SPGridView control in Web Part.

  • Create a Web Part
    • Add project references: Microsoft.SharePoint and System.Web
    • Add the following namespaces to your class:

using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections.Generic;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

    • Inherits your class with Microsoft.SharePoint.WebPartPages.WebPart

public class SampleGrid : WebPart
{
}

  • Override CreateChildControls method, create the ObjectDataSource, SPGridView, SPGridViewPager and SPMenuField controls as shown below:

protected override void CreateChildControls()
{
    // Why UseDefaultStyles = false?
    // See http://sharepointmalaya.blogspot.com/2009/07/how-to-make-spgridview-to-have-same.html for details
    this.UseDefaultStyles = false;

    // ObjectDataSource
    ObjectDataSource dataSource = new ObjectDataSource();
    dataSource.ID = "dataSource";
    dataSource.SelectMethod = "SelectData";
    dataSource.TypeName = this.GetType().AssemblyQualifiedName;
    dataSource.ObjectCreating += new ObjectDataSourceObjectEventHandler(objectCreating);
    this.Controls.Add(dataSource);

    // SPGridView
    spGridView = new SPGridView();
    spGridView.ID = "spGridView";
    spGridView.DataSourceID = dataSource.ID;
    spGridView.AutoGenerateColumns = false;
    spGridView.AllowPaging = true;
    spGridView.PageSize = 10;
    spGridView.AllowSorting = true;
    spGridView.EmptyDataText = string.Empty;
    this.Controls.Add(spGridView);

    // SPGridViewPager
    pager = new SPGridViewPager();
    pager.GridViewId = spGridView.ID;
    this.Controls.Add(pager);

    // SPMenuField - Name field
    SPMenuField nameCol1 = new SPMenuField();
    nameCol1.HeaderText = "Name";
    nameCol1.TextFields = "Name";
    nameCol1.NavigateUrlFields = "Name,Email,WebSite";
    nameCol1.NavigateUrlFormat = "/_layouts/sharepointmalaya/DispDetails.aspx?WebPartID=" + this.ID + "&FilterName={0}&ReturnUrl=" + Page.Request.Url.ToString();
    nameCol1.TokenNameAndValueFields = "KEYNAME=Name,KEYEMAIL=Email,KEYWEBSITE=WebSite";
    nameCol1.SortExpression = "Name";
    nameCol1.MenuTemplateId = "menuTemplate";

    // MenuTemplate
    MenuTemplate menuTemplate = new MenuTemplate();
    menuTemplate.ID = "menuTemplate";
    this.Controls.Add(menuTemplate);
    spGridView.Columns.Add(nameCol1);

    // MenuTemplate - View Item
    MenuItemTemplate menuItemTemplate0 = new MenuItemTemplate("View Item", "~/_layouts/images/LIST.GIF");
    menuItemTemplate0.ClientOnClickNavigateUrl = "/_layouts/sharepointmalaya/DispDetails.aspx?WebPartID=" + this.ID + "&FilterName={%KEYNAME%}&ReturnUrl=" + Page.Request.Url.ToString();
    menuTemplate.Controls.Add(menuItemTemplate0);

    // MenuTemplate - Seperator
    MenuSeparatorTemplate menuSepTemplate = new MenuSeparatorTemplate();
    menuTemplate.Controls.Add(menuSepTemplate);

    // MenuTemplate - Open WebSite
    MenuItemTemplate menuItemTemplate1 = new MenuItemTemplate("Open WebSite", "~/_layouts/images/ASP16.GIF");
    menuItemTemplate1.ClientOnClickNavigateUrl = "javascript:window.open('%KEYWEBSITE%');";
    menuTemplate.Controls.Add(menuItemTemplate1);

    // MenuTemplate - Send Email
    MenuItemTemplate menuItemTemplate2 = new MenuItemTemplate("Send Email", "~/_layouts/images/EML16.GIF");
    menuItemTemplate2.ClientOnClickScript = "javascript:document.location.href='MailTo:%KEYEMAIL%;'";
    menuTemplate.Controls.Add(menuItemTemplate2);

    // BoundField - Email field
    BoundField nameCol2 = new BoundField();
    nameCol2.DataField = "Email";
    nameCol2.SortExpression = "Email";
    nameCol2.HeaderText = "Email";
    spGridView.Columns.Add(nameCol2);

    // BoundField - WebSite field
    BoundField nameCol3 = new BoundField();
    nameCol3.DataField = "WebSite";
    nameCol3.SortExpression = "WebSite";
    nameCol3.HeaderText = "WebSite";
    spGridView.Columns.Add(nameCol3);

    this.ChildControlsCreated = true;
}

  • Code above create three (3) drop-down menu items and a separator menu as shown below:

image

  • Clicking on the “View Item” redirects to custom page in the _layouts folder. When clicking on the “Open WebSite”, it opens web site and “Send Email” menu open client email form.
  • Please note SPMenuField has a property TokenNameAndValueFields which can be used to store token names and values in the following format:

SPMenuField.TokenNameAndValueFields = "KEYNAME=Name,KEYEMAIL=Email,KEYWEBSITE=WebSite";

  • To consume SPMenuField token values, you must specify token name within the % sign as shown below:

“%TOKEN_NAME%” OR “%KEYWEBSITE%”

  • As shown in code example above, ObjectDataSource control require “SelectData” method. You need to create a public method SelectData which returns a System.Data.DataTable – a dummy data which has three (3) columns which are “Name”, “Email” and “WebSite”. See below:

public DataTable SelectData()
{
    DataTable table = new DataTable();
    table.Columns.Add("Name");
    table.Columns.Add("Email");
    table.Columns.Add("WebSite");

    table.Rows.Add("SharePoint Malaya","sharepointmalaya@gmail.com","http://sharepointmalaya.blogspot.com");
    table.Rows.Add("Faris","faris@gmail.com","http://sharepointmalaya.blogspot.com");
    table.Rows.Add("Farhana","farhana@gmail.com","http://sharepointmalaya.blogspot.com");

    return table;
}

  • In addition, ObjectDataSource control implement event handler ObjectCreating – You also need to create instance containing the event data as shown below:

private void objectCreating(object sender, ObjectDataSourceEventArgs e)
{
    e.ObjectInstance = this;
}

  • Next, bind the data with the SPGridView control as shown below:

protected override void Render(HtmlTextWriter writer)
{
    if (ChildControlsCreated)
        spGridView.DataBind();
    base.Render(writer);
}

  • Build and deploy to SharePoint site. That’s it – All Done. See below for screenshot:

image

Get sample code here:

Friday, July 17, 2009

How to Make SPGridView To Have Same Look And Feel Of The Out Of The Box SharePoint List View

When you attempt to develop a Web Part that uses an SPGridView control, you’ll notice the following differences to your SPGridView look and feel compared to the out of the box SharePoint List View:

  • SPGridView font type is Verdana, out of the box SharePoint List View font type is Tahoma
  • Font size and colour different
  • No alternating styles for items
  • Header style, pager styles, etc.

Screenshot below shows the differences:

 image

If you’re good in CSS and HTML, then you’ll find CSS Reference Chart for SharePoint 2007 is helpful and you should be able to change your SPGridView styles to have the same look and feel of of the out of the box SharePoint List View.

Instead of doing above you can assign the WebPart.UseDefaultStyles of your Web Part to false. See code below:

protected override void CreateChildControls()
{
    this.UseDefaultStyles = false;

By setting the UseDefaultStyles to false, your SPGridView styles will have the same look and feel of the out of the box SharePoint List View. See screenshot below:

image

Please note that UseDefaultStyles only applicable for SharePoint Web Part and not ASP.NET Web Part – for ASP.NET Web Part please use SPChromeSettings.UseDefaultStyles.

Thursday, July 16, 2009

Validate User Base Permissions Before Uploading Document to SharePoint Document Library

If you are building a custom Web Part to upload document to SharePoint Document Library, then you need to validate user’s base permission so that unauthorised user can’t perform upload. You can’t validate based on their permission levels since at anytime base permissions of any permission level can be changed by administrator. Plus, in object model there is no specific method to get the permission level or what permission level assigned to a group or a user.

This article describes how to perform document upload to SharePoint and validate user base permissions so that only authorized users are able to perform the upload.

In SharePoint, the out-of-the-box permission level allowed user with "Contribute" permission level or higher (i.e. "Full Control", "Design", "Manage Hierarchy" and "Approve") to upload document to SharePoint. The following code displays the base permissions for each permission level:

SPSite oSite = new SPSite("http://examplesite");
SPWeb oWeb = oSite.OpenWeb();

SPRoleDefinitionBindingCollection usersRoles = oWeb.AllRolesForCurrentUser;
foreach (SPRoleDefinition roleDefinition in usersRoles)
    retVal += roleDefinition.BasePermissions.ToString() + " | ";

System.Diagnostics.Debug.WriteLine(retVal);

Full Control” permission level:

  • FullMask
  • OR SPWeb.UserIsWebAdmin = TRUE

Design” permission level:

  • ViewListItems | AddListItems | EditListItems | DeleteListItems | ApproveItems | OpenItems | ViewVersions | DeleteVersions | CancelCheckout | ManagePersonalViews | ManageLists | ViewFormPages | Open | ViewPages | AddAndCustomizePages | ApplyThemeAndBorder | ApplyStyleSheets | CreateSSCSite | BrowseDirectories | BrowseUserInfo | AddDelPrivateWebParts | UpdatePersonalWebParts | UseClientIntegration | UseRemoteAPIs | CreateAlerts | EditMyUserInfo

Manage Hierarchy” permission level:

  • ViewListItems | AddListItems | EditListItems | DeleteListItems | OpenItems | ViewVersions | DeleteVersions | CancelCheckout | ManagePersonalViews | ManageLists | ViewFormPages | Open | ViewPages | AddAndCustomizePages | ViewUsageData | CreateSSCSite | ManageSubwebs | ManagePermissions | BrowseDirectories | BrowseUserInfo | AddDelPrivateWebParts | UpdatePersonalWebParts | ManageWeb | UseClientIntegration | UseRemoteAPIs | ManageAlerts | CreateAlerts | EditMyUserInfo | EnumeratePermissions
    OR SPWeb.UserIsWebAdmin = TRUE

Approve” permission level:

  • ViewListItems | AddListItems | EditListItems | DeleteListItems | ApproveItems | OpenItems | ViewVersions | DeleteVersions | CancelCheckout | ManagePersonalViews | ViewFormPages | Open | ViewPages | CreateSSCSite | BrowseDirectories | BrowseUserInfo | AddDelPrivateWebParts | UpdatePersonalWebParts | UseClientIntegration | UseRemoteAPIs | CreateAlerts | EditMyUserInfo

Contribute” permission level:

  • ViewListItems | AddListItems | EditListItems | DeleteListItems | OpenItems | ViewVersions | DeleteVersions | ManagePersonalViews | ViewFormPages | Open | ViewPages | CreateSSCSite | BrowseDirectories | BrowseUserInfo | AddDelPrivateWebParts | UpdatePersonalWebParts | UseClientIntegration | UseRemoteAPIs | CreateAlerts | EditMyUserInfo

Read” permission level:

  • ViewListItems | OpenItems | ViewVersions | ViewFormPages | Open | ViewPages | CreateSSCSite | BrowseUserInfo | UseClientIntegration | UseRemoteAPIs | CreateAlerts

and for "Site Collection Administrator" user, base permission as follows:

  • FullMask
  • OR SPWeb.UserIsSiteAdmin= TRUE

To validate whether user access rights to upload document to SharePoint, the following conditions shall be used:

  • SPWeb.UserIsSiteAdmin = TRUE OR
  • SPWeb.UserIsWebAdmin = TRUE OR
  • AddListItems is exist OR
  • EditListItems is exist OR
  • ApproveItems is exist OR

See code below for details:

public static void IsUserBasePermissionValidToUpload(SPWeb oWeb)
{
    try
    {
        if (oWeb.Exists)
        {
            // If user is site collection administrator or admin
            if (oWeb.UserIsWebAdmin || oWeb.UserIsSiteAdmin)
                return;

            // Get roles for current user
            SPRoleDefinitionBindingCollection usersRoles = oWeb.AllRolesForCurrentUser;
            // Validate if user has rights to upload document
            foreach (SPRoleDefinition roleDefinition in usersRoles)
            {
                if (roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.FullMask.ToString())
                    || roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.AddListItems.ToString())
                    || roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.EditListItems.ToString())
                    || roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.ApproveItems.ToString()))
                    return;
            }

            // If user has invalid rights, then throw exceptions
            throw new Exception("Unauthorised to upload document to SharePoint Document Library. " +
                "You are currently signed in as: " + oWeb.CurrentUser.LoginName);
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

SPUtility.Redirect – Redirect Pages at _layouts folder, the Safest Way

When you need to redirect to pages located at _layouts folder, the safest way is to use SPUtility.Redirect method. The following are sample to redirect to settings.aspx page:

SPUtility.Redirect("settings.aspx", SPRedirectFlags.UseSource | SPRedirectFlags.RelativeToLayoutsPage, HttpContext.Context);

If you want to redirect to custom pages at _layout folder, see below:

SPUtility.Redirect("sharepointmalaya/customadminsettings.aspx", SPRedirectFlags.Static | SPRedirectFlags.RelativeToLayoutsPage | SPRedirectFlags.RelativeToLocalizedLayoutsPage, HttpContext.Current);

Details on the SPRedirectFlags enumerations can be found here.

Wednesday, July 15, 2009

How To Check If MOSS Or WSS Is Installed

There are many approaches to check if MOSS or WSS is installed at specific installation site. One of the approach is to check the Windows Registry key.

If MOSS is installed, there will be registry entries in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\12.0

image

If WSS is installed, there will be registry entries in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0

image

Please note that if MOSS is installed both registry entries as shown above will be exist at installation sites.

I’ve created a helper class SharePointConfig.cs which exposes method and properties which are useful to those who are interested use this approach. See code below:

public class SharePointConfig
{
    private const string MOSS_REGISTRY_PATH = @"SOFTWARE\Microsoft\Office Server\12.0";
    private const string MOSS_BUILD_VERSION = "BuildVersion";
    private const string MOSS_TEMPLATE_PATH = "TemplatePath";

    private const string WSS_REGISTRY_PATH = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0";
    private const string WSS_BUILD_VERSION = "BuildVersion";
    private const string WSS_TEMPLATE_PATH = "TemplatePath";
    private bool _ismossinstalled;
    private bool _iswssinstalled;
    private string _buildversion;
    private string _templatepath;

    /// <summary>
    /// Initializes a new instance of the <see cref="SharePointConfig"/> class.
    /// </summary>
    public SharePointConfig()
    {
        GetSharePointConfig();
    }

    /// <summary>
    /// Gets a value indicating whether this instance is MOSS installed.
    /// </summary>
    /// <value>
    ///     <c>true</c> if this instance is MOSS installed; otherwise, <c>false</c>.
    /// </value>
    public bool IsMOSSInstalled
    {
        get { return _ismossinstalled; }
    }

    /// <summary>
    /// Gets a value indicating whether this instance is WSS installed.
    /// </summary>
    /// <value>
    ///     <c>true</c> if this instance is WSS installed; otherwise, <c>false</c>.
    /// </value>
    public bool IsWSSInstalled
    {
        get { return _iswssinstalled; }
    }

    /// <summary>
    /// Gets the build version.
    /// </summary>
    /// <value>The build version.</value>
    public string BuildVersion
    {
        get { return _buildversion; }
    }

    /// <summary>
    /// Gets the template path.
    /// </summary>
    /// <value>The template path.</value>
    public string TemplatePath
    {
        get { return _templatepath; }
    }

    /// <summary>
    /// Loads the share point config.
    /// </summary>
    public void GetSharePointConfig()
    {
        try
        {
            // Assume current user has full rights to registry settings
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                // Get MOSS registry key
                RegistryKey theRegistry = Registry.LocalMachine.OpenSubKey(MOSS_REGISTRY_PATH);

                if (theRegistry != null)
                {
                    // Get registry values
                    _buildversion = theRegistry.GetValue(MOSS_BUILD_VERSION).ToString();
                    _templatepath = theRegistry.GetValue(MOSS_TEMPLATE_PATH).ToString();
                    _ismossinstalled = MossOrWSSIsFound();
                }
                else
                {
                    // Get WSS registry key
                    theRegistry = Registry.LocalMachine.OpenSubKey(WSS_REGISTRY_PATH);

                    if (theRegistry != null)
                    {
                        // Get registry values
                        _buildversion = theRegistry.GetValue(WSS_BUILD_VERSION).ToString();
                        _templatepath = theRegistry.GetValue(WSS_TEMPLATE_PATH).ToString();
                        _iswssinstalled = MossOrWSSIsFound();
                    }
                }

            });
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    /// <summary>
    /// Mosses the or WSS is found.
    /// </summary>
    /// <returns></returns>
    private bool MossOrWSSIsFound()
    {
        bool retVal = false;
        try
        {
            if (!string.IsNullOrEmpty(_buildversion) && !string.IsNullOrEmpty(_templatepath))
            {
                Version buildVersion = new Version(_buildversion);
                if (buildVersion.Major == 12)
                    retVal = true;
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return retVal;
    }
}

The following tables list the members exposed by the SharePointMalaya.SSOHelper.SSOConfiguration type.

Public method SharePointConfig - Initializes a new instance of the SharePointConfig class, get registry key for either MOSS or WSS.

Public method IsMOSSInstalled - Gets a value indicating whether MOSS instance is installed.

Public method IsWSSInstalled - Gets a value indicating whether WSS instance is installed.

Public method BuildVersion - Gets either MOSS or WSS build version.

Public method TemplatePath - Gets either MOSS or WSS template path.

Get source code here:

Sample Web Part

image

Tuesday, July 14, 2009

“Open tool pane” link in Web Part for SharePoint

If you want to display “Open tool pane” link in Web Part for SharePoint, just like the one displayed in the Content Editor Web Part and several others out-of-the-box Web Parts. Then add the following JavaScript code to your Web Part class:

lblErrorMessage.text = "<a href=\"javascript:MSOTlPn_ShowToolPane2Wrapper('Edit', this,'" + this.ID + "')\">Open tool pane</a>"

Get source code here:

Screenshots

  • Figure 1: Display “Open tool pane” link in the Web Part content

image

  • Figure 2: User clicked on the “Open tool pane” link

image