Hi, I've just update to 5.3.0 Core/Angular. Previously, to obtain User Roles I did:
var userProfile = await _userManager.GetUserByIdAsync(id); await _userManager.AbpStore.UserRepository.EnsureCollectionLoadedAsync(userProfile, u => u.Roles); var roleId = userProfile.Roles.FirstOrDefault()?.RoleId;
Now AbpStore isn't accessibile due to protection level. How Can I get the RoleId, starting from a User ?
Thanks
Hi I have a custom base DbContext, to make it works i am using DefaultDbContextAttribute as suggested here <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/issues/1119">https://github.com/aspnetboilerplate/as ... ssues/1119</a>. If I use DefaultDbContextAttribute for only one implemented context i got the error: Found more than one concrete type for given DbContext Type. If I use DefaultDbContextAttribute for all implemented context except of only one it works, but i think it's not the expected behavior.
This doesn't work
public abstract class BaseDbContext : AbpDbContext
{
protected BaseDbContext (DbContextOptions options) : base(options)
{
}
}
[DefaultDbContextAttribute]
public class SecurityContext : BaseDbContext
{
public SecurityContext(DbContextOptions<SecurityContext> options) : base(options)
{
}
}
public class TestContext : BaseDbContext
{
public NuovoContext(DbContextOptions<TestContext > options) : base(options)
{
}
}
public class AdtContext : BaseDbContext
{
public AdtContext(DbContextOptions options) : base(options)
{
}
}
This works and use SecurityContext when BaseDbContext is needed
public abstract class BaseDbContext : AbpDbContext
{
protected BaseDbContext (DbContextOptions options) : base(options)
{
}
}
public class SecurityContext : BaseDbContext
{
public SecurityContext(DbContextOptions<SecurityContext> options) : base(options)
{
}
}
[DefaultDbContextAttribute]
public class TestContext : BaseDbContext
{
public NuovoContext(DbContextOptions<TestContext > options) : base(options)
{
}
}
[DefaultDbContextAttribute]
public class AdtContext : BaseDbContext
{
public AdtContext(DbContextOptions options) : base(options)
{
}
}
Is It right to add DefaultDbContextAttribute to all new DbContext thats inherits from BaseDbContext ?
Thank you @ismcagdas.
I've update my code according to your and now all works good.
The only difference is that I've a BaseClass to extends in order to use in other LegacyContext, and the string resolver extends DbPerTenantConnectionStringResolver instead of DefaultConnectionStringResolver.
So the issue is closed.
Thank you for clarification. So, what I need is ExternalAutentication for some users, and default authentication for other. I noted if I return true for every existing user that try to login, the field AuthenticationSource is populate with my external authentication name. So i would like to limit to one specific authentication source per user.
How can I achive this?
Thanks
No, my custom authentication is developed as Modules Plugins loaded by options.PlugInSources.AddFolder(@"C:\MyPlugIns"); All code involved is what I have posted I have to register the external authentication elsewhere?
Hi, I've create the code to implement an External Authentication module. What I don't realize is how to call from a client this different authentication system. I need to use both ways: the default abpTables and this new one. I've tried to call by "api/TokenAuth/ExternalAuthenticate/" but I receive the error: Unknown external auth provider: MyAuth
public class MyAuthExternalAuthenticationSource: DefaultExternalAuthenticationSource<Tenant,User>, ITransientDependency
{
public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
return Task.FromResult(true);
}
public override string Name => "MyAuth";
}
}
public override void PreInitialize()
{
Configuration.Modules.Zero().UserManagement.ExternalAuthenticationSources.Add<MyAuthExternalAuthenticationSource>();
}
What I'm missing? Thanks
Hi, We have a legacy context that needs to access to an external database. Default abp context is used as usual. Legacy context has a different connectionstring for every tenant. ConnectionStrings are retrived by a ILegacyConnectionStringService that reads from file. Look at GetNameOrConnectionString: is this the rigth way?
//Simple legacy context
public class AdtLegacyContext : AbpDbContext
{
public DbSet<TrcAnagraficaData> TrcAnagrafiche { get; set; }
public AdtLegacyContext(DbContextOptions<AdtLegacyContext> options) : base(options)
{
}
}
public class AdtLegacyRepositoryModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(AdtLegacyRepositoryModule).GetAssembly());
}
public override void PreInitialize()
{
//Replace the connectionString resolver service
Configuration.ReplaceService<IConnectionStringResolver, LegacyConnectionStringResolver>(Abp.Dependency.DependencyLifeStyle.Transient);
//Abp context
Configuration.Modules.AbpEfCore().AddDbContext<DefaultContext>(options =>
{
if (options.ExistingConnection != null)
{
DefaultContextConfigurer.Configure(options.DbContextOptions, options.ExistingConnection);
}
else
{
DefaultContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString);
}
});
//LegacyContext
Configuration.Modules.AbpEfCore().AddDbContext<AdtLegacyContext>(options =>
{
if (options.ExistingConnection != null)
{
AdtLegacyConfigurer.Configure(options.DbContextOptions, options.ExistingConnection);
}
else
{
AdtLegacyConfigurer.Configure(options.DbContextOptions, options.ConnectionString);
}
});
}
}
public class LegacyConnectionStringResolver : DbPerTenantConnectionStringResolver
{
private readonly ILegacyConnectionStringService _legacyConnectionStrings;
public LegacyConnectionStringResolver(ILegacyConnectionStringService legacyConnectionStrings, IAbpStartupConfiguration configuration, ICurrentUnitOfWorkProvider currentUnitOfWorkProvider, ITenantCache tenantCache) : base(configuration, currentUnitOfWorkProvider, tenantCache)
{
_legacyConnectionStrings = legacyConnectionStrings;
}
//Is this the right way?
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args["DbContextType"] == typeof(AdtLegacyContext))
{
var tenantId = GetCurrentTenantId();
if (!tenantId.HasValue)
{
throw new InvalidOperationException("Legacy db context must have tenant");
}
var connectionString = _legacyConnectionStrings.GetConnectionString(tenantId.Value);//Read from file
return connectionString;
}
return base.GetNameOrConnectionString(args);
}
}
Some progress. I think that the real problem wasn't focused.
In order to access to my external legacy database, I need to change at runtime the connection string. Exactly as you do when the Tenant as separate db.
So.... I guess the problems is here. Maybe that the solution is to implement a different ConnectionStringResolver ?
If so, what is the best approach to extends the default resolver and distinguish from default AbpContext and all the other legacy db context (this are more than one defined in many modules).
Thanks
Sure @ismcagdas . I have added on my two db context the specified type, but the error is still the same.
public AdtLegacyContext(DbContextOptions<AdtLegacyContext> options, ILegacyConnectionStringService legacyConnectionStrings) : base(options)
{
_legacyConnectionStrings = legacyConnectionStrings;
}
public AdtContext(DbContextOptions<AdtContext> options) : base(options)
{
}
ERROR 2018-03-14 16:15:03,624 [8 ] Mvc.ExceptionHandling.AbpExceptionFilter - Both an existing DbConnection and a connection string have been configured. When an existing DbConnection is used the connection string must be set on that connection. System.InvalidOperationException: Both an existing DbConnection and a connection string have been configured. When an existing DbConnection is used the connection string must be set on that connection. at Microsoft.EntityFrameworkCore.Storage.RelationalConnection..ctor(RelationalConnectionDependencies dependencies)
Other suggestions ? I'm sure that is possibile but maybe I'm missing some concept.