Our mistake. When migrating, we omitted the change which adds the [HttpPost]
decorator on the GetRoles
method in the RoleAppService
.
Without it, it seems that the method is recognized as a GET method and therefore has its input parameters split.
Thanks for the support.
I don't think it has anything to do with the service-proxies generation.
As you can see in my request, the swagger endpoint generated in the backend (https://localhost:44301/swagger/v1/swagger.json) already splits the Input class into its properties.
There must be some swagger configuration parameter enabling the split in the backend but I can't seem to find it...
Angular .net core. We are currently migrating from aspnetzero 8.8 to 10.3.
In the RoleAppService there's this method :
public async Task <ListResultDto> GetRoles(GetRolesInput input)
When we query the swagger endpoint, we get this :
"/api/services/app/Role/GetRoles": {
"get": {
"tags": [
"Role"
],
"operationId": "ApiServicesAppRoleGetrolesGet",
"parameters": [
{
"name": "Permissions",
"in": "query",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ListResultDtoOfRoleListDto"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ListResultDtoOfRoleListDto"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ListResultDtoOfRoleListDto"
}
}
}
}
}
}
},
Why does swagger reduce GetRolesInput
to Permissions
(which is its only Property) ? In the frontend, it triggers compilation errors in the roles.component which doesn't know what a GetRolesInput object is anymore.
I checked in your code and there it's generated just fine. I tried adding other properties to the class, they all seem to be split by swagger. I copied the service.config.nswag from aspnetzero and I also double checked the Startup file in the Web.Host project.
Did I miss a swagger config option somewhere ?
Thanks
Hi @ismcagdas
We ended up creating a separate table and not using an abpsetting for this. It's faster, it's useful for other use cases and it works fine. Thank you anyway for your reply !
.net core, angular, aspnetzero 8.8
In a manager, we read and update a serialized json from/to an abpsetting. We do this several times in a for loop over entity objects. At some point in the loop, the retrieved setting will be truncated (to a variable length), thus crashing the json parser. At the same time, in the database, the setting has been correctly set to a valid json value.
Here's our code :
The loop :
foreach (var entity in entities)
_myManager.UpdateEntityAsync(entity).GetAwaiter().GetResult();``
The manager :
[UnitOfWork]
public async Task UpdateEntityAsync(MyEntity entity)
{
await _myEntityRepository.UpdateAsync(entity);
AddDateRangeToReprocess(entity.Id, new DateRange(entity.Start, entity.End));
}
[UnitOfWork]
public void AddDateRangeToReprocess(short id, DateRange range)
{
var existingDateRanges = GetDateRangesToReprocess();
if (existingDateRanges == null)
{
existingDateRanges = new Dictionary<short, List<DateRange>>();
}
if (!existingDateRanges.ContainsKey(id) || existingDateRanges[id] == null)
{
existingDateRanges.AddOrUpdateIfExist(id, new List<DateRange>());
}
if (!existingDateRanges[id].Any(x => x == range))
{
existingDateRanges[id].Add(range);
}
if (_tenantManager.AbpSession.TenantId.HasValue)
{
_settingManager.ChangeSettingForTenant(_tenantManager.AbpSession.TenantId.Value, "EntityRanges", JsonConvert.SerializeObject(existingDateRanges));
}
}
[UnitOfWork]
public Dictionary<short, List<DateRange>> GetDateRangesToReprocess()
{
return JsonConvert.DeserializeObject<Dictionary<short, List<DateRange>>>(_settingManager.GetSettingValue("EntityRanges"));
}
Output example :
//Value of the setting in the database :
{"14":[{"Start":"2021-03-01T05:39:00Z","End":"2021-03-01T05:39:44Z","Duration":"00:00:44"},{"Start":"2021-03-08T16:51:45Z","End":"2021-03-08T16:52:05Z","Duration":"00:00:20"}]}
//Value of the setting when debugging in the manager (GetDateRangesToReprocess) :
{"14":[{"Start":"2021-03-01T05:39:00Z","End":"2021-03-01T05:39:44Z","Duration":"00:00:44"},{"Start":"2021-03-08T16:51:45Z","End":"2021-03-08T16:52:05Z",
There does not seem to be a specific length to which our setting is truncated.
We figured that maybe it had to do with the cache that was not invalidated properly ?
Hello, thanks for your answer.
My use case is as follows :
Usually, each of our customers manages a single site (= tenant).
However, we have one of our customers who manages two sites (two different tenants). This customer has several users and most of them should be able to connect to both tenants with the same username, role and permissions
Hello,
Is it possible to have my users at the host level so that they're shared across tenants ?
So when I edit a user (or its permissions, or anything else), changes would be echoed to other tenants.
We're on Aspnetzero V8.8.0 angular + .net core
that was the solution ;)
thanks !
Hello !
The issue is that i try to send emails from abp framework through an anonymous SMTP server and it does not work via ABP. When I send it from SMTP Prober or directly from one c# smtp client, it works fine.
But from abp, I have set these parameters but it does not seems to work.
do you have any idea if I made some erros in the abpsettings ?
thanks
No I don't. It's still in English.
In the AbpSettings table, the language setting has not been set for my public user.
I can maybe provide the full code for public user creation :
private async Task<AuthenticateResultModel> PublicAuthenticationForTenantId(int tenantId)
{
using (AbpSession.Use(tenantId, null))
{
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
var password = ...;
var userName = $"{Guid.NewGuid():N}";
Authorization.Users.User.CreateTenantAdminUser(AbpSession.TenantId.Value,
$"{userName}@public.com");
publicUser.UserName = userName;
publicUser.Name = StaticUserPublic.Name;
publicUser.Surname = StaticUserPublic.Surname;
publicUser.IsEmailConfirmed = true;
publicUser.ShouldChangePasswordOnNextLogin = false;
publicUser.IsActive = true;
publicUser.Password = new PasswordHasher<User>(new OptionsWrapper<PasswordHasherOptions>(new PasswordHasherOptions())).HashPassword(publicUser, password);
publicUser.Roles = new Collection<UserRole>(); var role = await _roleManager.GetRoleByNameAsync(StaticRoleNames.Tenants.Public);
publicUser.Roles.Add(new UserRole(AbpSession.TenantId, publicUser.Id, role.Id));
CheckErrors(await _userManager.CreateAsync(publicUser));
var defaultLanguage = _settingManager.GetSettingValueForTenant(LocalizationSettingNames.DefaultLanguage, tenantId);
_settingManager.ChangeSettingForUser(publicUser.ToUserIdentifier(), LocalizationSettingNames.DefaultLanguage, defaultLanguage);
CurrentUnitOfWork.SaveChanges(); //To get new user's Id.
return await Authenticate(new AuthenticateModel
{
UserNameOrEmailAddress = publicUser.UserName,
Password = password,
RememberClient = true,
SingleSignIn = false
});
}
}
}