Linq to ad, disconnectedcontext exception fired - c#

I have an exception which is fired when I test some code of mine using the library Linq to AD.
I am using a repository with this function :
public UserAD GetUser(string username)
{
UserAD user = null;
using (Root = CreateDirectoryEntry())
{
var users = new DirectorySource<UserAD>(Root, SearchScope.Subtree);
user = users.Where(x => x.AccountName == username)
.AsEnumerable()
.SingleOrDefault(); //not supported in LDAP; alternative in-memory SingleOrDefault
}
return user;
}
This works fine when I call it directly:
[TestMethod]
public void RepositoryUtenteAD_GetUser()
{
UserAD user = repositoryAD.GetUser("TestAD_OK");
Assert.AreEqual("blablabla", user.DistinguishedName);
Assert.IsFalse(user.AccountDisabled);
}
But I may use another method which will call GetUser:
[TestMethod]
public void RepositoryUtenteAD_AutenticazioneUtente_Authentication()
{
IAutenticazione auth = repositoryAD.AutenticazioneUtente("TestAD_OK", "TestAD_OK");
Assert.IsTrue(auth.IsAuthenticated);
}
and the Authentication method is as follows (cleared of meaning and details, the error remaining there) :
public IAutenticazione AutenticazioneUtente(string username, string password)
{
bool IsWhyNotAuthentifiedFound = false;
IAutenticazione authenticazione = new Autenticazione();
UserAD user = GetUser(username);
return authenticazione;
}
The test is running fine, the assert is giving me the good value, but after the Cleanup of my test I have a disconnectedcontext exception fired. I assume it comes from the Interop.Adsi dll I use.
In GetUser(username) Should I copy everything I have in my UserAD to make a clone and so be clear off context...? Or is there a more clever way to approach?
Thanks for your reading!

Found the solution even if it is a strange one. The bug only happens when running the test in debug mode, if i choose run instead of debug, everything is fine.
That close the chapter. Thanks for your reading.

Related

Unable to remove a user from an azure group using Active Directory Client Remove method

I was having a code which was running perfectly to remove a user from an azure group but suddenly It stops working..when I debug the code Remove() method is returning false as a boolean.
Below is the code which is not working.Can anyone please suggest me a quick fix.
public static async Task RemoveUserFromGroup(IGroup group, IUser user)
{
RemoveFromGroupResult result = new RemoveFromGroupResult();
try
{
((Group)group).Members.Remove(user as DirectoryObject);
await group.UpdateAsync();
result.ErrorMsg = string.Empty;
}
catch (Exception e)
{
result.IsAdded = false;
result.ErrorMsg = e.Message;
}
return result;
According to my test, the code((Group)group).Member always returns null List. So we cannot use the code ((Group)group).Members.Remove(user as DirectoryObject); await group.UpdateAsync(); to remove group member.
According to the situation, I suggest you use the Rest API to remove group member
DELETE https://graph.windows.net/myorganization/groups/{object_id}/$links/members/{member_id}?api-version=1.6

Seeding initial user on Identity module without double-seeding

I'm trying to use the ABP's identity module and have a seed for my first (admin) user.
In the identity module seed contributor's source code I see this:
public Task SeedAsync(DataSeedContext context)
{
return _identityDataSeeder.SeedAsync(
context["AdminEmail"] as string ?? "admin#abp.io",
context["AdminPassword"] as string ?? "1q2w3E*",
context.TenantId
);
}
So in my migrator module I added this:
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{
var dataSeeder = scope.ServiceProvider.GetRequiredService<IDataSeeder>();
var dsCtx = new DataSeedContext
{
["AdminEmail"] = "my#admin-email",
["AdminPassword"] = "my-admin-password"
};
AsyncHelper.RunSync(() => dataSeeder.SeedAsync(dsCtx));
}
base.OnApplicationInitialization(context);
}
This works... however there's probably another module creating a data seeder (more likely the one that actually gets executed on the migrator, but I can't really find it), so all my contributors (and probably the module contributors) get executed twice (that's to be expected, I guess).
Is there any way I can change the seeding context without actually running an IDataSeeder? and if this can't be done... is there a way I can "unregister" all IDataSeeders previous to mine so only mine gets executed?
The solution to this specific question (although I was hoping to find a more "general" solution), was to change the actual contributor. On your domain module (or wherever you see fit: your migrator or whatever), just do:
// Remove the contributor for the module
context.Services.RemoveAll(t => t.ImplementationType == typeof(IdentityDataSeedContributor));
// Add my custom constributor
context.Services.AddTransient<IDataSeedContributor, MyCustomConstributor>();
Where the implementation of the contributor is simply a copy of the default:
public class MyCustomConstributor : IDataSeedContributor
{
private readonly IIdentityDataSeeder _identityDataSeeder;
public IdentityDataSeedContributor(IIdentityDataSeeder identityDataSeeder)
{
_identityDataSeeder = identityDataSeeder;
}
public Task SeedAsync(DataSeedContext context)
{
return _identityDataSeeder.SeedAsync(
context["AdminEmail"] as string ?? "my#admin-email",
context["AdminPassword"] as string ?? "my-admin-password",
context.TenantId
);
}
}
Notice that you still get the username admin here... if you want to change it, you can just replace also the IIdentityDataSeeder implementation (using the same method, or the easier Services.Replace, which you can use since there should only be one implementation of IIdentityDataSeeder) and copy your own from the default one, changing the searched username.
For now, replacing the services on your module seems the way to go. Maybe the possibility to directly intercept the initialization stages of other modules might be there on future versions, but I haven't seen how for now.

Getting 404 Not Found only when re-creating database in tests for 2nd API call

I'm trying to create API integration tests for legacy code I've inherited.
Currently I have a piece of testing code that:
recreate database (using Fluent Migrations)
starts a web app (Owin.Hosting)
makes api call to get auth token
makes api call to authorized endpoint
It works perfectly if I skip first step and do only 2) 3) 4).
It's a bit weird that I'm also able to do steps 1) 2) 3) (so the auth API call works with database recreation included).
I thought my web api isn't working properly, but I'm able to do basic path when I don't recreate database. Then I thought maybe it's not working at all when I recreate database, but I'm able to authorize an user. I have no clues what could I try now.
[Collection("Database Create collection")]
public class RoleControllerTests : IDisposable
{
private readonly IDisposable _server;
private readonly string _url = new Configuration().ServerUrl;
public RoleControllerTests()
{
_server = WebApp.Start<Startup>(_url);
}
public void Dispose()
{
_server.Dispose();
}
[Fact]
public async Task basic_roles_should_exist_in_the_database()
{
// Arrange
var roleApi = RestClient.For<IRoleController>(_url);
IAuthorize auth = new Authorize();
roleApi.AuthenticationHeader = await auth.GetAuthenticationHeaderAsync();
// Act
var rolesData = await roleApi.List();
// Assert
rolesData.ShouldContain(x => x.Name == "User");
rolesData.ShouldContain(x => x.Name == "Displayer");
}
}
So I've changed testing framework to NUnit and it's working.
I have no idea why, does XUnit have some issues with changing things in runtime?

error occurred when requesting data via Entity Framework

I'm building an N-tier application which has to send JSON data, which is read from SQL Server 2012 through Enity Framework.
When I try to request a collection of users I get an "An error has occurred" page. It works with hardcoded data.
This is my code:
public IEnumerable<User> Get()
{
IUserManager userManager = new UserManager();
return userManager.GetUsers();
}
public IEnumerable<User> GetUsers()
{
return repo.ReadUsers();
}
public IEnumerable<User> ReadUsers()
{
IEnumerable<User> users = ctx.Users.ToList();
return users;
}
"ctx" is a reference to a DbContext-object.
EDIT: This works:
public IEnumerable<User> Get()
{
IList<User> users = new List<User>();
users.Add(new User() { FirstName = "TestPerson1" });
users.Add(new User() { FirstName = "TestPerson2" });
return users;
}
Browser screenshot: http://i.imgur.com/zqG0qe0.png
EDIT: Full error (screenshot): http://i.imgur.com/dt48tRG.png
Thanks in advance.
If your website returns internal error and no call stack you are not seeing the full exception(which makes it kind of hard to exactly point out your problem).
So first of all to get to the actual exception with call stack you have 2 methods.
Debug the website : start the website locally or attach your debugger to a locally running website. While stepping through the code the debugger will stop when it hits an exception and you'll see the exception details then.
Disable custom errors : IIS wants to protect your internal workings so standard behavior is not to show full exceptions. To disable this behavior edit your web.config and add the xml node under
After you get the actual exception please update your question with call stack & the real internal server error. My guess is that you have a serialization issue, maybe a circular reference of some sort. You're fix would be to either make a simpel viewModel(and not return the entity directly) or add serialization settings(json.net support circular references for example).
Edit
As suspected the serialization is giving you a hard time. The cause is the proxy creation used by the lazy loading.
You can disable the proxy creation with the following code(make note that this also disables lazy loading).
public IEnumerable<User> ReadUsers()
{
ctx.Configuration.ProxyCreationEnabled = false;
IEnumerable<User> users = ctx.Users.ToList();
return users;
}
if this works you might consider disabling proxy creation during the context initialization.
Try to return plain model, smth like
var logins = ctx.Users.Select(user => new FlatUserModel
{
Id = user.Id,
Name = user.UserName,
Email = user.Email
})
.ToArray();
return logins;
Also look in browser what do you get in response.
As it works with hard coded data there is possibility of lazyloading enabled on context.
If so disable lazy loading in the context or like this so that serialization to JSON does not load the entities from database.
public IEnumerable<User> ReadUsers()
{
ctx.Configuration.LazyLoadingEnabled = false;
IEnumerable<User> users = ctx.Users.ToList();
return users;
}

Unit testing methods with void type

I've got some code as shown below with multiple methods which call a web service to get some data from a database. This will produce a set of fields which are then added to another database from the web app. This all works great but I have no idea how to unit test any of it due to it mostly outputting voids, and the data coming from a database which changes every time the button is clicked. Is there a way to unit test to just if the methods work or not? Sorry I am very new to unit testing but I know how important it is so any help would be appreciated.
//Get webservice service
private Service1 GetService()
{
return new TestProjectService.Service1();
}
//Choose which webservice we want to use based on radio button selection
private TestProjectService.CommandMessages GetCommand(Service1 service)
{
var command = new TestProjectService.CommandMessages();
switch (WebServiceRadio.SelectedIndex)
{
case 0:
command = service.GetData();
break;
case 1:
command = service.GetDataLINQ();
break;
}
return command;
}
//Display the results in a label on screen
private void DisplayResult(string text)
{
LatestCommandLabel.Text = text;
}
//Get the current username of the user logged in
public string GetUsername()
{
return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
//Submit the data to the database using Linq
private void SubmitData(string username, TestProjectService.CommandMessages command)
{
var dc = new TestProjectLinqSQLDataContext();
var msg = new TestProjectCommandMessage
{
Command_Type = command.CommandType,
Command = command.Command,
DateTimeSent = command.DateTimeSent,
DateTimeCreated = command.DateTimeCreated,
Created_User = username,
Created_Dttm = DateTime.Now
};
dc.TestProjectCommandMessages.InsertOnSubmit(msg);
dc.SubmitChanges();
}
//Return the value and submit data to database
private void ReturnValue()
{
var service = GetService();
var command = GetCommand(service);
var username = GetUsername();
if (command != null)
{
DisplayResult(String.Format("Last Command Called (Using {0}) : {1}", WebServiceRadio.SelectedItem.ToString(), command.Command));
string userName = GetUsername();
SubmitData(username, command);
}
else
{
DisplayResult("No Commands Available");
}
}
//Onlick return value
protected void GetCommandButton_Click(object sender, EventArgs e)
{
ReturnValue();
}
Behavior verification is the approach used to test methods that don't return any values.
In a nutshell, since the method doesn't return any results, the only thing a test can do is make sure the method causes the appropriate actions to take place. This is typically accomplished by using a mock object, which keeps track of whether or not its methods have been called.
In order for your tests to use test doubles, you need to include seams in the design of your system.
I strongly recommend reading Dependency Injection in .Net, by Mark Seeman. Since you're new to unit testing, you undoubtedly have many questions on the mechanics involved in unit testing (and this answer probably sparked even more questions) - this book goes into great detail answering those questions.

Categories