Can't query by objectguid, always returns null value

Nov 8, 2013 at 9:08 PM
Edited Nov 8, 2013 at 9:09 PM
I've got a search function in my app that takes in a user's username or GUID and should return the correct person object. But when I search using a GUID, it always returns null even though I am in fact using the correct GUID. When I search by username, the results output a user with the properties of the GUID I just tried searching for. So I am thinking my filter is not setup correctly.

Here is my method:
public Person GetPersonByProperty(string serverAddress, string personPath,
                                          NetworkCredential networkCredential = null, string username = null,
                                          string department = null, Guid? objectGuid = null)
        {
            LdapConnection ldapConnection = new LdapConnection(serverAddress);
            if (networkCredential != null)
                ldapConnection.Credential = networkCredential;
            Person person;

            using (DirectoryContext db = new DirectoryContext(ldapConnection, true))
            {
                Expression<Func<IDirectoryAttributes, bool>> expression =
                    PredicateBuilder.Create<IDirectoryAttributes>();
                if (username != null)
                    expression = expression.And(da => Filter.Equal(da, "cn", username));
                if (department != null)
                    expression = expression.And(da => Filter.Equal(da, "department", department));
                if (objectGuid != null)
                    expression = expression.And(da => Filter.Equal(da, "objectguid", objectGuid.ToString()));
                
                person = db.Query(personPath, objectClass: "Person")
                           .Where(expression)
                           .Select(da => new Person
                               {
                                   Id = da.GetGuid("objectguid") ?? Guid.Empty,
                                   Address = da.GetString("postaladdress"),
                                   Department = da.GetString("department"),
                                   DistinguishedName = da.GetString("distinguishedname"),
                                   FirstName = da.GetString("givenname"),
                                   LastName = da.GetString("sn"),
                                   TelephoneNumber = da.GetString("telephonenumber"),
                                   MemberOf = da.GetStrings("memberof") as ICollection<string>,
                                   Title = da.GetString("title"),
                                   MiddleName = da.GetString("middlename")
                               }).FirstOrDefault();
            }

            return person;
        }
And I use it like so:
[HttpPost]
        public ActionResult Search(SearchModel searchModel)
        {
            PersonService personService = EntityServiceFactory.GetService<PersonService>();

            List<AdSearchResult> results = new List<AdSearchResult>();
            Guid searchGuid;
            Person legacyPerson = null;
            Person newPerson = null;
            if (Guid.TryParse(searchModel.SearchTerm, out searchGuid))
            {
                legacyPerson = personService.GetLegacyPerson(searchGuid);
                if (legacyPerson == null)
                    legacyPerson = personService.GetLegacyPerson(AdUtils.ReverseEndianOrder(searchGuid));
                newPerson = personService.GetPerson(searchGuid);
                if (newPerson == null)
                    newPerson = personService.GetPerson(AdUtils.ReverseEndianOrder(searchGuid));
            }
            else
            {
                legacyPerson = personService.GetLegacyPerson(searchModel.SearchTerm);
                newPerson = personService.GetPerson(searchModel.SearchTerm);
            }

            results.Add(new AdSearchResult() { LegacyPerson = legacyPerson, NewPerson = newPerson });

            searchModel.SearchResults = results;

            return View(searchModel);
        }
Find person and find legacy person look like this,The only difference between the methods is they use different constants to query different ADs:
public Person GetPerson(Guid id)
        {
            return GetPersonByProperty(LdapConnectionStrings.LdapServerAddress,
                                       LdapConnectionStrings.LdapUserPath,
                                       new NetworkCredential("Blah", "Blah"), objectGuid: id);
        }
I parse the inputted term to see whether it's a GUID or username, if it's a guid I try and look up . Sometimes the searched GUID may be the nativeguid instead of the objectguid, so first I try to search by the initial guid, and if no matches i reverse the endian order to see if i get any results then. But neither way returns any results so I think there may be something wrong with my filter. I search two ADs our new system and our legacy system, which has different GUIDs for each user.

So it works for username, but not GUIDs.

How can I fix this?
Coordinator
Nov 9, 2013 at 2:38 PM
I believe your problem is with objectGuid.ToString(). Guids have to be in a string octet format. I have an extension method called ToStringOctet() that you should use. You can see the method here. This also goes for any byte[] based properties (SecurityIdentifier, etc.).

On a side note, you may want to use CleanFilterValue on cn and department for your search if it's user facing. Without it, it is possible to get an exception from the directory with an invalid filter. You can test that behavior by entering any of these ( ) ~ : * & in the department or cn search field.
Marked as answer by sah302 on 11/11/2013 at 9:12 AM
Nov 11, 2013 at 5:13 PM
Great, this worked and thanks for the tip. Also could you update the documentation? I saw this here: https://linqtoldap.codeplex.com/wikipage?title=Formatting&referringTitle=Querying and it mentions to convert it, it would be nice if you referenced your .ToStringOctet() in there. Thank you!
Coordinator
Nov 15, 2013 at 1:52 AM
Good catch, thanks! I'll update it this weekend. The documentation is a little out of sync now so I need to go over it again.