Error when using update - Operation not allowed on relative DN

Aug 27, 2011 at 12:39 PM

Hi,

I am trying out your excellent LinqToLDAP provider, I do run into an error when I try to update, the error I receive is that "Operation not allowed on relative Distinguished Names" any idea why this may be. Below is my code:

 // Update a user
            using (var updateContext = new DirectoryContext(factory.GetConnection(), disposeOfConnection: true))
            {
                var updateUser = updateContext.Query<User>().Where(string.Format("userPrincipalName={0}""adoe")).FirstOrDefault();
                System.Console.WriteLine("Before change: {0}", updateUser.WhenChanged);
                updateUser.BusinessCategory = "Just promoted";
                var updated = updateContext.Update(updateUser);
                System.Console.WriteLine("After change: {0}", updateUser.WhenChanged);
            }
Aug 27, 2011 at 1:05 PM

QBE works though, think the way I have my root configure in the application could be causing the problem.

Coordinator
Aug 28, 2011 at 4:18 PM

girish66,

Can you post how your User object is mapped?

Aug 28, 2011 at 7:11 PM

Hi,

Thanks for your response, below is the user object, can I ask you if there are any methods to change a user password using the directorySecurity attribute

 

[DirectorySchema("CN=Users,CN=Customers,DC=Northwind,DC=Extranet", ObjectCategory = "Person")]
    public class User : DirectoryObjectBase
    {
        private string _businessCategory;
 
        [DirectoryAttribute("cn")]
        public string CommonName { getset; }
 
        [DirectoryAttribute(StoreGenerated = true)]
        public Guid ObjectGuid { getset; }
 
        [DirectoryAttribute("company")]
        public string Company { getset; }
 
        [DirectoryAttribute("adminDisplayName")]
        public string AdminDisplayName { getset; }
 
        [DirectoryAttribute("userPrincipalName")]
        public string UserPrincipalName { getset; }
 
        [DistinguishedName]
        public string DistinguishedName { getset; }
 
        [DirectoryAttribute("businessCategory")]
        public string BusinessCategory
        {
            get { return _businessCategory; }
            set
            {
                _businessCategory = value;
                AttributeChanged("BusinessCategory");
            }
        }
 
        [DirectoryAttribute(DateTimeFormat = null)]
        public DateTime? LastLogonTimestamp { getset; }
 
        [DirectoryAttribute(StoreGenerated = true)]
        public DateTime WhenChanged { getset; }
    }
Coordinator
Aug 28, 2011 at 11:58 PM

girish66,

I'm not able to reproduce that error, but it's caused when you try to update an attribute that makes up part of the DN.  BusinessCategory is not part of the DN so I'm not sure why you're getting that error.  Are you using Lightweight Directory Services?

Aug 29, 2011 at 12:27 AM

Hi,

Yes I am using AD LDS, could it be the way I have mapped my root that could be causing a problem?

 

 // Using pooled connection
            IPooledConnectionFactoryConfiguration ldapConfig = new LdapConfiguration()
                .MaxPageSizeIs(1000)
                //we only need to map Group this way since it doesn't use attributes
                //.AddMapping(new AutoClassMap<Group>("CN=Readers,CN=Roles,CN=Customers,DC=Northwind,DC=Extranet"))
                .AddMapping(new AttributeClassMap<Group>())
                .AddMapping(new AttributeClassMap<User>())
                .ConfigurePooledFactory("localhost")
                .UsePort(5000)
                // .AuthenticateBy(AuthType.Negotiate)
                // .AuthenticateAs(CredentialCache.DefaultNetworkCredentials);
                .AuthenticateBy(AuthType.Negotiate)
                .AuthenticateAs(new NetworkCredential("*****""********""********"));
Coordinator
Aug 29, 2011 at 3:38 AM
Edited Nov 12, 2011 at 5:07 PM

girish66,

Your server mapping looks good.  On a side note, since you've configured a connection factory you can use the parameter-less constructor for DirectoryContext.  You said that QBE works, can you show your code for that?

Coordinator
Aug 29, 2011 at 3:42 AM

girish66,

Also, for modifying passwords you can see how to do it here: http://stackoverflow.com/questions/1544336/how-to-change-passwords-using-system-directoryservices-protocols.  From what I understand you can't query for it, but you should be able to map it and update it accordingly.

Aug 29, 2011 at 5:10 PM

Hi, 

This is the QBE

 // Update using QBE
            using (var context = new DirectoryContext())
            {
                //context.Log = System.Console.Out;
                System.Console.WriteLine("Using update ------------------");
                var example = new
                                  {
                                      DistinguishedName = "",
                                      Cn = "",
                                      BusinessCategory = "",
                                      ObjectGuid = default(Guid),
                                      ObjectSid = default(SecurityIdentifier),
                                      WhenChanged = default(DateTime)
                                  };
 
                var user = context.Query(example, "CN=Users,CN=Customers,DC=Northwind,DC=Extranet", objectClass: "User")
                    .Where(u => u.Cn == "John Doe")
                    .FirstOrDefault();
                System.Console.WriteLine(user.WhenChanged);
 
                var toUpdate = new {BusinessCategory = "President and Chairman of the board"};
 
                IDirectoryAttributes updated = context.Update(user.DistinguishedName, toUpdate.ToDictionary());
                user = context.Query(example, "CN=Users,CN=Customers,DC=Northwind,DC=Extranet", objectClass: "User")
                    .Where(u => u.Cn == "John Doe")
                    .FirstOrDefault();
                System.Console.WriteLine(user.WhenChanged);
            }

For the password etc.. I am using the below

 // now, we proceed to set the user password
                lo_Modify = new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Add, "unicodePwd"Encoding.Unicode.GetBytes(ls_Password));
                connection.SendRequest(lo_Modify);
 
                // Add the user to the role
                 var roleRequest = new ModifyRequest("CN=Readers,CN=Roles,CN=Customers,DC=Northwind,DC=Extranet"DirectoryAttributeOperation.Add, "member", distinguishedName);
                connection.SendRequest(roleRequest);
 
                //// Remove role from user
                //var deleteRoleName = "CN=ldapdoe10,CN=Users,CN=Customers,DC=Northwind,DC=Extranet";
 
                //var removeRoleRequest = new ModifyRequest("CN=Readers,CN=Roles,CN=Customers,DC=Northwind,DC=Extranet", DirectoryAttributeOperation.Delete, "member", deleteRoleName);
                //connection.SendRequest(removeRoleRequest);
 
                // Remove user
                var deleteUser = "CN=ldapdoe12,CN=Users,CN=Customers,DC=Northwind,DC=Extranet";
                DeleteRequest deleteRequest = new DeleteRequest(deleteUser);
                connection.SendRequest(deleteRequest);


 

Coordinator
Aug 30, 2011 at 3:51 AM

girish66,

Can you try the latest code from the trunk and see if it works?