SharePoint 2010 Custom Ribbon Button–Copy Task

by josh 19. November 2010 07:19

The SharePoint 2010 Ribbon is highly customizable. This paper will demonstrate how to add a button to the View Item form that will create a copy of the current item in the list. This example will use the Tasks list, but the steps are generally applicable for any list type. The general steps are as follows:

 

1. Create a new Visual Studio SharePoint 2010 project of the type Empty SharePoint Project

2. Enter the web site for testing and choose Deploy as a sandboxed solution. (Note: If deploying along with workflows or other customizations that required GAC-installed DLLs or files on the file system you will want to use a Farm Solution)

3. In Solution Explorer, right click the project name and click Add -> New Item.

4. Choose Empty Element from the item types and give it a name, such as CustomActions

5. At this point you will have an empty elements file

1_thumb[1]_thumb[3][3]


 

Add the following XML between the Elements tags:

 

<CustomAction   Id="Contoso.CustomActions.CopyTaskAction"
Location="CommandUI.Ribbon"
RegistrationId="107"
RegistrationType="List"
Sequence="1">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.ListForm.Display.Manage.Controls._children">
<Button Id="Contoso.Ribbon.CopyTask"
Command="Contoso.Ribbon.CopyTask"
Sequence="5"
Image16by16="/_layouts/images/NoteBoard_16x16.png"
Image32by32="/_layouts/images/NoteBoard_32x32.png"
Description="Uses the notification area to display a message."
LabelText="Copy Task"
TemplateAlias="o1"/>
</CommandUIDefinition>
</CommandUIDefinitions>
</CommandUIExtension>
</CustomAction>


<CustomAction>

(http://msdn.microsoft.com/en-us/library/ms465980.aspx)

The CustomAction tag is used for deploying custom actions to the SharePoint UI. This includes many types of customizations, such as the Site Actions menu and the item context menus, as well as the ribbon.

The Location attribute specifies where the custom action will be created. For the Ribbon, the location should be CommandUI.Ribbon.

The RegistrationId and RegistrationType attributes specify what type of objects to attach the customization to as well as the specific IDs of the specified type. In this case, we want the customization to be attached to a list of type 107 (107 is the list template ID for the Tasks list).

Sequence is used throughout SharePoint declarative programming and refers to the order in which an element appears in the UI. Lower sequences appear first. SharePoint typically uses multiples of 10, but you will probably have to check the definitions yourself if you’re trying to place a customization in a very specific location, like between two other SharePoint elements.

<CommandUIDefinition>

(http://msdn.microsoft.com/en-us/library/ff458373.aspx)

This is used for adding specific elements to the SharePoint UI.

The Location attribute of the CommandUIDefinition specifies exactly where in the Ribbon the customization should be located. In this case we want the button to appear in the Manage group of the list item Display form. Specifying Controls._children tells SharePoint to add the customization to the controls collection of the specified group.

<Button>

(http://msdn.microsoft.com/en-us/library/ff458366.aspx)

As might be expected, the Button tag represents a button in the Ribbon.

The Command attribute specifies the command to be executed when the button is clicked. This will be used in the CommandUIHandler to execute some JavaScript code.

The Image16by16 and Image32by32 attributes allow specify the large and small icons to be used with the button. The 16 and 32 represent pixel sizes for the respective images.

The LabelText attribute is the text that will be displayed on the button in the Ribbon.

The TemplateAlias attribute specifies a display template for the button. These are defined by SharePoint and can be found in the SharePoint root directory at TEMPLATE\GLOBAL\XML\CMDUI.XML. In this case, setting the attribute to “o1” will display a large icon similar to the “Edit Item” button, and “o2” will display a small icon similar to the “Delete Item” button.

 

6. Deploy the solution from Visual Studio. At this point you will see the button in the View form but it will be disabled because there are no handlers defined for it yet.

2_thumb_thumb_thumb[3]


 

Now copy the following XML between the closing CommandUIDefinitions and the closing CommandUIExtension tags:

 

<CommandUIHandlers>
<CommandUIHandler
Command="Contoso.Ribbon.CopyTask"
CommandAction
="javascript:
if(confirm('Copy Task, are you sure?')){
var ctx;
var taskList;
var web;
var taskItem;

//Get client context
ctx = new SP.ClientContext.get_current();
//Get reference to current web
web = ctx.get_web();
//Load web into context
ctx.load(web);

//Get reference to current list
taskList = web.get_lists().getById('{ListId}');
//Load list into context
ctx.load(taskList);

//Get reference to current list item
taskItem = taskList.getItemById('{ItemId}');
//Load listitem into context, including specified columns.
ctx.load(taskItem);

//Perform batched queries on server
ctx.executeQueryAsync(onQuerySucceeded, onQueryFailed);
}




function onQuerySucceeded(sender, args) {

//Create ListItemCreationInformation for use when creating new task item
var taskItemInfo = new SP.ListItemCreationInformation();

//Create new request item
newTask = taskList.addItem(taskItemInfo);

//Set properties on new request from current request
newTask.set_item('Title','COPY OF TASK {ItemId}');
newTask.set_item('Body',taskItem.get_item('Body'));
newTask.set_item('AssignedTo',taskItem.get_item('AssignedTo'));
newTask.set_item('DueDate',taskItem.get_item('DueDate'));
newTask.set_item('Priority',taskItem.get_item('Priority'));
newTask.set_item('StartDate',taskItem.get_item('StartDate'));
newTask.set_item('TaskGroup',taskItem.get_item('TaskGroup'));

//Update database with changes
newTask.update();

//Load new request into context
ctx.load(newTask);

//Perform batched operations on server
ctx.executeQueryAsync(requestAddSucceeded, requestAddFailed);

}



function requestAddSucceeded(sender, args) {
//Notify user that copy succeeded
SP.UI.Notify.addNotification('Task copied successfully');
}

function requestAddFailed(sender, args)
{
//Notify user that copy failed
SP.UI.Notify.addNotification('Task failed to copy!');
}

function onQueryFailed(sender, args)
{
//Notify user that an error occurred
SP.UI.Notify.addNotification('Error copying task!');
}

"
/>
</CommandUIHandlers>


<CommandUIHandler>

(http://msdn.microsoft.com/en-us/library/ff458385.aspx)

This tag defines a handler for a custom action command. In this case we want to define a handler for the Contoso.Ribbon.CopyTask command, which we specify in the Command attribute.

The CommandAction attribute is where we define the handler for the command. Here we add the javascript to actually perform the copy using the SharePoint ECMAscript Client Object Model. I won’t go into detail here about programming against the Client OM, but there are many good articles, blog posts, etc. out there. Some good ones I’ve found are *here*…

In a nutshell, the javascript code gets a reference to the task using the {ListId} and {ItemId} tokens, which are replaced at runtime with the IDs of the list and item from the current context (e.g. the item being displayed in the View form). Then a new task is created in the same list and the properties are populated from the current task. As far as I can tell, this is the best way to perform a copy on a list item. There is no CopyTo method or anything like that, at least that I could find.

 

7. With the CommandUIHandlers code added, redeploy the solution. You will now be able to click the Copy Task button. 

3_thumb_thumb_thumb[3]


and when you click the button you will be prompted to confirm your desire to copy the task… 


4_thumb_thumb_thumb[3]


and when you click OK you will be notified, using the new notification framework, that the task copied successfully.


5_thumb_thumb_thumb[3]

 

8. Refreshing the list view, you will see the original task and the new copy.


6_thumb_thumb_thumb[3]

 

Here’s a few helpful blog posts related to Ribbon Customizations and the ECMAscript Client OM:

  • Chris O’Brien’s series on Ribbon Customizations
  • Channel 9 Developer Training videos on the Client OM

FileNotFound Exception when creating SPSite or getting reference to SPWebApplication (SharePoint 2010)

by josh 10. June 2010 04:10

Ok, this is the second time I’ve had this problem, so I’m going to blog about it so maybe I’ll remember next time. If you’re using VS 2010 and developing outside of IIS (console application in my case), you need to make sure your project is not targeting the x86 Platform. Go to your Project Properties, click the Build tab, and make sure the Platform target dropdown is set to x64 (or Any Platform). Another less than helpful error…

Create Root Web from Template in a SharePoint 2010 Site Collection

by josh 21. May 2010 05:32

In SharePoint 2007, you had to use stsadm.exe to install site templates to be used for creating the root site in a site collection. In SharePoint 2010, you still have the command-line option available with the PowerShell cmdlet Install-SPWebTemplate, but now it can also be done through the UI when creating a site collection.

 

To use a custom template to create a site collection, go to Central Administration –> Application Management –> Create Site Collections.

Fill out the information for your new site collection, choosing the Custom tab and “< Select template later… >”. Click OK to create the site collection.

 

image

 

When you get the Top-Level Site Successfully Created page, click the link to the new site collection. You’ll see the Template Selection page shown below.

 

image

 

Click the link to the solution gallery, where you can upload your desired site template. Don’t forget to Activate the template as well so it will be available for use.

image

Notice where you are – the solutions gallery of your newly created site. So you can upload templates to the solutions gallery of the site before you’ve chose a template for the site. Upload the solution and then navigate to the address of your site again, where you’ll be presented with the Template Selection page.

Now you can choose the Custom tab, and you will see your custom site template available to choose.

image

Creating a cloneable SharePoint 2010 Development Environment with PowerShell, Windows Sysprep, and SQL Server 2008 R2 Sysprep – PART 2

by josh 30. April 2010 03:24

This is a continuation from Part 1. This post will cover the PowerShell script used to configure SQL Server 2008 R2 and SharePoint 2010 on the machine.

The syntax to run the script is as follows:

.\build.ps1 .\settings.xml

assuming you are running the scripts from the root of the directory where they reside. What does the settings file look like? Glad you asked:

<?xml version="1.0" encoding="utf-8"?>

<Configuration

<Package Id="sts">

<Setting Id="LAUNCHEDFROMSETUPSTS" Value="Yes"/>

</Package>

<Package Id="spswfe">

<Setting Id="SETUPCALLED" Value="1"/>

</Package>

<Logging Type="verbose" Path="%temp%" Template="SharePoint Server Setup(*).log"/>

<PIDKEY Value="xxxxx-xxxxx-xxxxx-xxxxx-xxxxx" />

<Display Level="basic" CompletionNotice="no" />

<Setting Id="SERVERROLE" Value="APPLICATION"/>

<Setting Id="USINGUIINSTALLMODE" Value="0"/>

<Setting Id="SETUP_REBOOT" Value="Never" />

<Setting Id="SETUPTYPE" Value="CLEAN_INSTALL"/>

<SqlServer SqlSetupPath="D:\setup"

InstanceID="App"

InstanceName="MSSQLSERVER"

SqlSvcAccount="contoso\sqlservice"

SqlSvcPassword="P@ssw0rd"

RsSvcAccount="contoso\sqlservice"

RsSvcPassword="P@ssw0rd"

SqlSysadminAccounts="builtin\administrators"

AgtSvcAccount="contoso\sqlservice"

AgtSvcPassword="P@ssw0rd"

SecurityMode="SQL"

SaPassword="P@ssw0rd"

TcpEnabled="1"

>

</SqlServer>

<SharePoint>

<Farm ConfigureEmail="true"

FarmAccount="contoso\svcsharepoint"

FarmAccountPassword="P@ssw0rd"

DBServer="app"

ConfigDB="SharePoint_Config"

AdminContentDB="CentralAdmin_Content"

Passphrase="P@ssw0rd"

EmailFromAddress="sharepoint@contoso.com"

EmailReplyToAddress="sharepoint@contoso.com"

SMTPServer="smtp.contoso.com"

>

<CentralAdmin Port="1234">

<Servers>

<Server Name="app" />

</Servers>

</CentralAdmin>

</Farm>

</SharePoint>

</Configuration>

The settings are accessed from the PowerShell script by getting a reference to the xml

[xml]$config = Get-Content $settingsFilepath

and then referencing settings as follows:

$SqlSetupPath = $config.Configuration.SqlServer.SqlSetupPath

The first 9 elements, from Package down to the last Setting, are copied straight out of the config.xml file on the installation media for SharePoint in the \Files\SetupFarmSilent folder. The only change is to replace the product key with your own SharePoint 2010 product key.

The SqlServer element contains SQL Server specific settings for provisioning the SQL Server instance from the prepared image (from Part 1). The PowerShell script code is below:

invoke-expression "& ""$SqlSetupPath"" /QS /ACTION=CompleteImage /INSTANCEID=""$InstanceID""
/INSTANCENAME=""$InstanceName"" /SQLSVCACCOUNT=""$SqlSvcAccount"" /SQLSVCPASSWORD=""$SqlSvcPassword""
/RSSVCACCOUNT=""$RsSvcAccount"" /RSSVCPASSWORD=""$RsSvcPassword"" /SQLSYSADMINACCOUNTS=""$SqlSysadminAccounts""
/AGTSVCACCOUNT=""$AgtSvcAccount"" /AGTSVCPASSWORD=""$AgtSvcPassword"" /IACCEPTSQLSERVERLICENSETERMS 
/TCPENABLED=$TcpEnabled   "

Here are the settings explanations:

  • $SqlSetupPath – the path to the setup executable (e.g. D:\setup)
  • /QS – specifies that the installer should show progress, but not allow any input from user
  • /ACTION – for provisioning an instance from a sysprepped image, the action is "CompleteImage"
  • $InstanceID – the instance id (string) specified when creating the sysprep image
  • $InstanceName – the name to be used for the new instance
  • $SqlSvcAccount,$SqlSvcPassword – the username and password for the sql server account
  • $RsSvcAccount,$RsSvcPasswordusername and password for reporting services account
  • $SqlSysadminAccounts – accounts that should be added to the SQL Server sysadmin group
  • $AgtSvcAccount, $AgtSvcPassword – username and password for the SQL Server Agent account
  • /IACCEPTSQLSERVERLICENSETERMS – automatically accepts license terms without user interaction
  • $TcpEnabled – specify '1' to enable TCP for the SQL Server Service

There are many more options for configuring the server and they can be found here under Complete Image Parameters.

SharePoint Configuration

The SharePoint element in the settings.xml file contains the basic settings for creating a SharePoint farm and configuring it. These settings are used by the PowerShell cmdlets to perform the configuration.


Here is the SharePoint configuration script: (thanks to Gary Lapointe, SharePoint MVP and PowerShell guru (http://stsadm.blogspot.com) , for the examples on his blog that I incorporated into this script)

 (Build.ps1)

#Add SharePoint cmdlets reference (if you're running the SharePoint 2010 Management Shell you won't need this line)
Add-PSSnapin Microsoft.SharePoint.PowerShell

#Configure Farm
Write-Host -foregroundcolor yellow "# Configuring SharePoint..."
$farmAcct = New-Object System.Management.Automation.PSCredential $config.Configuration.SharePoint.Farm.FarmAccount, (ConvertTo-SecureString $config.Configuration.SharePoint.Farm.FarmAccountPassword -AsPlainText -force)


$configDb = $config.Configuration.SharePoint.Farm.ConfigDB  
$adminContentDb = $config.Configuration.SharePoint.Farm.AdminContentDB   
$server = $config.Configuration.SharePoint.Farm.DBServer
$smtp = $config.Configuration.SharePoint.Farm.SMTPServer
$fromAddr = $config.Configuration.SharePoint.Farm.EmailFromAddress
$replyAddr = $config.Configuration.SharePoint.Farm.EmailReplyToAddress

#Check farm passphrase - if null then use admin account password
if ($config.Configuration.SharePoint.Farm.Passphrase.Length -gt 0)
{       
    $passphrase = (ConvertTo-SecureString $config.Configuration.SharePoint.Farm.Passphrase -AsPlainText -force)   
}
else
{
     Write-Warning "Using the Farm Admin's password for a passphrase"
     $passphrase = $farmAcct.Password
}

#--------1. CREATE FARM----------
Write-Host -foregroundcolor green "# Creating Farm..."
New-SPConfigurationDatabase -DatabaseName $configDb -DatabaseServer $server -AdministrationContentDatabaseName $adminContentDb -Passphrase $passphrase -FarmCredentials $farmAcct
#Verifying farm creation
$spfarm = Get-SPFarm -ErrorAction
SilentlyContinue -ErrorVariable err
if ($spfarm -eq $null -or $err)
{

    throw "Unable to verify farm creation."
}

#--------2. SECURE SHAREPOINT RESOURCES----------
Write-Host -foregroundcolor green "# Securing SharePoint resources..."
Initialize-SPResourceSecurity

#--------3. INSTALL SERVICES----------
Write-Host -foregroundcolor green "# Installing SharePoint services..."
Install-SPService

#--------4. INSTALL FEATURES----------
Write-Host -foregroundcolor green "# Installing SharePoint features..."
Install-SPFeature -AllExistingFeatures

#--------5. INSTALL CENTRAL ADMIN----------
Write-Host -foregroundcolor green "# Installing Central Administration website..."
$installSCA = (($config.Configuration.SharePoint.Farm.CentralAdmin.Servers.Server | where {$_.Name -eq $env:computername}) -ne $null)
$url = "http://$($env:computername):$($config.Configuration.SharePoint.Farm.CentralAdmin.Port)"

$sca=[Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($url)

if ($installSCA -and $sca -eq $null)
{

  #Provisioning Central Administration
   New-SPCentralAdministration -Port $config.Configuration.SharePoint.Farm.CentralAdmin.Port -WindowsAuthProvider "NTLM"
   #Installing Help
   Install-SPHelpCollection -All
   #Installing Application Content

   Install-SPApplicationContent

}

#--------6. CONFIGURE OUTGOING EMAIL----------
if ($config.Configuration.SharePoint.Farm.ConfigureEmail -eq $true)
{
    Write-Host -foregroundcolor green "# Configuring Outgoing (SMTP) E-Mail..."
    ExecuteCommand "& stsadm -o email -outsmtpserver "" $smtp "" -fromaddress "" $fromAddr "" -replytoaddress "" $replyAddr ""  -codepage 65001  "

}
else
{
    Write-Host -foregroundcolor green "# Skipping Configuration of Outgoing (SMTP) E-Mail..."
}
echo ""
Write-Host -foregroundcolor green "# SharePoint install and initial configuration finished."

 

Ok, so this post is already way long so I'm not going to explain the pieces of this script. Most of them are self-explanatory and well-document elsewhere. Some great resources for scripting SharePoint are

   

 

Presenting 2 Sessions at SharePoint Saturday Huntsville

by josh 13. April 2010 08:14

I'll be presenting 2 sessions at the upcoming SharePoint Saturday event in Huntsville, AL on May 1, 2010.

Building a  Cloneable, Scripted SharePoint 2010 Development Environment

SharePoint 2010 Workflow – Business Analyst to Developer

 

 This is actually my first SharePoint Saturday to attend or present, so I'm excited. For those in Huntsville or the surrounding areas, you can register here.

 

“The form cannot be rendered” error when editing SharePoint 2010 list form in InfoPath

by josh 29. March 2010 05:14

One of the cool new features of SharePoint 2010 is the ability to customize list new/edit forms easily in InfoPath, but this requires the State Service to be configured for the farm. Otherwise you will see this error:

 infopath state service error

Unfortunately you don’t know there’s a problem until after you’ve customized the form in InfoPath and published it back to the list. At this point you can go into List Settings->Form Settings and set the list to use the default form and you’re back to where you started before editing the form. Or you could configure the state service so that you can use this cool new functionality.

To configure the state service, go to Central Administration, run the Farm Configuration Wizard, and select the State Service to be configured. Now all is well, editing forms works like a charm.