Pages

Friday, November 26, 2010

SharePoint: Diagnose “Error loading and running event receiver” problem

We developer gain experience as we work more and spend more time on learning and applying. Mostly, we only care about the how expertise developers are, in implementing things. But I also emphasis on another dimension of experience: “How expertise developers are in fixing or diagnosing problem”. This diagnosing expertise can mainly be gained with more and more real life working experience. Maybe everyday or every week or every moth, you face a problem and find out the solution by debugging or writing logs or finding solution on the internet. That’s how a problem  is resolved but this may lead you to an experienced person in solving similar problems or at least helping you diagnosing similar problems.

 

Ok, I’m beating around the bush, let me come to the real problem that the post is all about. If you have come around the problem that your event receiver is not running and you found that in log file the error message is something like “Error loading and running event receiver…” then you need to find out what’s wrong with the receiver. As the error message says, the problem might be with loading the event receiver or running the event receiver. You need to find out first if the problem is in loading event receiver. If the problem is in loading event receiver the fix the problem first.  To find out the issue, you can use the following steps:

Step 1: Event Receiver Loading Problem?

You need to find out first if your event receiver is executing or being invoked. The simplest way might be to use logging. If you already have logging capability in your code, you can use the logging. But make sure logging doesn’t have any permission related problem. The easiest way to resolve the issue is to allow user ‘everyone’ to have full control in the file/folder where the log file will be saved. However, revert the permission once you are done with diagnosis.

If your logging works from event receiver, then clearly, the problem is not loading receiver.

 

Step 2: Event Receiver Running Problem?

From step 1 if you find the problem is not loading problem then surely the problem is in running the event receiver. So put proper logs in the event receiver in tracking the problem.

Saturday, November 20, 2010

SharePoint: Event Receiver and Assembly Versions

I had encountered an interesting problem with event receiver few days back. By default we are used to attach an event receiver class to a list by declaring the event receiver in an xml file as shown below:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListTemplateId="101">
    <Receiver>
      <Name>MyEverReceiverOnAdd</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>MyProject.MyEventReceiver, Version=2.1.0.0, Culture=neutral, PublicKeyToken=</Assembly>
      <Class>PermissionsEventHandler.PermissionsHandler</Class>
      <Data></Data>
      <Filter></Filter>
    </Receiver>
  </Receivers>
</Elements>

Figure 1: Event Receiver for version 2.1.0.0

As you can see in the xml file above we need to specify the version of the assembly.

 

Let’s image a scenario:

1. You have deployed your SharePoint solution (which has event receivers) while the assembly version is 2.1.0.0. So when you deployed the SharePoint solution, the list event receivers  in the SharePoint webs are registered with that 2.1.0.0 version of dll.

2. After few months, another version of your product is ready and you have changed the dll version (as this is practice to change your dll version as the development goes on). Now your dll version is 2.2.0.0. So you have updated the event receiver’s definition in xml file to reflect the new dll version as shown below:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListTemplateId="101">
    <Receiver>
      <Name>MyEverReceiverOnAdd</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>MyProject.MyEventReceiver, Version=2.2.0.0, Culture=neutral, PublicKeyToken=</Assembly>
      <Class>PermissionsEventHandler.PermissionsHandler</Class>
      <Data></Data>
      <Filter></Filter>
    </Receiver>
  </Receivers>
</Elements>

Figure 2:Event Receiver for version 2.2.0.0

3. Now if you deploy the latest version of dll in server, the old assembly will be removed from GAC.Now you can get two different behaviors:

  • New site: If you create a new site after version 2.2.0.0 is deployed, there’ll be no problem as the new site will register it’s event receiver with the updated xml (which is using 2.2.0.0.0 as shown in image 2).
  • Old site: Here’s your are in trouble. You attached the event receiver after the version 2.1.0.0 is deployed. So the lists will look for that version of dll in GAC. 

 

Solutions:

So how can you handle the situation? After googling and analyzing I have found three solutions:

  • Fixed Version: One solution might be to keep the event receiver classes in a project whose version will not be changed. So you’ll always refer to the an assembly with the same dll version.
  • Deactivate/Activate Old Features: Another solution might be to uninstall/Deactive and then install/activate the event receiver features for all old sites. But this will add extra overhead in deployment. Additionally, if the number of webs are larger then it’s not viable solution.
  • DotNet Publisher Policy: .net publisher policy can be another option to redirect the reference of old assembly to new one. More information on publisher policy can be found in the links: http://msdn.microsoft.com/en-us/library/dz32563a.aspx, http://support.microsoft.com/kb/891030

Tuesday, November 9, 2010

SharePoint 2010 Error: Cannot make a cache safe URL for "1031/styles/Themable/corev4.css", file not found. Please verify that the file exists under the layouts directory.

I had to take backup from my client’s production site to make some analysis in my local server. So I took backup and restored the site in local server. Restored was successful. Then I changed the site collection administrator of the restored site as it was still pointing to the production server’s site collection administrator. 

 

Then I tried to browse the site and found the interesting error “Cannot make a cache safe URL for "1031/styles/Themable/corev4.css", file not found. Please verify that the file exists under the layouts directory.” The very first thing I noticed the path contains 1031. Anyone can guess that this is language id and thought came to my mind is that my client SharePoint site not in English. The production site was in German language and when I restored the site, its looking for resources in German language ID folder.

Then I download the language pack from MSND and refreshed the browser. It worked like magic….

Sunday, November 7, 2010

SharePoint 2010 Error: System.Web.HttpException: Directory 'C:\inetpub\wwwroot\wss\VirtualDirectories\80\_catalogs\masterpage' does not exist.

I had got the error when I tried to use pagemethods in SharePoint. I had registered the AjaxControlToolkit namespace in masterpage and then I replace ScriptManager with AjaxControlToolkit’s ToolkitScriptManager as shown below:

<ajaxToolkit:ToolkitScriptManager id="ScriptManager" runat="server" EnablePageMethods="true" EnablePartialRendering="true" EnableScriptGlobalization="false"   EnableScriptLocalization="true"/>

The problem was I enabled the pagemethods by setting EnablePageMethos to true. Disabling the pagemethods fixed the issue. However I didn’t explore why there’s the error if pagemethods is enabled.

So disable the pagemethods by setting EnablePageMethods=”false” and then then error will disappear…

SharePoint Restore Error: Your backup is from a different version of Microsoft SharePoint Foundation and cannot be restored to a server running the current version. The backup file should be restored to a server with version '14.0.0.5050' or later.

I had needed to move my dev environment from one Virtual machine to another. So I took backup from source server and tried to restore the backup in new server. However, I have got the error “Your backup is from a different version of Microsoft SharePoint Foundation and cannot be restored to a server running the current version. The backup file should be restored to a server with version '14.0.0.5050' or later.” I was totally confused as I had the same version of SharePoint in both server. Then I double checked the version and it was 14.0.4762.1000 for both servers.

Getting confused I googled and found that solution. This is a bug which is fixed by SharePoint 2010 August cumulative update. The updates are available in the following link:

 

After installing the updated the error gone…

Wednesday, November 3, 2010

SharePoint 2010: Editing an item whose modified version is in pending for approval, causes runtime exception

In SharePoint 2010, You can enable content approval by going to ‘Versioning Settings’ section of list settings page as shown below. The error I’ve found can only be found if we choose “Only Users who can approve items (and the author of the item)” as an option in “Who should see draft items in this list?”.

image

Figure 1: Content Approval settings page

Now let’s have a scenario where three users are involved. The first user, say admin, is in administrator group. There are other two users: contributor1 and contributor2 who belongs to contributor group. Say there’s a list MyList where Content Approval is enabled for the list and only users who can approve the item and the author of the item can see draft items. Now follow the steps:

  1. User contributor1 edits an item. And the draft item is pending for approval by admin user.

  2. User contributor2 visit the item and try to edit the item. When user click edit link the edit dialog comes up but when user click Save button the following error message is shown (if you have enabled stack trace):

image

Figure 2: Exception when try to edit an already pending item

The error message is shown below:

Cannot complete this action.

Please try again.<nativehr>0x80004005</nativehr><nativestack></nativestack>
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: Cannot complete this action.

Please try again.<nativehr>0x80004005</nativehr><nativestack></nativestack>

Expected Behavior

The expected behavior would be to disable the save button for item already in pending approval status. Or there should have an settings page where admin can define what to do for items whose draft version is in pending approval stage. The options could be:

  • Hide the item from users who can’t see draft items
  • Show the item as readonly to users who can not see draft items (so edit link could be disabled for users).

 

Conclusion

So if an updated item is waiting for approval and if any other user, except the author and user who can approve, try to edit the item, he/she’ll get the error page shown above. The error is only shown when options are selected for viewing draft items by only author and person who can approve items. Though draft item can be edited/viewed by author and approver, other users can see the old item and can edit. So the error is evident if other users try to edit the item.

Tuesday, November 2, 2010

SharePoint 2010 Runtime Error: “You must fill out all required properties before checking in this document."

In SharePoint 2010, you may find two ways the file upload in a library works based on whether you have custom required fields or not.

File upload in Document Library with no custom required field

By default when a library doesn’t have any required field, after uploading a document, the upload window redirects u to the library view page. So in this case there are two steps as shown below:

image

Figure 1: Two steps file upload process for library with not custom required fields

 

 

File upload in Document Library with custom required field

However, if you add a field as required then after uploading a document you will be shown an intermediate dialog window where you can provide values for required fields. The intermediate dialog is shown below:

image

Figure 2: For library with Required fields, user can see this dialog just after file upload

Now in this window you can enter values for required fields. But what if you don’t enter required field values and just cancel the dialog? In this case the file is checked out by you. You might expect that the dialog should be not canceled without entering required field values. But maybe SharePoint team just wanted to let the user to fill the required fields later on, without forcing to do so in the dialog immediately.

 

 

What if user leave the file checked-out by not entering values for required fields?

Now if user doesn’t fill the required fields on the dialog shown on figure 2 by clicking cancel button, then the file is not checked in and kept checked-out by the user who uploaded the file. Now if you select the ‘document’ item in library you can find the check-in button is enabled (shown in the image below) which means the document is checked-out.

image

Figure 3: File without filling required fields is checked-out

What if you try to check-in the file?

Now if you try to check-in the file by clicking “Check In” (as in figure 3), you will get an runtime exception as shown below:

image

Figure 4: Runtime exception on file check-in

What would be the expected behavior?

So what would be the expected behavior if user clicked on “Check In'” shown in figure 3? As I can expect that the window shown on figure 2 would be presented to let user know that the required fields are missing. So if user still cancels the dialog the file would be in checked-out state. If user put values for required fields and save then the file can be checked-in.

Sunday, October 24, 2010

SharePoint: StaticName, InternalName, DisplayName. Which one to use in case of Multilingual supported site?

SharePoint provides three different names for referring a field: DisplayName, Intername and StaticName. You can get more details on these three properties in the MSDN post. In short, Display name is what you see in the site. Internal name is the readonly name which is created when the filed in created and can’t be modified i.e., readonly and the name should be unique. Static name doesn’t need to be unique and can be changed. If you don’t change the static name, internal name and static name are same.

 

Ok, let’s come to point. We used to access list item’s value by using display name as shown below:

var value = ListItem[DisplayName]

The problem in this approach is that if display name can be different for different language. So using display name can work in a language but may not work in different language.

 

Problem I experienced in using Display name

I was working on content approval related stuffs. And I had found the approval status is kept in a field whose display name is ‘Approval Status’. So I had used code like shown below to get the approval status field value.

ListItem[‘Approval Status’]

Unfortunately, my client was using German version and when I deployed I found my code is not working. After spending some time I had figured out the column ‘Approval Status’ is missing in the list. And I finally figured out the column name is not ‘approval status’ but it’s German equivalent.

 

So, which one to use from InternalName, StaticName, DisplayName?

So which field to use when? If you need to access custom field created by you or your team, you can use display name (considering you are using different display name for different language) . If you are using any SharePoint provided field then better to use StaticName or Intername, since you are not sure if the display name will be changed or not.

Saturday, October 23, 2010

SharePoint: Active/Deactivate Feature programmatically

Sometimes you may need to activate/deactivate features programmatically. In my case, I needed to do some synchronization from a Synchronization feature. As part of the synchronization, I needed to move data from one list to another. However the destination list had event receiver attached. The event receiver was attached using another feature (say ListItemEventReceiverAttacher). So I needed to deactivate the feature (i.e., ListItemEventReceiverAttacher) to make sure that event receiver associated to the list is not active. So let’s come to the point rather than beating around the bush.

First of all, your feature can have scope of web, site or webapplication or Farm. so you need to get the feature first. You can do so by accessing Features properties of Site or web as shown below:

1. Get the activated Features available in the WebApplication/Site/Web level

var webApplicationFeatures = webapplication.Features
var webFeatures = web.Features;
var siteFeatures = site.Features;

2. once you have got the features you can find your feature by feature id or name, if the feature is activated, as shown below:

var feature = site.Features.SingleOrDefault(sf => sf.DefinitionId == myFeatureDefinitionId);

var feature = site.Features.SingleOrDefault(sf => sf.Definition.DisplayName.Equals("Feature Title"));

If the feature is null then the feature is not activated. Only activated features will be available through site.Features/web.Features property.

3. If feature is not activated, you can activate the feature as shown below:

if(feature==null)//if feature is not activated
{
site.Features.Add(featureId);//activate feature
}

4. If the feature is activated, you can deactivate the feature as shown below:

if(feature!=null)//if feature is activated
{
site.Features.Remove(feature.DefinitionId);//deactivate feature
}

Important: One important thing to notice that once you activate/deactivate a feature against an object (SPWebApplication/SPSite/SPWeb), you need to open a new SPWebApplication/SPSite/SPWeb object to get the changes you made. The scenario shown below:

using (SPSite site=new SPSite("http://myserver"))
{
    //Activate or deactivate feature
    //the changes will not be available in this scope.
}
using (SPSite site=new SPSite("http://myserver"))
{
    //Changes made to the feature in upper using block will be effeftive here
}

Monday, October 18, 2010

SharePoint 2010: Get Current page’s Url. Request.Url vs SPUtility.GetPageUrlPath

Few days back while I was working on SharePoint application page, I had needed to get the current page’s url. I’m used to using Request.Url to get the current page url and used Request.Url in several places. But interestingly, when I tried to get the current page url from application page, it was giving me the root web’s url (like http://mysharepoint/_layouts/pages/mypage.aspx) whereas my actual page’s url was something like http://mysharepoint/subsite/_layouts/pages/mypage.aspx. The Request.Url was just skipping the SPWeb name.

Then I tried the SharePoint’s SPUtility.GetPageUrlPath and found the actual url. Though the Request.RawUrl returns the relative url which includes the subsite name but it seems safe to use SPUtility.GetPageUrlPath method to get current page’s url to make sure the page is valid and we can trust SharePoint API more in SharePoint context rather than fully relaying on asp.net built-ins.