You're welcome. : )
hi
Should the appsettings.secrets.json file be included when deploying the application to client environments?
Yes, You should include it.
The license code in appsettings.secrets.json is different from API Key.
Resetting the API key will not affect the License code.
Thanks.
hi
The API Key is the token of PRO packages hosted on nuget.abp.io. Your private NuGet source is https://nuget.abp.io/your_key/v3/index.json This is automatically added as a feed to your NuGet.Config in your ABP solution. Do not share your private key with unauthorized users!
If you reset it, the previous key will no longer be able to restore packages from nuget.abp.io.
The live system will not be affected since it does not need to restore the packages.
You can send an email to info@abp.io to request a reset.
Please include your organization's info in the mail.
Thanks.
hi
Thanks, can you share a simple project?
liming.ma@volosoft.com
Thanks.
hi
How can I reproduce this?
Can you share some code and steps
Thanks.
hi
Can you share a template project to reproduce the problem?
You can also disable Dynamic Claims in all projects and try again.
https://abp.io/docs/latest/framework/fundamentals/dynamic-claims#enabling-disabling-the-dynamic-claims
Thanks.
hi
Can you add some code to the Program to read and log the AbpLicenseCode from appsettings.json
Thanks.
hi
AI is right.
You can override the DefaultHttpExceptionStatusCodeFinder.
https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultHttpExceptionStatusCodeFinder.cs#L70-L73
Thanks.
hi
Please use IRemoteStreamContent to replace IFormFile in your DTO and regenerate the Angular proxy.
https://abp.io/docs/latest/framework/architecture/domain-driven-design/application-services#working-with-streams
Thanks.
hi
The new version
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.EntityFrameworkCore.ChangeTrackers;
public class MyAbpEntityEntry
{
public string Id { get; set; }
public EntityEntry EntityEntry { get; set; }
public List<MyAbpNavigationEntry> NavigationEntries { get; set; }
private bool _isModified;
public bool IsModified
{
get
{
return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified);
}
set => _isModified = value;
}
public MyAbpEntityEntry(string id, EntityEntry entityEntry)
{
Id = id;
EntityEntry = entityEntry;
NavigationEntries = EntityEntry.Navigations.Select(x => new MyAbpNavigationEntry(x, x.Metadata.Name)).ToList();
}
public void UpdateNavigation(EntityEntry entityEntry, MyAbpNavigationEntry navigationEntry)
{
if (IsModified ||
EntityEntry.State == EntityState.Modified ||
navigationEntry.IsModified)
{
return;
}
var currentValue = navigationEntry.NavigationEntry.CurrentValue;
if (currentValue == null)
{
return;
}
if (navigationEntry.NavigationEntry is CollectionEntry)
{
navigationEntry.OriginalValue!.As<List<object>>().Add(entityEntry.Entity);
}
else
{
navigationEntry.OriginalValue = currentValue;
}
}
}
public class MyAbpNavigationEntry
{
public NavigationEntry NavigationEntry { get; set; }
public string Name { get; set; }
public bool IsModified { get; set; }
public object? OriginalValue { get; set; }
public object? CurrentValue => NavigationEntry.CurrentValue;
public MyAbpNavigationEntry(NavigationEntry navigationEntry, string name)
{
NavigationEntry = navigationEntry;
Name = name;
if (navigationEntry.CurrentValue != null )
{
OriginalValue = navigationEntry is CollectionEntry ? new List<object>() : navigationEntry.CurrentValue;
}
}
}
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AbpEfCoreNavigationHelper))]
public class MyAbpEfCoreNavigationHelper : AbpEfCoreNavigationHelper
{
protected Dictionary<string, MyAbpEntityEntry> MyEntityEntries { get; } = new();
public override void ChangeTracker_Tracked(object? sender, EntityTrackedEventArgs e)
{
EntityEntryTrackedOrStateChanged(e.Entry);
DetectChanges(e.Entry);
}
public override void ChangeTracker_StateChanged(object? sender, EntityStateChangedEventArgs e)
{
EntityEntryTrackedOrStateChanged(e.Entry);
DetectChanges(e.Entry);
}
protected override void EntityEntryTrackedOrStateChanged(EntityEntry entityEntry)
{
if (entityEntry.State != EntityState.Unchanged)
{
return;
}
var entryId = GetEntityEntryIdentity(entityEntry);
if (entryId == null)
{
return;
}
if (MyEntityEntries.ContainsKey(entryId))
{
return;
}
MyEntityEntries.Add(entryId, new MyAbpEntityEntry(entryId, entityEntry));
}
protected override void DetectChanges(EntityEntry entityEntry, bool checkEntityEntryState = true)
{
#pragma warning disable EF1001
var stateManager = entityEntry.Context.GetDependencies().StateManager;
var internalEntityEntityEntry = stateManager.TryGetEntry(entityEntry.Entity, throwOnNonUniqueness: false);
if (internalEntityEntityEntry == null)
{
return;
}
var foreignKeys = entityEntry.Metadata.GetForeignKeys().ToList();
foreach (var foreignKey in foreignKeys)
{
var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey);
if (principal == null)
{
continue;
}
var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
{
continue;
}
var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
{
myAbpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
}
if (!myAbpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
myAbpEntityEntry.IsModified = true;
DetectChanges(myAbpEntityEntry.EntityEntry, false);
}
if (navigationEntry != null && IsEntityEntryChanged(entityEntry))
{
navigationEntry.IsModified = true;
}
}
var skipNavigations = entityEntry.Metadata.GetSkipNavigations().ToList();
foreach (var skipNavigation in skipNavigations)
{
var joinEntityType = skipNavigation.JoinEntityType;
var foreignKey = skipNavigation.ForeignKey;
var inverseForeignKey = skipNavigation.Inverse.ForeignKey;
foreach (var joinEntry in stateManager.Entries)
{
if (joinEntry.EntityType != joinEntityType || stateManager.FindPrincipal(joinEntry, foreignKey) != internalEntityEntityEntry)
{
continue;
}
var principal = stateManager.FindPrincipal(joinEntry, inverseForeignKey);
if (principal == null)
{
continue;
}
var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
{
continue;
}
var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
{
myAbpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
}
if (!myAbpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
myAbpEntityEntry.IsModified = true;
DetectChanges(myAbpEntityEntry.EntityEntry, false);
}
if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
{
navigationEntry.IsModified = true;
}
}
}
#pragma warning restore EF1001
}
protected override bool IsEntityEntryChanged(EntityEntry entityEntry)
{
return entityEntry.State == EntityState.Added ||
entityEntry.State == EntityState.Deleted ||
entityEntry.State == EntityState.Modified;
}
public override List<EntityEntry> GetChangedEntityEntries()
{
return MyEntityEntries
.Where(x => x.Value.IsModified)
.Select(x => x.Value.EntityEntry)
.ToList();
}
public override bool IsEntityEntryModified(EntityEntry entityEntry)
{
if (entityEntry.State == EntityState.Modified)
{
return true;
}
var entryId = GetEntityEntryIdentity(entityEntry);
if (entryId == null)
{
return false;
}
return MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry) && myAbpEntityEntry.IsModified;
}
public override bool IsNavigationEntryModified(EntityEntry entityEntry, int? navigationEntryIndex = null)
{
var entryId = GetEntityEntryIdentity(entityEntry);
if (entryId == null)
{
return false;
}
if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
{
return false;
}
if (navigationEntryIndex == null)
{
return myAbpEntityEntry.NavigationEntries.Any(x => x.IsModified);
}
var navigationEntryProperty = myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex.Value);
return navigationEntryProperty != null && navigationEntryProperty.IsModified;
}
public override AbpNavigationEntry? GetNavigationEntry(EntityEntry entityEntry, int navigationEntryIndex)
{
var entryId = GetEntityEntryIdentity(entityEntry);
if (entryId == null)
{
return null;
}
if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
{
return null;
}
var element = myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex);
if (element == null)
{
return null;
}
return new AbpNavigationEntry(element.NavigationEntry, element.Name)
{
IsModified = element.IsModified,
OriginalValue = element.OriginalValue
};
}
protected override string? GetEntityEntryIdentity(EntityEntry entityEntry)
{
if (entityEntry.Entity is IEntity entryEntity && entryEntity.GetKeys().Length == 1)
{
return $"{entityEntry.Metadata.ClrType.FullName}:{entryEntity.GetKeys().FirstOrDefault()}";
}
return null;
}
public override void RemoveChangedEntityEntries()
{
MyEntityEntries.RemoveAll(x => x.Value.IsModified);
}
public override void Clear()
{
MyEntityEntries.Clear();
}
}