|
|
AD WebService Help. (Code Included)
Last post 05-29-2008, 1:41 PM by joe. 7 replies.
-
04-28-2008, 8:16 AM |
-
lair
-
-
-
Joined on 04-25-2008
-
-
Posts 21
-
-
|
AD WebService Help. (Code Included)
Hi,
I am building a web service to be used to update Active Directory. The information to be update will come from a join I already created from 2 different tables and databases.
First the information from the join will be query by the employeeID wich is also the object from AD with AD. My problem is that I am a totally newby with this kind of task and I am having trouble to check in the join data and then match by the employeeId in AD and update AD.
What I really need is for someone to help me check my code and help me to fix it and make to work the way I needed. I am getting close to the deadline for this project and really, really need some help with this. I order the book but can wait till get it, I hope to get it by this friday wich is my deadline. Also I need to verify that the error can be written in the logfile code.
Any help will be very appreciated. Please need help with this. :( I've been looking over the internet to different code and here is my frankenstein. WEB SERVICE CODE:
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Linq; using System.Data.Sql; using System.Data.SqlTypes; using System.Data.SqlClient; using System.DirectoryServices; using System.IO;
namespace ActiveDirectoryService { /// <summary> /// Active Directory Web Service /// Gets Data From XCADUsers and Finance Employee Table /// </summary> [WebService(Namespace = "http://myweb.com/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class Service1 : System.Web.Services.WebService {
#region Variables string employeeId = ""; string fName = ""; string lName = ""; string telNum = ""; string ipPhone = ""; string mobile = ""; string epager = ""; string manager = ""; string dpt = ""; string initials = ""; string dispName = ""; string email = ""; string homePhone = ""; string title = ""; string filePath = ""; string sLogFormat; string sErrTime;
public string connString = "Server=myserver;uid=myusername;pwd=mypass;Database=myDB;Integrated Security=True";
DirectoryEntry dEntry = null; DirectorySearcher ds = null; SqlConnection sqlConn = null; SqlCommand myCmd = null; StreamWriter sw = null; #endregion
#region AD Connection public void ADConn() { try { dEntry = new DirectoryEntry("LDAP://myDomain", "uid", "pass", AuthenticationTypes.Secure); ds = new DirectorySearcher(dEntry); } catch (Exception ex) { sw.Write("Error conecting to Active Directory: " + ex.Message); sw.Close(); } } #endregion AD Connection
#region for test public DirectoryEntry GetDirectory() { DirectoryEntry oDE; oDE = new DirectoryEntry(dEntry); return oDE; } private DirectoryEntry GetAllUsers() { DirectoryEntry de = GetDirectory(); DirectorySearcher deSearch = new DirectorySearcher(); deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=user))"; deSearch.SearchScope = SearchScope.Subtree; SearchResult results = deSearch.FindOne();
if (!(results == null)) { de = new DirectoryEntry(results.Path, "uid", "pass", AuthenticationTypes.Secure); return de; } else { return null; } } #endregion for test
#region XCADSQLConnection public void SqlConn() { try { sqlConn = new SqlConnection(connString); sqlConn.Open(); myCmd = new SqlCommand("Select * From view_join", sqlConn); } catch (Exception ex) { sw.Write("Error conecting to View: " + ex.Message); sw.Close(); } } #endregion
#region FindEmployee public bool FindEmp() { try { ds = new DirectorySearcher(dEntry, Query(), new string[] { "ADsPath" }); SearchResult sResult = ds.FindOne(); if (sResult == null) { sw.Write("Employee not found"); } DirectoryEntry ent = sResult.GetDirectoryEntry(); Properties(ent); } catch (Exception ex) { sw.Write("Error looking for employee in Active Directory: " + ex.Message); sw.Close(); return false; } return false; } #endregion
#region UpdateEmployee public bool UpdateEmp() { try { FindEmp(); Values(dEntry); dEntry.CommitChanges(); } catch (Exception ex) { sw.Write("Error updating employee in Active Directory: " + ex.Message); sw.Close(); return false; } return false; } #endregion
#region Query public string Query(String attribute, string srtText) { try { if (srtText.Length > 0) { return "(" + attribute + "=" + srtText + ")"; } return ""; } catch (Exception ex) { sw.Write("Error in query string value: " + ex.Message); sw.Close(); sqlConn.Close(); } return ""; } #endregion
#region QryEmployee public string Query() { String s = ""; String sFilter = "(&(ObjectCategory=person)(objectClass=user)"; s += Query("employeeId", employeeId); if (s.Length > 0) { sFilter += s + ")"; } else { sFilter += ")"; } return sFilter; } #endregion
#region WriteFile public void CreateLogFiles() { try { sLogFormat = DateTime.Now.ToShortDateString().ToString() + "" + DateTime.Now.ToLongTimeString().ToString() + "==> ";
string sYear = DateTime.Now.Year.ToString(); string sMonth = DateTime.Now.Month.ToString(); string sDay = DateTime.Now.Day.ToString(); sErrTime = sYear + sMonth + sDay; } catch (Exception ex) { sw.Write("Error: Writing Log File" + ex.Message); } } public void ErrLog(string sPathName, string sErrMsg) { try { sPathName = "@c:\\adUpdt\\errLog\\errLog.txt"; StreamWriter sw = new StreamWriter(sPathName + sErrTime, true); sw.WriteLine(sLogFormat + sErrMsg); } catch (Exception ex) { sw.Write("Cannot find file." + ex.Message); sw.Flush(); sw.Close(); } } #endregion
#region Values private void Values(DirectoryEntry ent) { try { ent.Properties["TelephoneNumber"].Value = telNum; ent.Properties["IPphone"].Value = ipPhone; ent.Properties["Mobile"].Value = mobile; ent.Properties["pager"].Value = epager; ent.Properties["Department"].Value = dpt; ent.Properties["manager"].Value = manager; } catch (Exception ex) { sw.Write("Error in values: " + ex.Message); sw.Close(); } } #endregion #region Properties private void Properties(DirectoryEntry currEntry) { if (currEntry == null) { return; } employeeId = currEntry.Properties["employeeId"].Value.ToString(); dEntry = currEntry; }
public string EmployeeID { get { return employeeId; } set { employeeId = value; } }
public string FirstName { get { return fName; } set { fName = value; } }
public string LastName { get { return lName; } set { lName = value; } }
public string TelephoneNumber { get { return telNum; } set { telNum = value; } }
public string IPPhone { get { return ipPhone; } set { ipPhone = value; } }
public string Mobile { get { return mobile; } set { mobile = value; } }
public string Pager { get { return epager; } set { epager = value; } }
public string Manager { get { return manager; } set { manager = value; } }
public string Department { get { return dpt; } set { dpt = value; } }
public string Initials { get { return initials; } set { initials = value; } }
public string DisplayName { get { return dispName; } set { dispName = value; } }
public string Email { get { return email; } set { email = value; } }
public string HomePhone { get { return homePhone; } set { homePhone = value; } }
public string Title { get { return title; } set { title = value; } }
public string FilePath { get { return filePath; } set { filePath = value; } } #endregion Properties
#region WebMethods #region GetXCADFinEmps [WebMethod(Description = "Get Employees")] public DataSet GetXEmps() { SqlConnection xConn = new SqlConnection(connString); xConn.Open(); DataSet xDS = new DataSet(); SqlDataAdapter xAdapter = new SqlDataAdapter("Select * From viewjoin", xConn); xAdapter.Fill(xDS, "view_join"); return xDS; } #endregion
#region Employees from Active Directory [WebMethod(Description = "Get Employees from Active Directory")] public DataSet GetADEmps() { SqlConnection aConn = new SqlConnection(connString); DataSet adDS = new DataSet(); SqlDataAdapter adAdapater = new SqlDataAdapter(); adAdapater.SelectCommand = new SqlCommand("Select * From view_ActiveDirectory", aConn); adAdapater.Fill(adDS, "view_ActiveDirectory"); return adDS; } #endregion #endregion WebMethods
private void InitializeComponent() {
} } }
Thanks.
|
|
-
04-28-2008, 9:59 AM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 1,767
-
-
|
Re: AD WebService Help. (Code Included)
One of the big keys here is to understand how your organization stores the employeeID in AD. If you know that, then you can create a query filter to find it.
For example, if your AD stores the employee ID in the attribute employeeID, then you should be good to go with the search. However, if they don't, you need to figure out which attribute they actually do use.
The tool I like to use for discovering this type of thing is ldp.exe. It comes with various versions of the admin pack or support tools for Windows (can't remember which one) and is also distributed with ADAM.
Ldp is a low level graphical tool (although just barely graphical :)) that allows you to execute fairly raw LDAP operations. It is excellent for prototyping queries and modification operations. You can also use it to find a user in your directory and see all of the attribute data that is populated for the user so you can see things like the attribute used to store the employeeID.
I'd suggest starting with that to see if you can figure out what you need.
Please continue to ask questions and we'll try to help you as best we can. We can't guaranteed that we'll be able to be responsive enough to help you hit your deadline, but we'll try. We are all busy people and this support forum is free after all. :)
I am sorry you bought the "other" book which is notoriously poor quality and very outdated by now as well.
|
|
-
04-28-2008, 10:10 AM |
-
lair
-
-
-
Joined on 04-25-2008
-
-
Posts 21
-
-
|
Re: AD WebService Help. (Code Included)
Thanks for responding.
We are using the employeeId. What I am confuse is with the query, I don't know if got the chance to look at my code. Please let me know when you get a chance and let me know if I will get some place with my code, if is is good or not to work.
And yes the book I bought is not good.
Thanks once again.
|
|
-
04-28-2008, 12:29 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 1,767
-
-
|
Re: AD WebService Help. (Code Included)
A query filter like:
(&(objectCategory=person)(employeeID=xxxxx))
should work if executed at the domain root unless you have multiple domains. Is that not working for you? If you have multiple domains, you will need to search them one at a time as employeeID is not in the global catalog by default.
This is why I recommend using ldp.exe to test your queries and make sure they behave as expected. It is similar in a way to Query Analyzer from SQL 2000. :)
Generally speaking, it is much easier for us to follow what you are doing by having you post simple hardcoded examples on the site rather than complete implementation level code as we have dig around in your method calls and try to retrace how it all hooks together.
|
|
-
04-28-2008, 1:05 PM |
-
lair
-
-
-
Joined on 04-25-2008
-
-
Posts 21
-
-
|
Re: AD WebService Help. (Code Included)
I try ldp.exe and did a search base on the employeeId and got this results:
***Searching... ldap_search_s(ld, "CN=Users,DC=domain,DC=org", 2, "(employeeId=105010)", attrList, 0, &msg) Result <0>: (null) Matched DNs: Getting 1 entries: >> Dn: CN=Last\, First G,CN=Users,DC=domain,DC=org 4> objectClass: top; person; organizationalPerson; user; 1> cn: Last, First; 1> description: Development Specialist; 1> distinguishedName: CN=Last\, First G,CN=Users,DC=domain,DC=org; 1> name: Last,First; 1> canonicalName: domain.org/Users/Last, First;
I did get the employee search by his employeeId.
|
|
-
04-28-2008, 2:13 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 1,767
-
-
|
Re: AD WebService Help. (Code Included)
Ok, so that looks promising. Unless you are certain that all of your users will be located in the CN=Users container, you might want to set the search root to the root of the domain instead.
In LDP, if you want it to show you all of the attributes populated for a given object, you can clear the list of attributes in the Search options. This will also give you an idea of how much data is returned in a query with the DirectorySearcher if you leave PropertiesToLoad null.
Is everything working at this point?
|
|
-
05-29-2008, 11:43 AM |
-
lair
-
-
-
Joined on 04-25-2008
-
-
Posts 21
-
-
|
Re: AD WebService Help. (Code Included)
I am having an issue when trying to retreive the users using the code above. When run it only displays 186 records and when filter by the employeeId it comes empty. The employeeId exists in ad and there are more than 186 records. Any idea why is not returning all the records?
public DataSet GetEmp() {
string username = "access"; string pwd = "access"; string _path = "LDAP://ADMIN";
DirectoryEntry entry = new DirectoryEntry(_path, username, pwd); entry.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = "(&(objectCategory=person)(employeeId=108046))"; SortOption option = new SortOption("displayName", SortDirection.Ascending); mySearcher.Sort = option; DataSet ds = new DataSet(); DataTable dtUsers = new DataTable("ActiveDirectoryUsers");
dtUsers.Columns.Add("employeeId"); dtUsers.Columns.Add("displayName"); dtUsers.Columns.Add("name"); dtUsers.Columns.Add("email"); dtUsers.Columns.Add("manager"); dtUsers.Columns.Add("telephoneNumber"); dtUsers.Columns.Add("pager"); dtUsers.Columns.Add("mobile"); dtUsers.Columns.Add("department");
mySearcher.PageSize = 1000; mySearcher.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
foreach (SearchResult resEnt in mySearcher.FindAll()) { DirectoryEntry de = resEnt.GetDirectoryEntry(); DataRow drUser = dtUsers.NewRow();
if (de.Properties["sAMAccountName"].Value != null && de.Properties["Mail"].Value != null && de.Properties["employeeId"].Value != null && de.Properties["manager"].Value != null && de.Properties["telephoneNumber"].Value != null && de.Properties["pager"].Value != null && de.Properties["mobile"].Value != null && de.Properties["department"].Value != null) { drUser["employeeId"] = de.Properties["employeeId"].Value.ToString(); drUser["displayName"] = de.Properties["displayName"].Value.ToString(); drUser["email"] = de.Properties["Mail"].Value.ToString(); drUser["manager"] = de.Properties["manager"].Value.ToString(); drUser["pager"] = de.Properties["pager"].Value.ToString(); drUser["mobile"] = de.Properties["mobile"].Value.ToString(); drUser["department"] = de.Properties["department"].Value.ToString(); dtUsers.Rows.Add(drUser); } } ds.Tables.Add(dtUsers); return ds; }
|
|
-
05-29-2008, 1:41 PM |
-
joe
-
-
-
Joined on 04-05-2006
-
Chicago, IL
-
Posts 1,767
-
-
|
Re: AD WebService Help. (Code Included)
The search base you used in LDP is not the same search base you used in your code. Why is that?
In LDP, I can't see what server you connected to, but the search base was:
CN=Users,DC=domain,DC=org
However, you have no search base specified in your ADSI path in your code, just a server name. The ADSI path syntax is:
<provider>://<server>/<object name>
So, if you want to do an apples to apples comparison, it should be /CN=Users,DC=domain,DC=org">LDAP://<server>/CN=Users,DC=domain,DC=org
Generally speaking, it is better to use the Domain class in S.DS.ActiveDirectory to create a new Domain object based on the name of your domain and then use it to get a DirectoryEntry object which you can then pass directly to the DirectorySearcher. This way, you don't have to hard code these things.
You also want to make sure you are using the same credentials for each query if you want to do an apples to apples comparison.
|
|
|
|