using Microsoft.AspNetCore.Mvc;
using System.DirectoryServices;
using System.Security.Principal;
using Newtonsoft.Json;
namespace SDAdmConsole.Controllers;
[ApiController]
[Route("api/[controller]")]
public class SearchUsrController : Controller
{
public IActionResult Index()
{
// List of Domains to Check users
string[] domains = { "tst-ads-001", "tst-ads-001." };
// Active Directory Properties we need to bring the results for
string[] propertiesToLoad = { "samAccountName", "displayName", "objectSid", "department", "employeeNumber", "manager", "userPrincipalName","badPwdCount", "lockoutTime",
"lastLogon", "lastLogonTimestamp", "pwdLastSet", "homeDirectory", "extensionAttribute1", "distinguishedName", "userWorkstations"
};
// Master Credentials for Active Directory LDAP search
string domainUser = "redacted";
string domainPassword = "redacted";
// Filter used for Active Directory Search
string searchQuery = "(&(objectCategory=user)(objectClass=user)(samAccountName=*steven.test*))";
// New empty Dictionary to put all the results returned into.
List<Dictionary<string, object>> resultList = new List<Dictionary<string, object>>();
// Search each domain in the list of Domains
foreach (string domain in domains)
{
// New Search builder
DirectorySearcher searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domain, domainUser, domainPassword), searchQuery, propertiesToLoad);
// Results returned as a collection
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult result in results)
{
// Create Dictionary to store all the values from each user found
Dictionary<string, object> resultDict = new Dictionary<string, object>();
// Convert raw SID in to a readable value
byte[] sidBytes = (byte[])result.Properties["objectSid"][0];
SecurityIdentifier sid = new SecurityIdentifier(sidBytes, 0);
string sidString = sid.Value;
resultDict.Add("displayName", result.Properties["displayName"][0]);
resultDict.Add("sAMAccountName", result.Properties["sAMAccountName"][0]);
resultDict.Add("department", result.Properties["department"][0]);
resultDict.Add("employeeNumber", result.Properties["employeeNumber"][0]);
resultDict.Add("manager", result.Properties["manager"][0]);
resultDict.Add("userPrincipalName", result.Properties["userPrincipalName"][0]);
resultDict.Add("badPwdCount", result.Properties["badPwdCount"][0]);
resultDict.Add("lockoutTime", result.Properties["lockoutTime"][0]);
resultDict.Add("lastLogon", result.Properties["lastLogon"][0]);
resultDict.Add("lastLogonTimestamp", result.Properties["lastLogonTimestamp"][0]);
resultDict.Add("pwdLastSet", result.Properties["pwdLastSet"][0]);
resultDict.Add("homeDirectory", result.Properties["homeDirectory"][0]);
resultDict.Add("objectSid", sidString);
//resultDict.Add("extensionAttribute1", result.Properties["extensionAttribute1"][0]);
//resultDict.Add("distinguishedName", result.Properties["distinguishedName"][0]);
//resultDict.Add("userWorkstations", result.Properties["userWorkstations"][0]);
//resultDict.Add("extensionAttribute1", result.Properties["extensionAttribute1"][0]);
//resultDict.Add("mail", result.Properties["mail"][0]);
//resultDict.Add("memberof", result.Properties["memberof"][0]); */
resultList.Add(resultDict);
}
}
// Convert Dictionary in to JSON array
string json = JsonConvert.SerializeObject(resultList);
// Return JSON List for the API request
return Ok(json);
}
}
The API works great if all of the properties returned have values in them. If any of them have an empty value, for example no home folder, the API request fails and returns the homepage html instead. There are no errors when compiling so I'm not sure what else to try.
I tried an if and else statement to say if the value is empty or null then put this string in place but still fails.
Any advice would be great thank you
I can assume that the error happens because you are trying to refer to an item in the collection by an index that doesn't exist. This can cause the application to throw an IndexOutOfRangeException
. Or possibly the collection is null
and then a NullReferenceException
will be thrown.
The solution could be to use conditional operators and null-conditional operators:
var resultDict = new Dictionary<string, object>();
resultDict.Add("displayName", result.Properties["displayName"]?.Count > 0 ? result.Properties["displayName"][0] : "");
resultDict.Add("sAMAccountName", result.Properties["sAMAccountName"]?.Count > 0 ? result.Properties["sAMAccountName"][0] : "");
resultDict.Add("department", result.Properties["department"]?.Count > 0 ? result.Properties["department"][0] : "");
resultDict.Add("employeeNumber", result.Properties["employeeNumber"]?.Count > 0 ? result.Properties["employeeNumber"][0] : "");
resultDict.Add("manager", result.Properties["manager"]?.Count > 0 ? result.Properties["manager"][0] : "");
resultDict.Add("userPrincipalName", result.Properties["userPrincipalName"]?.Count > 0 ? result.Properties["userPrincipalName"][0] : "");
resultDict.Add("badPwdCount", result.Properties["badPwdCount"]?.Count > 0 ? result.Properties["badPwdCount"][0] : 0);
resultDict.Add("lockoutTime", result.Properties["lockoutTime"]?.Count > 0 ? result.Properties["lockoutTime"][0] : 0);
resultDict.Add("lastLogon", result.Properties["lastLogon"]?.Count > 0 ? result.Properties["lastLogon"][0] : 0);
resultDict.Add("lastLogonTimestamp", result.Properties["lastLogonTimestamp"]?.Count > 0 ? result.Properties["lastLogonTimestamp"][0] : 0);
resultDict.Add("pwdLastSet", result.Properties["pwdLastSet"]?.Count > 0 ? result.Properties["pwdLastSet"][0] : 0);
resultDict.Add("homeDirectory", result.Properties["homeDirectory"]?.Count > 0 ? result.Properties["homeDirectory"][0] : "");
resultDict.Add("objectSid", sidString);
// other properties if needed
resultList.Add(resultDict);
This code will add empty strings or 0
values for absent properties. You can choose your own "no value" value.
If you want to avoid adding missing values to the dictionary altogether, instead of adding items with empty strings or zeros, you should check the values before each insertion:
if (result.Properties["displayName"]?.Count > 0)
resultDict.Add("displayName", result.Properties["displayName"][0]);
if (result.Properties["sAMAccountName"]?.Count > 0)
resultDict.Add("sAMAccountName", result.Properties["sAMAccountName"][0]);
if (result.Properties["department"]?.Count > 0)
resultDict.Add("department", result.Properties["department"][0]);
if (result.Properties["employeeNumber"]?.Count > 0)
resultDict.Add("employeeNumber", result.Properties["employeeNumber"][0]);
if (result.Properties["manager"]?.Count > 0)
resultDict.Add("manager", result.Properties["manager"][0]);
if (result.Properties["userPrincipalName"]?.Count > 0)
resultDict.Add("userPrincipalName", result.Properties["userPrincipalName"][0]);
if (result.Properties["badPwdCount"]?.Count > 0)
resultDict.Add("badPwdCount", result.Properties["badPwdCount"][0]);
if (result.Properties["lockoutTime"]?.Count > 0)
resultDict.Add("lockoutTime", result.Properties["lockoutTime"][0]);
if (result.Properties["lastLogon"]?.Count > 0)
resultDict.Add("lastLogon", result.Properties["lastLogon"][0]);
if (result.Properties["lastLogonTimestamp"]?.Count > 0)
resultDict.Add("lastLogonTimestamp", result.Properties["lastLogonTimestamp"][0]);
if (result.Properties["pwdLastSet"]?.Count > 0)
resultDict.Add("pwdLastSet", result.Properties["pwdLastSet"][0]);
if (result.Properties["homeDirectory"]?.Count > 0)
resultDict.Add("homeDirectory", result.Properties["homeDirectory"][0]);
resultDict.Add("objectSid", sidString);