Archive for June, 2010

06/29/10
Fahad Zia
tags:  

Add Web Parts to EditForm.aspx, DispForm.aspx or NewForm.aspx


add &toolpaneview=2 in the page query of EditForm.aspx, DispForm.aspx or NewForm.aspx


Fahad Zia

SharePoint Web Part Maintenance Page URL


Its time consuming to manually delete closed webparts on a page esp if there are more than 40(yes some user created these webparts and instead of deleting them closed them). So a quick way to do this is appending ?contents=1 after the .aspx in the url

06/28/10
Fahad Zia

Add Auditing policy to SharePoint Content Type Programmatically


Add Microsoft.Office.Policy.dll reference to the project. This file is found in “ISAPI” folder in 12 hive.

public static void AddAuditingPolicy(SPWeb web)
{
    //check if content type has a policy (any container can have at the most 1 policy assigned)
    //if not create new policy
    string strFeatureID = "Microsoft.Office.RecordsManagement.PolicyFeatures.PolicyAudit";
    SPList list = web.Lists[Helper.ListNames.NCR.ToString()];
    SPContentType listctype = list.ContentTypes[Helper.PREFIX];
    Policy policyAudit = Policy.GetPolicy(listctype);
    if (policyAudit == null)
    {
        Policy.CreatePolicy(listctype, null);
        policyAudit = Policy.GetPolicy(listctype);
        policyAudit.Name = string.Format("{0} Audit Policy", Helper.PREFIX);
        policyAudit.Statement = string.Format("Audits Edit/Delete/Restore {0} items",Helper.PREFIX);
        policyAudit.Description = policyAudit.Statement;
        if (policyAudit.Items[strFeatureID] == null)
        {
            string strCustomData = "<Audit><Update /><DeleteRestore /></Audit>";
            policyAudit.Items.Add(strFeatureID, strCustomData);
        }
    }
}

References:
http://msdn.microsoft.com/en-us/library/ms499244.aspx
http://knrs.blogspot.com/2007/12/sharepoint-create-expiration-policy.html
http://vspug.com/smc750/2007/07/09/making-your-sharepoint-applications-information-management-policy-aware/

06/25/10
Fahad Zia

Create SharePoint Permission Levels Programmatically


I recently used the following code to create permissions levels to SPWeb:

public static void CreatePermissionLevels(SPWeb web)
{
    SPRoleDefinition rd = new SPRoleDefinition();
    string[] strarrRoleDefName = { "Add Only", 
                                   "No Delete", 
                                   "Modify Only" };
    string[] strarrRoleDesc = {"This lets user to only add list items",
                               "This lets user to add/modify list items but not delete them",
                               "This lets user to only modify list items"};
    for (int i = 0; i < strarrRoleDefName.Length; i++)
    {
        if (!SPRoleDefinitionExists(web, strarrRoleDefName[i]))
        {
            switch (strarrRoleDefName[i].ToLower())
            {
                case add only":
                    rd.BasePermissions = SPBasePermissions.AddListItems |
                             SPBasePermissions.ViewFormPages |
                             SPBasePermissions.ViewListItems |
                             SPBasePermissions.ViewPages |
                             SPBasePermissions.Open;
                    break;
                case "no delete":
                    rd.BasePermissions = SPBasePermissions.AddListItems |
                             SPBasePermissions.ViewListItems |
                             SPBasePermissions.EditListItems |
                             SPBasePermissions.ViewFormPages |
                             SPBasePermissions.ViewPages |
                             SPBasePermissions.Open;
                    break;
                case "modify only":
                    rd.BasePermissions = SPBasePermissions.ViewListItems |
                             SPBasePermissions.EditListItems |
                             SPBasePermissions.ViewFormPages |
                             SPBasePermissions.ViewPages |
                             SPBasePermissions.Open;
                    break;
            }
            rd.Name = strarrRoleDefName[i];
            rd.Description = strarrRoleDesc[i];
            web.RoleDefinitions.Add(rd);
            web.Update();
        }
    }

}

//The following function code is taken from: http://vspug.com/michael/2009/05/15/how-to-overcome-missing-exists-function-on-sharepoint-objects-like-sitegroups-roledefinitions-lists-etc/
public static bool SPRoleDefinitionExists(SPWeb web, string roleName)
{
    XPathDocument doc = new XPathDocument(new StringReader(web.RoleDefinitions.Xml));
    if (null == doc.CreateNavigator().SelectSingleNode("//Role[@Name='" + roleName + "']"))
        return false;
    return true;
}
06/10/10
Fahad Zia

Upgrading/Versioning SharePoint Workflow Solution


Upgrading SharePoint workflow is simple, run stsadm- upgradesolution command like any other solution in SharePoint. However you need to know that it can affect existing in progress workflows. I learned it the hard way. Here is what happened, I developed a workflow using Visual Studio and deployed to production after testing. Now after a few weeks I was asked to fix some bugs and add some minor functionality to it. I did that in a few hours, tested and then deployed to production. All the newly created workflows worked fine but “some” of the in progress workflows’ tasks started throwing out “This task is curently locked by a runnign workflow and cannot be edited”. Googling this error pointed to some interesting articles on what causes it. From what i read the root cause is that the SPListItem[SPBuiltInFieldId.WorkflowVersion]!=1, this article seems to solve it by programmatically making it equal to 1 as can be seen here:
http://geek.hubkey.com/2007/09/locked-workflow.html

I tried it but it didnt work for me, although the WorkflowVersion was equal to 1 after running the code mentioned.

Googled more and came across this article which explained it a bit more :
http://blogs.code-counsel.net/Wouter/Lists/Posts/Post.aspx?List=c04a88a9%2Dd138%2D4ac3%2Da2bb%2Db95c9fdd114e&ID=118

Similar articles on this topic leads me to believe that this error is caused by de-serialization of a workflow that has been saved in the database. Since this in progress workflow was created by the older dll/code which is serialized when hydarting the workflow, when the user tries to update the task it deserializes this workflow but since the code has been updated its not able to do it and hence think the current action is not perfomed by the workflow that serialized this orginally.

So if you want to update workflows in the future you have the following options:
1. Terminate in progress workflows and start again
2. Let in progress workflows to complete before upgrading solution
3. Version your workflows manually by changing the GUID and changing its name , lets say “_v2” etc. So basically making a new workflow with a different name and attach to the list. Also making sure that the existing workflow is allowed to complete which can be done by going to “List Settings”->Workflow Settings->”Allow New Instances” set to “No”. I see something similar used by Nintex if you ever update the workflow from GUI you will versions of workflow automatically set to not allow new instances of pervious workflows.

Realted Articles:

http://geekswithblogs.net/MTex/archive/2008/03/01/120117.aspx
http://geek.hubkey.com/2007/09/locked-workflow.html
http://blogs.code-counsel.net/Wouter/Lists/Posts/Post.aspx?List=c04a88a9%2Dd138%2D4ac3%2Da2bb%2Db95c9fdd114e&ID=118

06/03/10
Fahad Zia

iTextSharp Image Resize


I have been using iTextSharp to export SPListItem to PDF. This item also has picture URL to show in PDFs. Everything worked fine except when I tried to put an image inside table cell, the image will resize itself to fill the cell(this is by design). And if the picture is big in dimensions it would cover tthe whole page with picture. I tried using various methods included in iTextSharp.text.Image object but the result was still not what i wanted. So i ended up using ScaleAbsolute with dimensions that i find using .NET code.
Here is the code that resizes the picture in memory and uses its dimensions in iTextSharp.text.Image.ScaleAbsolute :

Document pDoc = new Document(PageSize.A4, 30, 30, 40, 5);
using (Stream streamMainPic = GetPictureStream(list, strMainPicture))
{
    if (streamMainPic != null)
    {
        iTextSharp.text.Image imgMain = iTextSharp.text.Image.GetInstance(streamMainPic);
        imgMain.Border = 0;                                
        imgMain.SetAbsolutePosition(pDoc.Left + 145, pDoc.Top - 300);

        //Resize picture to fit 380x150 ratio if its bigger
        int intMaxWidth = 380;
        int intMaxHeight = 150;
        using (Stream streamMain2 = GetPictureStream(list, strMainPicture))
        {
            Bitmap bmpMain = new Bitmap(streamMain2);
            if (bmpMain.Height > intMaxHeight || bmpMain.Width > intMaxWidth)
            {
                double dblHeightRatio = Convert.ToDouble(intMaxHeight) / Convert.ToDouble(bmpMain.Height);
                double dblWidthRatio = Convert.ToDouble(intMaxWidth) / Convert.ToDouble(bmpMain.Width);
                double dblScaleRatio;

                //Use the smaller ratio
                if (dblHeightRatio > dblWidthRatio)
                {
                    dblScaleRatio = dblWidthRatio;
                }
                else
                {
                    dblScaleRatio = dblHeightRatio;
                }

                int intNewHeight = Convert.ToInt32(bmpMain.Height * dblScaleRatio);
                int intNewWidth = Convert.ToInt32(bmpMain.Width * dblScaleRatio);

                imgMain.ScaleAbsolute((float)intNewWidth,
                                       (float)intNewHeight);
            }
        }
        pDoc.Add(imgMain);
    }
    }
private static Stream GetPictureStream(SPList list, string strMainPicture)
        {
            Stream stream1;
            try
            {
                WebRequest reqImg = WebRequest.Create(new Uri(strMainPicture.Replace("../..", list.ParentWeb.Url)));
                reqImg.UseDefaultCredentials = true;
                WebResponse img = reqImg.GetResponse();
                StreamReader reader = new StreamReader(img.GetResponseStream());
                stream1 = reader.BaseStream;
            }
            catch (Exception ex)
            {
                stream1 = null;
            }
            return stream1;
        }