kamagra how much to take

Free SharePoint Redirection WebPart – Programming SharePoint WebParts With LINQ to Active Directory – Part 1

The real power of LINQ lies in the ambiguity to query collections of all Types, as long as they implement the IQueryable interface. Since Active Directory is essentially a collection of users, one should be able to use a LINQ-esque fashion to manipulate objects out of that particular store as well.

This is where LINQ to AD is awesome! It allows a wrapper to exist around System.DirectoryServices to allow more contemporary, succinct language constructs to be used while developing AD DS integrated tooling. Since I do a lot of security software that exploits AD DS, I wanted to give it a shot!

And it’s pretty impressive. As you can see in the code being explained, there are some quirks, but it’s a pretty cool approach that I believe I am going to use more frequently because I enjoy the layer of abstraction and really, really enjoy being able to use the LINQ code approach.

I have to break this up into two posts because it is exhaustively long. The second post has the download link.

So, for a test project let’s go through building a Redirection WebPart that will satisfy a couple requirements:

  1. Get a reference to the current user
  2. Query into AD DS, find that user, and retrieve the department property
  3. Using the department property, query into a pre-existing SPList, match it, and retrieve a corresponding URL
  4. Redirect the current context to that returned URL

First things first, you have to do download the LINQ to Active Directory project.

Firstly, the appropriate references have to be made, notably to the LINQ to Active Directory project as a referenced project or a compiled assembly. As well, the Active DS Type Library must be referenced so that the IADs interface is exposed. You will see why this is important shortly, but needless to say if not referenced you will get a somewhat cryptic error about an “unspecified error” occurring which is a pain in the ass.

This is what my project structure looks like following:

10-27-2009 1-43-04 PM

As you can see, there are two references out of some pretty orthodox ones being made. The Bds.DirectoryServices.Linq project is referenced, along with the ActiveDs assembly like discussed previously.

The WebPart consists of only two classes. The first one, User, is meant to structure a User object with the properties that should be queried during the AD iterations. For my particular requirement I am only interested in getting the account name and the corresponding department entry. The class and property decorations are provided to specify targets,  DirectoryAttribute for example correlates to the underlying LDAP property to query.

  1. [DirectorySchema("user", typeof(IADsUser))]
  2. public class User
  3. {
  4. [DirectoryAttribute("sAMAccountName")]
  5. public string AccountName { get; set; }
  6.  
  7. [DirectoryAttribute("Department", DirectoryAttributeType.ActiveDs)]
  8. public string Department { get; set; }
  9. }

 

I am going to throw on some generic properties now into the WebPart class to keep some of the more mutable values dynamic. Just four of them, one a URL string to hyrdate a SPSite object where the SPList exists, a string to represent which SPList to get, a third string to allow the column name to be specified, and a fourth string for the AD DS domain name.

  1.         [Personalizable, WebBrowsable(true),
  2.          WebDescription("The Url Where The Redirection List Exists"),
  3.          Category("Global Mode Configuration"),
  4.          WebPartStorage(Storage.Shared),
  5.          DefaultValue(""),
  6.          WebDisplayName("URL Of Redirection List Site")]
  7.         public string Url { get; set; }
  8.  
  9.         [Personalizable, WebBrowsable(true),
  10.          WebDescription("Redirection List"),
  11.          Category("Global Mode Configuration"),
  12.          WebPartStorage(Storage.Shared),
  13.          DefaultValue(""),
  14.          WebDisplayName("Redirection List")]
  15.         public string List { get; set; }
  16.  
  17.         [Personalizable, WebBrowsable(true),
  18.          WebDescription("URL List Property"),
  19.          Category("Global Mode Configuration"),
  20.          WebPartStorage(Storage.Shared),
  21.          DefaultValue(""),
  22.          WebDisplayName("Field Name That Contains URL Values")]
  23.         public string UrlProperty { get; set; }
  24.  
  25.         [Personalizable, WebBrowsable(true),
  26.          WebDescription("Active Directory Domain Name To Use"),
  27.          Category("Global Mode Configuration"),
  28.          WebPartStorage(Storage.Shared),
  29.          DefaultValue(""),
  30.          WebDisplayName("AD DS Domain name")]
  31.         public string DomainName { get; set; }

Getting the users department from AD using LINQ to Active Directory is a breeze as illustrated in the GetCurrentUserDepartment method below. The _entry global field is a DirectoryEntry object which is intialized OnLoad to the domain string literal specified as a WebPart property (the DomainName auto-property), using some brief string massaging to make it an agreeable DirectoryEntry constructor parameter format-wise.

  1. protected override void OnLoad(EventArgs e)
  2. {
  3. if (!_error)
  4. {
  5. try
  6. {
  7. base.OnLoad(e);
  8. if (!string.IsNullOrEmpty(DomainName))
  9. {
  10. _entry = new DirectoryEntry(string.Format("LDAP://{0}", DomainName));
  11. }
  12. else
  13. {
  14. HandleException(new Exception("Please Set A Domain Name!"));
  15. }
  16. }
  17. catch (Exception ex)
  18. {
  19. HandleException(ex);
  20. }
  21. }
  22. }

The second SearchScope parameter will specify the tranversal rules for the query, since I want to recur the whole substree I am going to use SearchScope.Subtree.

Following, the current SPContext is going to be used to get a the current SPUser.Login name, which passed into a regular expression to clean it as to match the account name return from Active Directory. An IQueryable<User> collection is built by executing a LINQ Where clause against the previously created DirectorySource object, matching the current SharePoint user to their record in Active Directory. Following, this collection is pushed to a List<User> typed collection using AddRange with the department set off the User.Department property. If no department is returned, it is set to a global string literal that represents a broken (no return) query, used later in conditional statements. Probably should use a String.Compare instead of the equality operator but you get the idea.

  1. private static string GetCurrentUserDepartment()
  2. {
  3. string department = string.Empty;
  4. SPSecurity.RunWithElevatedPrivileges(delegate
  5. {
  6. var usersDs = new DirectorySource<User>(_entry,SearchScope.Subtree);
  7. var cleanUserName = Regex.Replace(SPContext.Current.Web.CurrentUser.LoginName,".*\\\\(.*)", "$1", RegexOptions.None);
  8. IQueryable<User> users = usersDs.Where(usr => usr.AccountName == cleanUserName);
  9. // put in to fix LINQ to AD Bug
  10. var userList = new List<User>();
  11. userList.AddRange(users);
  12. if (userList.Count > 0)
  13. {
  14. User curUser = userList.FirstOrDefault();
  15. department = curUser.Department;
  16. }
  17. else
  18. {
  19. department = _breakStatement;
  20. }
  21. });
  22. return department;
  23. }

Next Section >> Part II – Building The Remainder Of The WebPart Class

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>