Pregunta Multiple claim providers people picker errors

  • viernes, 24 de agosto de 2012 14:52
     
      Tiene código

    I have created two custom claim providers. One called DVDS provides claims for our Form Based Authentication users. The other one called DFS provides claims for our ADFS users. As long as only one of them is deployed the People search works correctly. However, when both are deployed I have a problem. After I perform the search, click the Add button and the Ok button that follows instead of the users email address I get a string that says [DFS] or [DVDS] depending on which one was istalled first.

    Here's is my Claims Provider code. Both are very similar

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.SharePoint.Administration.Claims;
    using Microsoft.SharePoint.WebControls;
    namespace VDSCustomClaimsProvider
    {
        internal class ccp : SPClaimProvider
        {
            internal const string ClaimProviderDisplayName = "DVDS";
            internal const string TrustProviderDisplayName = "VDS";
            public override string Name
            {
                get { return ClaimProviderDisplayName; }
            }
            public string TPName
            {
                get { return TrustProviderDisplayName; }
            }
            public ccp(string displayName)
                : base(displayName)
            {
            }
            public static string EmailAddressClaimType
            {
                get { return "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"; }
            }
            public static string EmailAddressClaimValueType
            {
                get { return Microsoft.IdentityModel.Claims.ClaimValueTypes.String; }
            }
            public static string UserLogonClaimType
            {
                get { return "http://schemas.microsoft.com/sharepoint/2009/08/claims/userlogonname"; }
            }
            public static string UserLogonClaimValueType
            {
                get { return Microsoft.IdentityModel.Claims.ClaimValueTypes.String; }
            }
            public override bool SupportsEntityInformation
            {
                get { return true; }
            }
            public override bool SupportsHierarchy
            {
                get { return true; }
            }
            public override bool SupportsResolve
            {
                get { return true; }
            }
            public override bool SupportsSearch
            {            
                get { return true; }
            }
            protected override void FillClaimTypes(List<string> claimTypes)
            {
                if (claimTypes == null)
                {
                    throw new ArgumentNullException("claimTypes");
                }
                try
                {
                    claimTypes.Add(EmailAddressClaimType);
          
                }
                catch (Exception ex)
                {
                    throw new Exception("FillClaimTypes method has raised exception " + ex.Message);
                }
            }
            protected override void FillClaimValueTypes(List<string> claimValueTypes)
            {
                //throw new NotImplementedException();
                if (claimValueTypes == null)
                {
                    throw new ArgumentNullException("claimValueTypes");
                }
                try
                {
                    claimValueTypes.Add(EmailAddressClaimValueType);
           
                }
                catch (Exception ex)
                {
                    throw new Exception("FillClaimValueTypes method raised exception " + ex.Message);
                }
            }
            protected override void FillClaimsForEntity(Uri context, SPClaim entity, List<SPClaim> claims)
            {
                //throw new NotImplementedException();
                if (entity == null)
                {
                    throw new ArgumentNullException("entity");
                }
                if (claims == null)
                {
                    throw new ArgumentNullException("claims");
                }
                try
                {
                    claims.Add(CreateClaim(EmailAddressClaimType, "Email", EmailAddressClaimValueType));
                   
                }
                catch (Exception ex)
                {
                    throw new Exception("FillClaimsForEntity method has raised an exception " + ex.Message);
                }
            }
            protected override void FillEntityTypes(List<string> entityTypes)
            {
                entityTypes.Add(SPClaimEntityTypes.User);
            }
            protected override void FillHierarchy(Uri context, string[] entityTypes, string hierarchyNodeID, int numberOfLevels, 
    Microsoft.SharePoint.WebControls.SPProviderHierarchyTree hierarchy)
            {           
                try
                {
                    switch (hierarchyNodeID)
                    {
                        case null:
                            hierarchy.AddChild(new SPProviderHierarchyNode(this.Name, "All Users", "VDS_AllUsers", true));
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("FillHierarchy method has raised an exception " + ex.Message);
                }
            }
            protected override void FillResolve(Uri context, string[] entityTypes, SPClaim resolveInput, List<Microsoft.SharePoint.WebControls.PickerEntity> resolved)
            {
                try
                {
                    if (EntityTypesContain(entityTypes, SPClaimEntityTypes.User))
                    {
                        if (resolveInput.ClaimType.ToLower() == EmailAddressClaimType.ToLower())
                        {
                            PickerEntity pickerEntity = CreatePickerEntity();
                            pickerEntity.Claim = resolveInput;
                            pickerEntity.Key = "i:05.f|" + TPName + "|" + resolveInput.Value;
                            pickerEntity.Key = resolveInput.Value;
                            pickerEntity.EntityType = SPClaimEntityTypes.User;
                            pickerEntity.IsResolved = true;
                            resolved.Add(pickerEntity);
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("FillResolve:SPClaim method raised exception " + ex.Message);
                }
            }
            protected override void FillResolve(Uri context, string[] entityTypes, string resolveInput, List<Microsoft.SharePoint.WebControls.PickerEntity> resolved)
            {
                //throw new NotImplementedException();
                try
                {
                    if (EntityTypesContain(entityTypes, SPClaimEntityTypes.User))
                    {
                        
                        SPClaim claim = new SPClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", resolveInput, 
    Microsoft.IdentityModel.Claims.ClaimValueTypes.String,
                        SPOriginalIssuers.Format
                                  (SPOriginalIssuerType.Forms,
                                    TPName));
                       
                        PickerEntity pickerEntity = CreatePickerEntity();
                        pickerEntity.Claim = claim;
                        pickerEntity.Key = "i:05.f|" + TPName + "|" + resolveInput;
                        pickerEntity.EntityType = SPClaimEntityTypes.User;
                        pickerEntity.IsResolved = true;
                        resolved.Add(pickerEntity);
                    }
                    else
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("FillResolve:string method raised exception " + ex.Message);
                }
            }
            protected override void FillSchema(Microsoft.SharePoint.WebControls.SPProviderSchema schema)
            {
                //throw new NotImplementedException();
                try
                {
                    schema.AddSchemaElement(new SPSchemaElement(PeopleEditorEntityDataKeys.Email, "Email", SPSchemaElementType.Both));
                    schema.AddSchemaElement(new SPSchemaElement(PeopleEditorEntityDataKeys.JobTitle, "Title", SPSchemaElementType.Both));
                    schema.AddSchemaElement(new SPSchemaElement(PeopleEditorEntityDataKeys.Department, "Department", SPSchemaElementType.Both));
                }
                catch (Exception ex)
                {
                    throw new Exception("FillSchema method has raised an exception" + ex.Message);
                }
            }
           
            protected override void FillSearch(Uri context, string[] entityTypes, string searchPattern, string hierarchyNodeID, int maxCount, 
    Microsoft.SharePoint.WebControls.SPProviderHierarchyTree searchTree)
            {
                //throw new NotImplementedException();
                try
                {
                    if (EntityTypesContain(entityTypes, SPClaimEntityTypes.User))
                    {
                        helper ccpHelper = new helper();
                        ArrayList foundUsers = ccpHelper.SearchUser(searchPattern);
                        SPProviderHierarchyNode matchNode = null;
                       
                        if (!searchTree.HasChild("VDS_AllUsers"))
                        {
                            matchNode = new SPProviderHierarchyNode(this.Name, "All Users", "VDS_AllUsers", true);
                            searchTree.AddChild(matchNode);
                        }
                        else
                        {
                            matchNode = searchTree.Children.Where(node => node.HierarchyNodeID == "VDS_ALLUsers").First();
                        }
                        foreach (UserInfo foundUser in foundUsers)
                        {
                            PickerEntity pickerEntity = GetPickerEntity(foundUser.ClaimValue,
                                                                        foundUser.DisplayName,
                                                                        foundUser.EmailAddress,
                                                                        foundUser.JobTitle,
                                                                        foundUser.Department,
                                                                        foundUser.PictureUrl);
                            
                            pickerEntity.Key = foundUser.EmailAddress;
                            matchNode.AddEntity(pickerEntity);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("FillSearch method has raised an exception " + ex.Message);
                }
            }
            private PickerEntity GetPickerEntity(string claimValue, string displayName, string emailAddress, string jobTitle, string department, string pictureUrl)
            {
                try
                {
                    PickerEntity pickerEntity = CreatePickerEntity();
                    pickerEntity.Claim = new SPClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", emailAddress, 
    Microsoft.IdentityModel.Claims.ClaimValueTypes.String,
                     SPOriginalIssuers.Format
                                     (SPOriginalIssuerType.Forms,
                                      TPName));
                 
                    pickerEntity.Description = this.Name + ":" + displayName;
                    pickerEntity.DisplayText = emailAddress;
                    pickerEntity.EntityData[PeopleEditorEntityDataKeys.Email] = emailAddress;
                    pickerEntity.EntityData[PeopleEditorEntityDataKeys.JobTitle] = jobTitle;
                    pickerEntity.EntityData[PeopleEditorEntityDataKeys.Department] = department;
                    if (string.Compare(pictureUrl, "N/A") != 0)
                    {
                        pickerEntity.EntityData["Picture"] = pictureUrl;
                    }
                    pickerEntity.EntityType = SPClaimEntityTypes.User;
                    pickerEntity.IsResolved = true;
                    pickerEntity.EntityGroupName = "Users";
                    return pickerEntity;
                }
                catch (Exception ex)
                {
                    throw new Exception("GetPickerEntity method has raised an exception " + ex.Message);
                }
            }
        }
    }

    Any help would be greatly appreciated.

    thanks,

    Luis


    Luis R. Lebron

    • Cambiado GreggPJ - MSFT lunes, 27 de agosto de 2012 13:24 moving to correct forum (From:SharePoint 2010 - Using SharePoint Designer, Infopath, and other customization)
    •  

Todas las respuestas

  • lunes, 27 de agosto de 2012 11:14
    Moderador
     
     

    Hi,

    Thank you for your post.
    I'm trying to involve someone familiar with this topic to further look at this issue. There might be some time delay. Appreciate your patience.

    Thanks ,
    Entan Ming


    Entan Ming

    TechNet Community Support

  • lunes, 27 de agosto de 2012 20:59
     
     

    Hello Luis,

    Have you debugged your code and verified that the emailAddress parameter passed into your GetPickerEntity is correct when both claims providers are installed? If it is not, then the helper.SearchUser code might be populating this value incorrectly--can you share the code for this method?

    Thank you,


    David Wilborn MSFT

  • martes, 28 de agosto de 2012 14:23
     
     

    I debugged the code and it seems that every time the GetPickerEntity method was called the email address was correct. I did notice that when I click the "OK" button after the "Add" button, which is when the information is changed no functions seemed to be called.

    Here's the code you requested

     public ArrayList SearchUser(string searchPattern)
            {
                string[] patternToSearch = { searchPattern.ToLower() };
                return FindUserProfileUsers(patternToSearch);
            }

            private ArrayList FindUserProfileUsers(string[] searchKeywords)
            {
                System.Diagnostics.Debug.WriteLine(searchKeywords);

                ArrayList foundUsers = new ArrayList();
                string connStr = @"Data Source=win-devsp2010v2\sharepoint;Initial Catalog=MDS_Copy;Integrated Security=True";
               
                string query = "SELECT displayName, email, title, department, Auth_Source_Id FROM v_MDS_Directory WHERE (Auth_Source_Id = 2) AND (email LIKE @Email)";

                try
                {
                    SqlConnection conn = new SqlConnection(connStr);

                    SqlCommand cmd = new SqlCommand(query, conn);
                    cmd.Parameters.Add("@Email", System.Data.SqlDbType.NVarChar);
                    cmd.Parameters["@Email"].Value = "%" + searchKeywords[0] + "%";

                    conn.Open();

                    SqlDataReader drUsers = cmd.ExecuteReader();

                    if (drUsers.HasRows)
                    {
                        while (drUsers.Read())
                        {
                            string displayName = "N/A";
                            string email = "N/A";
                            string title = "N/A";
                            string department = "N/A";
                            int authenticationKey = 0;

                            if (drUsers.GetValue(0) != System.DBNull.Value)
                            {
                                displayName = drUsers.GetString(0);
                            }

                            if (drUsers.GetValue(1) != System.DBNull.Value)
                            {
                                email = drUsers.GetString(1);
                            }

                            if (drUsers.GetValue(2) != System.DBNull.Value)
                            {
                                title = drUsers.GetString(2);
                            }

                            if (drUsers.GetValue(3) != System.DBNull.Value)
                            {
                                department = drUsers.GetString(3);
                            }

                            SPClaim claim = new SPClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", email, Microsoft.IdentityModel.Claims.ClaimValueTypes.String,
                            SPOriginalIssuers.Format
                                      (SPOriginalIssuerType.TrustedProvider,
                                       CCP.TrustProviderDisplayName));

                            foundUsers.Add(new UserInfo(claim.Value, displayName, email, title, department, "N/A", authenticationKey));
                        } //End while
                    }

                    drUsers.Close();
                    conn.Close();

                    return foundUsers;
                }

                catch (Exception ex)
                {
                    throw new Exception("FindUserProfileUsers method has raised an exception " + ex.Message);
                }
            }


    Luis R. Lebron

  • martes, 28 de agosto de 2012 16:42
     
     

    Hi Luis,


    Looking back at your FillResolve implementation, I see that you are not setting the PickerEntity's DisplayText property. This is the text displayed in the editing control. Please try explicitly setting this property in your FillResolve code, and see if this resolves the issue for you.


    David Wilborn MSFT

  • martes, 28 de agosto de 2012 17:35
     
     

    David,

    I modified the code per your suggestion but I stall have the same problem.


    Luis R. Lebron

  • viernes, 31 de agosto de 2012 14:10
     
     

    Hello Luis,


    I have tested out your scenario, and you also need to set the pickerEntity.Description property. In the case with your multiple providers, this should then display the claim in Description [Claim Provider Name] format in the edit box.



    David Wilborn MSFT

  • viernes, 31 de agosto de 2012 18:08
     
     

    This helped somewhat.  Now I get the email address followed by the Claim Provider Name. But it only shows the name of the first claim provider that is installed. So if I install the DFS claim provider before the DVDS claim providers the display text looks like this:

    jdoe@mail.com[DFS]

    janed@mail.com[DFS] (even though it was provided by DVDS)

    regardless of which claim provider provided the information.

    thanks,


    Luis R. Lebron

  • viernes, 31 de agosto de 2012 22:07
     
     

    Hi Luis,

    You should also try adding code to your FillResolve method to verify the OriginalIssuer of the resolveInput claim before adding the picker entity to the return array. Check the resolveInput.OriginalIssuer to make sure that the claim being processed was issued by the claim provider code doing the processing (see See http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.claims.spclaim.originalissuer). If not, do not return a fill value. I suspect that the claim looks valid to your first claim provider and it is performing the FillResolve on the claim from the second provider.


    David Wilborn MSFT