InfoPath 2003 SP1 and Active Directory

I figured I'd be the only one in the developer division not blogging about Beta 1!

When I was on the InfoPath team, I wrote a hands on lab (Lab 15)which talked about using managed code with InfoPath. Excercise 3 of the lab talked about using managed code to access information in Active Directory using System.DirectoryServices.

While this seemed like a great idea at the time, I've since realized that there's a better approach to the problem.There's really only one big problem, and that's that System.DirectoryServices requires FullTrust permissions in order to run. Since InfoPath forms by default do not have FullTrust permissions granted, you'll have to jump through all sorts of hoops in order to run the form (that's a blog for another time).

A better approach is to have a machine with a Web Service on it which exposes the information from Active Directory that you need. This way, you don't need to make your form fully trusted, making it easier to deploy. In addition, other forms can hit your webservice, so you can reuse your code. Also, by using a web service, you don't even need InfoPath SP1! You can use data adapters to connect to the web service, and script to populate the fields you want populated.

Here's the code for the web service, which is almost verbatim taken from the lab.

using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Diagnostics;using System.Web;using System.Web.Services;using System.DirectoryServices;

namespace WhoAmI
{
  /// <summary>
/// Summary description for Service1.
/// </summary>
  [WebService(Namespace="<davfries.foobar/whoami/>")]
  public class Service1 : System.Web.Services.WebService
  {
    public Service1()
    {
     //CODEGEN: This call is required by the ASP.NET Web Services Designer
     InitializeComponent();
    }

...

   [WebMethod]
   public string GetName()
   {
      return System.Environment.UserName;
   }
   [WebMethod]
   public string GetDomain()
   {
     return System.Environment.UserDomainName;
   }

   [WebMethod]
   public string GetManager()
   {
     // get current user name
     string strUserName = System.Environment.UserName;
     // search for user whose mailNickname is the logon name

     DirectorySearcher ds = new DirectorySearcher("(mailNickname=" + strUserName + ")");
     SearchResult result = ds.FindOne();
     if(result == null)
     {
       return "Error finding user " + strUserName + " using Active Directory.";
     }
     DirectoryEntry employeeEntry = result.GetDirectoryEntry();
     // find manager's LDAP DN from the DirectoryEntry
     string strManagerDN = employeeEntry.Properties["manager"].Value.ToString();
     // use the DN to create a new DirectoryEntry  
     DirectoryEntry managerEntry = new DirectoryEntry("LDAP://" + strManagerDN);
     // get the alias of the manager
     string strManagerAlias = managerEntry.Properties["mailNickname"].Value.ToString();
     return strManagerAlias;
  }
 }
}

Then, in InfoPath business logic, you would have (something like) the following code:

IXMLDOMNode nodeManager =
thisXDocument.DOM.selectSingleNode("my:SalesReport/my:manager");
nodeManager.text = XDocument.GetDOM("GetManager").selectNodes("/dfs:myFields/dfs:dataFields/d:GetManagerResponse/d:GetManagerResult").text;

I hope this is helpful...