SharePoint Ribbon customization for a specific content type

I wanted to utilize the new SharePoint 2010 Ribbon for performing a custom action on items in a custom list.  The list contained items that were of a custom content type (lots of custom work going on).  With some great posts from Chris O’Brien and MSDN, I found all the XML needed to accomplish the task.  I also took advantage of the Custom Tab, Button Groups and Notifications while I was at it.

A couple of things to note when targeting the content type for ribbon customization.  The content type that was used for the CustomAction was created through code, so I didn’t have the ID at design time to add to the Ribbon customization.  I deployed the content type first, looked up the content type ID (this can be done quickly by viewing the properties of the CT and looking at the ID in the URL).  Once I had that ID, I was able to set the CustomAction RegistrationId to the ID and the RegriatrationType to “ContentType.”  Also, I only wanted the button to be active when one or more items were selected.  I modified the EnabledScript function to make that happen.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
    Id="SharePoint.Ribbon.SohemasTab"
    Location="CommandUI.Ribbon"
  RegistrationId="0x0100ECB394A7B088A843A2421FB7663F957602"
  RegistrationType="ContentType" >
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Tabs._children">
          <Tab Id="SharePoint.Ribbon.SohemasTab" Title="Sohema Commands" Description="Sohema Workflow Commands" Sequence="501">
            <Scaling Id="SharePoint.Ribbon.SohemasTab.Scaling">
              <MaxSize Id="SharePoint.Ribbon.SohemasTab.SohemaActionGroup.MaxSize"
                                     GroupId="SharePoint.Ribbon.SohemasTab.SohemaActionGroup"
                                     Size="OneLarge"/>
              <Scale Id="SharePoint.Ribbon.SohemasTab.SohemaActionGroup.Scaling.SohemasTabScaling"
                                   GroupId="SharePoint.Ribbon.SohemasTab.SohemaActionGroup"
                                   Size="OneLarge" />
            </Scaling>
            <Groups Id="SharePoint.Ribbon.SohemasTab.Groups">
              <Group
                              Id="SharePoint.Ribbon.SohemasTab.SohemaActionGroup"
                              Description="Contains Sohema Action items"
                              Title="Perform Sohema Actions"
                              Sequence="52"
                              Template="Ribbon.Templates.OneLargeExample">
                <Controls Id="SharePoint.Ribbon.SohemasTab.SohemaActionGroup.Controls">
                  <Button Id="Ribbon.Documents.New.SohemaPushToCSVRibbonButton"
                    Alt="Push selected item(s) to CSV"
                    Sequence="95"
                    LabelText="Push Sohema(s) To CSV"
                    Image16by16="/_layouts/images/SubcontractorSohema/ToCSV16x16.png"
                    Image32by32="/_layouts/images/SubcontractorSohema/ToCSV32x32.png"
                    Command="Command.SohemaPushButton"
                    TemplateAlias="PushSohema" />
                </Controls>
              </Group>
            </Groups>
          </Tab>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Templates._children">
          <GroupTemplate Id="Ribbon.Templates.OneLargeExample">
            <Layout Title="OneLarge" LayoutTitle="OneLarge">
              <Section Alignment="Top" Type="OneRow">
                <Row>
                  <ControlRef DisplayMode="Large" TemplateAlias="PushSohema" />
                </Row>
              </Section>
            </Layout>
          </GroupTemplate>
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
                    Command="Command.SohemaPushButton"
                    CommandAction="javascript:
            var notificationId = SP.UI.Notify.addNotification('Processing Sohemas');"
                    EnabledScript="javascript:function moreThanOneEnabled()
            {
              var items = SP.ListOperation.Selection.getSelectedItems();
              var ci = CountDictionary(items);
              return (ci > 0);
            }
            moreThanOneEnabled(); " />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

2 Comments

Installing Visual Studio 2010 on computer with VMWare running

This was a curious matter.  I installed Visual Studio 2010 on a machine that had VMWare Server running.  The VS install went through a restart and installed just fine.  When I tried to launch VMWare to access a VM through VMWare Web Access, the VMWare configuration site was not running.  Turned out that the VMWare Host Agent (VMwareHostd) was not started (even though it was still set to startup Automatically)!  I started that service and was able to access the VMWare config web site.  This happened on two different dev machines, so some part of the VS install was being stubborn.

Leave a comment

Adding a CSS file to a SharePoint 2010 Application page in VS 2010

A quick run down on the steps to add a Cascading StyleSheet to a SharePoint Application page in Visual Studio 2010

From the Visual Studio 2010 Solution Explorer, select the project, right click and select the Add option and then the “SharePoint Mapped Folder…”

AddMappedFolder

The “Add SharePoint Mapped Folder” dialog is presented which displays all the folders under {SharePointRoot}:

styles

Select the location that you would like to place your Stylesheet, which in most cases will be: {ProgramFiles}\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\STYLES

Once the STYLES folder is added, it may be easier to add a custom folder that will contain your CSS file(s)

styles2

Now that the folder structure is complete, you can add a stylesheet to that folder:

styles3

Inside your application page, reference the stylesheet within the PlaceHolderAdditionalPageHead ContentPlaceHolder similar to: <link type="text/css" rel="stylesheet" href="/_layouts/1033/styles/Sohema/sohema.css" />

styles_7

The details of adding the files to the package is nicely handled by Visual Studio and included in the Package xml files:

styles_8

Deploy your solution and notice the addition of your CSS file under the location that was specified:

styles_file

Add content to your CSS file and you’re done!

4 Comments

Suppress Visual Studio debug attach warning

This is such a pain in the neck, I had to re-blog this….

When you are debugging in VS 2010 and attaching to the w3wp.exe process, you’ll get this lovely warning (with no option to suppress!)

AttachWarning

To remove that warning, run the powershell command:

Set-ItemProperty HKCU:\Software\Microsoft\VisualStudio\10.0\Debugger -Name “DisableAttachSecurityWarning”  -value “1”

UPDATE!  Thanks to Donal Conlon for commenting that Visual Studio should not be running when you execute this command.

Thanks d1$c0!

2 Comments

SharePoint backup error "Operating system error 21"

While running a backup on a SharePoint server, I received the error:  “Error: Object SharePoint_Config failed in event OnBackup”

I was running the following STSADM script:

@REM —– BACKUP Farm —–
@SET BACKUPFILEPATHFULL=D:\Backup\full
STSADM -o backup -directory %BACKUPFILEPATHFULL% -backupmethod full -quiet

The full error text from the spbackup file was this:

[5/18/2010 6:35:39 PM]: Verbose: Starting object: Farm.
[5/18/2010 6:35:39 PM]: Progress: [Farm] 50 percent complete.
[5/18/2010 6:35:39 PM]: Verbose: Starting object: SharePoint_Config.
[5/18/2010 6:35:40 PM]: Verbose: [SharePoint_Config] SQL Server Connection String: Data Source=sp-sql-external.sohema.com;Initial Catalog=SharePoint_Config;Integrated Security=True;Enlist=False.
[5/18/2010 6:35:40 PM]: Verbose: [SharePoint_Config] SQL command started at: 5/18/2010 6:35:40 PM. This command may take a while to complete and without notification.
[5/18/2010 6:35:40 PM]: Verbose: [SharePoint_Config] SQL Server Command: BACKUP DATABASE [SharePoint_Config] TO DISK=@db_loc WITH NAME=@db_name, STATS=5, NOINIT, NOSKIP, NOFORMAT, NOREWIND
    @db_name=SharePoint_Config, @db_loc=D:\backup\full\spbr00060000015.bak
[5/18/2010 6:35:40 PM]: Verbose: [SharePoint_Config] SQL command timeout is set to 1.00 hours.
[5/18/2010 6:35:40 PM]: Error: Object SharePoint_Config failed in event OnBackup. For more information, see the error log located in the backup directory.
    SqlException: Cannot open backup device ‘D:\backup\full\spbr00060000015.bak’. Operating system error 21(The device is not ready.).
BACKUP DATABASE is terminating abnormally.

The problem was that I was not using a UNC path as the backup directory.  The backup ran without any errors when I changed the path variable to a valid path:

@SET BACKUPFILEPATHFULL=\\SP-WEB1\Backup\full

Leave a comment

Workflow Foundation Correlation Token error

Within a workflow that I was developing, there was a requirement to notify a group of SharePoint users that a lookup service had failed.  This particular activity was within a parallel activity sequence.  I chose to use the SendEmail activity to notify the users, but incorrectly set the Correlation Token to a new value.  When testing this functionality in the workflow I received an error:

SharePoint LOG
  1. WinWF Internal Error, terminating workflow Id#
  2. System.InvalidOperationException: Correlation value has not been initialized on declaration emailToken_JobNumberCreate for activity sendEmail_JobNumberNotCreated. at System.Workflow.Activities.CorrelationService.InvalidateCorrelationToken

The correct Correlation Token for a SendMail Activity is the “Workflow” token.  The reason, which is fairly obvious, is that the SendEmail activity maps to the workflow, not to a task, which would require a Task Token.

Source 1

Leave a comment

The U2U CAML Query tag

While I was building a CAML query for retrieving files from a document library, I used the U2U CAML query tool to construct the query syntax.  It worked fine in the tool and returned the proper data, but when I used that query in the code, I found that ALL files were returned and not just the ones I expected.

As it turns out, the U2U CAML Query tool adds the tag <Query> to the query although it should not be included when using it to query items from a SPList.   (Note: There are some instances where the Query tag is required, but for this case, it is not)

Here is a sample query:

SPListCollection spBPDLListCollection = spBPDLWeb.Lists;
SPList splist = spBPDLListCollection[documentLibraryName];

SPQuery query = new SPQuery();
// CAML for looking up documents owned by current user
query.Query = “<Where><Contains><FieldRef Name=’Author’ /><Value Type=’User’>”
+ currentDisplayName + “</Value></Contains></Where>
“;

// get the items specified with the query
SPListItemCollection items = splist.GetItems(query);

Leave a comment

Searching Stored Procedures

Here is a quick and easy way to search of stored procedures, views, user functions from within a database:

 –Search ALL user functions, views, stored procs

USE [PortalData]

SELECT OBJECT_NAME([id]) FROM syscomments

WHERE [id] IN (SELECT [id] FROM sysobjects WHERE xtype IN (‘fn’, ‘P’, ‘v’, ‘TR’, ‘U’, ‘X’))

AND [text] LIKE ‘%TypeSearchStringHere%

Leave a comment

Deleting Content Types that are still in use

If you are like me, you tend to deal with strange development nuances in the SharePoint environment.  One of those nuances is trying to delete a content type that is in use.   When I’m developing a solution that requires the creation of content types within the feature, I typically create that content type through code.  That will work on the first deployment of the feature since it does not exist yet.  On subsequent deployments, you will get an error that either the content type is in use (if you are trying to delete it before adding) or the content type already exists.  One thing I do is disable the deletion/creation of the content type if I’m not making any changes to it on subsequent deployments.  That will save a bit of development time.  The second problem I get every so often is the “content type still in use” error when trying to delete a content type.  I find this to happen if I am careless with removing items from a list, especially workflow tasks that are associated with a content type. 

I found a decent SQL Script (below) on the interweb that displays all the instances of my content type in the SharePoint databases.  In some cases, this will tell me where the “remnant” of the content type is and I can remove it.  Other times, it will display something that I already removed and I’m stuck.  If that happens, I first blow away the list where the content type was associated.  If the list removal doesn’t work, I will delete the site collection and build a new one.  (That is a luxury of having my own development VM.) I found that course of action to be quicker than trying to go through the database structure to find where to delete all instances of that content type.

 

Code Snippet
  1. SET @ContentTypeName='My Conent Type'
  2. SELECT w.Title AS [Web Site], w.FullUrl AS [Web Url], al.tp_Title AS [List Title], ct2.* FROM ContentTypes ct1 JOIN ContentTypes ct2 ON LEFT(ct2.ContentTypeId, Len(ct1.ContentTypeId))=ct1.ContentTypeId LEFT OUTER JOIN dbo.ContentTypeUsage ctu ON LEFT(ctu.ContentTypeId, Len(ct2.ContentTypeId)) = ct2.ContentTypeId LEFT OUTER JOIN dbo.AllLists al ON ctu.ListId = al.tp_Id AND ctu.WebId=al.tp_WebId LEFT OUTER JOIN dbo.Webs w ON al.tp_WebId = w.Id WHERE ct1.ResourceDir=@ContentTypeName

Sources: 1

Leave a comment

Filtered Data View for my items and items of groups that I am a member

I found that I could create a view that filtered items for myself ([Me]) and for the groups that I was in, but not both through the View editor.   By editing the group view in SharePoint Designer, I updated the CAML query to filter both groups and items “assigned to me” and it worked just dandy:

<Query>
<GroupBy Collapse=”FALSE” GroupLimit=”30″>
<FieldRef Name=”AssignedTo”/>
</GroupBy>
<OrderBy>
<FieldRef Name=”AssignedTo”/>
<FieldRef Name=”Status”/>
</OrderBy>
<Where>
<Or>
<Membership Type=”CurrentUserGroups”/>
<FieldRef Name=”AssignedTo”/>
</Membership/>
<Eq>
<FieldRef Name=”AssignedTo”/>
<Value Type=”Integer”>
<UserID Type=”Integer”/>
</Value>
</Eq>
</Or>
</Where>
</Query>

Leave a comment