Search This Blog

Monday, February 28, 2011

How to enable Translation management feature on your site

To enable Translation Management Library, we are required to activate these two features on our site:

1. stsadm -o activatefeature -name TransMgmtlib -url http://abc.com/
2. stsadm -o activatefeature -name TransMgmtFunc -url http://abc.com/

Translation Management Libraries are a type of library designed for translation management. They store a version of each file in each language to which you would like to translate. They also display metadata for each document, such as status (not started, in progress, complete), who is responsible for translating it, and checked in/out status.

Best Practices while working in SharePoint Localized Environment

In this post I would like to share some of my findings that can help you while working in SharePoint Localized Environment.


1. Use SPListTemplateType while creating lists programmatically

Don’t use this line of code when creating list programmatically:
//WRONG: In SharePoint Localized Environment
Guid guid = web.Lists.Add(listName, String.Empty, web.ListTemplates["Document"]);

Simply because “Document” list template might be called “Документ” in a localized environment. Instead, better use this one:
//CORRECT: In SharePoint Localized Environment
Guid guid = web.Lists.Add(listName, String.Empty, SPListTemplateType.DocumentLibrary);



2. Use “SPBuiltInContentTypeId” enumerator

When working with build-in content types, use "SPBuiltInContentTypeId" enumerator to get them. Don’t rely on display name, in a localized environment this will not work

3. Use "SPBuiltInFieldId" enumerator for system fields:

If you want to access built-in "Title" field in a localized environment, and you do something like this:

item["Title"] = "Some title";

You may end up with this error:

System.ArgumentException: Value does not fall within the expected range.
at Microsoft.SharePoint.SPFieldCollection.GetFieldByDisplayName(String strDisplayName, Boolean bThrowException)


This is why SharePoint team gives us "SPBuiltInFieldId"
enumerator which can be used to access all built-in fields by GUID. So, the above line will look like this:

item[SPBuiltInFieldId.Title] = "Some title";


:) Happy Coding!

Associating a workflow with a content type programmatically : SharePoint 2010

One of the common requirements in sharepoint projects using workflows is to associate the workflow with a content type so that whenever an item of that content type is created/changed, the workflow starts. Quite often ,we need to do this task programmtically using features/event receivers etc.

Well, here's the code snippet which specifies how to associate the sharepoint out of the box 'Collect feedback' workflow and the 'Approval' workflow with a content type. You'll need to use the 'Microsoft.SharePoint.Workflow' namespace to be able to run this code.

    string taskListTitle = "Tasks";
    string historyListTitle = "Workflow History";
    string collectFeedbackWorkflowName = "CollectFeedbackWorkflow";
    string approvalWorkflowName = "ApprovalWorkflow";
                                                      
    SPWorkflowTemplate collectFeedbackWorkflowTemplate = null;
    SPWorkflowTemplate approvalWorkflowTemplate = null;


    //Initializing with workflow template IDs
   
    Guid collectFeedbackWorkflowTemplateID = new Guid("3bfb07cb-5c6a-4266-849b-8d6711700409");
    Guid approvalWorkflowTemplateID = new Guid("8ad4d8f0-93a7-4941-9657-cf3706f00409");

    
    //Getting workflow template based on workflow id


       foreach (SPWorkflowTemplate template in this.CurrentWeb.WorkflowTemplates)
            {
              if (template.Id.Equals(collectFeedbackWorkflowTemplateID))
                 {
                   collectFeedbackWorkflowTemplate = template;                                                                       
                 }

                if (template.Id.Equals(approvalWorkflowTemplateID))
                 {
                   approvalWorkflowTemplate = template;
                 }
            }

     //--------------------------- Create collect feedback workflow association.--------------------------------------
      
      SPWorkflowAssociation collectFeedbackWorkflowAssociation = SPWorkflowAssociation.CreateWebContentTypeAssociation(collectFeedbackWorkflowTemplate,
                                                                                       collectFeedbackWorkflowName,
                                                                                       taskListTitle,
                                                                                       historyListTitle);

     //setting to specify that workflow can be started manually

      collectFeedbackWorkflowAssociation.AllowManual = true;

     //setting to specify that manage lists permissions is required for starting a workflow
                 
      if (collectFeedbackWorkflowAssociation.AllowManual)
             {

                SPBasePermissions emptyMask = SPBasePermissions.EmptyMask;
              
                emptyMask |= SPBasePermissions.ManageLists;
               
                collectFeedbackWorkflowAssociation.PermissionsManual = emptyMask;
             }

     //setting to specify that workflow will be automatically started whenever a new item is added
       collectFeedbackWorkflowAssociation.AutoStartCreate = true;

      //setting to specify that workflow will be automatically started whenever an item is changed/edited
       collectFeedbackWorkflowAssociation.AutoStartChange = true;

    
  //Adding workflow association to content type (objContentType is an object of type SPContentType)                     
       objContentType.WorkflowAssociations.Add(collectFeedbackWorkflowAssociation);


     //--------------------------- Create approval workflow association.--------------------------------------

       SPWorkflowAssociation approvalWorkflowAssociation = SPWorkflowAssociation.CreateWebContentTypeAssociation(approvalWorkflowTemplate,
                                                                                       approvalWorkflowName,
                                                                                       taskListTitle,
                                                                                       historyListTitle);

     //setting to specify that workflow can be started manually
       approvalWorkflowAssociation.AllowManual = true;
                           
    //setting to specify that manage lists permissions is required for starting a workflow

       if (approvalWorkflowAssociation.AllowManual)
           {

              SPBasePermissions emptyMask = SPBasePermissions.EmptyMask;
           
              emptyMask |= SPBasePermissions.ManageLists;
              
              approvalWorkflowAssociation.PermissionsManual = emptyMask;
           }

    //setting to specify that workflow will be automatically started whenever a new item is added
       approvalWorkflowAssociation.AutoStartCreate = true;

    //setting to specify that workflow will be automatically started whenever an item is changed/edited
       approvalWorkflowAssociation.AutoStartChange = true;

    
    //Adding workflow association to content type (objContentType is an object of type SPContentType)            
objContentType.WorkflowAssociations.Add(approvalWorkflowAssociation);

Similar code can also be used for the custom workflow templates that we deploy.It is just that in that case we will have to specify the template name for our custom workflow that we need to associate with the content type.
                              

Creating Link Column in SPGridView

In a scenario I have to create WebPart which shows a SPGridView in which there will be a Link column which is to be binded from a list column (Single Line Text type).I have googled much for it but could not find it. Under the guidance of Sourabh Khatri I have been able to come up with a solution which helps me to achieve my aim. I divided up it in three parts

1.WebPart
2.DAL
3.Entities


FILE#1: WebPart (TestWebPart.cs) (In this file I have designed the webpart, SPGridView and supporting class to make link column)

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

namespace WebPart
{
public class TestWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
protected override void CreateChildControls()
{
BoundField objField;
SPGridView objGrid;
TemplateField objTemplateField;
Table objTable;
TableCell objTableCell;
TableRow objTableRow;

ListInfo objListInfo = ListHandler.GetAllListItems();
try
{
if (objListInfo!= null && objListInfo.DataList != null)
{
objTable = new Table();
objTableRow = new TableRow();
objTableCell = new TableCell();
objGrid = new SPGridView();

objGrid.DataSource = objListInfo.DataList;

#region Styling the Grid
objGrid.AutoGenerateColumns = false;
objTableCell.CssClass = "gridborder";
objGrid.RowStyle.CssClass = "gridrow";
objGrid.AlternatingRowStyle.CssClass = "grid_alternaterow";
objTable.Width = Unit.Percentage(100);

#endregion

#region Creating Grid Columns

objTemplateField = new TemplateField();
objTemplateField.HeaderTemplate = new
GridViewRowTemplate(DataControlRowType.Header, "ColumnHeaderName");
objTemplateField.HeaderStyle.CssClass = "header";
objTemplateField.ItemTemplate = new
GridViewRowTemplate(DataControlRowType.DataRow, "ColumnName");
objGrid.Columns.Add(objTemplateField);

// A NonLink Field
objField = new BoundField();
objField.DataField = "Description";
objField.HeaderText = "Description";
objField.HeaderStyle.CssClass = "header";
objGrid.Columns.Add(objField);

#endregion

objGrid.DataBind();

objTableCell.Controls.Add(objGrid);
objTableRow.Cells.Add(objTableCell);
objTable.Rows.Add(objTableRow);
this.Controls.Add(objTable);
}
}
catch (Exception e)
{
}
base.CreateChildControls();

}



public class GridViewRowTemplate : ITemplate
{
private DataControlRowType templateType;
private string columnName;

public GridViewRowTemplate(DataControlRowType templateType,string columnName)
{
this.columnName = columnName;
this.templateType = templateType;
}

public void InstantiateIn(System.Web.UI.Control container)
{
switch (templateType)
{
case DataControlRowType.Header:
Literal objLiteral = new Literal();
objLiteral.Text = "" + columnName + "";
container.Controls.Add(objLiteral);
break;
case DataControlRowType.DataRow:
LinkButton linkButton = new LinkButton();
linkButton.DataBinding += new EventHandler(linkButton_DataBinding);
container.Controls.Add(linkButton);
break;
}
}

void linkButton_DataBinding(object sender, EventArgs e)
{
string reportName = string.Empty;
string ListItemName = string.Empty;
LinkButton linkBtn = (LinkButton)sender;
SPGridViewRow row = (SPGridViewRow)linkBtn.NamingContainer;
ListItemName= Convert.ToString(DataBinder.Eval(row.DataItem, " ListItemName "));

linkBtn.Text = ListItemName;
linkBtn.Attributes.Add("onclick", "javascript:alert(‘”+ListItemName+ ”’);”);
}
}
}
}


FILE#2:DAL(ListHandler.cs) (In this file I have read the list content to be shown in the SPGridView)

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Text;

namespace WebPart
{
public class ListHandler
{
public static ListInfo GetAllListItems ()
{
SPWeb objWeb = null;
SPListItemCollection objItems;
ListItemsInfo objListItemInfo = null;
System.IO.FileInfo objInfo;

try
{
objWeb = SPControl.GetContextWeb(HttpContext.Current).Site.RootWeb;
if (objWeb != null)
{
objItems = objWeb.Lists.TryGetList(“ListName”).Items;
if (objItems.Count > 0)
{
objListItemInfo = new ListItemsInfo ();
foreach (SPListItem objItem in objItems)
{
objListItemInfo.ListItems.Add(new ListInfo (objItem.Name, Convert.ToString(objItem[“ColumnName”]), Convert.ToString(objItem.Title)));
}
}
}

return objListItemInfo ;
}
else
{
throw new Exception("Cannot find the Web");
}
}
catch (Exception ex)
{
throw (ex);
}
}
}
}


FILE#3: Entities (ListInfo.cs) (This file is used for creating properties)

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.SharePoint;
using System.Collections.Generic;

namespace WebPart
{
public class ListInfo
{
public string ListItemName { get; set; }
public string Description { get; set; }
public string ListItemTitle { get; set; }

public ListInfo ()
{
}

public ListInfo (string ListItemName, string Description, string ListItemTitle)
{
this.ListItemName = ListItemName;
this.Description = Description;
this.ListItemTitle = ListItemTitle;
}
}

public class ListItemsInfo
{
public ListItemsInfo()
{
ListItems = new List<>();
}
public List
ListItems
{
get;
set;
}
}
}

Change "Add new announcements" Link on Sharepoint 2010

Whenever we use any list or library like Tasks, Announcements etc, The defaut view has a link that shows as "Add new Announcement" or "Add new event" depending upon the type of list we are using. But its quite possible that in the list, you may be saving data related to News or Event.

I have written a custom javascript function that if added to the page changes the text of "Add new <announcement/event/etc>" link to  "Add new <Title of your list name>").

For this I have written a Content Editor Web Part and added it at the top of the page in  which i am showing the lists.

Add a "Content Editor Web Part" on your page and in the Source Editor, copy/Paste the javascript as given below:

<html>
<head>
<script type="text/javascript" language="javascript">
//<![CDATA[
//first load the method caller on body load
if (typeof(_spBodyOnLoadFunctionNames) != "undefined")
 {
      if (_spBodyOnLoadFunctionNames != null)
       {
        _spBodyOnLoadFunctionNames.push("changeTitle");
       }
   }

function changeTitle()
{
var replacedUrlString='';
var splittedValues ='';
var ListName ='';
try
{
var aList = document.getElementsByTagName('a'); //get all the anchor tags that are in the pageif(aList.length>0)
  {
     for(var i = 0; i < aList.length; i++)
     {
          var objAnc = aList[i];
         //get the "add new" anchor tags
          if(objAnc.className=='ms-addnew')            
            {
               //get the list title from the anchot tag url and add the text to tag's HTML               replacedUrlString = objAnc.pathname.replace('/'+objAnc.nameProp,'');
               splittedValues = replacedUrlString.split('/')
               ListName = splittedValues[splittedValues.length-1];
               objAnc.innerHTML = 'Add new ' + ListName.toLowerCase();
            }
     }
   }
}
catch(e){}
}
//]]>
</script>
</head>
</html>


Create custom navigation provider

Hi,

Sometimes we need to overwrite the existing navigation provider and write our own provider to get the data from list,db or any other third party application.This post will help you to understand how you can implement the custom navigation provider.

The implementation requires the following steps

1.) Creation of new class which should be inherited from "PortalSiteMapProvider" class.
2.) Custom provider entry in web.config file
3.) Custom provider reference in master page or user control


Create new Class inherited from "PortalSiteMapProvider"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Publishing.Navigation;
using Microsoft.SharePoint.Publishing;
using System.Web;
using Microsoft.SharePoint;
using System.Security.Permissions;
using Microsoft.SharePoint.Security;
using System.Collections;

namespace XYZ.XYZ
{
//Assign the neccessary security permissions
[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[SharePointPermissionAttribute(SecurityAction.LinkDemand, ObjectModel = true)]
[AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[SharePointPermissionAttribute(SecurityAction.InheritanceDemand, ObjectModel = true)]
public class XYZNavigationProvider : PortalSiteMapProvider
{
//Create the in memory objects for storage and fast retreival
protected SiteMapNodeCollection siteMapNodeColl;
protected ArrayList childParentRelationship;

//These are only the top level nodes that will show in the top nav
protected ArrayList topLevelNodes;
private PortalSiteMapNode rootNode = null;
SiteMapNodeCollection objNodesCollection;

/// Override the initialize method of the superclass
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
try
{
lock (this)
{
if (rootNode != null)
{
return;
}
else
{
// Verify that config isn't null
if (config == null)
throw new ArgumentNullException("config is null");

// Assign the provider a default name if it doesn't have one
if (String.IsNullOrEmpty(name))
name = Constants.NAVIGATION_PROVIDER;

// Add a default "description" attribute to config if the
// attribute doesn’t exist or is empty
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Custom navigation provider");
}

NavigationArea = Convert.ToString(config["description"]);

base.Initialize(name, config);
}
}
}
catch (Exception ex)
{
throw(ex);
}

}

public override SiteMapNode CurrentNode
{
get
{
string currentUrl = FindCurrentUrl();
// Find the SiteMapNode that represents the current page.
SiteMapNode currentNode = FindSiteMapNode(currentUrl);

if (currentNode == null)
{
return base.CurrentNode;
}

return currentNode;
}
}

public override SiteMapNodeCollection GetChildNodes(System.Web.SiteMapNode node)
{
PortalWebSiteMapNode ptlWebSiteMapNode;
SiteMapNodeCollection objSiteMapNodeCollection = default(SiteMapNodeCollection);
try
{
PortalSiteMapNode portalNode = node as PortalSiteMapNode;

if (portalNode != null && portalNode is PortalWebSiteMapNode)
{
ptlWebSiteMapNode = (PortalWebSiteMapNode)portalNode;

if (portalNode.Type == NodeTypes.Area)
{
objSiteMapNodeCollection = ComposeNodes(node, (PortalWebSiteMapNode)portalNode);
}
else
{
objSiteMapNodeCollection = base.GetChildNodes(portalNode);
}
}
else
{
objSiteMapNodeCollection = new SiteMapNodeCollection();
}

}
catch (Exception ex)
{
throw(ex);
}
objNodesCollection = objSiteMapNodeCollection;
return objSiteMapNodeCollection;

}

public virtual SiteMapNodeCollection ComposeNodes(System.Web.SiteMapNode node, PortalWebSiteMapNode ptlWebSiteMapNode)
{
object Nodes;
PortalSiteMapNode RootNode;
SPQuery objSPQuery;
String Query;
SPListItemCollection objItems;
String PageURL;
String Title = String.Empty;
SiteMapNodeCollection nodeColl = new SiteMapNodeCollection();
SPSite currentSite;
SPWeb currentWeb;
SPList objList;
bool isChangePasswordVisible = true;
//The SiteMapNodeCollection which represents the children of this node
SiteMapNodeCollection children = new SiteMapNodeCollection();
PortalSiteMapNode portalNode = node as PortalSiteMapNode;
bool IsNavigationLinkEnable;



if (Nodes != null && Nodes is SiteMapNodeCollection)
{
return ((SiteMapNodeCollection)Nodes);
}



nodeColl = new SiteMapNodeCollection();
currentSite = SPContext.Current.Site;
currentWeb = currentSite.RootWeb;
objList = currentWeb.Lists[Constants.LIST_NAVIGATIONS];

objSPQuery = new SPQuery();
Query = String.Format("{0}", NavigationArea);
objSPQuery.Query = Query;

objItems = objList.GetItems(objSPQuery);

if (objItems != null && objItems.Count > 0)
{
foreach (SPListItem objItem in objItems)
{


Title = objItem[SPBuiltInFieldId.Title]);


if (!String.IsNullOrEmpty(PageURL))
{
RootNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, PageURL, Title, Title);
}
else
{
RootNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, "#", Title, Title);
}

// Call method to get the child items
GetChildNavigations(objItem.Title, RootNode, objList, ptlWebSiteMapNode);


nodeColl.Add(RootNode);
}
}

}


return nodeColl;
}

void GetChildNavigations(string KeyTitle, PortalSiteMapNode RootNode, SPList objList,PortalWebSiteMapNode ptlWebSiteMapNode)
{
SPQuery objSPQuery;
SPListItemCollection objItems;
PortalSiteMapNode childNode;
bool isChangePasswordVisible = true;
bool IsNavigationLinkEnable;

SiteMapNodeCollection objSiteMapNodeCollection = new SiteMapNodeCollection();
objSPQuery = new SPQuery();
String Title =String.Empty;
String PageURL;

//objSPQuery.Query = String.Format("{0}", Title);
objSPQuery.Query = String.Format("{0}", KeyTitle);

objItems = objList.GetItems(objSPQuery);

if (objItems != null && objItems.Count > 0)
{
foreach (SPListItem objItem in objItems)
{
Title = Convert.ToString(objItem[SPBuiltInFieldId.Title]);

if (!String.IsNullOrEmpty(PageURL))
{
childNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, PageURL, Title, Title);
}
else
{
childNode = new PortalSiteMapNode(ptlWebSiteMapNode, Title, NodeTypes.Custom, "#", Title, Title);
}

objSiteMapNodeCollection.Add(childNode);
// Call method again (recursion) to get the child items
GetChildNavigations(objItem.Title, childNode, objList, ptlWebSiteMapNode);
}
}
}

RootNode.ChildNodes = objSiteMapNodeCollection;
}
else
{
return;
}
}




#region Supporting Methods
// Get the URL of the currently displayed page.
private string FindCurrentUrl()
{
try
{
// The current HttpContext.
HttpContext currentContext = HttpContext.Current;
if (currentContext != null)
{
return currentContext.Request.RawUrl;
}
else
{
throw new Exception("HttpContext.Current is Invalid");
}
}
catch (Exception e)
{
throw new NotSupportedException("This provider requires a valid context.", e);
}
}

// Implement the FindSiteMapNode method.
public override SiteMapNode FindSiteMapNode(string rawUrl)
{

// Does the root node match the URL?
if (RootNode.Url == rawUrl)
{
return RootNode;
}
else
{
SiteMapNode candidate = null;
// Retrieve the SiteMapNode that matches the URL.
lock (this)
{
candidate = GetNode(objNodesCollection, rawUrl);
}
return candidate;
}
}

private SiteMapNode GetNode(SiteMapNodeCollection objNodesCollection, string url)
{
SiteMapNode objInnerNode = null;

if (objNodesCollection != null)
{
foreach (SiteMapNode objNode in objNodesCollection)
{
if (objNode.Url == HttpContext.Current.Request.Url.AbsoluteUri)
return objNode;
else if (objNode.HasChildNodes && objNode.ChildNodes.Count > 0)
{
objInnerNode = GetNode(objNode.ChildNodes, url);
if (objInnerNode != null)
{
return objInnerNode;
}
}
}
}
return null;
}

#endregion
}
}

Add entry in web.config

After creating the class, add the entry of the class in web.config file of the site.
Add this entry under the sitemap->provider tag.

< siteMap defaultProvider="CurrentNavigation" enabled="true" >
< providers >
< add name="XYZNavigationProviderTop" description="Custom Provider" type="XYZ.XYZNavigationProvider, XYZ" NavigationType="Current" / >
< /provider >
< /sitemap >

Use the custom navigation provider in the master page

< publishingnavigation:portalsitemapdatasource sitemapprovider="XYZNavigationProviderLeft"
id="XYZNavSiteMap" runat="server" showstartingnode="false"/ >


Sunday, February 27, 2011

Manage Item Level Permissions Programmatically

Many times we are into a situation like we need to manage the Item Level Permissions programmatically.
Below is the code snippet by which we can manage Item Level Permissions programmatically.

            SPSite objSPSite = new SPSite("<Site URL>");
            SPWeb objSPWeb = objSPSite.OpenWeb();
            SPList oSPList = objSPWeb.Lists["<List NAme>"];

            //Create new user to grant access
            /***************************/
            SPUserCollection users = objSPWeb.Users;
            SPUser CurrentUser = users[@"SHAREPOINT\system"];
            /***************************/
             
            foreach (SPListItem objSPListItem in oSPList.Items)
            {
                //Remove all Permissions
                RemoveAllPermissions(objSPListItem);
                //Grant permissions to List Items
                AddNewPermission(objSPListItem, objSPWeb, SPRoleType.Contributor, CurrentUser);
            }

/*************************************************************************/
Function to remove all Permissions from a List Item
private static void RemoveAllPermissions(SPListItem CurrentlistItem)
        {
            CurrentlistItem.BreakRoleInheritance(true);
            SPRoleAssignmentCollection objSPRoleAssColn = CurrentlistItem.RoleAssignments;
            for (int i = objSPRoleAssColn.Count - 1; i >=0 ; i--)
            {
                objSPRoleAssColn.Remove(i);
            }          
        }

/*************************************************************************/
Function To add new permission to a List Item
       
        private static void AddNewPermission(SPListItem ListItem, SPWeb objSPWeb, SPRoleType objSPRoleType, SPPrincipal objSPPrincipal)
        {
            SPRoleDefinition objSPRoleDefinition = objSPWeb.RoleDefinitions.GetByType(objSPRoleType);
            SPRoleAssignment objSPRoleAssignment = new SPRoleAssignment(objSPPrincipal);
            objSPRoleAssignment.RoleDefinitionBindings.Add(objSPRoleDefinition);
            ListItem.RoleAssignments.Add(objSPRoleAssignment);
            ListItem.Update();
        }
    }


Friday, February 18, 2011

SharePoint Sever details through object model programming

Many a times we need to check the server details like what is the version of current sharepoint server , upgrade status, service instances running, farm details like migration status etc etc

In SharePoint 2007 we can access all these properties from a class called as

SPServer : It gives us the properties like local settings and farm settings , service instances etc


Adding WebPart Dynamically - Part-II


In a scenario we have created a CustomWebPart whose .dll is kept in the application Bin folder as per the requirement, now we have to add that webpart at runtime on the activation of a Feature,(so we cannot place that webpart dll in GAC), for this i have followed the following steps:


1.       Open the webPart gallery and click edit on your webpart.
2.      Now Click on "View Xml" .
3.  Copy that XML which looks something like:

@"<?xml version=""1.0"" encoding=""utf-8""?>
<webParts>
<webPart xmlns=""http://schemas.microsoft.com/WebPart/v3"">
<metaData>
<type name=""CustomWebPart, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=""Title"" type=""string"">CustomWebPart</property>
<property name=""ControlName"" type=""string"">ucSiteSearch.ascx</property>
</properties>
</data>
</webPart>
</webParts>
You can also add your property values as I have added my custom propety value "ControlName" in the XML.
Now the Code snippet:
SPWebPartCollection objWebPartsCollection = objWeb.GetWebPartCollection(URLPage, Microsoft.SharePoint.WebPartPages.Storage.Shared);
string dwp = @"<?xml version=""1.0"" encoding=""utf-8""?>
<webParts>
<webPart xmlns=""http://schemas.microsoft.com/WebPart/v3"">
<metaData>
<type name=""CustomWebPart, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=""Title"" type=""string"">CustomWebPart</property>
<property name=""ControlName"" type=""string"">ucSiteSearch.ascx</property>
</properties>
</data>
</webPart>
</webParts>";

objWebPartsCollection.Add(dwp);


Nice way to store values at web application and web levels

I came across a nice way to store values at the web application and web levels for whatever needs you may have. In my case I need to store some global settings. To do this I was storing those in a list and when using those in application it was a long process. So after discovering these available property bags I was interested in trying to store existing values there.

SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent;
webApp.Properties.Add("Rule", "{FileName}");

// reference property later
string rule = webApp.Properties["Rule"];

Similarly you can use SPWeb property bags.

Thanks

Creating User Custom Actions through Code

In one of our projects, the requirement was to create an ECB menu item on list only if its configured by administrator from a custom web part (a custom web part with check boxes to determine whether an ECB is required or not). We accomplished it through custom code using client object modal.
by creating an object of UserCustomAction and assigning properties to it.
The UserCustomAction property returns the collection of custom actions for a site collection, Web site, list ot content Types. So this means that you can assign custom action to any of these.

In the below example, I am adding a user custom action for list items.
To place the new action on the menu (the one which is displayed when you hover on a list item and click to view the ECB), the Location property specifies EditControlBlock (ECB), Sequence specifies the order of placement in relation to other user custom actions, and Url specifies an absolute path to a page that defines the action.

using System;
using Microsoft.SharePoint.Client;
namespace MyCustomAction
{
    class CreateUserCustomActionList
    {
        static void Main()
        {
            String strSiteUrl = "http://mysharepointsite/";
            ClientContext clientContext = new ClientContext(strSiteUrl);
            Web objWeb = clientContext.Web;
            List objList = objWeb.Lists.GetByTitle("Demo List");
            UserCustomActionCollection collUserCustomAction = objList .UserCustomActions;
            UserCustomAction objUserCustomAction= collUserCustomAction.Add();
            objUserCustomAction.Location = "EditControlBlock";
            objUserCustomAction.Sequence = 100;
            objUserCustomAction.Title = "Demo User Custom Action";
            objUserCustomAction.Url = strSiteUrl + @"/_layouts/DemoPage.aspx";
            objUserCustomAction.Update();
            clientContext.Load(objList,
                list => list.UserCustomActions);
            clientContext.ExecuteQuery();
        }
    }
}

Replicating dependent lookup columns for a lookup column:SharePoint 2010

As we know , Dependent lookup columns is a new feature introduced in sharepoint 2010 to include other columns like Title, ID,Version,created,modified along with your lookup column etc. 

Once a lookup column with these dependent lookup columns is associated with a document library/list, they appear as shown in the screenshot.



Recently, we came across a requirement of replicating a lookup column's dependent lookup columns on another site.
The way we accomplished this is by
-storing all the dependent lookup columns for a lookup column in xml, and then,
-creating the lookup column and its dependent lookup columns on the other site from the xml.

The xml can be constructed by fetching all dependent lookup columns for a lookup column using the
GetDependentLookupInternalNames() method.

 SPFieldLookup changedSpFieldLookup = changedSpField as SPFieldLookup;                   
 List<string> dependentlookupNames=changedSpFieldLookup.GetDependentLookupInternalNames();
 //....construct the xml using the lookup names retrieved in 'dependentlookupNames'...

Once, this is done ,the xml that we constructed looks like this:

<AdditionalColumnConfiguration>
      <ColumnConfigData>           
          <DependentLookupColumnNames>
             <DependentLookupColumnName Key="Title">Title</DependentLookupColumnName>
             <DependentLookupColumnName Key="ID">ID</DependentLookupColumnName>
          </DependentLookupColumnNames>
      </ColumnConfigData>
</AdditionalColumnConfiguration>


Once this was done, in order to replicate the same settings on another site, we created a new lookup field and added the dependent lookup columns by parsing this xml.The method 'CreateDependentLookUpColumns' does this:

Here 'spPrimaryField' is the new lookup field with which the dependent lookups are to be associated.
'objSPContentType' is the content type in which spPrimaryField has already been added
'additionalConfigXml' is having the xml string specified above.

 private void CreateDependentLookUpColumns(SPFieldLookup spPrimaryField, string additionalConfigXml, SPContentType objSPContentType)
        {
            XmlDocument objAdditionalConfigXmlDoc = new XmlDocument();
            objAdditionalConfigXmlDoc.LoadXml(additionalConfigXml);

            XmlNode additionalConfigXmlNode = null;
            XmlNode configDataNode = null;
            XmlNode dependentColumnsNode = null;
            Boolean dependentColumnsExist = false;

            if (objAdditionalConfigXmlDoc != null)
            {
                additionalConfigXmlNode = objAdditionalConfigXmlDoc.DocumentElement;

                if (additionalConfigXmlNode != null)
                {
                    if (additionalConfigXmlNode.HasChildNodes)
                    {
                        configDataNode = additionalConfigXmlNode.SelectSingleNode("child::*[name()='ColumnConfigData']");

                        if (configDataNode != null)
                        {
                            dependentColumnsNode = configDataNode.SelectSingleNode("child::*[name()='DependentLookupColumnNames']");

                            if (dependentColumnsNode != null)
                            {
                                if (dependentColumnsNode.HasChildNodes)
                                {
                                    dependentColumnsExist = true;
                                }

                            }
                        }

                    }
                }
            }
            if (spPrimaryField != null && dependentColumnsExist)
            {
                if (!spPrimaryField.IsDependentLookup)
                {
                    foreach (XmlNode dependentColumnNode in dependentColumnsNode.ChildNodes)
                    {
                        string strDepColName = dependentColumnNode.InnerText;

                        if (!string.IsNullOrEmpty(strDepColName))
                        {
                            strDepColName = SPHttpUtility.HtmlDecode(strDepColName, true);
                        }

                        string displayName = spPrimaryField.Title + ":" + strDepColName;
                        if (displayName.Length > 255)
                        {
                            displayName = displayName.Substring(0, 255);
                        }

                        SPFieldLookup field = (SPFieldLookup)this.CurrentWeb.Fields.CreateNewField(SPFieldType.Lookup.ToString(), displayName);
                        if (field == null)
                        {
                            continue;
                        }

                        field.LookupList = spPrimaryField.LookupList;
                        field.LookupWebId = spPrimaryField.LookupWebId;
                        field.LookupField = dependentColumnNode.Attributes.GetNamedItem("Key").Value;
                        field.PrimaryFieldId = spPrimaryField.Id.ToString();
                        field.ReadOnlyField = true;
                        field.AllowMultipleValues = spPrimaryField.AllowMultipleValues;
                        field.UnlimitedLengthInDocumentLibrary = spPrimaryField.UnlimitedLengthInDocumentLibrary;

                        if (this.CurrentWeb.RegionalSettings.IsRightToLeft)
                        {
                            field.Direction = spPrimaryField.Direction;
                        }

                        field.Group = spPrimaryField.Group;
                        string strName = this.CurrentWeb.Fields.Add(field);
                        if (objSPContentType != null)
                        {
                            objSPContentType.FieldLinks.Add(new SPFieldLink(this.CurrentWeb.Fields.GetFieldByInternalName(strName)));
                            objSPContentType.Update();
                        }

                    }
                }


            }
        }

SharePoint Upgrdation from 2007 to 2010

Hi,

If you are working on SharePoint up-gradation from 2007 to 2010, this post will help to analyse the points, which you should keep in mind during the up gradation or for estimating up-gradation effort.

1) Analyses of the existing environment : The PreScan tool, will help you to analyse the existing environment.Run this tool on the existing environment and analyse the report given by tool.This report will help you to find out all the issues, needs to be fixed before starting the actual migration.

2) Analysis of the existing code : If the current application is customized and using the SharePoint API's, make sure that all the API's supported by new version also.

3) Analysis of the existing branding : If the current application is using the customized branding, take the relevant estimate for the upgrading of the customize branding on new version. In the SharePoint 2010, master page structure is completely different then MOSS, which will force you to re-write the whole customization from the scratch.

4) Migration Approach : SharePoint supports two approaches for the migration, 1) database migration 2) In place migration. you will get more details for this on http://technet.microsoft.com/en-us/library/cc263447.aspx
. Before going ahead, make sure that, the approach you are finalizing, should fulfill all the requirements.

5) General Farm settings configuration : You should consider the estimation for applying the general farm level settings in new environment available in the SharePoint 2007 environment like email settings, blocked file settings. In SharePoint 2010, few new settings also introduced by Microsoft (like health data collection, diagnostic logging, and mobile accounts) , consider the efforts for the configuration of these settings also .

6) SSP up-gradation : In the SharePoint 2010, Shared service provider has been changed by new service architecture.Link http://technet.microsoft.com/en-us/library/ee731990.aspx#Considerations will help you to analyse the up-gradation approach.

7) Web Configuration Changes : If the custom entries are defined in the application’s web.configuration file, these entries needs to be migrate on the SharePoint 2010 environment. This process requires manually identifying the entries available in the existing configuration files and moving them on new version.

Hope this post will help you in the up-gradation process.

Sourabh Khatri.