Nebulae Spiral

Spiralling Golden… and maybe blogging about code.

Archive for the ‘moss’ tag

RPC_E_ATTEMPTED_MULTITHREAD

with one comment

Exception information:
Exception type: COMException
Exception message: Attempted to make calls on more than one thread in single threaded mode. (Exception from HRESULT: 0×80010102 (RPC_E_ATTEMPTED_MULTITHREAD))

ooh yah baby. this ones a doozy.

If you’re running into this in your sharepoint development journey, you have well bypassed the open site / open list / get list item / do stuff with it stage and have moved into the world of creating object representations of your list items, probably databinding that object off the list item to work with it, then populating the listitem columns from the object before saving it. IMHO, this is a nice, clean and managable way of development, BUT you could run into a couple roadblocks. this one looks a tad daunting but its an easy one to get around.

My scenario uses 3 lists. Registrations, Organizations, and Solutions. An Organization has an owner (registration) and 0-many solutions. I know, I know, the organization should be a property of the registration, but i digress…

so i have an organization object. this object has a bunch of fancy properties – address, phone number, etc, etc, and also an Owner and a List<Solution> . During the databind of this object from the listitem, I attempted to set these objects and received the RPC_E_ATTEMPTED_MULTITHREAD error – if you google this error, which you probably have since you landed here, you’ll see some answers that will have you believe that you need to implicitly dispose of the SPSite, SPWeb – you may even be tempted to add a GC.Collect in there.

This didn’t – and still doesn’t – make a whole lot of sense to me because the access to the list item was wrapped in a using statement which of course only works with types that inherit from IDisposable, and will be disposed of when you exit the using statement, right? Right? so you would think that after you access that list item and leave the using statement, the SPSite is disposed of and youre good to go… which is not really the case and I don’t know the intricacies of it all but I do know how to bypass this problem and the answer is – Lazy Loading. yes, serious.

back to my databind…
as I am binding all the properties from the listitem i just retrieved and I try to set the owner which would have to go access that site and get that list item from the registrations list, create a new owner object from that item, the RPC_E_ATTEMPTED_MULTITHREAD error gets thrown. the same when I’m trying to populate the Associated Solutions. If you move the code to populate these properties into the public accessor ( the getter ) so that the property is loaded when it is accessed instead of when the object is databound – poof! problem solved.

If this doesn’t solve your problem, or you’re seeing this error in Sharepoint without having the structure i described above or some format of it, drop me a line and we can figure it out.

cheers,
trinity
err, neb

Written by Nebulae

September 4th, 2008 at 10:02 am

Posted in code

Tagged with , , ,

Handy SPFolder / SPList / SPFile / SPWhatever interface, using Generics and Elevated Privs.

with one comment

This is a handly little lib I wrote for accessing various types of objects using generics. enjoy :-)

class SPDataAdapter
{
    public static T GetObject(string location)
    {
        object obj = null;
        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (var site = new SPSite(location))
            {
                obj = site.OpenWeb().GetObject(location);
            }
        });
        return (T)obj;
    }
 
    public static T GetObject(string location, bool useElevatedPrivs)
    {
        if (useElevatedPrivs) return GetObject(location);
        using (var site = new SPSite(location))
        {
            return (T)site.OpenWeb().GetObject(location);
        }
    }
 
    public static SPList GetList(string location, bool useElevatedPrivs)
    {
        if (useElevatedPrivs) return GetList(location);
        using (var site = new SPSite(location))
        {
            return site.OpenWeb().GetList(location);
        }
    }
 
    public static SPList GetList(string location)
    {
        SPList list = null;
        SPSecurity.RunWithElevatedPrivileges(delegate
       {
            using (var site = new SPSite(location))
            {
                list = site.OpenWeb().GetList(location);
            }
        });
 
        return list;
 
   }
 
}

and to test:

 
[TestMethod()]
public void GetObjectTest1()
{
    GetObjectTest1Helper<SPFolder>();
}
 
public void GetObjectTest1Helper<T>()
{
    const string location = "http://spiral/Lists/Tasks";
    const bool useElevatedPrivs = true;
    var actual = SPDataAdapter.GetObject<T>(location, useElevatedPrivs);
    Assert.IsNotNull(actual);
}
 
[TestMethod()]
public void GetObjectTest()
{
    GetObjectTestHelper<SPFile>();
}
 
public void GetObjectTestHelper<T>()
{
    const string location = "http://spiral/Lists/Tasks/Attachments/1/nebulae.jpg";
    T actual = SPDataAdapter.GetObject<T>(location);
    Assert.IsNotNull(actual);
}

Written by Nebulae

August 28th, 2008 at 11:01 am

Posted in code

Tagged with , ,

SPList Factory – singleton access to your lists.

with one comment

A few months ago I was doing a refresher in GOF design patterns.  I have a couple favorites: memento, observer, state, and the factory of course :-)

So I was trying to implement these patterns in a conceptual SPAL ( sp access layer ), and what I’ve found is that having a SPListWrapper object, and a factory to create them and allow static access is *the bees knees*, especially if you want to implement an ajax interface.  Since you only load the list once, its pretty speedy too.

I absolutely love ajax and making the sharepoint interface more robust and seamless.  Any interface for that matter.  there is a library i use exclusively that covers all browsers and addresses the issues found in each of them, even the pesky ie memory leak.

What Im getting at is that I have a bunch of cool stuff to share that probably would become convoluted in a mass array of blog entries, so I think it would be worthwhile to vlog it.  stay tuned, could take a  few days while.

Written by Nebulae

August 6th, 2008 at 1:17 pm

Save Conflict in workflow on SPListItem.Update or SystemUpdate

with one comment

in this scenario, I have a really simple workflow that creates a task, does some infopath approval stuff, then copies that list item to another list. the kicker is when you want to add something about that copied item to the original item, say an id column so you have a reference. after saving the copy, you set a column on the original and try to update the listitem, and get a “save conflict” error.

Ive seen a lot of posts on this error, most of them point to not having access to that listitem because its locked by the workflow itself. I would assume that you can somehow capture the item before the workflow updates it, and set the properties you want. could someone enlighten me if this is true? I’ve seen posts saying to use a delay, to wrap it in a repeating try / catch until the item is unlocked, to try programmatically to check it out, and then save it. I can’t see any of this as being best answer.

What Ive decided is to attach an event handler to the second list to set the id in the first. this seems to be pretty reliable, plus I already had an event handler on that list. I’m really curious to know if there’s a resolution for this.

other info on this issue:
http://forums.msdn.microsoft.com/en-US/sharepointdevelopment/thread/641b40fb-614f-4266-95c0-d61c2f443146/

Written by Nebulae

August 1st, 2008 at 2:16 am

Posted in code

Tagged with , , ,

Sharepoint Workflow – When you just can’t create a task.

without comments

I’ve been writing sharepoint applications for quite some time.  In fact, I consider myself pretty damn good at it.  Somehow though, I’ve been able to avoid writing much workflow all this time.  Event Handlers have been all I needed to this point.

I’ve never wanted to beat my head into a wall so much as this last weeks adventure into workflow.  The infamous Julie kremer, who i hold in the highest of esteem as a friend and teacher, wrote a workflow for the OfficeLive app that Ive been working on for the last 5 or so months ( I think we’re on version 5 at this point, we iterate fast ) that takes a solution submitted by a small business owner and kicks off a workflow to have it approved before it shows up in the small business portal search – http://www.officelivepartnerdirectory.com.

My task is to create a workflow that the company object will pass through for approval. The goal is to catch any offensive company names or logos from showing up in the portal. This seems pretty easy, logistical, shouldn’t be a problem right?

Well, right off the bat I was getting an exception in mscorlib

Exception has been thrown by the target of an invocation.
   at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct&amp; sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
   at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext)
   at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
   at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
   at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)
   at System.Workflow.Runtime.Scheduler.Run()

I added a fault handler to the workflow and bubbled up the inner exception to see what the deal was:

private void code_HandleAllExceptions_ExecuteCode(object sender, EventArgs e)
{
    WriteException(faultHandlerActivity1_Fault1, "An error was handled by fault hander. " + faultHandlerActivity1_Fault1.InnerException);
}
private static void WriteException(Exception e, string message)
{
    WriteTrace("CompanyWF ERROR: " + message + " " + e.Message + "\n" + e.StackTrace, "ERROR");
}
 
private static void WriteInfo(string message)
{
    WriteTrace("CompanyWF: " + message, "INFO");
}
 
private static void WriteTrace( string message, string level )
{
    Trace.WriteLine("["+DateTime.Now+"] " + message, level);
}

which then reported a null reference exception:

[4120] ERROR: [7/25/2008 10:36:46 AM] CompanyWF ERROR: An error was handled by fault hander. System.NullReferenceException: Object reference not set to an instance of an object.
[4120]    at Microsoft.SharePoint.Workflow.SPWorkflowTask.SetWorkflowData(SPListItem task, Hashtable newValues, Boolean ignoreReadOnly)
[4120]    at Microsoft.SharePoint.Workflow.SPWinOETaskService.UpdateTaskInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean fSetWorkflowFinalize, Boolean fCreating, HybridDictionary specialPermissions)
[4120]    at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions)
[4120]    at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTask(Guid taskId, SPWorkflowTaskProperties properties, HybridDictionary specialPermissions) Exception has been thrown by the target of an invocation.
[4120]    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct&amp; sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
[4120]    at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
[4120]    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
[4120]    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
[4120]    at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
[4120]    at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext)
[4120]    at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
[4120]    at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
[4120]    at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)
[4120]    at System.Workflow.Runtime.Scheduler.Run()

One of the properties I was trying to push into the ExtendedProperties propertybag was null, I changed that and we were past this exception. The lesson here is to grab the InnerException of your fault handler and hope that it returns something descriptive, i guess :-)

In case you are wondering, the trace viewer i use is called DebugView, brought to my attention by the industrious Eric Jobin.

Another issue I was having with the InfoPath form though, was quite a bit harder to track down, but a stupid mistake in the long run.  I was creating a link to the infopath form with an item id in the query string, but it was the wrong item, wrong list :-)  The error I was getting was something extremely vague and Sharepointy, but what helped me figure it out was enabling (in a google friendly fashion) – verbose sharepoint  exception reporting – verbose sharepoint error handling – full Moss exception handling – good enough.

This is a lot easier than you might think, and you’ve probably done this before with other web applications you’ve needed to debug.  Open the Web.Config for your spsite and find:

<SharePoint>
    <SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">

and change it to:

<SharePoint>
    <SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="true">

then find the node:

<system.web>
    <customErrors mode="On" />

and set it to “Off”

you may have to recycle your app pool before changes take effect, but you should now see a stack trace when you cause an error – hopefully more helpful than the generic Unknown Exception that we had all come to love.

peace, and happy coding…
trinity

Written by Nebulae

July 27th, 2008 at 2:41 pm

Posted in Uncategorized

Tagged with , ,

Chris O’Brien’s blog

without comments

Chris O’Brien’s blog. – Great SharePoint resource.

Written by Nebulae

July 27th, 2008 at 11:38 am

Posted in Uncategorized

Tagged with , , ,