I have a problem saving users, from a csv file, in active directory, using an ASP.Net MVC 4 application (framework 4.5). The problem is that the first user is saved correctly, but the second returns me this error:
Server Error in '/ADManagementStudio' Application.
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
ASP.NET is not authorized to access the requested resource. [...]
[...]
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))]
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args) +630438
ADManagementStudio.Web.Controllers.UsersController.AddUsers(HttpPostedFileBase file) +1437
ADManagementStudio.Web.Controllers.UsersController.CSV(HttpPostedFileBase file) +23 lambda_method(Closure , ControllerBase , Object[] ) +127 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +248
2 parameters) +39
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
System.Web.Mvc.Async.<>c_DisplayClass39.b_33() +120 System.Web.Mvc.Async.<>c_DisplayClass4f.b_49() +452 System.Web.Mvc.Async.<>c_DisplayClass37.b_36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.<>c_DisplayClass2a.b_20() +31 System.Web.Mvc.Async.<>c_DisplayClass25.b_22(IAsyncResult asyncResult) +230
System.Web.Mvc.<>c_DisplayClass1d.b_18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.<>c_DisplayClass4.b_3(IAsyncResult ar) +15 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.<>c_DisplayClass4.b_3(IAsyncResult ar) +15
System.Web.Mvc.<>c_DisplayClass8.b_3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c_DisplayClass4.b_3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
I'm using impersonation in web.config, but I think it's funny that only the first user is saved and the others not, what's so different than the others? (or maybe I just ignore it because of my poor experience)
Here the code of the function:
private string AddUsers(HttpPostedFileBase file)
{
string tempFileName = string.Format("{0}_{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
string filePath = Path.Combine(Server.MapPath("~/AD_App_Data/temp"), tempFileName);
file.SaveAs(filePath);
FileInfo tempFileInfo = new FileInfo(filePath);
List<string[]> tempFileData = new List<string[]>();
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader(tempFileInfo.FullName, true))
{
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
string[] splitter = line.Split(';');
lines.Add(line);
tempFileData.Add(splitter);
}
}
tempFileInfo.Delete();
if ((tempFileData[0][0].ToLower() != "samaccountname") ||
(tempFileData[0][1].ToLower() != "displayname"))
{
return "Error! sAMAccountName or displayName fields not found!";
}
try
{
string LDAPContextPath = string.Format(
"LDAP://{0}/{1}",
ActiveDirectoryManage.GetServerName(),
ActiveDirectoryManage.GetLDAPUserPath());
List<string> newUsersPassword = new List<string>();
using (DirectoryEntry context = new DirectoryEntry(LDAPContextPath, "Administrator", "abcd,1234"))
{
foreach (string[] data in tempFileData.Skip(1))
{
using (DirectoryEntry userEntry = context.Children.Add(string.Format("CN={0}", data[1]), "user"))
{
userEntry.Properties["sAMAccountName"].Value = data[0];
userEntry.CommitChanges();
for (int i = 1; i < data.Length; i++)
{
int number;
if (int.TryParse(data[i], out number))
{
userEntry.Properties[tempFileData[0][i]].Value = number;
}
else
{
userEntry.Properties[tempFileData[0][i]].Value = data[i];
}
userEntry.CommitChanges();
}
string newPassword = Membership.GeneratePassword(12, 0);
userEntry.Invoke("SetPassword", newPassword);
userEntry.CommitChanges();
newUsersPassword.Add(newPassword);
userEntry.Properties["userAccountControl"].Value = 512;
userEntry.CommitChanges();
}
}
Thread.Sleep(1000);
}
string timestamp = string.Format(
"{0}{1}{2}-{3}{4}{5}",
DateTime.Today.Hour, DateTime.Today.Minute, DateTime.Today.Second,
DateTime.Today.Day, DateTime.Today.Month, DateTime.Today.Year);
string doneFileName = string.Format("{0}_{1}.csv", file.FileName, timestamp);
string donePath = Path.Combine(Server.MapPath("~/AD_App_Data/done"), doneFileName);
using (StreamWriter writer = new StreamWriter(donePath))
{
writer.WriteLine(AppendPassword(lines[0], "password"));
for (int i = 1; i < lines.Count; i++)
{
writer.WriteLine(AppendPassword(lines[i], newUsersPassword[i - 1]));
}
}
return doneFileName;
}
catch (DirectoryServicesCOMException ex)
{
return "Error! Exception! " + ex.Message;
}
}
Thank you in advice