Show or Hide Ribbon control based on Group Permission

In one of our releases, we came across a requirement to show or hide one of our custom button on ribbon control, based on the groups in which the logged in user is added.

To know, how to add a button on Ribbon control, refer – Adding a button on Ribbon

1. Add a class which will have code for the hiding the button. Lets say, we named the class as “ButtonShowHideDelegate

1. Add a delegate control to the solution from the installed templates as shown below-

Delegate option in Sharepoint Installed templates

Delegate option in Sharepoint Installed templates

2. A settings page will popup for configuring the Delegate Control as shown below –

DelegateControlSettingsClick on the Next button, and then Finish.

3. Open  the “Elements.xml” file and set the value for various properties as shown below –

elements.xmlDescription of above properties,

  • “Id” is the control of MasterPage  which we are replacing using our delegate control.
  • “Sequence” is the sequence set for control, set the value to any value below 100
  • “ControlAssembly” is the full name of the assembly along with the version and PublicKeyToken. You can get the PublicKeyToken from the assembly.
  • “ControlClass” is the class which will host the code to hide button

4. Below is the code to show/hide button on ribbon control based on the users permission

DelegateOnLoadDescription of the above code –

  • OnLoad” event – We have placed our code in this event so as to execute it while page is loading
  • The first “If” condition checks if the current URL is for the list for which we intend to apply the Show/Hide logic.
  • We take the collection of groups for which the current logged in user is a part of.
  • The LINQ statement checks if “sftp Owners” is one out of many groups of the users.
  • If user is not part of “sftp Owners” group, the custom button on ribbon is hidden for the user.

The above step takes care of the coding part of this requirement.

5. The only thing remaining now is adding this .dll to the SafeControls listSafeControlEntryAdd the “dll” to the SafeControl list as shown above. Please note the Safe Controls flag is set to Yes in the above screenshot.

After all the above steps, your delegate control is ready for deployment.

 

 

Adding a button on Ribbon Control of SharePoint site

In this post we shall go through code to add a button on the Sharepoint Ribbon Control. As many of you are aware, Microsoft has introduced ribbon control in Sharepoint 2010. Having introduced it, Microsoft also allows user to customize the ribbon control with activities like adding a button, a group, a tab etc.

So below is the code to add a button on ribbon control through code.

1.Event Receiver Code

Create a Sharepoint Feature and write the below code in the FeatureActivated event of Event Receive.

———————————————————————————————–

elevatedWeb.AllowUnsafeUpdates = true;
SPList list = elevatedWeb.Lists[“CustDocLib“];

//Creating Object for User CustomAction
SPUserCustomAction userCustomAction = list.UserCustomActions.Add();
userCustomAction.Title = “Execute Upload“;
userCustomAction.Name = “ExecuteUpload“;
userCustomAction.Location = “CommandUI.Ribbon“;
userCustomAction.CommandUIExtension = @”<CommandUIExtension><CommandUIDefinitions>
<CommandUIDefinition Location=’Ribbon.Documents.Manage.Controls._children’>
<Button Id=’Ribbon.Documents.Manage.Upload’ Sequence=’101′ TemplateAlias=’o1′
Image16by16=’_layouts/Images/uploaddoc.png’
Image32by32=’_layouts/Images/uploaddoc.png’
Command=’Ribbon.Documents.Manage.CustUpload.cmdCustUpload’ LabelText=’Cust Upload’ />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command=’Ribbon.Documents.Manage.CustUpload.cmdCustUpload’
EnabledScript=’javascript:enableCustUploadApproveButton();’
CommandAction=‘javascript:CustomCommandAction();’ />
</CommandUIHandlers></CommandUIExtension>“;
userCustomAction.Sequence = 1001;
userCustomAction.Update();

SPUserCustomAction scriptlink = elevatedSite.UserCustomActions.Add();
scriptlink.Location = “ScriptLink“;
scriptlink.ScriptSrc = “/_layouts/RibbonButton/CustUploadRibbonButtonScript.js“;
scriptlink.Update();

 ———————————————————————————————–

2. Java Script

As you can see above, it is calling a javascript method “enableCustUploadApproveButton()” to enable the newly added button.

You need to add a mapped folder for Layouts, and add a JScript file to accommodate your script.

The below script has functionality to enable button on selection of document

 ———————————————————————————————–

  function enableSFTPUploadApproveButton() {
var context = SP.ClientContext.get_current();
return SP.ListOperation.Selection.getSelectedItems(context).length >= 1;
}

 ———————————————————————————————–

The below script is called on click of the button which  we have added. You can customize it based on your requirements. In my case, I am opening an application page on click of button.

———————————————————————————————–

function CustomCommandAction() {

this.currentSiteUrl = ‘http://abcde:2222/sites/testSite&#8217;;
var context = SP.ClientContext.get_current(); // get client context
var web = context.get_web();
var selectedItems = SP.ListOperation.Selection.getSelectedItems(); // Get selected List items
var selectedListId = SP.ListOperation.Selection.getSelectedList();
if (CountDictionary(selectedItems) == 1 && web != null) {
var selectedList = context.get_web().get_lists().getById(selectedListId);
var listItm = selectedItems[0]; // this will only return ID of list item, to get list object server call has to be mad
this.listItem = selectedList.getItemById(listItm.id);
context.load(this.listItem); // Load listitem in spcontext to fetch all properties of listitem
context.load(context.get_site()); // To fetch site properties

var options = SP.UI.$create_DialogOptions();
var appUrl;
appUrl = this.currentSiteUrl + “/_layouts/RibbonButton/UploadFile.aspx?title=” + listItm.id

options.url = appUrl;
options.height = 600;
options.width = 800;
options.dialogReturnValueCallback = Function.createDelegate(null, DialogClosedCallback);
SP.UI.ModalDialog.showModalDialog(options); // To Open Page in Model Dialogue

context.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded),
Function.createDelegate(this, onQueryFailed));
}
}

———————————————————————————————–

Inserting Sharepoint List Item using SPMetal Classes

Microsoft has introduced a very useful tool, in the form of SPMetal, for performing CRUD (Create Read Update Delete) operations on sharepoint lists. This article shows how to insert a new item into a list. The below screen shot has an example with its explanation as given below.

Insert item using SPMetal

Sample source code

If you have not yet generated the Data Context and entity classes, follow the below link and generate your entity model –

Using SPMetal With Paramenters

  1. Instantiate an object of the data Context class by passing the site Url as a parameter.
    • DemoDataContext demoDataContext = new DemoDataContext(spWeb.Url);
  2. Create a generic object of EntityList having the List Entity as its source.
    • EntityList<CitiesObject> cities = demoDataContext.GetList<CitiesObject>(“Cities”);
    • The EntityList class can be found in  Microsoft.Sharepoint.Linq namespace.
    • In this example I have taken a list named Cities which has three custom columns namely CityName, State and Country apart from the out-of-the-box columns.
    • The entity corresponding to Cities is CitiesObject, which is passed to the generic method.
    • The GetList method of the DataContext object returns a reference to the List to which we are adding an Item.
  3. Create and instantiate an object of List type which is passed as source to the EntityList class above.
    • CitiesObject city = new CitiesObject() { Title=”New City”, CityName=”Pune”,Country=”India”,State=”Maharashtra”};
    • In my case I have created an object of type CitiesObject and have assigned value to its properties.
  4. Add the list item to list.
    • cities.InsertOnSubmit(city);
    • The above method InsertOnSubmit adds the list item to list. But these changes remain in memory.
    • If we have a collection of List Items, we can add the whole collection at on go, using a Method called InsertAllOnSubmit(IEnumerable<T>)
  5. Persist the changes
    • demoDataContext.SubmitChanges();
    • The SubmitChanges method is where the changes made above are actually persisted in the content Database.

Using SPMetal with parameters

SPMetal is a very useful tool in Sharepoint 2010, introduced by Microsoft for creating  Entity Data Model of the underlying Sharepoint lists. Though it is still at a very nascent stage, it can still be very productive as far as sharepoint customization in .Net is concerned.

Well you might get many articles telling you how to generate the entity classes  using SPMetal .

Hence I would concentrate more on the configuration part of SPMetal. The default command for generating entities is as follows:

SPMetal /web:http://<ServerName>/<SiteName> /code:<EntityClassName>.cs 

In the above command, we have passed two arguments. The first one tells us the site for which we are generating the entities, the second one specifies the filename in which the entity classes are to be generated. The file thus generated will have entity classes for all the lists in the site. In fact it will have classes for all the content types too. i.e by default it will have classes inheriting from “item” and “Folder” content type. The entity classes in turn would have all the fields in the lists.

There would hardly be a case where you need all the entities and fields. Hence SPMetal gives you a functionality where in which you can limit the number of entities generated, the content types for which entity is generated and the fields that are to be included.

This can be achieved by passing a third argument to the above command. This argument refers an XML file which hosts configuration for the lists and fields which are required.

SPMetal /web:http://<ServerName>/<SiteName> /code:<EntityClassName>.cs /parameters: ParamElements.xml 

The above command has an argument named parameters meaning the parameters based on which the entities would be generated. The content of the xml file could be configured as given below:

SPMetal

Parameters XML to be passed as an argument to the SPMetal command

As can be seen in the above xml, it starts with an element named Web. Apart from the reference to the SPMetal command we have an attribute named class. This is an optional value where you can assign a value to the Data context class which is generated through this attribute. Along with class you can also specify the AccessModifier for the Data Context class.

Inside the web element is the List element. The Name attribute specifies the List of which an entity has to be created. Below the List element, is the ExcludeOtherLists element. By using this element we are telling SPMetal that it only needs to consider lists which are mentioned in the List element.

Within the List element is the element for ContentType where we have mentioned the name as Item. Below the ContentType Tag is the ExcludeContentType element which has name attribute set to Folder. This element tells the SPMetal command to exclude the Folder Content Type.

Similarly, inside the ContentType element, we have explicitly mentioned the columns which are required in the form of class properties of the list entity. We have explicitly asked SPMetal to ignore all the columns which are not mentioned in the columns element. The Name attribute in the column element refers the name of the field as it is used in CAML query. The Member attribute specifies the name we want to keep for this column in the entity class. We can have similar  names for the entity classes generated by having a Member attribute at the list level.

The post is based on my understanding of SPMetal until now. Will update it as and when new things arise.

Creating Event Receiver in sharepoint 2010

Sharepoint 2010 allows us to have EventReceiver on a specific list as against all the lists in the site. To achieve this all we have to do is configure the elements.xml file with details specific to the list on which we intend to trigger an event.

Steps for creating a sample event receiver in Sharepoint 2010

1. Create a new project of type Event Receiver in the sharepoint templates.

2. Select Farm based solutions and pass on an appropriate site URL.

3. Choose Event receiver settings

  • In the Type of event receiver select “List Item Events”.
  • Select the list on which you intend to have the event receiver. In my case I am doing it on my custom list named “source”.
  • Select the events on which you intend to have receivers. I have selected one synchronous event “An item is being added”  and an asynchronous event “An item was added”.
  • Click Finish.
choosing event receiver settings

choosing event receiver settings

4. In the solution explorer, open the Elements.xml file which has got created. You will find a “Receivers” tag inside Elements. Note that by default “ListTemplateId” attribute is set to 100 which is used for generic lists.

5. Replace this attribute with ListUrl with value of the url set to the list on which we intent to have receiver.

6. Note that there would be two “Receiver” sections inside the “Receivers” section corresponding to the two events which we had selected earlier. Refer the Elements.xml file as below

<?xml version=”1.0″ encoding=”utf-8″?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”&gt;
<Receivers ListUrl=”http://<<servername>>/sites/Home/Lists/Source”&gt;
<Receiver>
<Name>EventReceiver1ItemAdding</Name>
<Type>ItemAdding</Type>
<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
<Class>EventHandlerDemo.EventReceiver1.EventReceiver1</Class>
<SequenceNumber>10000</SequenceNumber>
</Receiver>
<Receiver>
<Name>EventReceiver1ItemAdded</Name>
<Type>ItemAdded</Type>
<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
<Class>EventHandlerDemo.EventReceiver1.EventReceiver1</Class>
<SequenceNumber>10000</SequenceNumber>
</Receiver>
</Receivers>
</Elements>

7. Open the EventReceiver.cs file from the solution explorer. You shall have events corresponding to the events which we found in the Elements.xml file.

8. You can have your custom code in these events as per your requirements.

9. For any additional event you can override the event in the code behind (.cs) file and make its respective entry as a new receiver in the Elements.xml file.

10. Thats to it. Your Event receiver is ready to be deployed.

11. Test it by creating an item in your designated list and one item in non designated list.

Joins in CAML Query

Finally in SharePoint 2010, you can have Joins on List using CAML.

Here is an example:

For Test purpose I have created four lists having relation between them. i.e. Cities, Customers, Product and Orders.
The Customers list contains a lookup field pointing to the Cities list to specify in which city a customer lives. The Orders list contains a lookup field to the Customers and Product list to specify who’s the customer of a given order and what product he has ordered. Please make sure you have these relations in place as lookup fields are the basis on which we apply joins in CAML.

1. Declaring List Object: We have created an object of the Customers list from which records are to be fetched.

SPList CustomerList = SPContext.Current.Web.Lists[“Customers“];

2. Setting Join Property: One thing you woul notice below is that SPQuery object has been enhanced with a property named Joins.  This is the property which you need to set.
SPQuery CustomerCityQuery = new SPQuery();
CustomerCityQuery.Joins =

“<Join Type=’INNER’ ListAlias=’Cities‘>” +
“<Eq>” +
“<FieldRef Name=’City‘ RefType=’Id‘ />” +
“<FieldRef List=’Cities‘ Name=’ID‘ />” +
“</Eq>” +
“</Join>”;

The “Join” tag has an attribute named “Type”. It specifies the type of join we intend to have. In my case I have set it to “INNER”, the “ListAlias” property points to the list with which we are having this join i.e. Cities.

In my case, I have a lookup column in my Customers list named City which points to the Id in the list Cities. Hence the first “FieldRef” tag has its “Name” set to City  and “RefType” is set to Id.

The second “FieldRef” tag has attribute “List” set to Cities and “RefType” is set to ID signifying the column of the list on which Join has to be implemented.

3. Setting Projected fields: These are fields in joined lists that can be included in the view when one or more other lists have been joined in a query. In my case I have included CityName, State and Country columns from Cities list while creating lookup from Customers. In the below code I am adding CityName & State to the projected fields property of SPQuery.

StringBuilder ProjectedFields = new StringBuilder();

ProjectedFields.Append(“<Field Name=’CityName‘ Type=’Lookup’ List=’Cities’ ShowField=’CityName‘ />”);
ProjectedFields.Append(“<Field Name=’State’ Type=’Lookup’ List=’Cities‘ ShowField=’State‘ />“);
CustomerCityQuery.ProjectedFields = ProjectedFields.ToString();

4. The code ahead is similar to what we have in normal SPQuery operations without joins.
SPListItemCollection Results = CustomerList.GetItems(CustomerCityQuery);
foreach (SPListItem Result in Results)
{
SPFieldLookupValue CityTitle = new SPFieldLookupValue(Result[“CityName“].ToString());
SPFieldLookupValue CityCountry = new SPFieldLookupValue(Result[“State“].ToString());
Response.Write(string.Format(“Customer {0} lives in {1} – {2}”,
Result.Title,
CityTitle.LookupValue,
CityCountry.LookupValue));
}

This was my first attempt to have joins using CAML for Sharepoint 2010. Will refine this post as and when possible.

Sharepoint – Error in SPWorkflowTask.AlterTask Method

Recently I was working on a Sharepoint workflow.
We had to raise an event from our application form, which would trigger the eventHandler. We had used “OnTaskChange” event for that respective task in the workflow.
There were four different conditions on the “OnTaskChange” event which were segregated based on the If-Else condition.
It such happened that I was able to execute the first three conditions. The control was going to the workflow from the Application page, and I was able to debug the flow and the If-Else conditions as well.
But when I raised the fourth condition, It was not getting executed. After debugging I found that It is not reaching the workflow either.
It was giving “Object reference not set to an instance of an object” error on the

“SPWorkflowTask.AlterTask”

Method. The method basically accepts three parameters,
1. The Task Item
2. HashTable
3. Synchronisation Flag

Interestingly none of the three parameters were Null. Even after searching on the internet, I couldn’t get a break through. I checked the correlation token being set for the task on creation and the one passed “OnTaskChanged”.
After spending a lot of time, one of my colleague told me to check for the values being passed in the HashTable. That was it. Before executing the AlterTask method, the Workflow runtime checks the items in the workflow. If it finds any of the Item from the Hashtable missing, it does not allow the AlterTask method to execute.
In my case too, I was passing a null value for one of my flag, which  was getting checked in the workflow. After setting the flag, the workflow started working as expected.