neděle 7. února 2010

TargetInvocationException when using CreateTaskWithContentType activity

If you want to use ASP.NET pages with your workflow in SharePoint you need to follow these steps:

1) Create the web page.
2) Create ContentType containing your WebPage.
3) Add the ContentType to the ContentTypes gallery in SharePoint site.
4) Allow ContentTypes on the SharePoint task list, where the task of your workflow will be stored.
5) Add the ContentType to the list where your workflow tasks will be stored.
6) Finally you can use CreteTaskWithContentType activity and specify the GUID of the ContentType which you have created.

For more details of how to develop SharePoint workflows with ASP.NET pages refer to this blog.

If you do not add the ContentType to the gallery or if you forgot to add it to the SharePoint list, you can receive the following exception:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions) at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentType(Guid taskId, SPWorkflowTaskProperties properties, String taskContentTypeId, HybridDictionary specialPermissions)


The best way to add the ContentType to the ContentTypes library is to create Feature containing all your ContentTypes and install and activate the feature on SharePoint. On details pleas follow the part 4 of the above mention blog how-to.

Programatically allow and add ContentTypes on SharePoint list


Here is a method which I am using to programatically alow and add ContentTypes on SharePoint task list, which accepts String representing the GUID of the ContentType and SPList representing the task list.

I've found the code in this method again in part 4 of this great series.


public static void AllowContentType(SPList lTaskList, String lTaskContentType)
{

//make shure that the content types are enabled on the task list
if (lTaskList.ContentTypesEnabled != true)
{
//if not allow them. This can be done also in the SharePoint GUI
lTaskList.ContentTypesEnabled = true;
}

// convert given String representing the GUID to SPContentTypeId
SPContentTypeId myContentTypeID = new SPContentTypeId(lTaskContentType);

// Find the content type in SharePoint site content types library
SPContentType myContentType = lTaskList.ParentWeb.Site.RootWeb.ContentTypes[myContentTypeID];

//if the content type was found
if (myContentType != null)
{

// Check if the content type was already added to the SharePoint task list
bool contenTypeExists = false;
foreach (SPContentType contentType in lTaskList.ContentTypes)
{
if (contentType.Name == myContentType.Name)
{
// This content type was already added
contenTypeExists = true;
break;
}
}

// If I didn't find this content type in the list I will have to add it
if (contenTypeExists != true)
{
lTaskList.ContentTypes.Add(myContentType);
}
}
else
{
throw new Exception("Content type is not register with the web site");
}
}

neděle 3. ledna 2010

SharePoint - Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)

In one of my WebParts I was using this little piece of code to get the current user from SharePoint:

//values I wanted to work with
String name, email;

//get the currnet SPWeb
//THE PROBLEM: You should not dispose after calling GetContextWeb Method
using (SPWeb lWeb = SPControl.GetContextWeb(this.Context))
{
SPUser lUser = lWeb.CurrentUser;
name = lUser.Name;
email = lUser.Email;
}

after executing this I've got the folowing exception:

(Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))
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: Microsoft.SharePoint.WebPartPages.WebPartPageUserException: Došlo k výjimce. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))
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.

I have googled a bit and found the solution:

//get the currnet user
SPUser lUser = SPContext.Current.Web.CurrentUser;
//work with it as you need
name = lUser.Name;
email = lUser.Email;

In the MSDN Best Practices you can find, that when using the SPControl.GetContextWeb() or SPControl.GetContextSite() method you should not dispose the created objects.