Developer Dashboard in SharePoint 2010

What is developer dashboard:
SharePoint is very big system and
consists of so many modules integrated. We can do lot of customization and all
our code will be deployed to SharePoint and end users will use it. But, what if
client comes to you with the question, "why my SharePoint site is loading very
slow?" How you proceed?
First thing you need to check is all server
configurations like is memory is sufficient/ Processor is sufficient etc.. After
you found they are more than enough, now it's time to find problem in the code.
Till SharePoint 2007, it's very difficult to find which part of the code is
taking how much time and analyze it better. But luckily in SharePoint 2010,
Microsoft added a very nice feature for developers to detect which module is
taking how much time. It will record all the requests and the time to get
response etc.... This is what we are calling Developer Dashboard.

The
great advantatge with it is, it will differ the requests and show like, database
queries [Which query took how much time], SPRequest allocation, Webpart event
offsets, etc in very detailed way. I really love it. Thanks a ton to SharePoint
2010 team.

The developer dashboard records and display
performance statistics of the related code that executed to produce current
page.

How to enable/disable it on the specific site?
Method 1: 
[STSADM]

'On' Mode :
STSADM –o
setproperty –pn developer-dashboard –pv On


'Off' Mode:
STSADM –o setproperty –pn developer-dashboard –pv
Off


'OnDemand' Mode:
STSADM –o
setproperty –pn developer-dashboard –pv OnDemand


Suppose you'd
like to only display the developer dashboard if one or more acceptable values
are exceeded, there's a way to do that too by running:
STSADM –o setproperty –pn developer-dashboard –pv
expensiveoperationsonly


Once you executed the command the output
is "Operation executed successfully."

Method 2: Windows Powershell
script:

You need to open the windows power shell prompt and copy the
below script and hit enter.
$DevDashboardSettings =
[Microsoft.SharePoint.Administration.SPWebService]::ContentService.DeveloperDashboardSettings;
$DevDashboardSettings.DisplayLevel
= 'OnDemand';
$DevDashboardSettings.RequiredPermissions =
'EmptyMask';
$DevDashboardSettings.TraceEnabled =
$true;
$DevDashboardsettings.Update();

The both above methods will
enable developer dashboard to entire farm level.


UPDATED**
"DevDashboardSettings.RequiredPermissions determines which
users will see the developer dashboard. EmptyMask means all users will be able
to access developer dashboard. Any mask available in SPBasePermissions object
can be used to filter down to a specific group so that only a small subset of
users will be able to access developer dashboard."

Now, when you browse
to the web site you can't find it immediately on the screen. You need explicitly
enable for the page. Find a small image at the corner of the page as shown
below.

That image behaves as a toggle button. When you
click very first time then the developer dashboard will be enabled for the
specific page. When you click again, then it will go off. You can't see that
until you click it again.
How it looks like:


Note: This option is page specific
level. So, when you enable it and move to another page it's default state is
closed/disabled.

How to delete event receiver from a SharePoint list

In  Hot wo add event receiver to a SharePoint list, we saw how we added an event receiver to a list. Now, we will see how
to delete the existing event receiver on a list.

  1. private void DeleteEventReceiverFromAList(string siteUrl)  

  2.     {  

  3.         using (SPSite site = new SPSite(siteUrl))  

  4.         {  

  5.             using(SPWeb web = site.OpenWeb())
     

  6.             {  

  7.                 try 

  8.                 {  

  9.                     SPList list = web.Lists["myList"];  

  10.                     if (list != null)  

  11.                     {  

  12.                         string className = "EventReceiverClass";  

  13.                         string asmName = "EventReceiverAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a865f0ecc234ea51";
     

  14.                         web.AllowUnsafeUpdates = true;  

  15.  

  16.                         int receivers = list.EventReceivers.Count;
     

  17.                         bool isAddedReceiverExist = false;  

  18.                         bool isUpdatedReceiverExist = false;  

  19.                         for (int i = 0; i < receivers; i++)
     

  20.                         {  

  21.                             SPEventReceiverDefinition eventReceiver = list.EventReceivers[i];
     

  22.                             if (eventReceiver.Class == className && eventReceiver.Type == SPEventReceiverType.ItemAdded)
     

  23.                             {  

  24.                                 eventReceiver.Delete();  

  25.                                 break;  

  26.                             }  

  27.                         }  

  28.                     }  

  29.                 }  

  30.                 catch { }
     

  31.                 finally 

  32.                 {  

  33.                     web.AllowUnsafeUpdates = false;  

  34.                 }  

  35.             }  

  36.         }  

  37.     } 
In this code also, there is nothing to explain very detail. Please let me
know if you have any questions.

Hot wo add event receiver to a SharePoint list

This is very generic and everyone knows how to add an event receiver. But,
usually we attach the event receiver on a list template, site etc. This post
deals with adding event receiver to a specific list.

  1. private void AddEventReceiverToAList(string siteUrl)  

  2. {  

  3. using (SPSite site = new SPSite(siteUrl))  

  4. {  

  5. using (SPWeb web = site.OpenWeb())
     

  6. {  

  7. try 

  8. {  

  9. SPList list = web.Lists["myList"];  

  10. if (list != null)  

  11. {  

  12. int receivers = list.EventReceivers.Count;
     

  13. string className = "EventReceiverClass";  

  14. string asmName = "EventReceiverAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a865f0ecc234ea51";
     

  15. web.AllowUnsafeUpdates = true;  

  16. bool isAddedReceiverExist = false;  

  17. for (int i = 0; i < receivers; i++)
     

  18. {  

  19. SPEventReceiverDefinition eventReceiver = list.EventReceivers[i];
     

  20. if (eventReceiver.Class == className && eventReceiver.Type == SPEventReceiverType.ItemAdded)
     

  21. {  

  22. isAddedReceiverExist = true;
     

  23. break;
     

  24. }  

  25. }  

  26. if (!isAddedReceiverExist)
     

  27. list.EventReceivers.Add(SPEventReceiverType.ItemAdded, asmName, className);
     

  28. }  

  29. }  

  30. catch { }
     

  31. finally 

  32. {  

  33. web.AllowUnsafeUpdates = false;  

  34. }  

  35. }  

  36. }  

This is very straight forward code and hope you got it.

How to access web.config in SharePoint timer job

 

In SharePoint customization we have the requirements to write custom code for
web parts, timer jobs etc. In this post I want to tell you some interesting
things in SharePoint. I have written some timer jobs to deploy into my
SharePoint server to match some requirements or to solve some problems.


My requirement is, I want to access the web application or web site
configuration [web.config] file in the SharePoint timer job. But, the
limitations in SharePoint stops me to access the configuration files in timer
job. Below are the problems I faced.


  • SharePoint timer job is running in different process named OWSTIMER.EXE.
  • SharePoint web application or site will run with the help of process
    W3WP.EXE.
  • So, the application configuration file is associated with the W3WP.EXE, so
    there is no way to access the web.config file in the owstimer.exe process at
    all. The context is completely different and out of domain. So, we need to call
    or access the web.config file explicitly in timer job. How to?
  • Remember, always C# is completely object oriented and you can access
    everything through objects.
  • Usually the timer job installed as a feature. And all the logic of the timer
    job will go inside the Execute() method. So, write below statements in that
    method and access the complete web.config file. Below is the example of
    accessing appsettings.
 SPWebApplication webApplication = this.Parent as SPWebApplication;  
Configuration config = WebConfigurationManager.OpenWebConfiguration("/", webApplication.Name);  
String appValue = config.AppSettings.Settings["appSettingKey"].Value;
 
WebConfigurationManager is the class which is in the namespace
Systen.Web.Configuration. This way, you can access the config settings from a
web.config of a SharePoint web site. Hope you understood this well and please
let me know what you think.

Add a Web service 2.0 in SharePoint 2007 step by step

Today at my work, I need to implement JQuery in SharePoint on a module. I
need to make AJAX calls to get the data from the database depending on the value
in a text box. So, I choose JQuery, because I know it well and it will take very
less time to implement. But for JQuery I need to create page web methods. But
SharePoint doesn't support Page web methods because SharePoint is completely
built upon ASP.NET 2.0.


So, what is the solution, how can I make a call to the server and get the
data from DB? After thought some time about it, finally I got a brilliant and
better idea of using web services. Please follow the steps below to implement
Web services in SharePoint.



  • We are using client side technologies like JQuery etc to call Web service to
    get the data from server. By default, it is not supported. For that, we need the
    supporting DLL's[System.Web.Script.Services] for the Web service
    script on the SharePoint server. These DLL's are needed to process the web
    service request and send the response[JSON]. For those DLL, you need to install
    the Ajax extensions 1.0.
  • Create a web service using Visual studio. It will generate
    two files webservice.asmx and webservice.cs. Write all the web methods required
    inside the webservice.cs file. I will explain you with an example more detail
    later in this post.
  • Now, we need a location to keep our *.cs [webservice.cs] file. So, for that,
    create App_Code folder in the SharePoint site file system
    virtual directory root [c:\inetpub\…\wss\virtualdirectories\portnumber]. You can
    find the advantages of using App_code folder, in SharePoint web application App_Code folder in SharePoint – Custom web services in SharePoint – Part 1.
  • By default SharePoint won't allow the script handlers and http modules. For
    this reasons, we need to make the web.config changes as
    explained Web.config changes - Custom web services in SharePoint 2007 – Part 2.
  • Change the settings in central admin to remove asmx extension from blocked
    file types. Blocked file types in SharePoint 2007 – Custom web services 2.0 in SharePoint 2007 – Part 3.

After you are ready with all the above steps, then please follow the steps
below.



  • Check the related dll's are added in the system, after installed Ajax
    extensions. Below are the namespaces you required in the webservice.cs file.

    using System.Web.Services;
    using
    System.Web.Script.Services;


  • Copy the webservice.asmx file to the SharePoint website virtual directory
    file system path [c:\inetpub\…\wss\virtualdirectories\portnumber\].
  • Copy the file webservice.cs file, and paste it in the app_code folder of the
    SharePoint web site.
  • Please follow the post web.config changes as explained.
  • Central administration changes as explained above.

There we are done with the process. This is really working great and we can
solve really very difficult problems like all scenarios where we need to
communicate with DB without doing post back etc. This is very smooth and fast
way of retrieving results. I like to hear feedback. This is the one of the best
solutions I found. Please post any problems if you face while implementing this
process.

Blocked file types in SharePoint 2007 – Custom web services 2.0 in SharePoint 2007 – Part 3

Please read the post "Add a Web service 2.0 in SharePoint 2007 step by step " before
continue here.


I think, most of the people don't know about blocked file types and where can
we set them. SharePoint by default, won't allow all the file extensions because
of some security issues.


Why the SharePoint team didn't allow them by default. There is a strong
reason behind it. i.e. not other than Security reasons. For example, EXE
extension file, script files etc.


How to remove a blocked file type?



  • Open central administration site.
  • Go to Operations tab.
  • Find a section named "Security Configuration".
  • Under this section, you can find a link for "Blocked file
    types
    ".

    Blocked file types



  • On this page, you can see a text box area which displays all the file
    extensions one per line, which SharePoint blocked by default.

      image



  • You can edit and delete the extension. Then SharePoint allows user to upload
    the file or access the file.

So, if you are facing the problem of not able to upload the files of type
.asmx, .exe, .chm etc.. This is the place where you set it. Happy
SharePointing.

Web.config changes - Custom web services in SharePoint 2007 – Part 2

Please read the article "Add a Web service 2.0 in SharePoint 2007 step by step " before
continue this post. Then you will get some idea on what is the need of change in
web.config for implementing custom web service 2.0 in SharePoint.


SharePoint framework don't allow to call web services from java script by
default. For this, we explicitly tell the web application that when any request
from javascript to web services then use this http handlers, http modules and
allow *.asmx files to serve in SharePoint.


So, please follow the steps below.


Changes required in the sections.



  • HttpHandlers and httpModules in
    <System.Web> section.
  • Adding a new section named <System.WebServer>.
  • This is not needed, but useful if you have installed two versions of Ajax
    libraries[1.0 and 3.5] for System.Web.Extensions. Assembly binding redirect in
    <runtime>
  • Add  System.web.Extensions assembly to the <assemblies> section. This
    is very important.

Please add the sections as it is in the web.config file of your SharePoint
web site to get the web services 2.0 work.


1. <httpHeaders> section:
    <remove verb="*"
path="*.asmx"/>
    <add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/></httpHandlers>


2. <httpModules> section:


    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>


3. <System.WebServer> section:


<system.webServer>
        <validation
validateIntegratedModeConfiguration="false"/>
        <modules>

            <remove name="ScriptModule"/>
            <add
name="ScriptModule" preCondition="managedHandler"
type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
       
</modules>
        <handlers>
            <remove
name="WebServiceHandlerFactory-Integrated"/>
            <remove
name="ScriptHandlerFactory"/>
            <remove
name="ScriptHandlerFactoryAppServices"/>
            <remove
name="ScriptResource"/>
            <add name="ScriptHandlerFactory"
verb="*" path="*.asmx" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

            <add name="ScriptHandlerFactoryAppServices" verb="*"
path="*_AppService.axd" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

            <add name="ScriptResource" preCondition="integratedMode"
verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

        </handlers>
    </system.webServer>


4. <runtime> Section:


<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

            <dependentAssembly>
               
<assemblyIdentity name="System.Web.Extensions"
publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect
oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
           
</dependentAssembly>
            <dependentAssembly>

                <assemblyIdentity name="System.Web.Extensions.Design"
publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect
oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
           
</dependentAssembly>
        </assemblyBinding>


5. <assemblies> section:


Add this entry to <assemblies> section.


<add assembly="System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35" />


That's it!!! With these changes it will allow you to access web services from
java script. I spent my valuable time to find this way to solve so many
problems. Do you like this?

App_Code folder in SharePoint – Custom web services in SharePoint – Part 1

On the way of explaining the process of implementing custom web services in
SharePoint, I thought of telling you the advantage of App_Code folder in
SharePoint. So, Please read Add a Web service 2.0 in SharePoint 2007 step by step before continue here.


If you are a .NET developer then you know the advantage of App_Code folder.
When I am new to SharePoint technology, I thought like we can't add App_Code
folder in SharePoint root folder because i didn't find it in the virtual
directory path. […/Inetpub/wwwroot/…../] But few days back, when I got time, I
want to do experiment on the App_Code folder in SharePoint. So, what are the
advantages and how to do it please follow below steps.



  • Go to SharePoint web site virtual directory file system path. There you can
    find web.config file, _app_bin, App_Browsers etc…
  • Create a folder named App_Code.
  • Copy a class file [.cs], which you want to use in SharePoint coding inside
    the App_Code folder.

Now, you can access this class any where in the SharePoint web site. Very
useful one right?

How to read xml from web page and bind the data to Silverlight module in SharePoint 2007 Part-2

Some times we have requirements in SharePoint that we need to pull images from
SharePoint library and display those images in Silverlight module with rich UI.
But we know that Silverlight runs on client side, we can't access the SharePoint
libraries in the Silverlight projects because of permission issues as
well.
So, here we build an architecture that SharePoint will build the XML
for us and write it on the page and Silverlight grabs the XML from the page and
displays the images on the UI. How nice it is. You can get the first part i.e.
get xml (image) data from the SharePoint libraries How to show images in Silverlight by reading images from SharePoint 2007 library Part-1.

Here,
we are discussing about the code we need to place in Page.xaml.cs file to read
xml from web page.

  1. public Page()
     

  2. {  

  3. string controlid = "divImgs"; //You can also use intiparams of Silverlight params to get the id.
     

  4. InitializeComponent();  

  5.  

  6. string xmlstring = string.Empty;  

  7. if (controlid != null)  

  8. {  

  9. HtmlElement ctl = HtmlPage.Document.GetElementById(controlid);
     

  10. if (ctl != null)  

  11. xmlstring = (string)ctl.GetProperty("innerHTML");  

  12. }  

  13.  

  14. if (!string.IsNullOrEmpty(xmlstring))
     

  15. {  

  16. ProcessXML(xmlstring);  

  17. }  

The above code is the Page constructor of the Page. Xaml.cs file.
1.
Here, we are catching the control on the HTML document and reading it's HTML. if
you remember, while coverting the data view web part data from HTML to XML, in
the XSLT i assigned an id for a html tag called "divImgs". We are using this id
here in the cs file, and reading the HTML, obviously it will get the xml data to
the xmlstring variable.
2. No, we need to process the XML and bind the data
to the silverlight control. This is why i am calling a function called "Process
XML".

  1. private void ProcessXML(string xml)  

  2. {  

  3. images = new List<string>();  

  4. if (xml != string.Empty)  

  5. {  

  6. try 

  7. {  

  8. StringReader textStream = null;  

  9. textStream = new StringReader(xml);  

  10.  

  11. if (textStream != null)  

  12. {  

  13. using (XmlReader reader = XmlReader.Create(textStream))
     

  14. {  

  15. while (!reader.EOF)
     

  16. {  

  17. if ((reader.IsStartElement()) && (reader.LocalName == "slides"))  

  18. {  

  19. if (reader.HasAttributes)  

  20. {  

  21. reader.MoveToAttribute("baseUrl");  

  22. }  

  23. }  

  24. else 

  25. {  

  26. if ((reader.LocalName == "slide") && (reader.HasAttributes))
     

  27. {  

  28. reader.MoveToAttribute("imageUrl");  

  29. string imageName = reader.Value.ToLower();
     

  30. if ((imageName.Contains(".jpg")  

  31. || imageName.Contains(".png")))  

  32. images.Add(reader.Value);  

  33. }  

  34.  

  35. }  

  36. reader.Read();  

  37. }  

  38. }  

  39. }  

  40. }  

  41. catch (Exception ex)
     

  42. {  

  43. }  

  44. }  

3. In the above code, images is the global variable of type
List<string>. We are filling this object with the image urls by reading
the xml string.
4. Now by calling the ProcessXML function, we are done with
getting image urls. So we have collection of image urls, and use this object to
give input as the Silverlight module controls and display on the UI.
 

How to show images in Silverlight by reading images from SharePoint 2007 library Part-1

 Hi,
Silverlight works on client side, so it's not possible to add
SharePoint libraries in Silverlight project. But we have a way that we can
access SharePoint data and show it up in Silverlight in SharePoint site.
We
have a requirement where we need to pull data from the SharePoint libraries and
lists and show the data in Silverlight. Here i will explain a scenario where we
can pull the images from image library and show it in Silverlight.


Follow the steps below to do this.
Get data from SharePoint library and make it in the
form of XML.



  1. Go to the page where we want to show the Silverlight module on the site or
    create a new page.
  2. Open the page in SharePoint designer.
  3. Add a data view web part to the page some where in web part zone.
  4. Select the data source library from Task Pane menu.
  5. Select the library/list from the data source library where your images are
    present.
  6. Click on the library and select Show Data.

  7. Select the columns, which refer the Title, Image Path etc you want to show
    in Silverlight from Data Source details task pane.
  8. Select the option Insert select fields as "Multiple item view". So now our
    data view web part is filled with the data. [If you want apply some properties
    like show images in asc order etc..]
  9. After selected the columns, apply a filter to get only images from the
    library/lists. we can do this by selecting the filters option from the data view
    web part.
  10. Here, select the image title or url column in the field name, in comparison
    select contains and here enter valid formats Silverlight allows in the value
    field.

  11. Save the page and open it in the browser [IE].
  12. Till now what we did is, we are getting the data from the SharePoint
    library/Lists and showing up it in the data view web part and it renders as a
    table.
  13. Now, we need to change the XSLT of the data view web part to get the table
    format of data as the XML format. We have XSLT, so we can easily do that.
  14. Add the below XSLT code to the data view web part by going to edit for the
    web part and modify settings --> XSL editor.
  15. Remove text in the editor and add this code.



  16. If you observe i am pulling some values from the data view and making xml.


  17. Now, when you save the web part and see the page, you can't see anything in
    the data view web part, because now your data is in the format of xml.
  18. You can see this by doing view source and search for "
  19. We are done with part 1 now. i.e. getting data from SharePoint library. Now
    we will move to second part.
Get XML
from the page and give that as input to Silverlight module:

At this
point, we got the xml i.e. xml is on the page, now we need to read the xml from
the page in the silverlight project and display the images as we want by
applying animations, styles etc..
You can see the part 2 How to read xml from web page and bind the data to Silverlight module in SharePoint 2007.

Conditional Statement example in SharePoint 2207 workflow


In SharePoint workflow, when we are using the if/else activities, the if/
else methods contains Event argument called ConditionalEventArgs.

if you set e.Result=true, then if block will executes,

if you set e.Result=false, then else block will executes.


private void
IfMethod(object sender, ConditionalEventArgs e)


{


if (isTrue)


e.Result = true;


else


e.Result = false;


}



private void
ElseMethod(object sender, ConditionalEventArgs e)


{


if (!isTrue)


e.Result
= true;


else


e.Result = false;


}


depending on the boolean variable "isTrue", the if/else blocks will
executes…

In the above case, i am setting "isTrue" variable depending on my logic,
before calling if/else statements.

For while activity also, same logic applies.

if you set e.Result=true, it will iterate until you set
e.Result=false.

Role of ItemMetadata.xml in Infopath forms [SharePoint 2207 workflow]

 Introduction:

ItemMetadata.xml is the file used to store/transfer
the data from one Infopath to another. The name of the file is case -
sensitive.

For example, in a sharepoint workflow, there are 10 steps, in
each step we are using infopath and we want send some information from one to
the next infopath form, the information won't save any where. we need to tell
explicitly to infopath to store in xml file. that is nothing but
ItemMetadata.xml.

It acts as the secondary data source to the
infopath.

To compensate for the possibility of schema differences between
the task data and the form it only stores the schema instead of
data.

Example schema is

<z:row xmlns:z="#RowsetSchema"
ows_fieldname=""/>

Note: Every field name should be prefixed with
ows

In programming, we can retrieve the data from info path using the
property called
ExtendedProperties.

afterProperties.ExtendedProperties["filedName"].ToString();

How to create new instance of SharePoint 2007 workflow through C# code

 In SharePoint 2007, very good feature I like much is that framework
supports for writing custom events, features, workflows or any other stuff... We
can customize complete SharePoint system at any context.
While working with
SharePoint custom workflows, we get some scenarios where we need to stop a
workflow or start a new instance of workflow through coding. So, I did some
research on the MSDN library and saw all the dll's by doing some reflection on
the libraries and found some functions and classes which supports
this.

Here, I want to present a small code snippet which does terminating
currently running wokflow and start a new instance of the workflow on the same
list item.

  1. SPListItem listItem = workflowProperties.Item;
     

  2. SPList spList = workflowProperties.List;  

  3. string initData = workflowProperties.InitiationData;
     

  4.  

  5. const string WF_GUID = "The GUID of workflow template";
     

  6. workflowProperties.Site.WorkflowManager.RemoveWorkflowFromListItem(workflowProperties.Workflow);
     

  7. workflowProperties.Site.WorkflowManager.Dispose();
     

  8.  

  9. SPWorkflowAssociation associationTemplate= spList.WorkflowAssociations.GetAssociationByBaseID(new Guid(WF_GUID));  

  10.  

  11. workflowProperties.Site.WorkflowManager.StartWorkflow(listItem, associationTemplate, initData); 

Hope this will give you a good start to code on SharePoint workflow start and
terminate through coding. Let me know, what you think.

Give anonymous access to the reports

Give anonymous access to the Application.

1. Go to IIS.

2. Select
reports application –> properties –> Directory Security –>
Authentication and Access control –> Edit –> Enable Anonymous
access

Give anonymous access to a report.

1. Open the reports on
the report server located at http://<servername>/reports

2. Browse
to the report that needs to be accessed anonymously.

3. Select properties
tab for the report.

4. Select security from the left
navigation.

5. Select New Role Assignment from this page.

a. Give
a group name - everyone (in the "group or user name" text box).

b. Select
the option Browser role and then click OK.

[Browser role is for READ -
ONLY access].

SharePoint 2007 : My Calendar web part login problem for different accounts

 Introduction
When i work with
my calendar web part in SharePoint i got lot of questions and things happend. I
configured every thing correctly in My Calendar web part. i.e. Mail server
address, Mailbox.
But, when i open the page which contains calendar web part,
it prompts for user name and password of SharePoint site and another for the
Calendar login . i.e. login page of OWA application. If i provide the
credentials it will work very fine.

Now the problem starts. If the same
application is trying to access by another users, other than me then they always
failed to login to my calendar web part. This is because, in mailbox i given my
mail account, when others try to access the web part, it won't work at all. What
they need at that time is they will edit the web part, and will change the mail
box entry to their own email address. But this is not possible for all users
because all users don't have access to edit page/web part.

My Calendar
web part is not working for multiple users in SharePoint 2007. When you add the
web part on a page, which mail entry you given in the Mail box that account only
can login. I will tell you the reason behind it. My calender web part is
developed only for the purpose of showing their calendar events on the my site page. My site usually have access to
edit/delete etc for current logged in user, so he will see the content belongs
to him. But as per my requirements i want to use the calendar on the site other
than the my site pages.

Solution
To solve the above mentioned
problem, i created a custom web part to work for any logged in user. You can get
this code and build it, add the appsetting variables in the web.cofig and deploy
it to your site, You can get the deploy instructions of web part in
MSDN.

Web.Config changes:
We
need to provide 2 inputs to the web part.
1. Site Url.
2. Exchange Server
Url.

Requirements:
We have
setup a job [Usually we will setup while installing SharePoint and configuring
the SSP] in your SharePoint server Shared services Provider [SSP], to pull user
accounts from the Active Directory to Sharepoint profile database. Because below
code gets the emailid automatically from the user profile database depending on
the logged in user. And places that emailid in Mail Box entry of the my calendar
web part.

Usually, when we configure the Profile import, we will give
source and configure the schedule too. i.e. Every day night or every week etc…
it pulls data from given source [ex: Active directory] to profile
database.



 
  1. using System;
     

  2. using System.Collections.Generic;
     

  3. using System.Text;
     

  4. using Microsoft.SharePoint.Portal.WebControls;
     

  5. using Microsoft.SharePoint.Portal.Topology;
     

  6. using Microsoft.SharePoint.Portal;
     

  7. using Microsoft.SharePoint.Portal.UserProfiles;
     

  8. using System.Runtime.InteropServices;
     

  9. using System.Web.UI;
     

  10. using System.Web.UI.WebControls;
     

  11. using System.Web.UI.HtmlControls;
     

  12. using System.Configuration;namespace MyCalendarWebPart  

  13. {  

  14. [Guid("15241046-2128-4a1d-b6d5-24c8a67c4d28")]
     

  15. public class MyCalendarWebPart : Microsoft.SharePoint.WebPartPages.WebPart
     

  16. {  

  17. private OWACalendarPart wpCalendar;
     

  18. HtmlGenericControl litMsg = null;  

  19. HtmlGenericControl roundedCorner;  

  20.  

  21. protected override void CreateChildControls()  

  22. {  

  23. wpCalendar = new OWACalendarPart();  

  24. litMsg = new HtmlGenericControl();  

  25. roundedCorner = new HtmlGenericControl();  

  26. roundedCorner.InnerHtml = "";  

  27.  

  28. Controls.Add(configureCalendar());  

  29. Controls.Add(litMsg);  

  30. Controls.Add(roundedCorner);  

  31.  

  32. base.CreateChildControls();
     

  33. }  

  34.  

  35. private OWACalendarPart configureCalendar()
     

  36. {  

  37. try 

  38. {  

  39. //Connect to the portal and get the portal context.
     

  40. TopologyManager topology = new TopologyManager();  

  41. PortalSite portal = topology.PortalSites[new Uri(ConfigurationManager.AppSettings["SiteUrl"])];  

  42. PortalContext context = PortalApplication.GetContext(portal);
     

  43.  

  44. //initialize user profile config manager object
     

  45. UserProfileManager profileManager = new UserProfileManager(context);
     

  46. UserProfile profile = profileManager.GetUserProfile(true);  

  47.  

  48. wpCalendar.Title = "My Calendar";  

  49. wpCalendar.ViewName = "Weekly";  

  50. wpCalendar.CssClass = "";  

  51.  

  52. // use the profile object to retrieve the properties you need in your company to
     

  53. // retrieve the mail box name
     

  54. string workmail = profile[PropertyConstants.WorkEmail].ToString();
     

  55.  

  56. wpCalendar.MailboxName = workmail;  

  57. wpCalendar.OWAServerAddressRoot = ConfigurationManager.AppSettings["ExchangeServerUrl"];  

  58.  

  59. wpCalendar.Height = "655″;  

  60. wpCalendar.Width = "600″;  

  61. wpCalendar.ImportErrorMessage = "No EmailID found for your account.";  

  62. }  

  63. catch 

  64. {  

  65. litMsg.InnerHtml = "No EmailID found for your account.";  

  66. }  

  67.  

  68. return wpCalendar;
     

  69. }  

  70.  

  71. protected override void RenderWebPart(HtmlTextWriter output)
     

  72. {  

  73. try 

  74. {  

  75. wpCalendar.RenderControl(output);  

  76. litMsg.RenderControl(output);  

  77. roundedCorner.RenderControl(output);  

  78. }  

  79. catch (Exception ex)
     

  80. {  

  81. output.Write(ex.ToString());  

  82. }  

  83. }  

  84.  

  85. public override void RenderControl(HtmlTextWriter writer)
     

  86. {  

  87. base.RenderControl(writer);  

  88. }  

  89. }  


Note: In above code i am pulling site url and exchange server url from
the appsettings of web.config of the site.

Group By in DataTable in C# Linq in SharePoint 2010

//Get data from SharePoint
            SPWeb _web = GetWeb();
            SPList list = _web.Lists["List"];
            SPQuery query = new SPQuery();
            query.Query = "" + _user.Name.Trim()
                          + ""
+ selectedYear.Trim() + "";
DataTable dt = list.GetItems(query).GetDataTable();

//Get DataRows
            if (dt != null && dt.Rows.Count > 0)
            {
                //Group the data
                var groupedRows = from row in dt.AsEnumerable()
                                  group row by row.Field(dt.Columns["Department"]) into grp
                                  orderby grp.Key
                                  select new
                                  {
                                      Name = grp.Key,
                                      _grp = grp
                                  };
                foreach (var grp in groupedRows)
                {
                    AccordionPane currentPane = CreateAccordinHeaderPane(mainacc, grp.Name);
                    groupedRows.ToList();
                    List rows = grp._grp.ToList();
                    AddContentToPane(currentPane, rows);
                }
            }
DataTable dt = new DataTable();
            dt = rows.CopyToDataTable(); -> Gets

Programmatically upload user profile picture Sharepoint 2010

The first things would be to create a custom screen for uploading a picture into the User Photos Picture library (url – http://SpSite/User%20Photos/Profile%20Pictures).

Then updating the user profile to refer the new uploaded picture. Below is the code that will do just that.

public void UpdateUserPicture(SPSite site)
{

string userAccount = "domain\\account";

ServerContext ctx = ServerContext.GetContext(site);

UserProfileManager upm = new UserProfileManager(ctx);

UserProfile up = upm.GetUserProfile(userAccount);

UploadUserPircutre();

up["PictureUrl"].Value = "http://SpSite/User%20Photos/Profile%20Pictures/pic.jpg";

up.Commit();
}

Get values from multichoice column client object model sharepoint 2010

A short code snippet about how to add and retrieve values from multichoice column using client object model.

ListItemCollection listItems = list.GetItems(camlQuery);

//Add values -

listItems[0]["MultiChoiceField"] = newstring[] {"Choice 1″,"Choice 4″ };

//Retrieve -

  if (listItems[0]["testmultichoice"] != null)
      {
        string[] values = listItems[0]["testmultichoice"] as string[];

        if (values != null)
        {
          var result = from c in values where c.Contains(searchChoice) select c;
          if (result != null)
            choices = result.ToList();
        }

      }
      return choices;

Update Meeting Workspace Theme Programmatically SharePoint 2010

I want to update the theme for a meeting workspace during its creation.

I have added this code to the ONET.xml file (Configuration ID=0) in the MPS Site Template:

<Feature ID="39DD29FB-B6F5-4697-B526-4D38DE4893E5″ />

</WebFeatures>

<ExecuteUrl Url="_layouts/SiteMap/SiteMap.aspx?thmx=1″/>

</Configuration>

So in the URL specified above, it passes a parameter used to identify a portion of code to execute in the page_load event.

here is the code in the SiteMap page:

string theme = Request.QueryString.Get("thmx");       if (theme != null)       {         SPWeb thisWeb = SPContext.Current.Web;         SPWeb TempWeb = SwitchUser(thisWeb, thisWeb.Url, "System");         TempWeb.AllowUnsafeUpdates = true;         TempWeb.Update();          SPSite site = new SPSite(SPContext.Current.Site.RootWeb.Url);          ReadOnlyCollection<ThmxTheme> managedThemes = null;         managedThemes = ThmxTheme.GetManagedThemes(site);         foreach (ThmxTheme theme2 in managedThemes)         {           if (theme2.Name == "IH_Custom")           {             //theme2.ApplyTo(TempWeb, true);             ThmxTheme.SetThemeUrlForWeb(TempWeb, theme2.ServerRelativeUrl);             TempWeb.Update();             break;           }         }         TempWeb.AllowUnsafeUpdates = false;         Response.Redirect(TempWeb.Url);       } 

Ignore the switchUser routine; I was just testing to see if the System account was getting the same error.  In both cases (as current user or System) I was getting this error when it hit either of these lines of code to execute:

//theme2.ApplyTo(thisWeb, true);  OR

ThmxTheme.SetThemeUrlForWeb(TempWeb,
theme2.ServerRelativeUrl);

Customize the ribbon programmatically from web parts and field controls

In this article series:

  1. Customizing the ribbon – creating tabs, groups and controls
  2. Adding ribbon items into existing tabs/groups
  3. Ribbon customizations - dropdown controls, Client Object Model and JavaScript Page Components
  4. Customize the ribbon programmatically from web parts and field controls (this post)

In contrast to my earlier posts, this article isn't a detailed walkthrough – rather, it is a compendium of techniques and information which should help you implement ribbon customizations for web parts, custom field controls or indeed, any other kind of page control. At the time of writing I haven't really seen a great deal written on this, aside from a couple of resources I'll mention. I would have loved to have written detailed walkthroughs here, but alas I can't because a) Microsoft have recently published some good info for one of the scenarios, so I'd prefer to point you to that, b) To run through all the scenarios here in depth would take weeks and c) Because if I don't stop writing about the ribbon soon I'll still be on this topic this time next year, and frankly I have a book chapter to write on a completely different area of SharePoint 2010 which I need to crack on with! So we'll look at each requirement and I'll discuss what I think are the key techniques you'd use along with some observations from me.

Note that due to the general lack of documentation so far on this topic (and the fact I haven't bottomed everything out in all the scenarios), a couple of things here are speculation rather than hard fact. I'll make these items clear, and will endeavour to come back to this article and add updates as new information emerges.

Before we dive in, remember that if you're abiding by ribbon design principles you should most likely be working with a ContextualGroup (discussed towards the end of Adding ribbon items into existing tabs/groups) – this is the container to use for ribbon elements which are only relevant depending on what the user is doing (shown visible but not active here):

ContextualGroup

If this isn't what you want, note that things are probably easier if you just need to add some controls on an existing tab or group which get activated under certain circumstances. In this case you can just supply some JavaScript to the 'EnabledScript' attribute of your controls – I showed this in my Notifications/Status demo in Customizing the ribbon (part 1) – creating tabs, groups and controls. The rest of this article focuses on how you might get a contextual group (see image above) to show in different scenarios.

Adding ribbon items from a web part

In SharePoint 2010 the web part framework now has special provision for ribbon customizations, which means a couple of things are taken care of for you. Microsoft have now published some guidance on this scenario in the form of an article on the SharePoint Developer Documentation blog - How to Create a Web Part with a Contextual Tab. There's a lot of golden info in there, but I'll distil the main points here:

  • Using server-side code, the 'RegisterDataExtension' method of SPRibbon can be used to pass XML to the ribbon framework.
    • This is an alternative to the fully declarative approach using the CustomAction element. As far as I can tell, either technique can be used for ribbon customizations specific to a certain control only (as opposed to ribbon customizations for say, all lists of a specific type where CustomAction is the way to go).
  • Your web part needs to implement the new IWebPartPageComponentProvider interface and it's WebPartContextualInfo property
    • This allows you to specify information about the associated ribbon customization(s) and the ID of the associated page component (which we discussed last time) for your custom bits. This allows the ribbon framework to 'link' your web part with your ribbon changes – meaning that certain things are taken care of for you e.g. firing commands only when your web part has focus on the page (if you specified this behaviour by use of 'getFocusedCommands' in your page component). Without this you would have to write JavaScript code to manually handle page events for controls emitted by your web part e.g. the click event for a textbox.

Adding ribbon items from a field control

Like web parts, I think (speculating here) there is special provision in the framework for ribbon customizations from a field control. Consider that, like web parts, field controls should typically only show their contextual ribbon options when they have focus - since this would be the case for all field controls, it makes sense to me that Microsoft might abstract some handling around this for us. If not, you would be responsible for writing JavaScript to detect when the user clicked into your field so that you could show your ContextualGroup.

Digging around, I notice that all SharePoint field controls have 4 new properties (since they are implemented on one of the base classes, Microsoft.SharePoint.WebControls.FormComponent):

  • RibbonTabCommand
  • RibbonContextualGroupCommand
  • RibbonGroupCommand
  • RibbonCommand

I'm surmising that these control properties would be set declaratively in the hosting page and are designed to match up with commands specified in an accompanying page component - this would enable you to run client-side code similar to my sample last time, perhaps to initialize data for your ribbon controls and so on. However, when I try to implement these commands, my page component's 'handleCommand' method never receives these commands. So either I'm doing something wrong or this theory is incorrect. In which case, not to worry ribbon customizations for field controls should still be entirely possible, there will just be more work to do. Read on.

Using server-side code to show ribbon items

Thinking outside of any 'framework support' for where our ribbon customizations are targeted at, we can always write server-side or client-side code to show a contextual group. In fact, I already showed the server-side code for this in Adding ribbon items into existing tabs/groups (ribbon customization part 2):

 protected override void OnPreRender(EventArgs e)
 {
     SPRibbon currentRibbon = SPRibbon.GetCurrent(this.Page);
     currentRibbon.MakeTabAvailable("COB.SharePoint.Ribbon.ContextualTab");
     currentRibbon.MakeContextualGroupInitiallyVisible("COB.SharePoint.Ribbon.ContextualGroup", string.Empty);
     
     base.OnPreRender(e);
 }

This is probably only appropriate if your stuff is contextual-ish – an application page would be a good example of this. In this example all we care about is that the user is on our page, then we can show our options. It doesn't matter which control has focus, effectively our options are OK to show by default when the page loads. However, if you need page-level 'contextuality' (I may have just invented that word by the way - use it in a sentence to your boss today) then most likely you'll be wanting to use JavaScript to show your contextual group when the user is doing something specific on the page e.g. editing a certain field. You'd then be looking to some client-side code to detect this and respond accordingly.

Using client-side code to show ribbon items

So, final scenario - what if you need to show ribbon items from something which isn't a web part or field control (or like me you couldn't get there with anything in the field control framework which may or may not be designed to help), and it has to be done client-side to be fully contextual? Well, disappointingly I'm drawing another blank here so far – I'd love to hear from anyone who knows the answer to this. In case you're doing ribbon development and are interested, here's a summary of my journey:

  • Checked SP.Ribbon namespace in Client OM
  • Spent many happy hours in the debugger and various out-of-the-box JavaScript files, looking for examples of where the core product does this (e.g. calendar, rich text editor to name a couple)
  • Found some interesting methods on the CUI.Ribbon object, such as showContextualGroup('foo') and selectTabByCommand('bar')
    • Noted that across the entire SharePoint root, these methods are only called by the RTE, not globally across the SharePoint codebase
    • Noted that the RTE code gets a CUI.Ribbon instance from a property (RTE.RichTextEditorComponent.$3b() – N.B. most of the JS is obfuscated or machine-generated* down here)
  • Tried to use SP.Ribbon.PageManager.get_instance().get_ribbon() (used elsewhere in the OOTB codebase) to get me a CUI.Ribbon instance, however this gave me a null
  • Tried to use the '_ribbon' page level variable, however this appears not to be of type CUI.Ribbon as the debugger shows it does not have the methods I'm trying to call
  • Tried a couple of other things which I've forgotten now

Needless to say, I'd love to hear what I'm missing on this. If nothing else, hopefully MS will release some more information soon which will shed some light on how to handle this scenario.

Summary

This post doesn't claim to have all the answers, but it might serve as a "leg up" if you're trying to build any of these scenarios now. I'm hoping that the lack of deep information in this area is a reflection on the fact that RTM is still some time away, and that ribbon dev will get some love in the SDK between now and then. The key scenarios I discussed here are displaying custom ribbon elements from web parts and field controls, but also the more generic cases of displaying customizations with server or client-side code.

Ribbon customizations - dropdown controls, Client Object Model and JavaScript Page Components

In this article series:

  1. Customizing the ribbon – creating tabs, groups and controls
  2. Adding ribbon items into existing tabs/groups
  3. Ribbon customizations - dropdown controls, Client Object Model and JavaScript Page Components (this post)
  4. Customize the ribbon programmatically from web parts and field controls

Once you understand how to get your customizations into the right place in the ribbon, you may find you want to go beyond simply adding buttons and make use of other controls such as dropdowns, checkboxes, flyout anchors and so on. This type of ribbon development is fairly involved, but as with so many things in SharePoint development, once you've done it the first time you know the overall "template" for subsequent occasions - hopefully what I'm showing here is a good starting point for quite a few advanced things you might want to do. The key is that a JavaScript "page component" is generally required in addition to the declarative XML we've seen in my earlier posts.

[Beta sidenote] At the time of writing (Feb 2010, still in beta), after some time on this I'm forming the opinion that ribbon development could be one of the more complex development areas in SP2010. Maybe some stellar documentation from Microsoft could change this, but right now there are many dark corners which are quite difficult to understand – currently there is practically no coverage of much of this stuff in the SDK (and very little anywhere really), so unless you have inside information it's mainly blood, sweat and tears all the way. I've mentioned this to the PM in the Product Group (Elisabeth Olson), and it sounds like more MS guidance is on the way soon, so let's hope.

The sample

My sample shows the use of a custom dropdown in the ribbon – I'll go into more detail later, but the concepts I'm showing here can be used for many controls in the ribbon, not just a dropdown. So if what you're wanting to do doesn't specifically involve a dropdown, I'd suggest reading on anyway as this technique is still probably what you will use.

When clicked the first time, it uses the Client Object Model to fetch a collection of lists in the current web, then presents them as options in the dropdown:

CustomDropdownInRibbon

CustomDropdownInRibbonExpanded

When an item is selected, a simple JavaScript alert is raised with the name of the selected list, though a real-life implementation would of course do something more useful with the value. The goal here is to illustrate how to work with ribbon controls other than buttons, and also how to write code behind them – once you can do this, you'll be able to build a wide range of solutions.

One key thing to note – it IS possible to add items to a dropdown or other control entirely in XML. I'm choosing to use a JavaScript page component to illustrate what happens when you need "code-behind" e.g. to iterate all the lists in a web in my case.

What's required – summary

  1. Declarative XML to provision the ribbon controls
  2. JavaScript "page component", typically declared in external .js file
  3. Addition of JavaScript to page (using whatever technique is most appropriate to the scope of your ribbon customization – code in a web part/delegate control which is added to AdditionalPageHead, etc.). This will:
    1. Link the external .js file
    2. Ensure core dependent .js files are loaded e.g. SP.js, CUI.js
    3. Call into the initialization function within our page component – this registers our component with the ribbon framework and ensures our component gets added to the page.

    1. Declarative XML

    I used the following XML – here I'm actually showing a cut-down extract which is just for the group containing my controls. Really it's just the 'Controls' section which is the most interesting bit, the surroundings would depend on whether you are wanting to create a new tab or add the items into an existing tab/group, see my previous articles for those details.

    Key points of note are the Command, PopulateQueryCommand, and QueryCommand attributes on the dropdown – these will link into our JavaScript page component:

     <Group
       Id="COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup"
       Description="Contains advanced ribbon controls"
       Title="Page component sample"
       Sequence="53"
       Template="Ribbon.Templates.COB.OneLargeExample">
       <Controls Id="COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Controls">
         <Label Id="COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Label" 
                ForId="COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown" 
                Command="LabelCommand"
                LabelText="Select list:"
                Sequence="16" 
                TemplateAlias="c1"/>
         <DropDown
           Id="COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown"
           Sequence="17"
           Command="COB.PageComponent.Command.DoAction"
           PopulateDynamically="true"
           PopulateOnlyOnce="true"
           PopulateQueryCommand="COB.PageComponent.Command.PopulateDropDown"
           QueryCommand="COB.PageComponent.Command.QueryDoAction"
           Width="75px"
           TemplateAlias="c2" />
       </Controls>
     </Group>

    2. JavaScript page component

    This is the complex bit, the first time at least. We are effectively writing object-oriented JavaScript which contains a class which powers our ribbon control. Consider JavaScript such as this the 'template' to use for page components, where you'll modify the actual implementation bits each time. I've commented some key points, suggest having a scroll through and then we'll walk through the highlights:

     Type.registerNamespace('COB.SharePoint.Ribbon.PageComponent');
      
     COB.SharePoint.Ribbon.PageComponent = function () {
         COB.SharePoint.Ribbon.PageComponent.initializeBase(this);
     }
      
     // the initialize function needs to be called by some script added to the page elsewhere - in the end, it does the important work 
     // of calling PageManager.addPageComponent()..
     COB.SharePoint.Ribbon.PageComponent.initialize = function () {
         ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null, COB.SharePoint.Ribbon.PageComponent.initializePageComponent), 'SP.Ribbon.js');
     }
     COB.SharePoint.Ribbon.PageComponent.initializePageComponent = function() {
         
         var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
         if (null !== ribbonPageManager) {
             ribbonPageManager.addPageComponent(COB.SharePoint.Ribbon.PageComponent.instance);
         }
     }
      
     COB.SharePoint.Ribbon.PageComponent.prototype = {
         init: function () { },
      
         getFocusedCommands: function () {
             return ['COB.PageComponent.Command.FieldControl.GroupCommand', 'COB.PageComponent.Command.FieldControl.TabCommand', 'COB.PageComponent.Command.FieldControl.ContextualGroupCommand', 'COB.PageComponent.Command.FieldControl.RibbonCommand'];
         },
      
         getGlobalCommands: function () {
             return ['COB.PageComponent.Command.DoAction', 'COB.PageComponent.Command.PopulateDropDown', 'COB.PageComponent.Command.QueryDoAction'];
         },
      
         canHandleCommand: function (commandId) {
             if ((commandId === 'COB.PageComponent.Command.DoAction') 
                 (commandId === 'COB.PageComponent.Command.PopulateDropDown')  (commandId === 'COB.PageComponent.Command.QueryDoAction')) {
                 return true;        
             }
             else {
                 return false;
             }
         },
      
         handleCommand: function (commandId, properties, sequence) {
             if (commandId === 'COB.PageComponent.Command.FieldControl.GroupCommand') {
                 alert("COB.PageComponent.Command.FieldControl.GroupCommand fired");
             }
             if (commandId === 'COB.PageComponent.Command.FieldControl.TabCommand') {
                 alert("COB.PageComponent.Command.FieldControl.TabCommand fired");
             }
             if (commandId === 'COB.PageComponent.Command.FieldControl.ContextualGroupCommand') {
                 alert("COB.PageComponent.Command.FieldControl.ContextualGroupCommand fired");
             }
             if (commandId === 'COB.PageComponent.Command.FieldControl.RibbonCommand') {
                 alert("COB.PageComponent.Command.FieldControl.RibbonCommand fired");
             }
             if (commandId === 'COB.PageComponent.Command.QueryDoAction') {
                 // this command executes as soon as tab is requested, so do initialization here ready for if our dropdown gets requested..
                 loadCurrentWebLists();
             }
             if (commandId === 'COB.PageComponent.Command.PopulateDropDown') {
                 // actually build the dropdown contents by setting the PopulationXML property to a value with the expected format. We have to deal with possible 
                 // timing issues/dependency on core SharePoint JS code with an ExecuteOrDelay..
                 ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null, getDropdownItemsXml), 'SP.js');
      
                 properties.PopulationXML = getDropdownItemsXml();
             }
             if (commandId === 'COB.PageComponent.Command.DoAction') {
                 // here we're using the SourceControlId to detect the selected item, but more normally each item would have a unique commandId (rather than 'DoAction'). 
                 // However this isn't possible in this case since each item is a list in the current web, and this can change..
                 var selectedItem = properties.SourceControlId.toString();
                 var listName = selectedItem.substring(selectedItem.lastIndexOf('.') + 1);
                 alert("You selected the list: " + listName);
             }
         },
      
         isFocusable: function () {
             return true;
         },
      
         receiveFocus: function () {
             return true;
         },
      
         yieldFocus: function () {
             return true;
         }
     }
      
     // **** BEGIN: helper code specific to this sample ****
      
     // some global variables which we'll use with the async processing..
     var lists = null;
     var querySucceeded = false;
      
     // use the Client Object Model to fetch the lists in the current site..        
     function loadCurrentWebLists() {
         var clientContext = new SP.ClientContext.get_current();
         var web = clientContext.get_web();
         this.lists = web.get_lists();
      
         clientContext.load(lists);
         clientContext.executeQueryAsync(
                Function.createDelegate(this, this.onQuerySucceeded),
                Function.createDelegate(this, this.onQueryFailed));
     }
      
     function onQuerySucceeded() {
         querySucceeded = true;
     }
      
     function onQueryFailed(sender, args) {
         querySucceeded = false;
     }
      
     function getDropdownItemsXml() {
         var sb = new Sys.StringBuilder();
         sb.append('<Menu Id=\'COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown.Menu\'>');
         sb.append('<MenuSection DisplayMode=\'Menu\' Id=\'COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown.Menu.Manage\'>');
         sb.append('<Controls Id=\'COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown.Menu.Manage.Controls\'>');
         if (querySucceeded)
         {
             var listEnumerator = lists.getEnumerator();
      
             while (listEnumerator.moveNext()) {
                 var oList = listEnumerator.get_current();
                 
                 sb.append('<Button');
                 sb.append(' Id=\'COB.SharePoint.Ribbon.WithPageComponent.PCNotificationGroup.Dropdown.Menu.Manage.');
                 sb.append(oList.get_title());
                 sb.append('\'');
                 sb.append(' Command=\'');
                 sb.append('COB.PageComponent.Command.DoAction');
                 sb.append('\'');
                 sb.append(' LabelText=\'');
                 sb.append(SP.Utilities.HttpUtility.htmlEncode(oList.get_title()));
                 sb.append('\'');
                 sb.append('/>');
             }
         }
         sb.append('</Controls>');
         sb.append('</MenuSection>');
         sb.append('</Menu>');
         return sb.toString();
     }
       
     // **** END: helper code specific to this sample ****
      
     COB.SharePoint.Ribbon.PageComponent.registerClass('COB.SharePoint.Ribbon.PageComponent', CUI.Page.PageComponent);
     COB.SharePoint.Ribbon.PageComponent.instance = new COB.SharePoint.Ribbon.PageComponent();
      
     NotifyScriptLoadedAndExecuteWaitingJobs("COB.SharePoint.Ribbon.PageComponent.js");
      
    • The 'initialize' function is typically responsible for calling 'addPageComponent' on the ribbon PageManager (but not before SP.Ribbon.js has loaded)
    • The commands referenced in the JS are those specified in the control XML e.g. for my dropdown
      • The 'getFocusedCommands' function returns an array of commands which should execute when my control has focus
      • The 'getGlobalCommands' function returns an array of commands which should execute regardless of focus
      • We need to list the commands which can be handled in the 'canHandleCommand' function, and provide the actual implementation for each of these in 'handleCommand'
  1. Note the following crucial points about the various commands used:
    • PopulateQueryCommand – used to build the list of items in the control. This is where I'm using the Client Object Model (ECMAScript version) to fetch the lists for the current web.
    • QueryCommand – called when the parent container (e.g. tab) is activated. Remember the ribbon is all about "script on demand" (lazy loading), so I'm choosing this as a better place to do my initialization work of the actual Client OM request – more on this later.
    • Command – called when the user actually selects an item
    • IMPORTANT – these commands apply to lots of ribbon controls other than dropdowns e.g. FlyoutAnchor, SplitButton, ToggleButton, TextBox, Checkbox, Spinner, etc. This is why this information is relevant even if it's not specifically a dropdown control you're working with.
    • The key to populating controls which take collections is to use the 'properties' object passed to handleCommand, using either: ul>
    • properties.PopulationXML
    • properties.PopulationJSON
    • I'm using properties.PopulationXML to supply the items which should appear in my dropdown, and the format required is:
          1: <Menu Id="">
          2:   <MenuSection Id="">
          3:     <Controls Id="">
          4:       <Button Command="" Id="" LabelText="" />
          5:       ..a 'Button' element here for each item in the collection..
          6:     </Controls>
          7:   </MenuSection>
          8: </Menu>
      I haven't yet seen an example of how to use the .PopulationJSON property, so don't know the exact names to use in the JSON.
        • There are some interesting facets to combining the Client OM with the ribbon JS framework – effectively the async model used means the result of your method call may not be ready by the time the ribbon framework needs it (it happens on a different request after all). I'll explain how I dealt with this in my example towards the end of this article.

        3. Page-level JavaScript

        The final element is the JavaScript you need to add to the page to call into the page component. In my example I'm happy for this JavaScript to be added to every page in my site (since that's the scope of my ribbon customization), so I used a delegate control in AdditionalPageHead to add a custom user control, the body of which looks like this:

         <SharePoint:ScriptLink Name="sp.js" LoadAfterUI="true" OnDemand="false" Localizable="false" runat="server" ID="ScriptLink1" />
         <SharePoint:ScriptLink Name="CUI.js" LoadAfterUI="true" OnDemand="false" Localizable="false" runat="server" ID="ScriptLink3" />
         <SharePoint:ScriptLink Name="/_layouts/COB.SharePoint.Demos.Ribbon/COB.SharePoint.Ribbon.PageComponent.js" LoadAfterUI="true" OnDemand="false" Localizable="false" runat="server" ID="ScriptLink2" />
             <script type="text/javascript">
              
                 //<![CDATA[
                     function initCOBRibbon() {
                         COB.SharePoint.Ribbon.PageComponent.initialize();
                     }
              
                     ExecuteOrDelayUntilScriptLoaded(initCOBRibbon, 'COB.SharePoint.Ribbon.PageComponent.js');
             //    
             //]]>
        </script>

        The important things here are that we ensure required system JS files are loaded with the ScriptLink tag, do the same for our JS file, then call the .initialize() function of our page component.

        So those the component pieces for complex controls in the ribbon! A wide variety of ribbon customizations should be possible by tailoring this information/sample code as needed (remember 'handleCommand' is the key implementation hook), and I definitely think that starting from such a template is the way to go.

        Appendix - considerations for using the Client Object Model in the ribbon

        When working with the ribbon it quickly becomes apparent that if the Client Object Model didn't exist, things would be much trickier – they are a natural pairing for many requirements. Despite this, some challenges arise – consider that a control (e.g. dropdown) will have it's items collection populated as late as possible if 'PopulateDynamically' is set to true (generally a good idea) i.e. when the dropdown is actually clicked to select an item! This is because the ribbon is designed around a "script on demand" model (you'll often see "SOD" references in Microsoft's JavaScript) – this ensures only the required JavaScript is downloaded to the client, and no more. This solves the issue where on SharePoint 2007 WCM sites, we would suppress the core.js file for anonymous users because it was big and not required for these users. Anyway, when the dropdown is clicked, at this point the ribbon framework calls 'handleCommand' with the command specified for the 'PopulateQueryCommand' value. If you run your Client OM code here it's no good, since you won't get the result there and then due to the async model – the result will be provided to the callback function, long after 'handleCommand' has completed, so the end result is your control will be empty.

        Consequently, you need to do the actual processing before the 'PopulateQueryCommand' is called. You could choose to do as soon as the page loads, but in most cases this could be inefficient – what if the user doesn't come near your ribbon control on this page load? In this case we would have incurred some client-side processing and an extra request to the server which was completely unnecessary – on a high-traffic page, this could be bad news. Without any documentation it's hard to be sure at this stage, but it seems the 'QueryCommand' is a good place to put such Client OM code – this seems to be called when the parent container (e.g. tab) is made visible (at which point there's now a chance the user could use our control). In my code I have the actual Client OM query run here and store the result in page-level variable - this is then picked up and iterated for the 'PopulateQueryCommand'. By the time the script runs this command to populate the control, the query has already executed and has the data ready – happy days. I'll be interested to see what emerges in this area to see whether this is the expected pattern or, well, if I've got things completely wrong.

        Summary

        Complex ribbon customizations are likely to require a JavaScript page component - in general page components are somewhat complex (partly because of the current lack of documentation perhaps), but once you have a suitable template, subsequent implementations should be easier. If you need to use Client Object Model code, beware of the "async/lifecycle issue" discussed here and ensure your code has data ready for the ribbon framework.