Exception when attempting to link an object to the currently authenticated user - c#

I currently have an ASP.NET Web Api 2 application which, for the purposes of this question, manages 'Items'. ASP.NET Identity 2 is used to provide authentication for requests, and the data is handed by Entity Framework 6.
My aim is for the item's Owner property to be set automatically to the user who authenticated the POST request. Below is the code so far:
public async Task<IHttpActionResult> PostItem(Item item)
{
var userId = User.Identity.GetUserId();
var user = await UserManager.FindByIdAsync(userId);
// Set the Owner to the currently authenticated user
item.Owner = user;
db.Items.Add(item); // Exception Thrown Here
await db.SaveChangesAsync();
...
}
However, when the method is called, the following exception occurs. The current userId and user are being found correctly, yet there is still an issue adding the Item once its Owner property has been set.
A first chance exception of type 'System.InvalidOperationException'
occurred in EntityFramework.dll
Additional information: An entity object cannot be referenced by
multiple instances of IEntityChangeTracker.

The problem is that you're trying to track the same entity using two different contexts and that doesn't work. maybe you should look in your code and see which of your entities is being tracked by two context, It is possible since you are using a global variable (db) as a reference to your context.

Related

Abp Tenant creation not working. AbpAuthorizationException at CreateStaticRoles

After update to Abp 2.3 my tenant creation is not working anymore.
The exception is been throwing when the roles are created:
//TenantAppService.cs
//We are working entities of new tenant, so changing tenant filter
using (CurrentUnitOfWork.SetTenantId(tenant.Id))
{
//Create static roles for new tenant
CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id)); <-- Here
The exception:
Exception thrown: 'Abp.Authorization.AbpAuthorizationException' in
mscorlib.dll
Additional information: [At least one of these permissions must be granted]
I didn't change the TenantAppService that came from Module Zero, but if I remove the AbpAuthorize from class it works.
[AbpAuthorize(PermissionNames.Pages_Tenants)] //If removed works
public class TenantAppService : SeducaAppServiceBase, ITenantAppService
{
...
Tks.
The problem was AbpCache.
What I need to do is restart the app (cleaning everything) or call the api method (api/AbpCache/ClearAll)
reference: https://github.com/aspnetboilerplate/aspnetboilerplate/issues/573
It's solves all my problems with permissions
The user who is calling this method has to be granted permission with PermissionNames.Pages_Tenants.

BotFramework: How to handle multiple entities for a single Intent?

In LUIS I have created some utterances for which Intent is detected and I have set 3 different Entities for it i.e For Example I am trying to build a bot to detect user's issue related to an application. So when User enters Unable to Open Android I have set intent as Find_Issue and Entities as 1.Product 2.Issue 3.Error. But since Unable to Open Android doesn't contain any error code. I am getting only 2 entities Product & Issue. Now I want to get the value for Error if no error it would be stored as none.
Here is the Task Code so far
[LuisIntent("Find_Issue")]
public async Task getIssue(IDialogContext context, LuisResult result)
{
EntityRecommendation getProduct;
EntityRecommendation getIssue;
EntityRecommendation getError;
if(result.TryFindEntity("Product",out getProduct))
{
chatdetails.issuedetails.product = getProduct.Entity;
}
if (result.TryFindEntity("Issue", out getIssue))
{
chatdetails.issuedetails.issue = getIssue.Entity;
}
if (result.TryFindEntity("Error", out getError))
{
chatdetails.issuedetails.error = getError.Entity;
}
}
chatdetails.issuedetails is the class created to store the values of Product,Issue,Error
I am not getting how to proceed further.
When defining an intent in LUIS you can also define it's Action Parameters. Action Parameters consists of a parameter name, an entity type, a prompt and if it's required or not.
Then, when using the latest version of the BotFramework Nuget package, your LuisDialog will automatically detect that a required parameter (as in your scenario with the Error entity) is missing and will automatically fire a prompt for the parameter, using the message defined in the Action Parameter.
For technical details about how this thing around the action parameters works, please check this thread.

load child objects in EF5

I have a method in my generic repository:
public IQueryable<T> Query<T>() where T : class, IEntity
{
return _context.Set<T>();
}
This is method for getting user:
public User GetUser(string email)
{
return _repository.Query<User>().FirstOrDefault(u => u.Email == email);
}
Finally, I put the user to session:
AppSession.CurrentUser = UserService.GetUser(email);
In my action I need to get the current user and get collection of objects Notifications (one-to-many):
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
But, here I get the error:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I know that Notifications not loaded when I getting User from DB.
How to say EF to load Notifications objects? I know about Include, but I cannot use it in GetUser method.
When the first HttpRequest ends after looking up your CurrentUser object, your _repository reference that the CurrentUser is expecting for additional lookups like EmailNotifications isn't available.
The exception is thrown because CurrentUser doesn't have the original object context, so you either have to attach the CurrentUser object to the new objectContext that your _repository is using, or use the easier solution of simply reloading the user through the new context that was created for your current request in the repository.
Before attempting to find the notifications in your action, add the following line:
AppSession.CurrentUser = UserService.GetUser(AppSession.CurrentUser.Email);
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
As #Ryan said it is due to the fact that the object context is not available to lazy load in the associated notifications.
What I'd suggest is turn off lazy loading (if possible) as can cause lots of issues later and then do something like ...
var user = UserService.GetUser(AppSession.CurrentUser.Email);
user.Notifications = NotificationService.GetUserNotifications(user.Id /* or another identifier */);
AppSession.CurrentUser = user;
To do this you will require a new NotificationService, this can load (as suggested above) but also handle the execution of notifications (sending emails etc).
You should now have the notifications for that user in your Application session cache.
HTH

Entity Framework: An entity object cannot be referenced by multiple instances of IEntityChangeTracker

I have a User table, with a many-to-many relationship to an Alerts table. After creating a Membership user, I am adding some extra info into the database.
MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
if (createStatus == MembershipCreateStatus.Success) {
User user = new MidTier.Models.User();
user.FullName = model.FullName;
if (Alerts.Count() > 0)
{
var userAlerts = SetAlert(Alerts); // creates an IEnumerable of Alerts (from a list of int )
foreach (var alert in userAlerts)
{
user.Alerts.Add(alert); //add each alert to the user
}
}
userRepository.Add(user); //throwing error
userRepository.Save();
}
I get an error (' An entity object cannot be referenced by multiple instances of IEntityChangeTracker.') on calling the Add method. there are lots of references about this error on the net even here on SO, but after reading all those comments and suggestions, I a havent found a solution or the reason I am getting this error.
there are lots of references about
this error on the net even here on SO,
but after reading all those comments
and suggestions, I a havent found a
solution or the reason I am getting
this error.
If you really searched you should already know that error says you that some entity in object graph is already attached to other context. Because of that your code sample is mostly not related. The real important code is wrapped in your methods - probably SetAlerts and userRepository.Add. If these two methods use internally context and they don't use the same instance it is the reason for your exception.

Nhibernate Session closed exception issue with Asp.net mvc telerik ajax grid

I am getting Nhibernate Session closed exception with asp.net mvc telerik ajax grid. The grid is bound to an entity Sale that has a related entity User. The exception thrown is when trying to access the User entity. I have used the fetchMode to eager load it but I still get the same exception. This exception only occur if I switch between the grid pages multiple times. Anyone encountered this issue?
The code for that data access is as follow:
public IList<Sale> List()
{
var manager = new ManagerFactory().GetSaleManager();
var iCriteria = manager.Session.GetISession().CreateCriteria(typeof(Sale))
.SetFetchMode("AspnetUser3.Agents3", FetchMode.Eager);
return iCriteria.List<Sale>();
}
The code that try to access the related object in the object graph is as follow:
AgentId = sale.AspnetUser3.Agents3[0].Id,
The exception thrown
NHibernate.Exceptions.GenericADOException: could not load an entity: [SalesEntry.Data.Model.AspnetUser#7aaabf99-d77d-4edf-b949-9c4c0f3e85d8][SQL: SELECT aspnetuser0_.[UserId] as column1_12_0_, aspnetuser0_.[UserName] as column2_12_0_, aspnetuser0_.[LoweredUserName] as column3_12_0_, aspnetuser0_.[MobileAlias] as column4_12_0_, aspnetuser0_.[IsAnonymous] as column5_12_0_, aspnetuser0_.[LastActivityDate] as column6_12_0_, aspnetuser0_.[ApplicationId] as column7_12_0_ FROM [dbo].[aspnet_Users] aspnetuser0_ WHERE aspnetuser0_.[UserId]=?] ---> System.ObjectDisposedException: Session is closed!
Object name: 'ISession'.
It's happening because User is being lazy loaded and you're likely seeing a situation where the session is being closed before the User object is loaded. Then when the Grid accesses the User reference you get this exception. Make sure you're following the Unit of Work pattern.
Also you may want to use a Model class to bind to your grid, rather than the entity directly. That way you control what kind of access is done and you avoid having unexpected changes to your entities/database.

Categories