Dev4Side Blog

Dev4Side at Microsoft Technical Conferences in Italy

TechnicalConferences

We are super-excited to announce that our team will be at the event of the year in Italy: Microsoft Tecnical Conferences 2011.

This event groups three of the most important conferences in Italy about SharePoint 2010, SQL Server and Unified Comunication.
The location is Milan and the dates to save are: 19-20-21 April 2011.

Check-out the Agenda and register to attend the event !

Hope to see you there !

 

WCF Client Error Can't find method SecurityTokenRequirement get_IsOptionalToken()

During a SharePoint 2010 development, I have encountered in this stange error when i used a WCF client that needs to authenticate with a webservice using the NTLM Autentication model :

WCF Client Error:: Can't find method: 'Boolean System.IdentityModel.Selectors.SecurityTokenRequirement. get_IsOptionalToken()'

Be aware that this is a bug that can be solved after installing a Microsoft hotfix and after restarting your server even if the kb article says that the reboot is not required.

Windows 2008 R2 and Windows 7
KB article: http://support.microsoft.com/kb/976462
Hotfix: http://code.msdn.microsoft.com/KB976462

Windows 2008 and olders
KB-article: http://support.microsoft.com/kb/976394
Installer: http://code.msdn.microsoft.com/KB976394

 

KB-article: http://support.microsoft.com/kb/976462

Installer: http://code.msdn.microsoft.com/KB97646

 

KB-article: http://support.microsoft.com/kb/976462

 

Incorrect dates taken from SharePoint 2010 Client Object Model

When using SharePoint 2010 client object model, I give for granted that all data returned from my query on list elements were correct. Better to say, I have never encountered any problem so far, but I have never interacted with fieds like "Date and Time". In this last week, I needed to read the elements present in a task list and screen print them in a client-side application.

At the beginning, after reading all data of  the SharePoint list, I haven't noticed anything weird, but later on, I have noticed a mismatch between the dates in my application and the ones visible in the SharePoint 2010 interface.

Just try to create a new Task list in one of your SharePoint 2010 sites, add some tasks with different dates and paste this code in a console application (after having added the reference both to the Microsoft.SharePoint.dll library and to the Microsoft.SharePoint.Client.dll client object model libraries and Microsoft.SharePoint.Client.Runtime.dll):

Console.WriteLine("Client object model:");
ClientContext context = new ClientContext("http://sharepoint2010/");
using (context)
{
    List l = context.Web.Lists.GetByTitle("Tasks");
    ListItemCollection items = l.GetItems(CamlQuery.CreateAllItemsQuery());
    context.Load(items, its => its.Include(i => i["StartDate"]));
    context.ExecuteQuery();
    foreach (ListItem item in items)
    {
        Console.WriteLine("{0}", (DateTime)item["StartDate"]);
    }
}

Console.WriteLine("Server object model:");
SPSite site = new SPSite("http://sharepoint2010/");
using (site)
{
    SPWeb web = site.OpenWeb();
    SPList list = web.Lists["Tasks"];
    foreach (SPListItem item in list.GetItems("StartDate"))
    {
        Console.WriteLine("{0}", (DateTime)item["StartDate"]);
    }
}

If you follow this code on any SharePoint site (created with any language, even the one of your client machine), I am sure you will realize that there are different values for date and time.

If you don't believe me, have a look at this screenshot:

WrongDates

 

As you can see, the first 4 dates are different from those in the same list through the side server object model. Don't look at the hours (as in my "Date and time" field the user was allowed to add only the dates),  but in these 4 values there is a discrepancy of a day.
I focused immediately on the bug (you can imagine why… :), then it came up in my mind that my application is executed on the client, so it is very likely that the language used is different then the one used to create the SharePoint site (or the language used to set the "Regional settings" section). As a matter of fact, getting back the ToUniversalTime() method of the DateTime class, I understood that the dates were exactly the same.
Therefore, the problem was: "What can I do to visualize the dates through the same culture of my client application?".
I tried to use the ConvertToDateTime method moving the same culture in the "Regional Settings" page of the SharePoint site, but it did not work! Dates were still diverse.

DateTime s = Convert.ToDateTime(((DateTime)item["StartDate"]), new CultureInfo("en-US"));
Console.WriteLine("{0}", s);

By seeking in the SDK, I finally find the fantastic Utility class and the even more amazing FormatDateTime  method, which executes the DateTime conversion according to the format you want in the SharePoint 2010 "Regional Settings".
When I apply it to my code, my date values are correctly visualized as in my site interface.

Console.WriteLine("Client object model:");
ClientContext context = new ClientContext("http://sharepoint2010/");
using (context)
{
    Web web = context.Web;
    List l = web.Lists.GetByTitle("Tasks");
    ListItemCollection items = l.GetItems(CamlQuery.CreateAllItemsQuery());
    context.Load(web, w => w.Language);
    context.Load(items, its => its.Include(i => i["StartDate"]));
    context.ExecuteQuery();

    foreach (ListItem item in items)
    {
        DateTime start = ((DateTime)item["StartDate"]);
        ClientResult result = Utility.FormatDateTime(context, context.Web, start, DateTimeFormat.DateTime);
        context.ExecuteQuery();
        DateTime rightStart = Convert.ToDateTime(result.Value, new CultureInfo((int)web.Language));
        Console.WriteLine("{0}", rightStart);
    }
}

Practically, during a normal query through the SharePOint 2010 clinet object model, dates go back to the client application in the UTC format and need to be converted.
Here it is the result when executing the second method (correct) together with the first one (incorrect).

RightDates

I also want to give you the sources, so you can try yourself what I just said (without writing from scratch):

ClientObjectModelDates.zip (37,4 Kb)

Hope this helps..

 

Retrieving the COM class factory for component with CLSID BDEADF26-C265-11D0-BCED-00A0C90AB50F failed due to the following error 800703fa

If you receive

Retrieving the COM class factory for component with CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} failed due to the following error: 800703fa.

and every SharePoint's page looks like this:

Server Error in '/' Application.


 

Retrieving the COM class factory for component with CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} failed due to the following error: 800703fa.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for component with CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} failed due to the following error: 800703fa.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:

[COMException (0x800703fa): Retrieving the COM class factory for component with CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} failed due to the following error: 800703fa.] Microsoft.SharePoint.Library.SPRequest..ctor() +54 Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous) +430 Microsoft.SharePoint.SPRequestManager.GetContextRequest(SPRequestAuthenticationMode authenticationMode) +325 Microsoft.SharePoint.Administration.SPFarm.get_RequestAny() +136 Microsoft.SharePoint.Administration.SPTemplateFileSystemWatcher.RefreshInstalledLocales() +60 Microsoft.SharePoint.Administration.SPTemplateFileSystemWatcher.Initialize() +69 Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.System.Web.IHttpModule.Init(HttpApplication app) +931 System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +480 System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +336 System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +350 System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +382 [HttpException (0x80004005): Retrieving the COM class factory for component with CLSID {BDEADF26-C265-11D0-BCED-00A0C90AB50F} failed due to the following error: 800703fa.] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +11301814 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +88 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +4341684

you can fix this issue by setting the Load User Profile to True in your site's Application pool's advanced settings:

retrieving-the-com-class-factory

After that, just reload your page and the problem should be fixed.

Enable or disable a SharePoint 2010 Ribbon control depending on the user selection

If we decide to customize the Ribbon bar, adding some custom controls in a particular tab or group, we also have the chance to decide when this Ribbon can be enabled or disabled. Obviously, the one that is enabled (or disabled) will be the command that the final user can execute by clicking on the Ribbon;  then, the SharePoint 2010 interface will have to renderize the Ribbon by making immediately clear  that it is not possible to execute operations on the page content starting from that specific control.

A Javascript function, which is added in the definition related to the Ribbon command, will do the control. In particular, this function should be added in the "EnableScript" attribute of the "CommandUIHhandler" element and should be a Boolean value, so the SharePoint 2010 interface can understand when enabling or disabling the control.

In order to enable or disable our Ribbon control on the basis of the selection by the user on the list elements, we have to use the Client Object Model for ECMAScript offered by SharePoint 2010 and its classes for the selection. Let's see how:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="Ribbon.HelloWorld"
                RegistrationId="101"
                RegistrationType="List"
                Location="CommandUI.Ribbon"
                Title="Hello world ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.HelloWorld.Button"
                  LabelText="Hello world"
                  TemplateAlias="o1"
                  Image32by32="/_layouts/images/PeppeDotNet/HelloWorld32by32.png"
                  Sequence="31"
                  Command="HelloWorld" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="HelloWorld"
                          CommandAction="javascript:alert('Action for only one item !');"
                          EnabledScript="javascript:SP.ListOperation.Selection.getSelectedItems().length == 1;"/>
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

In the example, we have decided that our trial Ribbon should be enabled only when the user has selected a single element. In the SharePoint team blog you can find another implementation of this behaviour, available through the CountDictionary() function.

HelloWorldRibbon_10

 

If the user has selected more elements or if he has not chosen any yet, the button is disabled.

HelloWorldRibbon_09

 

HelloWorldRibbon_11

 

This allows to execute operations on single items of a SharePoint list. Similarly, if we want to execute operations on more than one item selected from a list, we would have to write the code controlling that the user selection contains more than one element (just the opposite as written before).

<CommandUIHandler Command="HelloWorld"
                  CommandAction="javascript:alert(Action for multiple items !');"
                  EnabledScript="javascript:SP.ListOperation.Selection.getSelectedItems().length > 1;"/>

This allows to execute the same operation on more documents (or items) selected by the user. In fact, the SP.ListOperation.Selection.getSelectedItems() function, peculiar of the client-side object model for ECMAScript (we will see a brief introduction later on), will return a collection of elements containing all the objects that have been selected by the user, with their identifier, which are useful to execute our custom operations.

If the selection is single, that function will return a collection containing a single element.

HelloWorldRibbon_12

HelloWorldRibbon_13

 

In these examples, we have used classes exposed by the client-side object model for ECMAScript in order to enable or disable our Ribbon control.  We have the opportunity to do any kind of calculation in our script, using one or more functions, keeping in mind that the main function should return a Boolean value.

<CommandUIHandler Command="HelloWorld"
                  CommandAction="javascript:alert('Action only for work-hours !');"
                  EnabledScript="javascript:function enableRibbonOnWorkingHours() {
                                    var hour = getCurrentHour();
                                    return (hour &gt;= 9 &amp;&amp; hour &lt;= 18);
                                  };
                                  function getCurrentHour()
                                  {
                                    var d = new Date();
                                    return d.getHours();
                                  }
                                  enableRibbonOnWorkingHours();"/>

In the following post we will see how to move externally to the XML file of custom Ribbon definition (this means in a specific .js file) all Javascript code that is used both for the control activation and inactivation  and for the action that needs to be copied after the user has clicked on the control itself.

 

Custom Control Icon in the Ribbon Bar

In the previous post, we have seen how you can customize the Ribbon control size in a tab and a group already present in the Ribbon Bar. We have identified two main templates, respectively defined with the alias "o1" and "o2", and we have seen that, depending on which template you choose, different images are visualized that represent our control.

In detail, some kind of controls can be represented by two different images, obviously of different dimensions:

  • Image 32 x 32: its URL should be defined in the "Image32by32" attribute
  • Image 16 x 16: its URL should be defined in the "Image16by16" attribute


Controls that offer the possibility of visualizing these two different image formats are the following:

  • Button
  • SplitButton
  • ToggleButton
  • FlyoutAnchor


We can define a further series of attributes which modify the visualization in any of these two images. Here they are in detail:

  • Image32by32Class / Image16by16Class: CSS class name will be applied to the image.
  • Image32by32Left / Image16by16Left: negative value representing the offset to the left margin with which the image is renderized.
  • Image32by32Top / Image16by16Top: negative value representing the offset to the top margin with which the image is renderized.

The last two attributes are utilized by SharePoint to renderize part of images containing icons that are useful to different controls.

Other controls, which can be configured in order to visualize an image in the Ribbon Bar, are the GalleryButton control (through the "Image" attribute)and the Label control (which only contains the "Image16by16" attribute).

If you wish more information about the schema of all the controls you can add in the Ribbon Bar, please have a look at the on-line documentation on this address:
http://msdn.microsoft.com/en-us/library/ff458369.aspx

 

The TeamplteAlias attribute of a Ribbon Control

In the Ribbon bar customization, you have not only to specify the tab and the group in which the controls related to our custom Ribbon should be visualized (as we have seen in the first of posts concerning Ribbon), but we also have to specify the way in which these controls should be renderized.

In order to do so, any control, which can be added in the extension of the developing SharePoint interface, shows the TemplateAlias attribute. This attribute is necessary to specify the template identifier you intend to use in order to set a width and a size to this control, when a template is applied to a group in which our custom Ribbon has to be added.

In the first example, we have applied to the button the template with alias "o1". This alias allows the rendering system of the SharePoint 2010 Ribbon bar to set the maximum width and height to the button. Besides, it applies to this button the image in which the URL is defined in the "Image32by32" attribute.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="Ribbon.HelloWorld"
                RegistrationId="101"
                RegistrationType="List"
                Location="CommandUI.Ribbon"
                Title="Hello world ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.HelloWorld.Button"
                  LabelText="Hello world"
                  TemplateAlias="o1"
                 Image32by32="/_layouts/images/PeppeDotNet/HelloWorld32by32.png"
                  Sequence="31"
                  Command="HelloWorld" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="HelloWorld"
                          CommandAction="javascript:alert('Hello world from BIG Ribbon !');" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

 

We are already concerned in the result of a button with "TemplateAlias" attribute valued with "o1".

 

HelloWorldRibbon_07

 

If we want to visualize our custom Ribbon in a smaller format, we have to specify a new value for the TemplateAlias attribute. This is the "o2" value, which specifies the maximum text dimension, the position and the use of the image whose URL is defined in the "Image16by16" attribute.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="Ribbon.HelloWorld"
                RegistrationId="101"
                RegistrationType="List"
                Location="CommandUI.Ribbon"
                Title="Hello world ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.HelloWorld.Button"
                  LabelText="Hello world"
                  TemplateAlias="o2"
                  Image16by16="/_layouts/images/PeppeDotNet/HelloWorld16by16.png"
                  Sequence="31"
                  Command="HelloWorld" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="HelloWorld"
                          CommandAction="javascript:alert('Hello world from LITTLE Ribbon !');" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

Once the deployment is done, you will see our custom button appearing in the second control group (in the "Manage" group of the "Documents" tab), together with all those controls with minimum height. If you wish to move before, during or after the other controls already there, you can play with the "Sequence" attribute values (as explained in this post).

 

HelloWorldRibbon_08

 

The template alias we have seen so far ("01" and "o2") are valid when we want to add a control in one of the groups that already exist in the SharePoint 2010 Ribbon bar. If we want to create custom tabs and groups, we can define our custom templates for the controls visualization.

 

Ribbon position management on SharePoint 2010 Ribbon bar

As we have seen in our first example, we can add custom Ribbon to a specific tab and group, specifying the correct value in the "Location" attribute.
In this way, without further specification, all the items that belong to our Ribbon (buttons, checkbox, etc…) will be visualized as last in the group where the Ribbon has been added.

Note: In this sense, it is necessary to define what we mean with "last", as these controls will be visualized after all those defined with the same "TemplateAlias" (in the following posts we will explain how useful this attribute can be).

In the figure below, what we see is that the "Manage" group of "Documents" tab (belonging to every SharePoint 2010 site Document Library) has two controls with "TemplateAlias" attribute with "o1" value. These controls are needed in order to visualize the document properties or their modification.

In the previous example, the custom Ribbon is positioned with a "Hello World" label, after the other two.

HelloWorldRibbon_05 

If we want to move our custom button ahead (or in any other position), we have to give our control "Sequence" attribute a whole value.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="Ribbon.HelloWorld"
                RegistrationId="101"
                RegistrationType="List"
                Location="CommandUI.Ribbon"
                Title="Hello world ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.HelloWorld.Button"
                  LabelText="Hello world"
                  TemplateAlias="o1"
                  Sequence="1"
                  Command="HelloWorld" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="HelloWorld" 
                         CommandAction="javascript:alert('Hello world from Ribbon !');" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

In this way, choosing to give the value 1 to the attribute (or a number lower than 10), we have decided that our custom button should be renderized as first in the "Manage" group of the "Documents" tab.

HelloWorldRibbon_04 

If you specify the value 11 (greater than 10 and lower than 20), our custom Ribbon will be positioned between the control of properties visualization and of editing.

HelloWorldRibbon_06

This is because every Ribbon, already present in the bar, has a "Sequence" attribute value starting from 10 (for the first control on the left) and goes in tens for every single following control.
In our example, the controls present in the "Documents" tab of the "Manage" group have the following values for the "Sequence" field:

  • View properties - 10
  • Edit properties - 20


In order to visualize the correct values of each of the controls present in the Ribbon bar and in the specific group that we have chosen for the visualization of our customization to the SharePoint 2010 interface, we can sift through "CMDULXML" definition file in the path:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML


Here you can see how these two controls are defined:

<Button Id="Ribbon.Documents.Manage.ViewProperties"
        Sequence="10"
        ...
        TemplateAlias="o1" />
<Button Id="Ribbon.Documents.Manage.EditProperties"
        Sequence="20"
        ...
        TemplateAlias="o1" />

If you are familiar with the custom actions in WSS 3.0/MOSS 2007, you have realized that the concept of sequence of action visualization is exactly the same, with the only difference that, in this specific case, this concept is applied to the Ribbon bar and not to the context menu in the SharePoint interface.

In the next post we will see which are the available templates to renderize a control in a group present in the SharePoint Ribbon 2010 Ribbon Bar.

 

Our first Ribbon for SharePoint 2010

SharePoint 2010 interface customization can be very useful in order to carry out operations on lists and items or in order to widen the normal SharePoint behavior in a way that you can add some custom functionalities, which are useful for our applications.
One of the customization we can do is to develop a custom Ribbon we can add to the Ribbon bar in the default layout of the new version of SharePoint.
First of all, it is very important to know that it is best practice to use ribbons for all those operations that, in MOSS 2007/WSS 3.0, give users a benefit through custom actions. In general, it is very convenient to develop a Ribbon if you want to work on lists and single or multiple list elements.

In order to define a Ribbon within Visual Studio 2010, we have to create a "Empty Share Point Project" project type and add  a new "Empty element" element type.

 

HelloWorldRibbon_01 

 

This template type contains an empty xml file in which we can define our Ribbon. As I said, the link between a Ribbon and the custom actions we got to know in MOSS 2007 is very important, as we use the "CustomAction" tag for the definition of our first custom Ribbon.
Here is an example that helps us clarify this last concept:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="HelloWorld"
                Title="Hello World"
                Location="CommandUI.Ribbon"
                RegistrationType="List"
                RegistrationId="101">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.HelloWorld"
                  TemplateAlias="o1"
                  Command="HelloWorld"
                  LabelText="Hello world"/>
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="HelloWorld"
                          CommandAction="javascript:alert('Hello world from ribbon !");" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

As you can see, like the custom actions of Sharepoint previous version, we can choose to add our Ribbon in its related bar (through "Location" attribute), the contest in which our Ribbon will appear (through "RegistrationType" and "RegistrationId" attributes) and what's new compared to the old version. We can define which is going to be the extension to the interface represented by our Ribbon.
The extension is a single control or a series of controls (in our example a simple button) that are going to be visualized in Ribbon bar, in any of the available tabs and give custom actions to the final users.
In the following example, I have chosen my extension position in the "Documents" tab that is present in all SharePoint 2010 Document Library and in the "Manage" group. This choice is specified in the "Location" attribute of the "CommandUIDDefinition" element which represents my extension.

 

HelloWorldRibbon_02

 

 

HelloWorldRibbon_03

 

In general, to add our Ribbon in the different tabs and groups, you have to follow this simple rule:


Ribbon.[Tab].[Group].Controls._children

If you want the list of all the available tab and list identifiers, you can address to the documentation of this website:

http://msdn.microsoft.com/en-us/library/bb802730.aspx

Then, we can bind a specific command to every control (button, checkbox, etc)that is present in our extension to the SharePoint interface. This command will be one or more Java Script instructions we can define in the "CommandAction" attribute of the "CommandUIHandler" element, and this command is useful to define the Ribbon behavior.

I'm not going more into details because there is a vast of information that I will pick up in the next posts.
I remind you if you want a pre-made project template for the creation of a ribbon, you can find it in the Microsoft Code Gallery on this address:

http://code.msdn.microsoft.com/vsixforsp

 

Error: "'b' is null or nota n object" using ECMA script client SharePoint 2010 object model

In the last two weeks I worked a lot on the Client Object Model for ECMA Script, related to the operations that the final user can do through Ribbon bar. I hope I can add some contents for the Dev4Side blog and for the Italian SharePoint Community, because SharePoint 2010 UI Framework is very nice.

However, while working I have encountered this error:

'b' is null or not an object 

This was triggered when I tried to retrieve properties of a selected item, soon after having executed the executeQueryAsync() method.
This method requires the specification of two delegates in order to call server side or to manage a possible error.
In my case, the script did not reach neither the first administrator nor the second one, but it was stopped during the callback.

Here you can see the WRONG code I wrote:

var selectedItem;

function initializeScript() { 
   var items = SP.ListOperation.Selection.getSelectedItems(); 
   var context = new SP.ClientContext.get_current();
   var currentList = context.get_web().get_lists().getById(SP.ListOperation.Selection.getSelectedList()); 
   selectedItem = currentList.getItemById(items[0].id); 
   context.load(selectedItem);
   context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
}

function onSuccessMethod(sender, args) { 
   alert('success');
}

function onFailureMethod(sender, args) {
   alert('fail');
}

Where is the error? The error is in the specification of the two delegates names.
In my script, I refer to onSuccessMethod and onFailureMethod methods with the keyword "this". This script would work if I extracted it from the "initializeScript" function, but being in the function, the keyword causes error in the callback because the two delegates cannot be found.
Deleting the keyword "this", the callback mechanism understands which are the methods that need to manage all the events. In this way, everything works again.

var selectedItem;

function initializeScript() { 
   var items = SP.ListOperation.Selection.getSelectedItems(); 
   var context = new SP.ClientContext.get_current();
   var currentList = context.get_web().get_lists().getById(SP.ListOperation.Selection.getSelectedList()); 
   selectedItem = currentList.getItemById(items[0].id); 
   context.load(selectedItem);
   //context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
   context.executeQueryAsync(Function.createDelegate(this, onSuccessMethod), Function.createDelegate(this, onFailureMethod));
}

function onSuccessMethod(sender, args) { 
   alert('success');
}

function onFailureMethod(sender, args) {
   alert('fail');
}

So, If you encounter this error, you should know that the two delegates names managing the callback should be written without any errors.