5

I have created a timer job (SPJobDefintion) which is properly registered and working in a sharepoint 2010 environment.

In the Execute method of the Timer Job I'm able to use the following code, which sets a field of a specific SPListItem. This works fine.

using (SPSite mySite = new SPSite(mySiteId))
{
  using (SPWeb myWeb = mySite.OpenWeb(myWebId)))
  {
    SPList myList= myWeb.Lists[myListId];
    SPListItem myItem = myList.GetItemById(myItemId);

    myItem["myField"] = myValue;
    myItem.Update();
   }
}

For design reasons I would like to put that code in a separate method of a separate class. So I created the following class:

namespace myNamespace
{
  class myClass
  {

    [...some stuff...]        

    public myClass()
    {
      [...more stuff...]
    }

    public void setField()
    {
      using (SPSite mySite = new SPSite(mySiteId))
      {
        using (SPWeb myWeb = mySite.OpenWeb(myWebId)))
        {
          SPList myList = myWeb.Lists[myListId];
          SPListItem myItem = myList.GetItemById(myItemId);

          myItem["myField"] = myValue;
          myItem.Update();
        }
      }
    }
  }
}

Actually I would expect that calling this following code in the Execute method of the timer job should end in the same result.

MyClass myClassInstance = new myClass();
myClassInstance.setField();

Unfortunately I'll get the following exception:

Microsoft.SharePoint.SPException was unhandled by user code
  Message=""
  Source=Microsoft.SharePoint
  ErrorCode=-2147418113
  NativeErrorMessage=FAILED hr detected (hr = 0x8000ffff)

  NativeStackTrace=""
  StackTrace:
       bei Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
       bei Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, [...])
       bei Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, [...])
       bei Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, [...])
       bei Microsoft.SharePoint.SPListItem.Update()
       bei myNamespace.myClass.<>c__DisplayClass1.<setField>b__0()
   InnerException: System.Runtime.InteropServices.COMException
       Message=<nativehr>0x8000ffff</nativehr><nativestack></nativestack>
       Source=""
       ErrorCode=-2147418113
       StackTrace:
            bei Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, [...])
            bei Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, [...])
       InnerException: 

When I put the setField() method directly in the class where the Execute method is, the method will work properly. If I declare this method as static, the same Exception will occur.

I also tried to run the SPListItem.Update(), where the exception occurs, with elevated privileges (should be not the reason, because the code should be run in the OWSTIMER context). I also tried to play around with the allowUnsafeUpdates() on the SPSite and the SPWeb. Both with no success.

In the web I found only one description of this problem http://codekicker.de/fragen/sharepoint-2010-Sharepoint-2010-TimerJob-wirft-Fehler-timer (in German), unfortunately without any solution.

What else could be the reason, that this constellation will not work? Any idea?

Mat S
  • 51
  • 1
  • 4
  • 1
    I can't see anything wrong with your code, and there's nothing special about a timer job that means you can't call code like this in a different class. I'm concerned about your call stack - the base method is `myNamespace.myClass.<>c__DisplayClass1.b__0()` when ,from tour code example, I'd have expected it to just be `myNamespace.myClass.setField()`. Have you got anything more complicated going on here? – Rawling Nov 24 '12 at 23:03
  • Your sample code missing lines where you pass/set site/web ID. Not sure if it is a problem or not but consider providing samples that show all interesting parts... Side note: there is no real walue in having "my" prefix for parameters/members, even in samples. – Alexei Levenkov Nov 25 '12 at 01:06
  • Shouldn't the class be `public`? Also you can debug timer jobs (attach to owstimer.exe) and your code so where exactly does the exception occur? I guess here: `myItem.Update();`? – Dennis G Nov 25 '12 at 13:53
  • Thanks for all the comments until now! 1.) The weird entry in the stack trace is a result of my bad reformatting. Your right, it should be (and is) myNamespace.myClass.setField() 2.) To reduce the complexity of the code I decided to remove the pass/sets of the Guids/IDs. This is definitely not the reason for the strange behavior. I think using the "my" prefix is a very subjective decision. A few people (like me) like it, because it makes clear which members, instances, etc. are created by myself. – Mat S Nov 25 '12 at 14:32
  • 3.) As the stack trace shows, the error occurs at myItem.Update(). It debugged the code a hundred times ;) I thought internal as access modifier should be enough, as long as I access the code from the same assembly. However, to be sure, I tried it also with a public access modifier, unfortunately with the same result... – Mat S Nov 25 '12 at 14:35

1 Answers1

2

It definitely needs myWeb.AllowUnsafeUpdates = true; before updating any list item. do not forget to reset it back to false after updating it.

One thing I would make sure is to make sure the user the code is running as have full rights to update the item. I would suggest, logging in as the site administrator and try to run the code from a button click event (rather than a timer job) or some other event just to make sure that it is not a user permission issue.

Thanks

Senthil S

Senthil S
  • 75
  • 7