C# Add User to Active Directory - The attribute syntax specified to the directory service is invalid
Asked Answered
S

2

5

I am having an issue when attempting to create a new user in active directory. I followed the steps provided in this link for using PrincipalContext (with the exception that I am only doing one user at a time when they are hired and entered into the system and not multiple so no loop is required). I am also using a UserPrincipal Extender.

Here is the code that I have:

protected void CreateUserPE()
{
    try
    {
        PrincipalContext userCtx = new PrincipalContext(ContextType.Domain, DomainFQDN, DomainFull);
        string UserName = txtFirstName.Text.ToLower() + " " + txtLastName.Text.ToLower();
        string password = "superSecretPassword";

        UserPrincipalsEx newUser = new UserPrincipalsEx(userCtx, UserName, password, true);
        newUser.SamAccountName = txtFirstName.Text.ToLower() + "." + txtLastName.Text.ToLower();
        newUser.UserPrincipalName = txtFirstName.Text.ToLower() + "." + txtLastName.Text.ToLower() + "@rasm.com";
        newUser.EmployeeId = txtEmpID.Text;
        newUser.LastName = txtLastName.Text;
        newUser.GivenName = txtFirstName.Text;
        newUser.DisplayName = txtFirstName.Text + " " + txtLastName.Text;
        newUser.Name = txtFirstName.Text + " " + txtLastName.Text;
        newUser.SetPassword(password);
        newUser.HomePostalAddress = txtAddress.Text + ", " + txtCity.Text + ", " + txtState.Text + ", " + txtZip.Text;
        newUser.CountryName = txtCountry.Text;
        newUser.HomePhone = txtHomePhone.Text;
        newUser.MobilePhone = txtMobilePhone.Text;
        newUser.DateOfBirth = txtDOB.Text;
        newUser.EmergencyContact = txtEmergencyCnt.Text;
        newUser.EmergencyPhone = txtContactPhone.Text;
        newUser.Relationship = ddlRelationship1.SelectedItem.ToString();
        newUser.EmergencyContact2 = txtEmergencyCnt2.Text;
        newUser.EmergencyPhone2 = txtContactPhone2.Text;
        newUser.Relationship2 = ddlRelationship2.SelectedItem.ToString();
        newUser.EyeColor = ddlEyeColor.SelectedItem.ToString();
        newUser.HairColor = ddlHairColor.SelectedItem.ToString();
        newUser.Height = txtHeight.Text;
        newUser.Weight = txtWeight.Text;
        newUser.Gender = ddlGender.SelectedItem.ToString();
        newUser.PersonalEmail = txtPersonalEmail.Text;
        newUser.PassportExpires = txtPassportExp.Text;
        newUser.HomeBase = ddlHomeStation.SelectedItem.ToString();
        newUser.WorkLocation = txtWorkLocation.Text;
        newUser.PID = txtPID.Text;
        newUser.Team = txtTeam.Text;
        newUser.Manager = "CN=" + txtSupervisor.Text + "," + DomainFull;
        newUser.Title = ddlJobTitle.SelectedItem.ToString();
        newUser.JobCode = txtJobCode.Text;
        newUser.PLC = txtPLC.Text;
        newUser.BPLC = txtBPLC.Text;
        newUser.Specialty = txtSpecialty.Text;
        newUser.Position = txtPosition.Text;
        newUser.DateOfHire = txtDOH.Text;
        newUser.DateOnContract = txtDOC.Text;
        newUser.TaskOrder = ddlTaskOrder.SelectedItem.ToString();
        newUser.Classification = ddlClass.SelectedIndex.ToString();
        newUser.Section = txtSection.Text;
        newUser.GatePass = txtGatePass.Text;
        newUser.GatePassExpires = txtGatePassExp.Text;
        newUser.WorkPhone = txtWorkPhone.Text;
        newUser.CompanyEmail = txtCompEmail.Text;
        newUser.aKOEmail = txtMilEmail.Text;
        newUser.aKOSponsor = txtMilEmailSp.Text;
        newUser.CACSponsor = txtCacSponsor.Text;
        newUser.CACSponsorEmail = txtCacSponsorEmail.Text;
        newUser.CacCardExpires = txtCacExpires.Text;
        newUser.Enabled = true;
        newUser.ExpirePasswordNow();
        newUser.Save();
        newUser.Dispose();
    }
    catch
    {

    }
}

The program goes all the way to newUser.Save() and then throws the following error in the catch statement:

System.DirectoryServices.AccountManagement.PrincipalOperationException was caught
  HResult=-2146233087
  Message=The attribute syntax specified to the directory service is invalid.

  Source=System.DirectoryServices.AccountManagement
  ErrorCode=-2147016693
  StackTrace:
   at System.DirectoryServices.AccountManagement.ADStoreCtx.Insert(Principal p)
   at System.DirectoryServices.AccountManagement.Principal.Save()
   at Personnel_Employee.CreateUserPE() in c:\inetpub\wwwroot\TestingFolder\Personnel\Add\Employee.aspx.cs:line 263
   InnerException: System.DirectoryServices.DirectoryServicesCOMException
   HResult=-2147016693
   Message=The attribute syntax specified to the directory service is invalid.

   Source=System.DirectoryServices
   ErrorCode=-2147016693
   ExtendedError=87
   ExtendedErrorMessage=00000057: LdapErr: DSID-0C090D11, comment: Error in attribute conversion operation, data 0, v23f0
   StackTrace:
        at System.DirectoryServices.DirectoryEntry.CommitChanges()
        at System.DirectoryServices.AccountManagement.SDSUtils.ApplyChangesToDirectory(Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes)
   InnerException: 

Where am I going wrong.

Superordinate answered 12/6, 2014 at 20:18 Comment(20)
The exception is thrown on newUser.Save() ? It's a bit boring, but can you provide the lines you replace by '... More Similar Code ...'. I suspect that the trouble comes from an atribute syntax.Ammoniate
I performed the edit as you requested. Most of the attributes are custom added to Active Directory through MMC.EXE. I set all my custom ones to "Unicode String" for syntax. I also created a class called UserPrincipalsEx.cs to extend all the attributes that are not available by default."Superordinate
I think I understand. UserPrincipalsEx is declared : class UserPrincipalsEx : UserPrincipal ?Ammoniate
public class UserPrincipalsEx : UserPrincipal { public UserPrincipalsEx(PrincipalContext context) : base(context) { } public UserPrincipalsEx(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { }Superordinate
Are you aware of the fact that you have to map, your class properties with the the Active-Directory attributes, using attributes ?Ammoniate
[DirectoryProperty("aKOEmail")] public string aKOEmail { get { if (ExtensionGet("aKOEmail").Length != 1) return null; return (string)ExtensionGet("aKOEmail")[0]; } set { this.ExtensionSet("aKOEmail", value); } }Superordinate
Is this what you mean by mapping?Superordinate
You have not enough reputation to chatAmmoniate
[DirectoryProperty("aKOEmail")]public string aKOEmai ... means that you map you property aKOEmai to aKOEmai attribute in your Active-Directory. "aKOEmai" is not a standard attribute do you add it in your Active-Directory ?Ammoniate
I created a new attribute in MMC.EXE after adding the Schema snap-in, created a new OID with the script provided by Microsoft, and added the attribute to the User class.Superordinate
Nice and you do so for each new attributes ? When you create the attribute in the schema do take care of the syntax you use ?Ammoniate
Yes, all custom attributes are created (took a while) and they are all "Unicode string"Superordinate
Ok, after that you assign all the new attributes to an abstract class, and add the abstract class to user class ? do you take time to reload the schema ?Ammoniate
I am not sure that I have done that. By now I have posted all the code I have that pertains to inserting into Active Directory. Could this be what I am missing?Superordinate
Il always modify Directories (Active-Directory, OpenLDAP ...) using LDIF script (never using UI to deploy) And I always use Abstract classes to group my own attributs. Sorry to tell you that, but you met a trouble with one attribute. If I were you I would use a dichotomizing approch, testing again with an extention class using half attributes, and so on till I found the attribute, with the bad spelling or syntax.Ammoniate
So I am reading this as putting the "newUser.Save()" after each attribute to see where it fails???Superordinate
So ? Do you find the problem ?Ammoniate
I added save() after my first entry (SamAccountName) and got an error of "The specified directory service attribute or value does not exist." I commented it out, ran again, and go this on (UserPrincipalName) "SamAccountName or Name must be assigned to a newly-created Principal object in this store prior to saving." Does this mean that you have to add the properties in a certain order???Superordinate
There is no order, just some attributes are mandatory.Ammoniate
Here is an example of extending UserPrincipal.Ammoniate
M
8

You can not update an attribute with null or empty. I personaly dislike solutions with dummy values. If you are using the context principle just simply check for null or empty and dont update if its the case like:

if (!string.IsNullOrEmpty(txtbox.Text)){ newUser.attributeName = txtbox.Text}

If you are using an directory entry instead of an usercontext you can do something like this:

string adPath = "LDAP://server.domain.com/CN=John,CN=Users,dc=domain,dc=com";
DirectoryEntry userEntry = new DirectoryEntry(adPath);
if (txtBox.text == "")
{
    userEntry.Properties["proppertyName"].Clear();
}
else if (!string.IsNullOrEmpty(txtBox.text))
{
    userEntry.Properties[attribute.Key].Value = txtBox.text;
}
// dont do a thing when txtBox.Text is empty

It looks like more code but its much easier to make a foreachloop for it if you have a list with all attribute like:

private void UpdateEntryAttributes(DirectoryEntry entry, Dictionary<string, string> attributes)
{
    foreach (KeyValuePair<string, string> attribute in attributes)
    {
    entry.Properties[attribute.Key].Value = attribute.Value;

    if (attribute.Value == "")
    {
        entry.Properties[attribute.Key].Clear();
    }
    else if (!string.IsNullOrEmpty(attribute.Value))
    {
        entry.Properties[attribute.Key].Value = attribute.Value;
    }
}
Misspend answered 12/2, 2019 at 11:7 Comment(0)
B
3

This can happen when attempting to write either a null or empty string to an AD field that prohibits it. An easy way to check whether this is the problem is to temporarily replace all such values with a dummy string (length > 0) and then run the code again. If that works, you can attempt a fix by changing the offending value--with AD, sometimes if null doesn't work, then an empty string will work, or vice versa.

Braiding answered 10/11, 2018 at 20:55 Comment(2)
Arrrrgh, the attribute was null or empty string. Thank you for posting this! It's so frustrating trying to figure out the cryptic AD error messages. Upvoted!Nevile
It doesn't mention what attribute, very helpful messages indeed...Erdei

© 2022 - 2024 — McMap. All rights reserved.