while playing with custom claims provider I've found interesting thing in SPActiveDirectoryClaimProvider
. If you investigate a code using any .net assembly browser\decompiler (.NET Reflector or ILSpy) you will find a memory leak of SPWeb
object in method FillResolve
. Take a closer look at the code:
// Microsoft.SharePoint.Administration.Claims.SPActiveDirectoryClaimProvider
private void FillResolve(Uri context, string[] entityTypes, bool inputIsEmailOnly, string resolveInput, List<PickerEntity> resolved)
{
SPWeb sPWeb = null;
SPSite sPSite = null;
if (!SPThreadContext.Items.Contains("SPActiveDirectoryClaimProviderIgnoreContext"))
{
bool catchAccessDeniedException = SPSecurity.CatchAccessDeniedException;
try
{
SPSecurity.CatchAccessDeniedException = false;
sPSite = new SPSite(context.AbsoluteUri);
if (sPSite != null)
{
sPWeb = sPSite.OpenWeb();
}
if (!sPWeb.Exists)
{
sPWeb = null;
}
}
catch
{
if (sPSite != null)
{
sPSite.Dispose();
sPWeb = null;
}
}
finally
{
SPSecurity.CatchAccessDeniedException = catchAccessDeniedException;
}
}
try
{
SPWebApplication webApp = SPWebApplication.Lookup(context);
SPPrincipalType scopes = SPActiveDirectoryClaimProvider.ConvertEntityTypeToPrincipalTypes(entityTypes);
SPPrincipalInfo sPPrincipalInfo = SPUtility.ResolveWindowsPrincipal(sPWeb, webApp, resolveInput, scopes, inputIsEmailOnly);
if (sPPrincipalInfo != null)
{
if (inputIsEmailOnly && MatchType.EmailAddress == sPPrincipalInfo.MatchType && SPActiveDirectoryClaimProvider.DisableEmailResolve())
{
ULS.SendTraceTag(2466693u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, "Dicarding match '{0}' for input '{1}' because it is email match and feature is disabled.", new object[]
{
sPPrincipalInfo.LoginName,
resolveInput
});
}
else
{
PickerEntity pickerEntity = this.CreatePickerEntity(sPPrincipalInfo);
if (pickerEntity != null)
{
resolved.Add(pickerEntity);
ULS.SendTraceTag(1634481712u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, string.Format(CultureInfo.InvariantCulture, "Returning AD resolve match '{0}' for input '{1}'.", new object[]
{
pickerEntity.Key,
resolveInput
}));
}
}
}
else
{
if (!inputIsEmailOnly)
{
int maxCount = 10;
bool flag = false;
IList<SPPrincipalInfo> list;
if (sPWeb != null)
{
list = SPUtility.SearchPrincipals(sPWeb, resolveInput, scopes, SPPrincipalSource.Windows, null, maxCount, out flag);
}
else
{
list = SPUtility.SearchWindowsPrincipals(webApp, resolveInput, scopes, maxCount, out flag);
}
List<PickerEntity> list2 = new List<PickerEntity>();
foreach (SPPrincipalInfo current in list)
{
if (inputIsEmailOnly && MatchType.EmailAddress == current.MatchType && SPActiveDirectoryClaimProvider.DisableEmailResolve())
{
ULS.SendTraceTag(2466694u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, "Dicarding match '{0}' for input '{1}' because it is email match and feature is disabled.", new object[]
{
current.LoginName,
resolveInput
});
}
else
{
PickerEntity pickerEntity2 = this.CreatePickerEntity(current);
if (pickerEntity2 != null)
{
list2.Add(pickerEntity2);
ULS.SendTraceTag(1634481713u, ULSCat.msoulscat_WSS_ClaimsAuthentication, ULSTraceLevel.VerboseEx, string.Format(CultureInfo.InvariantCulture, "Returning AD resolve search match '{0}' for input '{1}'.", new object[]
{
pickerEntity2.Key,
resolveInput
}));
}
}
}
if (list2.Count == 1 && list2[0].Claim != null && SPClaim.EqualClaimValues(list2[0].Claim.Value, resolveInput))
{
resolved.Add(list2[0]);
}
else
{
if (list2.Count > 0)
{
PickerEntity pickerEntity = base.CreatePickerEntity();
pickerEntity.IsResolved = false;
pickerEntity.DisplayText = resolveInput;
pickerEntity.MultipleMatches.AddRange(list2);
resolved.Add(pickerEntity);
}
}
}
}
}
catch
{
throw;
}
finally
{
if (sPSite != null)
{
sPSite.Dispose();
}
}
}
According to the best practice (http://msdn.microsoft.com/en-us/library/office/ee557362%28v=office.14%29.aspx) we should dispose SPWeb
objects that were created using OpenWeb
method. But sPWeb
object is not disposed in any part of the method. It means, that every time we perform search and resolve in people picker, one SPWeb
object will be leaked. I don't have msdn subscription in order to contact Microsoft regarding this problem. This issue is true for SharePoint 2010 (SP2) and SharePoint 2013 (SP1).
I believe community can confirm memory leak and contact Microsoft to fix this issue.