Donnerstag, 3. Juli 2014

SharePoint ThreadAbortException

Problem: If you are doing a SPSite.OpenWeb() (or maybe its done for you, when you request the profile service) and you do not have the permissions to the site there is an UnauthorizedAccessException being thrown. But if you are trying to catch it, immediately after the catch an ThreadAboardException is thrown and you code does not continue. That is because of access denied exceptions inside page requests are explicitly handled by the platform. For example, when Forms-based authentication is used, anonymous users are redirected to the login page. If the user is already authenticated, he may be redirected to an error message page such as _layouts/AccessDenied.aspx.
When you are developing web parts that behavior is okay but running such code in a timer job or WCF webservice is problematic.

Solution: You should turn off that behaviour by setting the following flag:

bool originalCatchValue = SPSecurity.CatchAccessDeniedException;
SPSecurity.CatchAccessDeniedException = false;

try
{
   // your code

}
finally
{
   SPSecurity.CatchAccessDeniedException = originalCatchValue;
}


Within the try statement you are able to catch the UnauthorizedAccessException as usual.


2nd Problem: Another reason you get a ThreadAbortException could be that your request could not be validated by SharePoint. This could be the case if you are developing a WCF webservice within SharePoint context. In the exception stacktrace you should see  Microsoft.SharePoint.SPWeb.ValidateFormDigest()

Solution:
In this case SPContext.Current is not null, Sharepoint tries to verify requests using security validation digest provided by FormDigest Class. According to msdn:
"To make posts from a Web application that modify the contents of the database, you must include the FormDigest control in the form making the post. The FormDigest control generates a security validation, or message digest, to help prevent the type of attack whereby a user is tricked into posting data to the server without knowing it. The security validation is specific to a user, site, and time period and expires after a configurable amount of time. When the user requests a page, the server returns the page with security validation inserted. When the user then submits the form, the server verifies that the security validation has not changed".
In WCF service you don't have security digest. To avoid this check try to set HttpContext.Current to null temporary when you call siteCollection.Add() method:

var ctx = HttpContext.Current;
try
{
    HttpContext.Current = null;
    // your code
}
finally
{
    HttpContext.Current = ctx;
}