Can't add members to a group whilst creating the group

Jan 22, 2012 at 6:26 AM
Edited Jan 26, 2012 at 9:00 AM

I've created a directory object class and ClassMap for a group (in v202).  If I try to add members to the group at the point of creation, I get an error: "The value must be a string, byte[], or Uri type. Parameter name: value".  If I create the group and then add the members, it works.  Is this expected?

I originally noticed this on seeAlso on user, which is also a multi-valued attribute.  I checked and if I defined seeAlso as if it were a single-valued attribute, using String instead of Collection<String>, I can set a value whilst creating the user.  So, it's something about it being multi-valued, rather than anything to do with that particular attribute (c.f. description which can behave oddly).

The directory object class has member defined as:

private Collection<string> _member;     // group
public Collection<String> member
{
    get { return this._member; }
    set
    {
        if (value != this._member)
        {
            this._member = value;
            AttributeChanged<GroupObject, Collection<String>>(a => a.member);
        }
    }
}

And the ClassMap just uses:

Map(x => x.member);

The error is:

System.ArgumentException

The value must be a string, byte[], or Uri type.
Parameter name: value

   at System.DirectoryServices.Protocols.DirectoryAttribute.Add(Object value)
   at System.DirectoryServices.Protocols.DirectoryAttribute..ctor(String name, Object[] values)
   at LinqToLdap.DirectoryContext.b__8[T](<>f__AnonymousType0`2 <>h__TransparentIdentifier5) in C:\Users\ahatter\Documents\Visual Studio 2010\Projects\linqtoldap\Trunk\LinqToLdap\DirectoryContext.cs:line 278
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at LinqToLdap.DirectoryContext.Add[T](T entry, String distinguishedName) in C:\Users\ahatter\Documents\Visual Studio 2010\Projects\linqtoldap\Trunk\LinqToLdap\DirectoryContext.cs:line 275
   at ilminator.LinqToLdap.DirectoryObjects.Tester.Program.Main(String[] args) in C:\Documents and Settings\me\my documents\visual studio 2010\Projects\ilminator.LinqToLdap.DirectoryObjects.Tester\ilminator.LinqToLdap.DirectoryObjects.Tester\Program.cs:line 45
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

I can post all of the classes if you want but I'm using a hierarchy for the directory objects: Top <- SecPrinMailRecipEtc <- GroupObject and they've each got quite a few properties so it's a bit messy.  It's for my latest article which is about setting up an assembly to hold definitions.

**** EDIT ****

I've now finished that article and posted it here so you can see the full hierarchy of objects.

Also, I've had a go with S.DS.P and I was able to add multiple members to a group at the point of creation:

    string hostOrDomainName = "dc1";
    var name = "SDSPTestGroup1";
    string dn = String.Format("CN={0},OU=Test,DC=big,DC=wooden,DC=badger",
        name);

    LdapConnection connection = new LdapConnection(hostOrDomainName);
    try
    {
        var objectClass = new DirectoryAttribute("objectClass", "group");
        var groupType = new DirectoryAttribute("groupType", "-2147483644");
        var sAMAccountName = new DirectoryAttribute("sAMAccountName", name);
        var member = new DirectoryAttribute("member", new string[] 
        {
            "CN=TestUser1,OU=Test,DC=big,DC=wooden,DC=badger",
            "CN=TestUser2,OU=Test,DC=big,DC=wooden,DC=badger"
        });
        var attributes = new DirectoryAttribute[]
        {
            objectClass, groupType, sAMAccountName, member
        };
        AddRequest addRequest = new AddRequest(dn, attributes);

        AddResponse addResponse =
            (AddResponse)connection.SendRequest(addRequest);

        Console.WriteLine("A {0} with a dn of\n {1} was added successfully " +
            "The server response was {2}",
            objectClass.ToString(), dn, addResponse.ResultCode);
    }
    catch (Exception e)
    {
        Console.WriteLine("\nUnexpected exception occured:\n\t{0}: {1}",
                            e.GetType().Name, e.Message);
    }
which is basically lifted from Intro to S.DS.P.