Friday, August 28, 2009

Get WorkFlow Task Item from List Item Id

 

        public static SPListItem WorkflowTaskItemBasedOnListItem(SPWeb web, string listName, string workflowTaskListName, int itemId)
        {
            SPListItem workflowItem = null;
            SPList workflowTasks = web.Lists[workflowTaskListName];
            SPList mainList = web.Lists[listName];
            SPListItem listItem = mainList.GetItemById(Convert.ToInt32(itemId));
            SPWorkflowFilter filter = new SPWorkflowFilter();
            filter.InclusiveFilterStates = SPWorkflowState.Running;
            // Get a list of workflow tasks associated with current Item
            SPWorkflowTaskCollection workTaskColl = web.Site.WorkflowManager.GetItemTasks(listItem, filter);
            foreach (SPWorkflowTask task in workTaskColl)
            {
                if (task != null)
                {
                    workflowItem = workflowTasks.GetItemById(task.ID);
                    break;
                }
            }

            return workflowItem;
        }

 

This function returns a workflow item based on Parent List item Id. It reads the List Item and finds the associated workflow which are still running against this list item.

Type 'Microsoft.SharePoint.SPUser' in Assembly 'Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' is not marked as serializable. Type 'Microsoft.SharePoint.SPUser' in Assembly

Make sure you are not storing any object of SPUser type in Session on ViewState. I was getting this error SPUser was persist in ViewState. We changed the logic to store LoginName and everything worked fine

The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again

Recently, I was getting this error when non-admin were trying to alter a workflow task. My code was running under elevated permission using the option first as described in my last post(using SharePoint\System) user

To fix, I need to run the code under elevated permission using second option as described in my last post(RunWithElevatedPrivileges)


    string siteURL = SPContext.Current.Site.Url;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        SPSite objSite = new SPSite(siteURL);
        SPWeb web= objSite.OpenWeb();

        web.AllowUnsafeUpdates = true;

        Hashtable taskHash = new Hashtable();
        SPListItem item = null;
        item["Status"] = "Completed";
        SPWorkflowTask.AlterTask(item, taskHash, false);
        web.AllowUnsafeUpdates = false;
    });

Running Code with Elevated Permissions

 

There are 2 ways to run code under elevated permissions. The first one is using the token created from SharePoint\System(internal user) user

public static SPWeb GetElevatedWeb
        {
            get
            {
                var superUser = SPContext.Current.Web.AllUsers[@"SHAREPOINT\SYSTEM"];
                var superToken = superUser.UserToken;
                using (var site = new SPSite(SPContext.Current.Web.Url, superToken))
                {
                    return site.RootWeb;
                }
            }
        }

This function returns a SPWeb object which is created using elevated permissions

The second method is using SPSecurity.RunWithElevatedPrivileges

public static SPWeb GetSPElevatedWeb
        {
            get
            {
                SPWeb web = null;
                string siteURL = SPContext.Current.Site.Url;
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPSite objSite = new SPSite(siteURL);
                    web = objSite.OpenWeb();
                });
                return web;
            }
        }

The SPSite object is created by reading the SPContext object before calling RunWithElevatedPrivileges as the context will change in the code block

Monday, August 03, 2009

Create custom groups in SharePoint

To create custom groups in SharePoint, use the SPWeb SiteGroups collection.

web.SiteGroups.Add(groupName, owner, member, description)

Groups created using code will not automatically appear in left navigation. For them to appear there, the groups need to be associated with web. The code to this is

web.Properties["vti_associategroups"] = web.Properties["vti_associategroups"] + “;” +  web.SiteGroups[groupName].ID.ToString();

web.Properties.Update();

Function to read List Item Id based on task

taskListItemId = id of task item

web = Web object

SPListItem taskItem = taskList.GetItemById(taskListItemId);
Guid workflowInstanceId = new Guid((string)taskItem["WorkflowInstanceID"]);
SPWorkflow workflowInstance = new SPWorkflow(web, workflowInstanceId);
SPList itemList = workflowInstance.ParentList;
SPListItem parentListItemId = itemList.GetItemById(workflowInstance.ItemId);

Other way of getting Elevated Web

SPUser superUser = SPContext.Current.Web.AllUsers[@"SHAREPOINT\SYSTEM"];
string superToken = superUser.UserToken;
using (var site = new SPSite(SPContext.Current.Web.Url, superToken))

      return site.RootWeb; 
}

This function would return a web object running under the super user “SharePoint\System” (inbuilt) account

Retrieve the attachments of List Item

To retrieve the attachment, access the folder object of the item and then read the files

SPFolder folder = Web.Folders["Lists"].SubFolders[listName];

folder = folder.SubFolders["Attachments"].SubFolders[itemNo];
foreach (SPFile file in folder.Files)
{
}

Read AD SPUser in SharePoint

Web object’s AllUsers property returns user which have accessed the site. To validate a user which has never existed on the site use

Web.EnsureUser(strUserLogin);

Add\remove Quick launch link

       Add a quick launch link group

     public static void AddQuickLaunchGroup(SPWeb web, string groupName)
        {
            SPNavigationNodeCollection quickLaunchNodes = web.Navigation.QuickLaunch;
            SPNavigationNode groupMenu = new SPNavigationNode(groupName, "", false);
            quickLaunchNodes.AddAsFirst(groupMenu);
            web.Update();
        }

        Remove quick link group-

        public static void RemoveQuickLaunchGroup(SPWeb web, string groupName)
        {
            SPNavigationNodeCollection quickLaunchNodes = web.Navigation.QuickLaunch;
            foreach (SPNavigationNode node in quickLaunchNodes)
            {
                if (string.Compare(node.Title, groupName) == 0)
                {
                    quickLaunchNodes.Delete(node);
                    web.Update();
                    break;
                }
            }
        }

        Add Quick launch link to a group-


        public static void AddQuickLaunchLink(SPWeb web, string groupName, string linkName, string linkUrl)
        {
            SPNavigationNodeCollection quickLaunchNodes = web.Navigation.QuickLaunch;
            foreach (SPNavigationNode node in quickLaunchNodes)
            {
                if (string.Compare(node.Title, groupName) == 0)
                {
                    SPNavigationNode linkNode = new SPNavigationNode(linkName, linkUrl, true);
                    node.Children.AddAsFirst(linkNode);
                    web.Update();
                    break;
                }
            }
        }

        Remove quick launch link from a group-


        public static void RemoveQuickLaunchLink(SPWeb web, string groupName, string linkName)
        {
            SPNavigationNodeCollection quickLaunchNodes = web.Navigation.QuickLaunch;
            foreach (SPNavigationNode node in quickLaunchNodes)
            {
                if (string.Compare(node.Title, groupName) == 0)
                {
                    foreach (SPNavigationNode nodeChild in quickLaunchNodes)
                    {
                        if (string.Compare(nodeChild.Title, linkName) == 0)
                        {
                            node.Children.Delete(nodeChild);
                            web.Update();
                            break;
                        }
                    }
                }
            }
        }

Add field to default view in SharePoint List

SPView view = list.DefaultView;
view.ViewFields.Add(fieldName);
view.Update();

Create a Lookup field in SharePoint list

/// <summary>
/// Adds the lookup field to list.
/// </summary>
/// <param name="web">The web.</param>
/// <param name="list">The list.</param>
/// <param name="fieldName">Name of the field.</param>
/// <param name="lookupListName">Name of the lookup list.</param>
/// <param name="lookupFieldName">Name of the lookup field.</param>

SPField AddLookupFieldToList(SPWeb web, SPList list, string fieldName, string lookupListName, string lookupFieldName)
        {
            SPList destList = web.Lists[lookupListName];
            list.Fields.AddLookup(fieldName, destList.ID, required);
            SPFieldLookup field = list.Fields[fieldName] as SPFieldLookup;
            field.LookupField = destList.Fields[lookupFieldName].InternalName;
            field.Update(true);
            return field;
        }

Create a User field in SharePoint List

SPList list;

list.Fields.Add(fieldName, SPFieldType.User, required);
SPFieldUser field = list.Fields[fieldName] as SPFieldUser;
field.SelectionMode = SPFieldUserSelectionMode.PeopleOnly;
field.AllowMultipleValues = false;
field.Presence = true;
field.Update(true);

Tuesday, June 23, 2009

The selection of directory service properties is disabled because the portal is in an untrusted domain

In User Profile, I was unable to modify any user property mapping due to missing Data Source field dropdown. There was no question of untrusted domain as I am using only one active directory and SharePoint was able to import from that. I finally managed to fix these by following these steps:

  • Goto to Profile and Import Settings
  • Click View Import Connections
  • Click on Existing Import Connection and select edit
  • In Authentication Information section, make sure the account is SharePoint Admin Domain account and not the default account
  • Click Ok and you should now able to see mapping data source drop down

Tuesday, April 07, 2009

Delete a Web Part in SharePoint

If you are planning to remove a web part from a page, ALWAYS click on Delete menu rather than pressing the X button. Clicking on X button would close the web part and you will receive a warning in your servers event log. The web part is not actually deleted from the page, it is removed from the Visible area of the page and placed in the Web Part Page Gallery.

You can delete a CLOSED web part  by using the Web Part Maintenance page. Browse to http://www.yourserver.com/yoursite/yourpage.aspx?contents=1

You could see the web part that has been closed. Now, delete it by selecting the checkbox and pressing Delete

Accessing Current User in MOSS

You could get the current user in SharePoint by calling the following code:

SPUser user = SPContext.Current.Web.CurrentUser;

But to access the current user inside the code running under Elevated Privileges, open new reference to SPSite.

SPSecurity.RunWithElevatedPrivileges(delegate()

{
    using (SPSite site = new SPSite(“http:\\MOSS_SITE”))

{
      using (SPWeb web = site.OpenWeb())

          SPUser user =SPContext.Current.Web.CurrentUser;

    }

}
);

The above code will switch the user context and now, you would get the user under which application pool is running

Mystery of SharePoint\System Account

When you run your code with Elevated Privileges, the code runs under the identity of the hosting application pool. SharePoint\System account exists ONLY within content of SharePoint runtime(not recognised by Windows Security subsystem) and map internally to the account under which application pool is running.

If you are running application pool under DOMAIN\SSUSER account, the code is still audited as running under SharePoint\System account. So, if you get access error on SharePoint site stating that SharePoint\System account don’t have access to the resource, this is because the application pool identity account don’t have access to the resource. Don’t spend time looking for SharePoint\System account :-)

Friday, April 03, 2009

Set Manager Profile property value

To assign manager from one profile to another, you could not set it directly. You need to convert the Source Manager profile to a UserProfile object and then assign the account name to the destination profile manager’s property.

UserProfileManager upManager;
UserProfile sourceProfile,
destProfile;

string managerId = sourceProfile["manager"].Value.ToString();

if (upManager.UserExists(managerId))

{

UserProfile managerProfile = upManager.GetUserProfile(managerId);

destProfile["manager"].Value = managerProfile["Accountname"].Value;

}

Tuesday, March 31, 2009

Change the Regional Setting of Site

You could change the regional setting of the site by browsing to Site Actions > Site Settings > Regional Settingsimage

You could also change the Locale using the following code:

using (SPSite site = new SPSite("http://SITE"))
{
    using (SPWeb web = site.OpenWeb())
    {
        SPRegionalSettings newRegionalSettings = new SPRegionalSettings(web);

        // Change to Australia
        newRegionalSettings.LocaleId = 3081; 
        web.RegionalSettings = newRegionalSettings;
        web.Update();
    }
}

Friday, March 27, 2009

In-Line Script in SharePoint Page

You could add in-line script to a SharePoint page or Page template.

<asp:Content ID="main" runat="server"  ContentPlaceHolderID="PlaceHolderMain">
<% Response.Write("Hello Sanjay Sansanwal"); %>
</asp:Content>

You would able to access this page without error provided this page is ghosted(uncustomised) as WSS complies a ghosted page into an assembly DLL for processing.

But if you customise this page or open in SharePoint,  SharePoint safe mode don’t allow this and you would get error “Code blocks are not allowed in this file”.

You could force SharePoint to allow in-line scripts in customised pages by adding following to the web.config

<SharePoint>
  <SafeMode ... >
    <PageParserPaths>
      <PageParserPath
          VirtualPath="/Study/CustomPages/*"
          IncludeSubFolders="true"
          CompilationMode="Always"
          AllowServerSideScript="true" />
    </PageParserPaths>
  </SafeMode>
</SharePoint>

Note: You should avoid doing this as it compromise SharePoint security. In-Line scripts are not allowed in customised pages so that unwanted user could not write malicious code to hack the system.