I am kind of scratching my head to resolve this issue where I have to remove all the Claims in one go. When I use the below code, I get this error Collection was modified; enumeration operation may not execute
Since, I am changing/modifying the value from the enumerator that I am currently looping through, therefore, I am getting this error. Any idea how can I resolve this issue. I have used the below code:
private static readonly string[] claimTypes=
{
ClaimTypes.Role,
ClaimTypes.UserSpecific.IdleSessionTimeout,
ClaimTypes.CustomerSpecific.ApplicationId,
ClaimTypes.CustomerSpecific.CustomerId,
ClaimTypes.CustomerSpecific.CustomerName,
ClaimTypes.CustomerSpecific.CurrencyCode,
ClaimTypes.CustomerSpecific.Locale,
ClaimTypes.CustomerSpecific.TimeZone,
ClaimTypes.CustomerSpecific.ReportingUnitId
};
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
foreach (var identity in principal.Identities)
{
foreach (var claim in identity.FindAll(claim => claimTypes.Any(type => type == claim.Type)))
{
identity.TryRemoveClaim(claim);
}
}
}
Since this was giving error so I thought of using the below code. but this also does not work.
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
var claimNamedList = principal.Identities.Select(x=>x.Claims.Select(y=>y.Type).ToList());
foreach (var identity in principal.Identities)
{
var claimNameList = identity.FindAll(claim => claimTypes.Any(type => type == claim.Type));
foreach (var name in claimNameList)
{
var aa = principal.Identities.Select(x => x.Claims.Where(b => b.Type == name.Type));
identity.TryRemoveClaim(name);
}
}
}
In order to solve this, you need to create a new collection that you enumerate:
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
foreach (var identity in principal.Identities)
{
var claimsToRemove = identity
.FindAll(claim => claimTypes.Any(type => type == claim.Type))
.ToArray();
foreach (var claim in claimsToRemove)
{
identity.TryRemoveClaim(claim);
}
}
}
By using ToArray (or ToListor another To* method), the results of the enumeration are stored in a new collection that you can enumerate over. When removing items, this does not affect the newly created collection so the error will be gone.
Related
Hello I have this project on Entity Framework for an exam, I have 157 test to pass and I pass 155, the last 2 are very similar to others but I dont understand why fails, I put some code so I can explain better:
public void GetUsers_OnDeletedObject_Throws() {
Site.Delete();
Assert.That(() => Site.GetUsers(), Throws.TypeOf<InvalidOperationException>()); }
I defined the Delete() method to recorsively call Delete to resources in the site(like users), then remove the site from the context.
From now on any method in the site must throw InvalidOperationException because the site doesn't exist anymore, but in some way Site.GetUsers() find a site and dont throw.
The real mistery is if I try to insert other methods (written in same way) between the delete and the assert the extra method throw InvalidOperationException!
Site.Delete() code:
using (var ctx = new SiteContext(connectionString))
{
var site = ctx.Sites.Find(Name);
foreach (var a in GetAuctions()) ctx.Auctions.Remove(a);
foreach (var s in GetSessions()) ctx.Sessions.Remove(s);
foreach (var u in GetUsers()) ctx.Users.Remove(u);
ctx.Sites.Remove(site);
ctx.SaveChanges();
}
Part of GetUsers where should throw
public IEnumerable<IUser>GetUsers()
{
using (var ctx = new SiteContext(connectionString))
{
var site = ctx.Sites.SingleOrDefault(s => s.Name == Name);
AlreadyDeleted(site);
AlreadyDeleted() code:
public static void AlreadyDeleted(object o)
{
if (null == o) throw new InvalidOperationException();
}
I am making an ASP.NET intranet website that uses Active Directory and I am trying to get all the groups a user belongs to, even sub groups etc ... So that means I had to make a recursive method to load all the groups in an ArrayList following the example given here : https://www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C
Hence I have a method to recursively fill an ArrayList based on group membership:
public ArrayList AttributeValuesMultiString(string attributeName, string objectDn,
ArrayList valuesCollection, bool recursive)
{
DirectoryEntry ldapConnection = new DirectoryEntry(objectDn);
PropertyValueCollection valueCollection = ldapConnection.Properties[attributeName];
IEnumerator en = valueCollection.GetEnumerator();
while (en.MoveNext())
{
if (en.Current != null)
{
if (!valuesCollection.Contains(en.Current.ToString()))
{
valuesCollection.Add(en.Current.ToString());
if (recursive)
{
AttributeValuesMultiString(attributeName, "LDAP://" +
en.Current.ToString(), valuesCollection, true);
}
}
}
}
ldapConnection.Close();
ldapConnection.Dispose();
return valuesCollection;
}
That I call from this other method:
public ArrayList Groups(string userDn, bool recursive)
{
ArrayList groupMemberships = new ArrayList();
return AttributeValuesMultiString("memberOf", userDn, groupMemberships, recursive);
}
Using the recursive boolean I can build my group's arraylist, but the first method can be used for other multistring object loading. Now when I test this just by a simple call to the method
//adManager is an instance of the class containing the methods above
//groups is an ArrayList
//testChain is my distinguishedName
groups = adManager.Groups(testChain, true);
foreach (var g in groups)
Console.WriteLine(g.ToString());
I have the following exception:
System.Runtime.InteropServices.COMException : Unspecified error
And the point at which I have the exception is at the assignment:
PropertyValueCollection valueCollection = ldapConnection.Properties[attributeName];
I really don't see the problem, especially that this method was recommended on another SO thread, so I'm guessing it's functional
EDIT Seems that my problem comes from an authentication issue. I added impersonation in my test code but I still get an exception :
using (HostingEnvironment.Impersonate())
{
var domainContext = new PrincipalContext(ContextType.Domain, "radiofrance.rootad.inetrf");
var groupPrincipal = GroupPrincipal.FindByIdentity(domainContext, IdentityType.Name, "Users");
if (groupPrincipal != null)
{
groups = adManager.Groups(testChain, true);
foreach (var g in groups)
Console.WriteLine(g.ToString());
}
else
Console.WriteLine("Fail");
}
I'm trying write an analyzer, I need to find all assignments made to a field using Roslyn.
private async static Task<bool> VariableDoesNotMutate(SyntaxNodeAnalysisContext context, VariableDeclaratorSyntax firstVariable)
{
var variableSymbol = context.SemanticModel.GetDeclaredSymbol(firstVariable);
var references = await SymbolFinder.FindReferencesAsync(variableSymbol, context.GetSolution());
foreach (var reference in references)
{
//How do I check for assignment?
}
//need to filter by assignments
return references.Count() > 1;
}
I heard using the symbolFinder was correct, but I'm not sure how to do this.
The symbol finder requires a solution, which I only have access to through a hack, so I'm assuming there is another way to do this.
Issues:
When I try to Find all references to a variable only the Declaration is returned an I do not find any other references how can I fix this?
Once I have a reference How can I determine if it's an assignment?
I Couldn't find any references originally because my document was not in the correct solution. Analyzer's don't provide you a way to get to the Solution and as #SLaks say's for preformance reasons you should not do this:
To Get the Solution You need to reflect into the AnalyzerOptions I've written an answer how to do so here
However, If you need to you can do this Get The Equivalent Symbol in the Solution and work off of that. This is potentially dangerous
static async Task<ISymbol> GetEquivalentSymbol(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax field, CancellationToken cancellationToken)
{
var solution = context.GetSolution();
var classDeclaration = field.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault();
var namespaceDeclaration = field.Ancestors().OfType<NamespaceDeclarationSyntax>().FirstOrDefault();
var className = classDeclaration?.Identifier.ValueText;
var initialVariable = field.Declaration.Variables.FirstOrDefault();
foreach (var project in solution.Projects)
{
foreach (var document in project.Documents)
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
var root = await document.GetSyntaxRootAsync(cancellationToken);
if (null != namespaceDeclaration)
{
var namespaceNode = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>()
.FirstOrDefault(node => node.Name.ToString() == namespaceDeclaration.Name.ToString());
if (null == namespaceNode)
{
continue;
}
}
var classNode = root.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault(node => node.Identifier.ValueText == className);
var desiredField = classNode?.DescendantNodes().OfType<FieldDeclarationSyntax>()
.FirstOrDefault(x => x.Declaration.Variables.First().Identifier.ValueText == initialVariable.Identifier.ValueText);
if (desiredField == null)
{
continue;
}
var symbol = semanticModel.GetDeclaredSymbol(desiredField.Declaration.Variables.FirstOrDefault());
return symbol;
}
}
return null;
}
Then you can get the references like so:
var equivalentSymbol = await GetEquivalentSymbol(context, field, cancellationToken);
var references = await SymbolFinder.FindReferencesAsync(equivalentSymbol, context.GetSolution(), cancellationToken);
i tried this method that I created but it prompts me an error:
Realms.RealmInvalidObjectException:This object is detached. Was it deleted from the realm?'
public void deleteFromDatabase(List<CashDenomination> denom_list)
{
using (var transaction = Realm.GetInstance(config).BeginWrite())
{
Realm.GetInstance(config).Remove(denom_list[0]);
transaction.Commit();
}
}
what is the proper coding for deleting records from database in realm in C# type of coding?
You are doing it the right way. The error message you are getting indicates that the object was removed already. Are you sure it still exists in the realm?
UPDATE:
I decided to update this answer because my comment on the other answer was a bit hard to read.
Your original code should work fine. However, if you want deleteFromDatabase to accept lists with CashDenomination instances that either have been removed already or perhaps were never added to the realm, you would need to add a check. Furthermore, note that you should hold on to your Realm instance and use it in the transaction you created. In most cases, you want to keep it around even longer, though there is little overhead to obtaining it via GetInstance.
public void deleteFromDatabase(List<CashDenomination> denom_list)
{
if (!denom_list[0].IsValid) // If this object is not in the realm, do nothing.
return;
var realm = Realm.GetInstance(config);
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom_list[0]);
transaction.Commit();
}
}
Now, if you want to use identifiers, you could look it up like you do, but still just use Remove:
public void deleteFromDatabase(int denom_id)
{
var realm = Realm.GetInstance(config);
var denom = realm.All<CashDenomination>().FirstOrDefault(c => c.denom_id == denom_id);
if (denom == null) // If no entry with this id exists, do nothing.
return;
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom);
transaction.Commit();
}
}
Finally, if your CashDenomination has denom_id marked as PrimaryKey, you could look it up like this:
public void deleteFromDatabase(int denom_id)
{
var realm = Realm.GetInstance(config);
var denom = realm.ObjectForPrimaryKey<CashDenomination>(denom_id);
if (denom == null) // If no entry with this id exists, do nothing.
return;
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom);
transaction.Commit();
}
}
public void deleteFromDatabase(Realm realm, long cashDenominatorId)
{
realm.Write(() =>
{
var cashDenominator = realm.All<Person>().Where(c => c.Id == cashDenominatorId);
Realm.RemoveRange<CashDenomination>(((RealmResults<CashDenomination>)cashDenominator));
});
}
Which you would call as
Realm realm = Realm.GetInstance(config);
var denom_list = ...
// ...
deleteFromDatabase(realm, denom_list[0].id);
I already made it having this code :) thanks to #EpicPandaForce 's answer.
public void deleteFromDatabase(int denom_ID, int form_ID)
{
//Realm realm;
//and
//RealmConfiguration config = new RealmConfiguration(dbPath, true);
//was initialized at the top of my class
realm = Realm.GetInstance(config);
realm.Write(() =>
{
var cashflow_denom = realm.All<CashDenomination>().Where(c => c.denom_id == denom_ID);
var cashflow_form = realm.All<CashForm>().Where(c => c.form_id == form_ID);
realm.RemoveRange(((RealmResults<CashDenomination>)cashflow_denom));
realm.RemoveRange(((RealmResults<CashForm>)cashflow_form));
});
}
it is now deleting my data without exception :)
I have the following action method:-
try
{
repository.DeleteServer(id, ADusername);
repository.Save();
return Json(new { IsSuccess = "True", id = id, description = tag }, JsonRequestBehavior.AllowGet);
}
which will call the following repository method to delete an object:-
public void DeleteServer(int id,string username)
{
var server = tms.TMSServers.SingleOrDefault(a=>a.TMSServerID == id);
var auditinfo = IntiateTechnologyAudit(tms.AuditActions.SingleOrDefault(a => a.Name.ToUpper() == "DELETE").ID,
server.Technology.TechnologyType.AssetTypeID,
username, server.TMSServerID);
var technology = tms.Technologies.Include(a=>a.TMSSwitchPorts).SingleOrDefault(a => a.TechnologyID == id);
technology.IsDeleted = true;
tms.Entry(technology).State = EntityState.Modified;
tms.TMSServers.Remove(server);
foreach (var switchport in technology.TMSSwitchPorts)
{
tms.TMSSwitchPorts.Remove(switchport);
}
InsertOrUpdateTechnologyAudit(auditinfo);
}
the problem i am facing is insdie the foreach where the deletion will not be performed and no exception will be raised. when i debug my code the action method will call the deleteserver methods, then when the code reach the foreach it will not iterate over the technology.TMSSwtichPort instead the code will break without errors and the .save inside my action method will not be reached ?can any one advice what might be the problem ?
Thanks
I would imagine it's because you are using a foreach over a collection that you are indirectly modifying by deleting members.
Running your foreach over a separate collection might help, because then your enumeration isn't invalidated by the delete:
var toDelete = technology.TMSSwitchPorts.ToList();
foreach (var switchport in toDelete)
{
tms.TMSSwitchPorts.Remove(switchport);
}