Dynamics 2011: Setting Owner of Activity record - c#

I am trying create Activity record in Dynamics 2011 with owner name set as "test_user". Instead below code is taking credential which is used to access Dynamics API. Is there any way to impersonate "test_user" user without passing his password? Thank you.
string TargetCrmService = ConfigurationManager.AppSettings["TargetCrmService"];
string UserName = ConfigurationManager.AppSettings["UserName"];
string Domain = ConfigurationManager.AppSettings["Domain"];
string Password = ConfigurationManager.AppSettings["Password"];
Uri organizationUri = new Uri("http://CRMDEV/XRMServices/2011/Organization.svc");
Uri homeRealmUri = null;
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = Domain + "\\" + UserName;
credentials.UserName.Password = Password;
OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(organizationUri, homeRealmUri, credentials, null);
var _userId = (from u in orgProxy.CreateQuery<SystemUser>()
where u.FullName == "Kevin Cook"
select u.SystemUserId.Value).FirstOrDefault();
IOrganizationService _service = (IOrganizationService)orgProxy;
_service.CallerId = _userId;
try
{
//Entity activity = new Entity("activitypointer");
Entity activity = new Entity("appointment");
activity["subject"] = "Test Meeting 1";
activity["description"] = "Test Description";
activity["scheduledstart"] = DateTime.Now;
activity["scheduledend"] = DateTime.Now.AddMinutes(30);
activity["createdbyname"] = "test_user";
activity["modifiedbyname"] = "test_user";
activity["createdbyname"] = "test_user";
activity["owneridname"] = "test_user";
Guid id = _service.Create(activity);
Console.WriteLine("id: " + id);
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
}
Modified Code
Based on example on http://msdn.microsoft.com/en-us/library/gg309629.aspx
var _userId = (from u in orgProxy.CreateQuery<SystemUser>()
where u.FullName == "Kevin Cook"
select u.SystemUserId.Value).FirstOrDefault();

You have two methods of setting the owenr id of an entity in CRM.
Use the AssignRequest to update the record after it is created.
Use impersonation with the OrganizationServiceProxy, CallerId to use the particular user you'd like to be the owner when it's created. You don't need their password to do impersonation, just their CRM SystemUserId

Related

Trying to access Properties in Active Directory to add to a Database

Working on pulling user info from an AD based on an ID that is entered. The error I get is:
Cannot implicitly convert type "string" to type "System.DirectoryServices.DirectoryEntry"
happening here in the Save method:
DirectoryEntry de = new DirectoryEntry();
de = QueryAD(objSearchRolesViewModel.NID);
Opening the connection:
private DirectoryEntry GetDirectoryObject()
{
DirectoryEntry oDE;
oDE = new DirectoryEntry("LDAP://myConnection");
return oDE;
}
Querying AD:
public string QueryAD(string userNID)
{
DirectorySearcher ds = new DirectorySearcher
{
SearchRoot = new DirectoryEntry(""),
//start searching from local domain
Filter = userNID
};
ds.PropertiesToLoad.Add("givenname");
ds.PropertiesToLoad.Add("sn");
ds.PropertiesToLoad.Add("mail");
// start searching
SearchResultCollection searchCollection = ds.FindAll();
try
{
foreach (SearchResult result in searchCollection)
{
if (result.Properties.PropertyNames != null)
foreach (string propKey in result.Properties.PropertyNames)
{
// Display each of the values for the property identified by the property name.
foreach (object prop in result.Properties[propKey])
{
if ((propKey == "userPrincipalName"))
{
return prop.ToString();
}
}
}
return "Unknown User";
}
catch (Exception ex)
{
return "Unknown User";
}
}
Save new user:
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
DirectoryEntry de = new DirectoryEntry();
de = QueryAD(objSearchRolesViewModel.NID);
USERACCOUNT objUserAccount = new USERACCOUNT
{
HPID = Convert.ToInt32(objSearchRolesViewModel.NewUserHealthPlans),
DOMAIN = "Aeth",
NTUSERID = objSearchRolesViewModel.User_Id,
ROLEID = Convert.ToInt32(objSearchRolesViewModel.UserRole),
FIRSTNAME = GIVENNAME GOES HERE,
LASTNAME = SURNAME GOES HERE,
EMAIL = MAIL GOES HERE,
ACTIVE = true/*Convert.ToBoolean(objSearchRolesViewModel.ActiveStatus)*/,
DEFAULTPLANID = Convert.ToInt32(objSearchRolesViewModel.NewUserPrimaryHealthPlan),
CREATEID = userID,
CREATEDATE = DateTime.Now,
UPDATEID = userID,
UPDATEDATE = DateTime.Now
};
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
}
I need to be able to access the properties from Active Directory and add them to what is being sent to the DB when a new user is added.
A couple nit-picky things:
Opening the connection
Creating a DirectoryEntry object doesn't actually open any connection. That is how almost all of Microsoft's libraries work: constructors do not make any I/O requests. The first network request is made when you first start using the object.
Also, new DirectoryEntry("") has exactly the same effect as new DirectoryEntry() - the empty string doesn't get you anything. But also, if you don't set the SearchRoot property, it will automatically set it to the current domain anyway. So you don't even need to set it unless you need to set it to a different domain or OU.
Now on to answering the question:
You have gotten a couple answers already, but they aren't ideal. You certainly can use the System.DirectoryServices.AccountManagement namespace if you want, which is just a wrapper around System.DirectoryServices to make things easier. But like all things that make things easier, it does so at the cost of performance. It always has worse performance over using System.DirectoryServices directly, yourself. One reason is because whenever a UserPrincipal object is created, it retrieves every attribute that has a value for the account. You probably aren't using every attribute.
If you can wrap your head around using DirectoryEntry/DirectorySearcher yourself, you will have better performing code.
Jawad's answer will also work, but it has one key issue that will slow down your code: DirectorySearcher will return all the attributes you request. You already set PropertiesToLoad, which is good - it will limit the results to only the attributes you need. But if you use GetDirectoryEntry(), that info is lost. If you then start using .Properties on the DirectoryEntry, it will make a new network request and ask for all attributes that have values. That can be a lot of data that you aren't using, apart from being a second network request that you could avoid.
I would suggest just returning a SearchResult from QueryAD, which will let you use the data that was returned in the search.
You can also use FindOne() instead of FindAll(), since you are only using the first result anyway. This will make AD stop looking after it finds one result. Just test for null in case the user wasn't found.
public SearchResult QueryAD(string userNID)
{
DirectorySearcher ds = new DirectorySearcher(userNID) {
PropertiesToLoad = {"givenname", "sn", "mail"}
};
return ds.FindOne();
}
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
var result = QueryAD(objSearchRolesViewModel.NID);
if (result == null)
{
//user wasn't found!
}
USERACCOUNT objUserAccount = new USERACCOUNT
{
HPID = Convert.ToInt32(objSearchRolesViewModel.NewUserHealthPlans),
DOMAIN = "Aeth",
NTUSERID = objSearchRolesViewModel.User_Id,
ROLEID = Convert.ToInt32(objSearchRolesViewModel.UserRole),
FIRSTNAME = (string) result.Properties["givenName"]?[0],
LASTNAME = (string) result.Properties["sn"]?[0],
EMAIL = (string) result.Properties["mail"]?[0],
ACTIVE = true/*Convert.ToBoolean(objSearchRolesViewModel.ActiveStatus)*/,
DEFAULTPLANID = Convert.ToInt32(objSearchRolesViewModel.NewUserPrimaryHealthPlan),
CREATEID = userID,
CREATEDATE = DateTime.Now,
UPDATEID = userID,
UPDATEDATE = DateTime.Now
};
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
}
The Properties of a SearchResult will always present properties as arrays, even if they are single-valued attributes in AD. This is different than DirectoryEntry. But that is the reason for the [0] in result.Properties["givenName"]?[0] as string. The ? is to test for null, because if the attribute is not set in AD, then it won't appear in the Properties collection at all.
I wrote an article about getting better performance when programming with AD, with a focus on C#. You might enjoy reading it.
In your code, QueryAD(objSearchRolesViewModel.NID); returns a string but you are assigning it to a DirectoryEntity. This wont work.
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
DirectoryEntry de = new DirectoryEntry();
de = QueryAD(objSearchRolesViewModel.NID); // <--- This is the issue.
...
Look up DirectoryEntry from the QueryAD function and return that object to make your call work.
public string QueryAD(string userNID) // You will need to return DirectoryEntry to make your code work.
{
DirectorySearcher ds = new DirectorySearcher
EDIT:
I find using UserPrincipal with PrincipalContext to be much simpler. Look up PrincipalContext by using your domain name and provide creds if not running with domain account. Then, simply, lookup user by SamAccountName, Name/ID or DistinguishedName.
You will need, 'System.DirectoryServices.AccountManagement' nuget package for Principal usage.
public static UserPrincipal QueryAD(string UserName)
{
PrincipalContext context = new PrincipalContext(ContextType.Domain, "Aeth", "user", "password");
// Without creds if the account running the code is already a domain account
//PrincipalContext context = new PrincipalContext(ContextType.Domain, "Aeth");
// You can search the account by SamAccountName, DistinguishedName, UserPrincipalName or SID
return UserPrincipal.FindByIdentity(context, IdentityType.Name, UserName);
}
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
UserPrincipal user = QueryAD(objSearchRolesViewModel.User_Id);
USERACCOUNT objUserAccount = new USERACCOUNT
{
HPID = Convert.ToInt32(objSearchRolesViewModel.NewUserHealthPlans),
DOMAIN = "Aeth",
NTUSERID = objSearchRolesViewModel.User_Id,
ROLEID = Convert.ToInt32(objSearchRolesViewModel.UserRole),
FIRSTNAME = user.GivenName, // Get FirstName
LASTNAME = user.Surname, // Get LastName
EMAIL = user.EmailAddress, // Get Email Address
ACTIVE = user.Enabled, // Get User Status
DEFAULTPLANID = Convert.ToInt32(objSearchRolesViewModel.NewUserPrimaryHealthPlan),
CREATEID = userID,
CREATEDATE = DateTime.Now,
UPDATEID = userID,
UPDATEDATE = DateTime.Now
};
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
}
Following is your code that uses DirectoryEntry method. Make sure you add credentials if you are running this code with account that does not have access to AD.
Method to search AD
public DirectoryEntry QueryAD(string UserName)
{
try
{
DirectorySearcher ds = new DirectorySearcher
{
SearchRoot = new DirectoryEntry(),
//start searching from local domain
Filter = "(&" +
"(objectClass=user)" +
"(name=" + UserName + "))" // This is Username
};
// start searching
return ds.FindOne().GetDirectoryEntry();
}
catch (Exception ex)
{
throw new ApplicationException("error occured while querying AD");
}
}
Method to Check if Account is Active
private bool IsActive(DirectoryEntry de)
{
if (de.NativeGuid == null) return false;
int flags = (int)de.Properties["userAccountControl"].Value;
return !Convert.ToBoolean(flags & 0x0002);
}
Method to Save the User to your DB
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
DirectoryEntry userEntry = QueryAD(objSearchRolesViewModel.User_Id);
if (userEntry == null)
{
//Handle error where No User was Found.
throw new ApplicationException("User Not Found");
}
USERACCOUNT objUserAccount = new USERACCOUNT
{
HPID = Convert.ToInt32(objSearchRolesViewModel.NewUserHealthPlans),
DOMAIN = "Aeth",
NTUSERID = objSearchRolesViewModel.User_Id,
ROLEID = Convert.ToInt32(objSearchRolesViewModel.UserRole),
FIRSTNAME = userEntry.Properties["givenname"].Value.ToString(),
LASTNAME = userEntry.Properties["sn"].Value.ToString(),
EMAIL = userEntry.Properties["mail"].Value.ToString(),
ACTIVE = IsActive(userEntry),
DEFAULTPLANID = Convert.ToInt32(objSearchRolesViewModel.NewUserPrimaryHealthPlan),
CREATEID = userID,
CREATEDATE = DateTime.Now,
UPDATEID = userID,
UPDATEDATE = DateTime.Now
};
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
}

How do I add a salesforce community user using the API?

I've downloaded the API WSDL and added it to my C# project and have many successful integrations running throught it both bringing down and upserting data. I'm having a lot of trouble with creating community user accounts for our learning management system though.
I can't tell if I need to supply an account, or a contact, or a user type, and no matter what I try I end up with an error that doesn't lead me to a logical fix.
I think i'm closest with the below configuration, which is giving me this error: "You can't create a contact for this user because the org doesn't have the necessary permissions. Contact Salesforce Customer Support for help."
This is my C# code I'm trying to create a User account with:
public UpsertResponse UpsertLearningUser()
{
SFProd.User U = new SFProd.User();
U.Id = UserID;
U.Username = UserName;
U.Alias = TechCode;
U.CommunityNickname = FirstName + "." + LastName;
U.FirstName = FirstName;
U.LastName = LastName;
U.MiddleName = MiddleName;
U.Title = Title;
U.Department = Department;
U.Division = Division;
U.IsActive = Active;
U.IsActiveSpecified = true;
U.UserPermissionsChatterAnswersUser = true;
U.UserPermissionsChatterAnswersUserSpecified = true;
//U.UserPermissionsMobileUser = true;
//U.UserPermissionsMobileUserSpecified = true;
U.Phone = Phone;
U.EmployeeNumber = ADPNumber;
U.NS_Internal_ID__c = NSEmployeeID.ToString();
U.Employee_ID__c = double.Parse(EmployeeID.ToString());
U.Employee_ID__cSpecified = true;
U.Zone__c = Department;
U.Region__c = Division;
U.Certification_Level__c = CertificationLevel;
if (CertificationLevelDate != DateTime.Parse("1/1/1900"))
{
U.Certification_Level_Date__c = CertificationLevelDate;
U.Certification_Level_Date__cSpecified = true;
}
U.Country = Country;
U.State = State;
U.City = City;
U.PostalCode = PostalCode;
U.Street = Street;
U.Email = Email;
U.TimeZoneSidKey = "America/Chicago";
U.EmailEncodingKey = "ISO-8859-1";
U.ProfileId = "00ef10000016tfvAAA";
U.LanguageLocaleKey = "en_US";
U.ContactId = ContactID;
List<SFProd.sObject> Objs = new List<SFProd.sObject>();
Objs.Add(U);
return new UpsertResponse(SFConnection.RunUpsert("Username", Objs)[0], UserID);
}
Has anyone else done this sucessfully? or have any idea what I'm doing wrong?
There is a special function for creating external users. Try a variation of the CreateExternalUser() function: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_sites.htm

Adding User to Organization Unit and Group using Google Directory API

I am successful to create new user account using Google Directory API in .Net platform, but now I need to add that created user to Organization Unit and Group. I see the API details in this link to add the user to Organization Unit but any example showing insertion to Organization Unit would be greatly appreciated.
Updated with working code: Below is the code to create new user account using Directory API:
String serviceAccountEmail = ".........#developer.gserviceaccount.com";
X509Certificate2 certificate = new X509Certificate2(#"C:\key.p12", "secret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[]
{
DirectoryService.Scope.AdminDirectoryUser
},
User = "test#example.com",
}.FromCertificate(certificate));
var ser = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Google Account",
});
try
{
var user = new Google.Apis.Admin.Directory.directory_v1.Data.User()
{
Name = new Google.Apis.Admin.Directory.directory_v1.Data.UserName()
{
GivenName = FirstName.Text,
FamilyName = LastName.Text
},
Password = password
};
User newUser = new User();
UserName newUserName = new UserName();
newUser.PrimaryEmail = Email.Text;
newUserName.GivenName = FirstName_txt.Text;
newUserName.FamilyName = LastName_txt.Text;
newUser.Name = newUserName;
newUser.Password = password;
//Adding User to OU:
newUser.OrgUnitPath = "/Employee";
User results = ser.Users.Insert(newUser).Execute();
//Adding User to Group:
Member newMember = new Member();
newMember.Email = Email.Text;
newMember.Role = "MEMBER";
newMember.Kind = "admin#directory#member";
api.Members.Insert(newMember, "Employee#example.com").Execute();
Any idea how to insert the created user in Organization Unit and Group using Directory API?
To insert the new user into a Organization Unit just set the OU path when you create the user.
User newUser = new User();
UserName newUserName = new UserName();
newUser.PrimaryEmail = Email.Text;
newUserName.GivenName = FirstName_txt.Text;
newUserName.FamilyName = LastName_txt.Text;
newUser.Name = newUserName;
newUser.Password = password;
**newUser.OrgUnitPath ="\My\Organization\Unit\path\";**
User results = ser.Users.Insert(newUser).Execute();
Now your user has been added to the OU path.
To add a member into a group see the following code.
Member newMember = new Member();
newMember.Email = userKey;//email of the user that you want to add
newMember.Role = "MEMBER";
newMember.Type = "USER";
newMember.Kind = "admin#directory#member";
ser.Members.Insert(newMember, "MyDestinationGroup#mydomain").Execute();
that's it.
Note: you must review the scopes for the correct permissions.
Hope this help you.

AD User created by application isn't properly resolving to a upn suffix

I am working on some code that creates an AD user programmatically (to be pulled into a MS DYnamics CRM 2013 environment), and the code works with one weird quirk. I have a list of UPN's created on our AD structure, but for some reason my AD users aren't resolving to them.
So, I have a list of UPN suffix's that include example.com. I set the username to be first.last#example.com, and it's not letting me use this to sign in to CRM. When I check the AD entry, I can see that it kind of correctly assigned the logon name to first.last#example.com, but #example.com appears in the list twice, the entry that was actually created and this new one. So it's not recognizing that #example.com is a pre-existing UPN suffix, and I can't use the first.last#example.com to sign in to CRM with, I have to use the example.local\first.last. I hope this made sense. Thank you very much.
So how do I tell then AD record when it signs in to use the pre-existing UPN and not... do whatever it's doing? Here's my code:
try
{
string connectionPrefix = "LDAP://" + ldapPath;// ldapPart;// ldapPath
var adminUsername = ConfigurationHelper.GetConfigSettingByName(orgservice,
"ADPasswordReset.AdminUsername", unsecureConfig, secureConfig);
var adminPassword = ConfigurationHelper.GetConfigSettingByName(orgservice,
"ADPasswordReset.AdminPassword", unsecureConfig, secureConfig);
if (CheckIfUserExists(getSAMNameFromUserName(userName), trace) == true)
{
throw new Exception("A User with that name already exists.");
}
DirectoryEntry dirEntry = new DirectoryEntry(connectionPrefix, adminUsername, adminPassword, AuthenticationTypes.Secure);
DirectoryEntry newUser;
string cn = firstName + " " + lastName;
newUser = dirEntry.Children.Add("CN=" + cn, "user"); //display name - This is the "Display" name that shows up on the AD list.
newUser.Properties["displayName"].Value = cn;
newUser.Properties["samAccountName"].Value = getSAMNameFromUserName(userName);//userName;
newUser.Properties["userPrincipalName"].Value = checkUserName(userName);
newUser.Properties["givenName"].Value = firstName; //Firstname
newUser.Properties["sn"].Value = lastName; //Lastname? -Surname
newUser.Properties["LockOutTime"].Value = 0; //unlock account. Set this to 0 to unlock the account.
newUser.CommitChanges();
oGUID = newUser.Guid.ToString();
//Must be handled after the previous stuff. Unsure why.
newUser.Invoke("SetPassword", new object[] { userPassword });
newUser.CommitChanges();
//For some reason, can't be handled before the password is set?
newUser.Properties["userAccountControl"].Value = 0x0200; //0x0200
newUser.CommitChanges();
dirEntry.Close();
newUser.Close();
}
public static string checkUserName(string userName)
{
if (!userName.Contains("#"))
{
return userName + "#example.local";
}
return userName;
}
public static string getSAMNameFromUserName(string domainUserName)
{
int stop;
string s = domainUserName;
if (s.Contains("#"))
{
stop = s.IndexOf("#");
return (stop > -1) ? s.Substring(0, stop) : string.Empty;
}
return domainUserName;// string.Empty;
}
In your code you set the UPN to example.local not example.com:
public static string checkUserName(string userName)
{
if (!userName.Contains("#"))
{
return userName + "#example.local";
}
return userName;
}
A user can only have one UPN even if the domain has multiple possible suffixes configured. If you want username#example.com to resolve, the user must have example.com set as it's suffix.
Thank you all who took the time to help.
Whitespace. Grrr, whitespace.
For anybody who comes across this thread in the future, the problem was that something during the AD creation was appending whitespace to my username and domain. So instead of "example.com" it was saving the domain as "example.com " (notice the whitespace at the end?). I .Trim()'d everything and it appears to be working just fine. :)
My new code becomes:
public static string checkUserName(string userName)
{
if (!userName.Contains("#"))
{
return userName.Trim() + "#domain.local".Trim();
}
return userName.Trim();
}
try
{
string connectionPrefix = "LDAP://" + ldapPath;// ldapPart;// ldapPath
var adminUserName = GetAdminUserName(orgservice, unsecureConfig, secureConfig);
var adminPassword = GetAdminPassword(orgservice, unsecureConfig, secureConfig);
if (CheckIfUserExists(getSAMNameFromUserName(userName), trace) == true)
{
trace.Trace("About to handle success. A User already exists: " + getSAMNameFromUserName(userName));
trace.HandleSuccess();
throw new Exception("User " + getSAMNameFromUserName(userName) + " already exists.");
}
DirectoryEntry dirEntry = new DirectoryEntry(connectionPrefix, adminUserName, adminPassword, AuthenticationTypes.Secure);
DirectoryEntry newUser;
string cn = firstName.Trim() + " " + lastName.Trim();
newUser = dirEntry.Children.Add("CN=" + cn, "user"); //display name - This is the "Display" name that shows up on the AD list.
newUser.Properties["displayName"].Value = cn;
newUser.Properties["samAccountName"].Value = getSAMNameFromUserName(userName).Trim();
newUser.Properties["userPrincipalName"].Value = checkUserName(userName).Trim();
newUser.Properties["givenName"].Value = firstName.Trim(); //Firstname
newUser.Properties["sn"].Value = lastName.Trim(); //Lastname? -Surname
//newUser.Properties["LockOutTime"].Value = 0; //unlock account. Set this to 0 to unlock the account.
newUser.CommitChanges();
oGUID = newUser.Guid.ToString();
//Must be handled after the previous stuff. Unsure why.
newUser.Invoke("SetPassword", new object[] { userPassword });
newUser.CommitChanges();
//For some reason, can't be handled before the password is set?
newUser.Properties["userAccountControl"].Value = 0x10200; //0x0200
newUser.CommitChanges();
//http://stackoverflow.com/questions/20710535/is-there-a-way-to-set-a-new-users-domain-suffix-through-the-userprincipal-class
newUser.Close();
dirEntry.Close();
//newUser.Close(); //Close user first, then dirEntry because of the heirarchy call?
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
System.DirectoryServices.DirectoryServicesCOMException newE = new System.DirectoryServices.DirectoryServicesCOMException(E.Message);
//DoSomethingwith --> E.Message.ToString();
throw newE;
}

Getting manager email id from active directory

How to get user manager email id from active directory? I have written code with which I can get user's firstname, lastname, email id and his manager name based on userid, but I want to get manager email id along with his manager name.
Can somebody please help me how to get this? Here is my code:
protected void ddlAdsuser_SelectedIndexChanged(object sender, EventArgs e)
{
DirectoryEntry root = new DirectoryEntry("LDAP://RootDSE");
string myDomain = root.Properties["defaultNamingContext"].Value.ToString();
DirectoryEntry domain = new DirectoryEntry("LDAP://" + myDomain);
DirectorySearcher dsUsers = new DirectorySearcher(domain);
dsUsers.Filter = "(userPrincipalName=" + ddlAdsuser.Text + ")";
foreach (SearchResult sResultSet in dsUsers.FindAll())
{
lblfname.Text = GetProperty(sResultSet, "givenName");
lbllname.Text = GetProperty(sResultSet, "sn");
lblemail.Text = GetProperty(sResultSet, "mail");
string Manager = string.Empty;
Manager = GetProperty(sResultSet, "manager");
if (Manager != "")
{
if (Manager.Contains("CN="))
{
int Length = Manager.IndexOf(',');
Manager = Manager.Substring(3, Length - 3);
}
else
{
Manager = string.Empty;
}
}
lblManagerID.Text = Manager; //Here displaying the manager name.
}
}
public static string GetProperty(SearchResult searchResult, string PropertyName)
{
if (searchResult.Properties.Contains(PropertyName))
{
return searchResult.Properties[PropertyName][0].ToString();
}
else
{
return string.Empty;
}
}
DirectorySearcher objDirSearch = new DirectorySearcher(SearchRoot);
DirectoryEntry dentUser = null;
string pstrFieldName, pstrValue;
pstrFieldName = "company";
pstrValue = "12345"; //Employee number
/*setting the filter as per the employee number*/
objDirSearch.Filter = "(&(objectClass=user)(" + pstrFieldName + "=" + pstrValue + "))";
SearchResult objResults = objDirectorySearch.FindOne();
dentUser = new DirectoryEntry(objResults.Path);}
string strManager = dentUser.Properties["manager"].Value.ToString();
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.DistinguishedName, strManager);
string strManagerMailID = user.EmailAddress;
Simple code and working great:
public static string GetEmail(string userId)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userId);
return user.EmailAddress;
}
You must add assembly System.DirectoryServices.AccountManagement.dll.
If you have any troubles with connection to AD, you can try to add AD server name in PrincipalContext constructor.
Just do a second search for the manager.
Note that you way of building the query filter is buggy, you need to escape some characters (Especially the " quote) in order to avoid broken queries depending on user input.

Categories

Resources