Thursday, July 14, 2016

Working with BeforeProperties and AfterProperties on SPItemEventReceiver

I always forget this and when I come to create a new SharePoint Event Receiver I wonder why theBeforeProperties or AfterProperties are sometimes not populated.

Consider an example, we need to handle the ItemUpdating event for a document library and prevent a user from changing a certain column.  The code might look like this:
public override void ItemUpdating(SPItemEventProperties properties)
{
 if (properties.BeforeProperties["Title"] != properties.AfterProperties["Title"])
    {
        properties.Cancel = true;
        properties.ErrorMessage = "This column cannot be changed";
    }
}
For a document library, this works just fine.  For documents, Before and After properties are guaranteed for post events, such as ItemUpdating and ItemUpdated, but Before properties are not available for post events on list items.

The Before/After properties works differently between LIST and DOCUMENT LIBRARY

SharePointList

Event
BeforeProperties
AfterProperties
ListItem
ItemAdding
Null
New  Value
Null
ItemAdded
Null
New Value
New Value
ItemUpdating
Null
Changed Value
Original Value
ItemUpdated
Null
Changed Value
Changed Value
ItemDeleting
Null
Null
Original Value
ItemDeleted
Null
Null
Null

 
SharePointDocument Library
Event
BeforeProperties
AfterProperties
ListItem
ItemAdding
Null
Null
Null
ItemAdded
Null
Null
New Value
ItemUpdating
Original Value
Changed Value
Original Value
ItemUpdated
Original Value
Changed Value
Changed Value
ItemDeleting
Null
Null
Original Value
ItemDeleted
Null
Null
Null

Properties.ListItem refers to the current list item values at this point in the event. 
Original Value refers to the value which is already existing in the content DB.
New Value refers to the value which is being added newly in add event.
Changed Value refers to the value which is being updated in Update event.
So, if we go back to our original problem listed above.  How can we prevent a user from changing a certain column for an item in a list event?  From the list table, you can see if we hook into the ItemUpdating event, we can compare the current item’s value (properties.ListItem) to the AfterProperties value.  The code would look like this:
// SPListItem item= properties.ListItem;
// String oldvalue=item[“Title”].ToString();
if (properties.ListItem["Title"] != properties.AfterProperties["Title"])
{
    properties.Cancel = true;
    properties.ErrorMessage = "This column cannot be changed";
}
Hope it Helps.. 

correlation tokens in SharePoint workflow

Correlation Token:
  • Is way to group together a set of related activity.
  • worflowTokem - created by default in workflows used to group together the whole workflow.
  • Is a unique identifier that enables mapping between the objects in a workflow and the environment that is hosting the Windows Workflow Foundation (WF) workflow runtime.
  • It can be referred for uniquely identifying each instance of a workflow, modification or task.  When SharePoint initiates a workflow, it does not have a unique set of objects. Instead, if one instance of the workflow is already running when the second initiates, the second will reuse objects from the first.
  • Correlation token properties ensure that the single activity object is operating on the correct workflow instance and accessing the correct details about the workflow.

You will have a separate correlation token for the each of the following:

  • The workflow itself.
  • Each task you need to reference in the workflow

Declare the correlation token for the workflow in the OnWorkflowActivated activity. Then, for each activity that affects the entire workflow, bind that activity’s correlation token to the correlation token of the OnWorkflowActivated activity.

Displaying Custom Fields in Content Query Web Part

The Content Query Web Part (CQWP) allows you to display data from a list anywhere within a Site Collection..


However, by default the CQWP only displays the freaking ‘Title’ field, if you want to display all the other field in the list you have to do all the below modifications,
                                              

In the Tool Pane, expand Presentation and experiment with the drop down options under Styles. Select Apply to see the changes. These are default styles available in MOSS 2007.
All these styles will be available in a single file named “ITEMSTYLE.XSL”. This file is available under Style Library/XSL Style Sheets/.You can use SharePoint designer to customize this file.

Take a minute to look at the file.  Every time you see "<xsl:template..." that is the start of a new Item Style.  There is one for each of the out-of-the-box Item Styles that show up in the Styles drop down in the Web Part Tool Pane.  For every custom Item Style that is needed, a newxsl:template> </xsl:template> block will have to be created.

1)    Scroll down to the bottom of the file. Copy the last xsl:template code block and paste it above the closing xsl:stylesheet tag.

2)    Change the name and match properties in the Template tag to a unique name of your choice:
            Format:
       <xsl:template name="NewsItemStyle" match="Row[@Style='NewsItemStyle']"        mode="itemstyle">
3)  Before we style any content, we need to have the web part pull in the content we want to display. Some content is already pulled in by default, such as Title.  For anything else that is not pulled by default, we need to tell the web part to get those fields. Steps to do that
A.       In the Content Query Web Part you have inserted on the page, click edit, and then click Export.
B.    In the File Download dialog box, click Save. In the Save As dialog box, type a name and location for the .webpart file. Click Save in the Save As dialog box to save the file.
C.    Open the saved file and search for “CommonViewFields” text, you can able to see tags like this,
                 <property name="CommonViewFields" type="string"></property>
D.  Add the list column name and along with column type you need in the new style.

 
And the Field type can be notified below,

E.  After adding the necessary fields inside the tag, save the file.
F.  Finally import this file as web part in moss2007.(Delete the previously added content query web part)

4)      Now customize the ITEMSTYLE.XSL file with necessary UI design format,
Example:
<div class="description">
    <xsl:value-of select="@Rollup" />
    <xsl:value-of select="@Body" />
</div>

Note:
Rollup and Body are the fields we added in the .WEBPART file.

5)      Complete code for NewsItemStyle has been written here.

<xsl:template name="NewsItemStyle" match="Row[@Style='NewsItemStyle']" mode="itemstyle">
   <xsl:variable name="SafeLinkUrl">
            <xsl:call-template name="OuterTemplate.GetSafeLink">
                 <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
       </xsl:variable>
       <xsl:variable name="DisplayTitle">
            <xsl:call-template name="OuterTemplate.GetTitle">
                <xsl:with-param name="Title" select="@Title"/>
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
       </xsl:variable>
       <xsl:variable name="RowNum" select="count(./preceding-sibling::*)" />
       <table>
   <tr>
   <td style="vertical-align:top;">
       <table>
   <!-- <xsl:if test="$RowNum &lt; 4"> //to restrict the number of rows-->
   <tr>
   <td valign="top">
   <a href="{$SafeLinkUrl}"><img border="0" height="50" width="80">
<xsl:attribute name="src"><xsl:value-of select="substring-before(substring(@Rollup, string-length(substring-before(@Rollup, 

'/St'))+1,string-length(@Rollup)),',')" />
   </xsl:attribute>
   </img>
   </a>
   </td>
   <td style="vertical-align:top;">
   <table>
     <tr>
   <td style="color:#3A80B8; font-family:'Century Gothic'; font-weight:bold; font-size:12px" valign="top">
   <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
                <a class="NewsTitle" href="{$SafeLinkUrl}" title="{@LinkToolTip}">
                    <xsl:value-of select="$DisplayTitle"/> 
                </a>
   <br />
   <span style="color:#595959; font-family:Verdana; font-weight:bold; font-size:10px">
                <xsl:value-of select="ddwrt:FormatDate(@Created, 2057, 3)"/>
</span>  
</td>
   </tr>
   </table>
</td>
</tr>
   <!--</xsl:if>-->
       </table>
   </td>
   </tr>
       </table>       
 </xsl:template>


6)      Please “check in” the file and Now you can able to view you Custom style in Tool pane and under Presentation heading,

7)      Select all the necessary properties in Content query web part and publish the page.

Debug a Feature Receiver in VS 2010

To debug a feature receiver in Visual Studio 2010:

1. Open the Visual Studio 2010 project that contains your feature.

2. In Solution Explorer, right-click the project node, and then click Properties.

3. On the SharePoint tab, in the Active Deployment Configuration drop-down list, click No Activation.

4. Then attach to the w3wp.exe process that is running your particular SharePoint instance.(However, I  have found that if you need to debug a feature that is activated with stsadm.exe, there is an extra step required.  The reason is that you need to not only attach to the w3wp.exe process but you also need to attach to stsadm.exe as well.).

5. Open the feature receiver class that you want to debug, and then insert a breakpoint. Hit F5 and enjoy!!

6.There is, however a very fast and easy way to start debugging your Feature EventReceiver’s overridden methods, like FeatureActivated() and FeaureDeactivating(): Simply add the following line of code at the point you want to start debugging:

1
System.Diagnostics.Debugger.Launch();

Debugging Custom SharePoint Timer Jobs

When you create a timer job for SharePoint 2010, you cannot directly press F5 to debug your code. Instead, you must attach the debugger to the SharePoint 2010 Timer process (Owstimer.exe). This how-to topic describes how to debug a timer job by attaching the Visual Studio debugger to the timer process.

Steps to debug a timer job in Visual Studio 2010
  1. On the Start menu, point to Administrative Tools, and then click Services.
  2. In the Services window, make sure the SharePoint 2010 Timer service is started(You can also restart this service to make the changes reflect in sharepoint server).
  3. In your Visual Studio 2010 project that contains your custom timer job,set the break point at the first line of Execute() method.
  4. Note Make sure that the code has not changed since you deployed the timer job; otherwise, the debugger will not match your source code to the deployed assembly.
  5. On the Debug menu, click Attach to Process.
  6. In the Attach to Process dialog box, click OWSTIMER.EXE, and then click Attach.
  7. In the SharePoint Central Administration Web site, click Monitoring, and then click Review job definitions.
  8. Click the name of your job, and then click Run Now on the Edit Timer Job page.
  9. Verify that the Visual Studio 2010 debugger stops execution on your breakpoint.
  10. Happy Debugging.
If the above steps didn't work properly then try the below steps,
  • Insert an always-failing assertion statement at the beginning of the Execute method. You should use Debug.Assert(false) rather than Trace.Assert(false) since debug calls are detached from the release builds; then you don’t have to remove them from your code before moving to staging or production.

  • Every time the timer job starts, you will get a pop-up window like the one shown in Figure 12. This window hinders the execution of the timer job until you close the message box. Note that timer jobs run in parallel, so this window will never halt the execution of other timer jobs running simultaneously. For now, leave this window alone.
  • You might be wondering why you should insert the assert statement at the beginning of the Execute method of the timer job. It is true that you can just attach a debugger to owstimer.exe and wait for the subsequent cycle of the timer job, but it could be tough to find out whether the application has been effectively attached to the process since the jobs may not fire for several minutes. You could be left with Visual Studio attached to the owstimer.exe process with breakpoints set and wondering whether the job is running or wondering whether the breakpoints are not being hit because of some problem with loading the symbol files(.pdb).By adding the following code to the Execute method, you will see your timer jobs running.
  • Any time you update your custom timer job class and deploy the assembly to the global assembly cache, you mustrestart all the timer services in the farm. If you don’t restart the timer service, it will run the old copy of your timer job class. Yes, the timer service caches the assemblies. Restarting the SharePoint timer service is the only way to refresh the assembly cache and force it to use your updated assembly. 
  • And follow the same steps again as mentioned above.
  • Happy Debugging.