3 comments

SharePoint: Missing Server Side Dependencies: MissingFeature

Published on Monday, May 20, 2013 in

In one of my projects we have a SharePoint solution which is deployed in a Dev, Test, Acceptance and Production environment. It seems that throughout the environments here and there we got some attention points. The SharePoint health analyzer found several problems such as MissingFeature, MissingSetupFile, MissingWebPart, SiteOrphan and all of those fall under the Missing Server Side Dependencies rule. The funny thing is that in most cases these are false positives. Mostly there’s a deleted object referencing a feature or a WebPart hasn’t be retracted completely. Both case don’t have any side effects. But we can’t have the Health Analyzer unhappy do we?

At first sight you find quite some good articles on how to resolve this:

There’s even a utility on codeplex which is also often referenced in this context:

However what I didn’t realized at fist is that since SharePoint 2010 SP1 there seems to be recycle bin at various levels.

Example #1: in order to fix the MissingWebPart issue I navigated to http://site.custom.com/_catalogs/wp which gave me an overview of all WebPart files present at that site.  The one referenced in the Health Analyzer was present as well. As we no longer needed it I deleted it. Simply deleting it did not make the Health Analyzer happy.

If you want this error to go away you also need to delete it from the site recycle bin:

image

And also from the site collection recycle bin:

image

Example #2: Besides files SharePoint also keeps entire sites in the recycle bin. So you might be having a MissingFeature problem because SharePoint retains a previous/test version of a site for you. You can easily retrieve those with PowerShell:

  • $site = Get-SPSite https://site.customer.com;
  • $site.RecycleBin | ?{$_.ItemType -eq "Web"};
  • $deletedWebs = $site.RecycleBin | ?{$_.ItemType -eq "Web"};
  • $deletedWebs | % {$site.RecycleBin.Delete($_.Id)}

The second line will print the deleted sites, the 4th line will actually delete them from the Site recycle bin.

Example #3: my last example has to to with deleted site collections. It seems that every time you delete a site collection they are also retained by SharePoint. If these reference features that you no longer wish to deploy, the Health Analyzer will be unhappy as he finds site collections in the databases without the features being available on the farm. After some searching I found the following SQL query:

USE [SPS2010_ContentDB]
SELECT * FROM features
JOIN webs ON (features.webid = webs.id)
WHERE featureid = 'e8c6c808-ab0b-43ab-bdbc-a977753d754e'

The featureID comes from the Health Analyzer information.We then looked through some more tables like:

SELECTFROM [SPS2010_ContentDB].[dbo].[AllSites]

And we saw that there were a lot more entries then we’d expect. So that’s when we realized there had to be some recycle bin for site collections. Some googling quickly gave us: SharePoint 2010: SP1 Site Collection Recycle Bin

In order to see what deleted sites are currently know to SharePoint. The command below will give ALL deleted sites collections but you can also scope the command to a Web Application.

  • Get-SPDeletedSite

In order to delete all sites in the recycle bin:

  • Get-SPDeletedSite |Remove-SPDeletedSite

However after executing the last command you’ll see that the Health Analyzer is still unhappy and that your SQL query still shows the entries. It seems that there’s a time job on SharePoint which handles the cleanup once a day. If you want to speed up the process, just do a run now on the Gradual Site Delete time job.

Some additional queries I used in the MissingSetupFiles & MissingWebPart problems:

  • MissingSetupFile:

USE [SPS2010_ContentDB]
SELECT * FROM AllDocs
WHERE SetupPath = 'Features\EPS.SPS.Core_jQueryReferenceWebPart\jQueryReferenceWebPart\jQueryReferenceWebPart.webpart'

  • MissingWebPart:

USE [SPS2010_ContentDB]
SELECT * FROM AllDocs
INNER JOIN AllWebParts ON AllDocs.Id = AllWebParts.tp_PageUrlID
WHERE AllWebParts.tp_WebPartTypeID = 'e8c6c808-ab0b-43ab-bdbc-a977753d754e'

0 comments

App-V and User Variables within the Bubble

Published on in

This post is just for me. I want to find this piece of information again whenever I might need it:

The problem: we wanted to avoid creating 20  App-V packages or entries in SCCM just because there’s groups of people having different connection URLs. For now we’d like to have this URL as a property of the AD group we use to assign the App-V application with.

The solution: create a pre-execute script which performs an LDAP query to retrieve the property of the group the user is a member of and set that URL as a user variable. Within the App-V package you can then simply reference that user variable (%APP_URL% for example).

The clarification: It seems to be by design that you can successfully set user variables with a pre-execute script, but you can’t read them within that bubble! Here’s the official answer: KB959452

The solution: we dropped the user variable idea and changed or pre-execute script to generate the application its config files.

0 comments

SharePoint: Encoded Claim Values

Published on Thursday, May 16, 2013 in , ,

One of the things which pops up quite fast when working with SharePoint and claims based authentication is the weird identifiers you find throughout SharePoint. In one of my troubleshooting sessions I stumbled upon this post which provides a nice picture of the meaning of several parts of an encoded claim.

The post : How Claims encoding works in SharePoint 2010

The picture: Link to original picture (larger)

One thing I came across as well is that when you encode a principal in PowerShell, the shell isn’t capable of showing all encoded strings. Especially the 6th character is often displayed as a ? while in reality it’s some exotic character. The following lines of PowerShell code should print the SharePoint representation of the given claim (with it’s type and value)

  • $mgr = Get-SPClaimProviderManager
  • $tp = Get-SPTrustedIdentityTokenIssuer -Identity "Cust ADFS Provider"
  • $cp = Get-SPClaimProvider -Identity "ADFSClaimsProvider"
  • $claim = New-SPClaimsPrincipal -ClaimValue "readPermission" -ClaimType http://schemas.customer.com/claims/technicalrole -TrustedIdentityTokenIssuer $tp
  • $mgr.EncodeClaim($claim)

However if you want to see how the encoded claim really looks, I advise you to capture the output of $mgr.EncodeClaim($claim) and pipe it to Out-File claim.txt E.g.

  • $mgr.EncodeClaim($claim) | out-file claim.txt

To conclude this post, I would advise to never hardcode any encoded claims in your scripts or code. After all the 4th character is generated on a per farm base and could very well be different in another SharePoint environment. As long as you keep encoding the claim based upon the actual input (claim value, type & provide), you should be safe though.

1 comments

FIM Password Portal Customization

Published on in

Due to me being creative with the FIM 2010 R2 Password Reset feature, I had to change some of the strings which are displayed during a password reset action on the password reset site. Luckily the FIM product team has foreseen this and allows you to customize whatever string you like. They’ve got it detailed over here: TechNet: FIM 2010 R2 Portal Customization

I stumbled across some things though:

In the guide they seem to suggest that you have to name resources files as Strings.<country>-<locale>.resources. To be honest I never tested naming the files like this. From what I could see from other files (like the DLLs in the folder) I could see that there’s no need to add the <country>. I simply named them Strings.<language>.resources and I can confirm that this works. This makes supporting different locales a lot easier. It’s also consistent with the DLLs (their filenames) the language packs add.

Conclusion #1: if you are having troubles getting your customizations work, try dropping the <country> from the filename.

image

However, once I got my files in place my customizations weren’t visible in IE. Luckily the event log showed me an error I could continue with:

image

In words:

System.Xml: System.Xml.XmlException: Invalid character in the given encoding. Line 18, position 32.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.InvalidCharRecovery(Int32& bytesCount, Int32& charsCount)
   at System.Xml.XmlTextReaderImpl.GetChars(Int32 maxCharsCount)
   at System.Xml.XmlTextReaderImpl.ReadData()
   at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars)
   at System.Xml.XmlTextReaderImpl.ParseText()
   at System.Xml.XmlTextReaderImpl.ParseElementContent()
   at System.Xml.XmlReader.ReadString()
   at System.Resources.ResXResourceReader.ParseDataNode(XmlTextReader reader, Boolean isMetaData)
   at System.Resources.ResXResourceReader.ParseXml(XmlTextReader reader)

I opened a file and tripple checked the XML syntax. All seemed fine. Then I saw this:

image

After some googling and thinking I came to the conclusion the encoding of the XML file was the problem. Using Notepad++ (a great utility btw!) you can simply open the file, change the encoding and save the file.

image

Conclusion #2: if you are having troubles, make sure your encoding of your resource files is set to UTF-8?

And some bonus information: If you want to copy paste the default values for some of the strings you can reverse engineer the DLL’s provided by the product. I had some troubles finding ALL strings.

Some of them are located here: C:\Program Files\Microsoft Forefront Identity Manager\2010\Password Reset Portal\bin

image

But there’s also strings which are in DLL’s which are not in the product folder but in the GAC: c:\Windows\assembly\GAC_MSIL\Microsoft.IdentityManagement.CredentialManagement.Portal.Gates.resources

image

0 comments

SharePoint: EncodeClaim: ArgumentException for claimType

Published on Sunday, May 12, 2013 in ,

I have a colleague who wrote a Custom Claim Provider for a SharePoint deployment which uses ADFS as its authentication provider. The goal of the custom claim provider was to ensure that the people picker would resolve things by searching our Active Directory. One of the other things we were working on was to set permissions on certain sites from within .NET code. Online we found several ways to get this task done, but my colleague kept running into an ArgumentException error.

I tried to simulate what he was doing in PowerShell. Our troubleshooting would benefit from this as a typical refresh of the custom code on SharePoint takes several minutes. One thing we quickly found out that it was working for a claim type we’ve had available in SharePoint and which was also specified in the claims provider. However lately we registered a new claim type in SharePoint, and for some reason this was not being accepted. Here’s how we registered it:

From a SharePoint PowerShell prompt:

  • $claimType = http://schemas.customer.com/claims/entity
  • $claimTypeSPS = "Entity"
  • $ti = Get-SPTrustedIdentityTokenIssuer "Cust ADFS Provider"
  • $ti.ClaimTypes.Add($claimType)
  • $ti.Update()
  • $map = New-SPClaimTypeMapping –IncomingClaimType "$claimType" –IncomingClaimTypeDisplayName "$claimTypeSPS" –SameAsIncoming
  • Add-SPClaimTypeMapping –Identity $map –TrustedIdentityTokenIssuer $ti

Typically this should be enough to start using the claim type “Entity” in SharePoint. However when we executed the following lines:

  • $mgr = Get-SPClaimProviderManager
  • $tp = Get-SPTrustedIdentityTokenIssuer -Identity "Cust ADFS Provider"
  • $cp = Get-SPClaimProvider -Identity "ADFSClaimsProvider"
  • $claim = New-SPClaimsPrincipal -ClaimValue "readPermission" -ClaimType http://schemas.customer.com/claims/technicalrole -TrustedIdentityTokenIssuer $tp
  • $mgr.EncodeClaim($claim)

We stumbled upon this error:

image

In words: Exception calling "EncodeClaim" with "1" argument(s): "Exception of type 'System.ArgumentException' was thrown.
Parameter name: claimType"
At line:1 char:194
+ $claim = New-SPClaimsPrincipal -ClaimValue "readPermission" -ClaimType "
http://schemas.customer.com/claims/entity" -TrustedIdentity
TokenIssuer $tp -IdentifierClaim:$false;$mgr.EncodeClaim <<<< ($claim)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

So we started digging into it. Long story short, as far as we can tell, from the moment you specify a custom claim provider on your Security Token Issuer, you must include all claims of the security token issuer in the custom claim provider. You can easily check which claim types are currently visible to SharePoint by executing the following lines:

  • $cp = Get-SPClaimProvider -Identity "ADFSClaimsProvider"
  • $cp.ClaimProvider.ClaimTypes()

Remark:

  1. Don’t confuse the Get-SPTrustedIdentityTokenIssuer and the Get-SPClaimProvider.
  2. Often the name of the custom claim provider is the same as it’s proper name, but without spaces. This property is also called the internal name.

Here’s a screenshot, I could clearly see that Entity was not included:

image

And here’s a small code snippet:

image

Now after adding the claim type in the code, and redeploying the necessary assemblies, things still didn’t work. As far as we can tell the following actions are also required:

  1. Restart your SharePoint PowerShell shell
  2. Run the Update() method on the Claim Provider Manager ($mgr = Get-SPClaimProviderManager and $mgr.Update() )

image

And now we can see that we can successfully encode the claim:

image

Conclusion #1: whenever you write a custom claim provider, make sure to include all the claim types you want to use for that Token Issuer. It doesn’t matter whether you only want to add them programmatically or if you want them to be available for regular users through the graphical interface.

However, after this we were still having issues. We were trying to add the encoded claim as a member of a SharePoint group. This would allow people having the specified claim to access the site we are securing. Here’s the command we executed:

  • $tp = Get-SPTrustedIdentityTokenIssuer -Identity "Cust ADFS Provider"
  • $url = https://sharepoint.customer.com
  • $group = "Visitors"
  • $claimType = http://schemas.customer.com/claims/entity
  • $claimValue = "DepartmentX"
  • $web = Get-SPWeb $url
  • $SPgroup = $web.SiteGroups["$group"]
  • $principal = New-SPClaimsPrincipal -ClaimValue $claimValue -ClaimType $claimType -TrustedIdentityTokenIssuer $tp
  • $SPprincipal = New-SPUser -UserAlias $principal.ToEncodedString() -Web $web
  • $SPgroup.AddUser($SPprincipal)

So we are still having issues with the claim types we added. The error makes me suspect the resolving capabilities of the custom claim provider. After some googling I finally found this post: Adding users and claims to a site from PowerShell Here’s the relevant part:

image_thumb2

Conclusion #2: whenever you write a custom claim provider, make sure to provide fillResolve capabilities for your custom claim types. I don’t think you are obliged to add them to the fillResolve method which takes a string as value to resolve, but you have to add them to the fillResolve method which takes an SPclaim as value to resolve. You can then simply put an if statement to auto-resolve everything of the claimtypes you don’t want to be looked up.

you can add this in the protected override void FillResolve(Uri context, string[] entityTypes, SPClaim resolveInput, List<Microsoft.SharePoint.WebControls.PickerEntity> resolved) method

if (resolveInput.ClaimType == CustClaimType.Entity)
{
    resolved.Add(GetPickerEntity(resolveInput.Value, resolveInput.Value, resolveInput.ClaimType));                   
    return;
}

Some more background reading: