In identity module ,
We have a AbpIdentityOptionsFactory to create IdentityOptions by abp Settings module.
That is easy to store identityOptions base on tenant or other SettingValueProvider...
but when i set value by ISettingManager( setting-management module),
identityOptions doesn't know the value is changed, below code:
var oldValue = IdentityOptions.Value.Password.RequiredLength;
await settingManager.SetGlobalAsync(IdentitySettingNames.Password.RequiredLength, newValue);
var updatedValue = IdentityOptions.Value.Password.RequiredLength;
updatedValue should be newValue but it is oldValue.
@hikalkan :
could you tell me how to enhance AbpIdentityOptionsFactory like IOptionsMonitor do .let it can auto change when database(by settingstore) is change.
or is it now enough that , no need to enhance ?
@maliming
thank for reply.
in that unit test doesn't present this question .
it should be in the same scope to modify value and get value directly like
using (var scope1 = ServiceProvider.CreateScope())
{
var options = scope1.ServiceProvider.GetRequiredService<IOptions<IdentityOptions>>().Value;
options.Password.RequiredLength.ShouldBe(6); //Default value
options.Password.RequiredUniqueChars.ShouldBe(1); //Default value
_settingProvider.GetOrNullAsync(IdentitySettingNames.Password.RequiredLength).Returns(Task.FromResult("42"));//====>pretend changed by settingManager
options.Password.RequiredLength.ShouldBe(42);//=====>error,value is 6
}
in fact
it will be fine if modify value by ISettingManager and get value by(IOptions
but you should take care in one request the options value is different with db.
so i hope to enhance it to avoid mistake
and this is my test code
public class SampleAppService : EpsyAppService, ISampleAppService
{
public IOptions<IdentityOptions> IdentityOptions { get; set; }
public ISettingManager _settingManager { get; set; }
public Volo.Abp.SettingManagement.ISettingManager settingManager { get; set; }
public SampleAppService(){}
public async Task<object> PostIdentity(string newValue)
{
var oldValue = IdentityOptions.Value.Password.RequiredLength;
await settingManager.SetGlobalAsync(IdentitySettingNames.Password.RequiredLength, newValue);
var updatedValue = IdentityOptions.Value.Password.RequiredLength;
return Task.FromResult(new { oldValue, newValue, updatedValue });
}
}
i use it in SampleController to try it.
This is because IOptions is a singleton. I can't think of any way to enhance it.
i found it ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor
in this article ,the option can watch file change (appsettings.json).
but i have no idea how to do with abp ISettingManager
@hikalkan What do you think?
Options are cached by aspnet core. I don't know if there is a way of invalidating the cache. I should check it deeper.
Currently, options are cached only for a single request. Normally you update the settings in a separate request, so you can get the new values in the next request.
I am moving this to the next milestone since it is not urgent and there is no problem in most cases.
For now, you may want to set options after changing the setting, so other services can get the latest setting value.
Most helpful comment
Options are cached by aspnet core. I don't know if there is a way of invalidating the cache. I should check it deeper.