- ABP Framework version: v6.0.0
- UI type: Blazor
- DB provider: EF Core
- Tiered (MVC) or Identity Server Separated (Angular): yes
- Exception message and stack trace:
- [12:18:25 DBG] PermissionStore.GetCacheItemAsync: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application [12:18:25 DBG] Found in the cache: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application [12:18:25 DBG] PermissionStore.GetCacheItemAsync: pn:R,pk:admin,n:OpenIddictPro.Application [12:18:25 DBG] Found in the cache: pn:R,pk:admin,n:OpenIddictPro.Application [12:18:25 DBG] PermissionStore.GetCacheItemAsync: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application [12:18:25 DBG] Found in the cache: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application [12:18:25 INF] Executing ObjectResult, writing value of type 'Volo.Abp.OpenIddict.Applications.Dtos.ApplicationDto'. [12:18:25 INF] Executed action Volo.Abp.OpenIddict.ApplicationController.GetAsync (Volo.Abp.OpenIddict.Pro.HttpApi) in 42.6238ms [12:18:25 INF] Executed endpoint 'Volo.Abp.OpenIddict.ApplicationController.GetAsync (Volo.Abp.OpenIddict.Pro.HttpApi)' [12:18:25 INF] Request finished HTTP/1.1 GET https://localhost:44388/api/openiddict/applications/496c821d-cf08-a729-a0d7-3a06ce526930?api-version=1.0 - 0 - 200 - application/json;+charset=utf-8 47.6289ms [12:18:34 INF] Request starting HTTP/1.1 PUT https://localhost:44388/api/openiddict/applications/496c821d-cf08-a729-a0d7-3a06ce526930?api-version=1.0 application/json;+charset=utf-8 653 [12:18:34 INF] Executing endpoint 'Volo.Abp.OpenIddict.ApplicationController.UpdateAsync (Volo.Abp.OpenIddict.Pro.HttpApi)' [12:18:34 INF] Route matched with {controller = "Applications", area = "openiddictpro", action = "Update"}. Executing controller action with signature System.Threading.Tasks.Task`1[Volo.Abp.OpenIddict.Applications.Dtos.ApplicationDto] UpdateAsync(System.Guid, Volo.Abp.OpenIddict.Applications.Dtos.UpdateApplicationInput) on controller Volo.Abp.OpenIddict.ApplicationController (Volo.Abp.OpenIddict.Pro.HttpApi). [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application.Update [12:18:34 DBG] Found in the cache: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application.Update [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:R,pk:admin,n:OpenIddictPro.Application.Update [12:18:34 DBG] Found in the cache: pn:R,pk:admin,n:OpenIddictPro.Application.Update [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application.Update [12:18:34 DBG] Found in the cache: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application.Update [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application [12:18:34 DBG] Found in the cache: pn:U,pk:94c36bd4-906c-396b-19fa-3a06ce4ddc17,n:OpenIddictPro.Application [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:R,pk:admin,n:OpenIddictPro.Application [12:18:34 DBG] Found in the cache: pn:R,pk:admin,n:OpenIddictPro.Application [12:18:34 DBG] PermissionStore.GetCacheItemAsync: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application [12:18:34 DBG] Found in the cache: pn:C,pk:vSkysoft_BlazorServer,n:OpenIddictPro.Application [12:18:34 WRN] Savepoints are disabled because Multiple Active Result Sets (MARS) is enabled. If 'SaveChanges' fails, then the transaction cannot be automatically rolled back to a known clean state. Instead, the transaction should be rolled back by the application before retrying 'SaveChanges'. See https://go.microsoft.com/fwlink/?linkid=2149338 for more information. To identify the code which triggers this warning, call 'ConfigureWarnings(w => w.Throw(SqlServerEventId.SavepointsDisabledBecauseOfMARS))'. [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 INF] Executing ObjectResult, writing value of type 'Volo.Abp.OpenIddict.Applications.Dtos.ApplicationDto'. [12:18:34 INF] Executed action Volo.Abp.OpenIddict.ApplicationController.UpdateAsync (Volo.Abp.OpenIddict.Pro.HttpApi) in 402.5191ms [12:18:34 INF] Executed endpoint 'Volo.Abp.OpenIddict.ApplicationController.UpdateAsync (Volo.Abp.OpenIddict.Pro.HttpApi)' [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 DBG] Added 0 entity changes to the current audit log [12:18:34 INF] Request finished HTTP/1.1 PUT https://localhost:44388/api/openiddict/applications/496c821d-cf08-a729-a0d7-3a06ce526930?api-version=1.0 application/json;+charset=utf-8 653 - 200 - application/json;+charset=utf-8 670.3044ms
- Steps to reproduce the issue:"
8 Answer(s)
-
0
hi
Please share the full steps to reproduce. Thanks.
-
0
@using Volo.Abp.OpenIddict.Pro.Blazor.Pages
@inherits ApplicationManagement
@{ base.BuildRenderTree(__builder); }
@if (HasUpdatePermission){
<DxPopup HeaderText="@L["Application"]" @bind-Visible="ApplicationPopup" Context="DxPopupContext" @ref="dxPopup"> <BodyContentTemplate>
<DxFormLayout> <DxFormLayoutItem ColSpanMd="12" Context="item"> <DxComboBox Data="organizationUnitDtoList" FilteringMode="DataGridFilteringMode.Contains" TextFieldName="DisplayName" ValueFieldName="Id" ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" @bind-Value="@(EditingEntity.ExtraProperties["OrganizationUnitId"])"> @L["OrganizationUnit"] </DxComboBox> </DxFormLayoutItem> <DxFormLayoutItem ColSpanMd="12" Context="item"> <DxCheckBox @bind-Checked="@(NeedVAuthority)"> @L["NeedVAuthority"] </DxCheckBox> </DxFormLayoutItem> <DxFormLayoutItem ColSpanMd="12"> <div class="right-align"> <DxButton RenderStyle="ButtonRenderStyle.Primary" Text="@L["Cancel"]" Click="()=>ApplicationPopup=false" />
<DxButton RenderStyle="ButtonRenderStyle.Secondary" Text="@L["Confirm"]" Click="ConfirmChange" />
</div> </DxFormLayoutItem> </DxFormLayout> </BodyContentTemplate>
</DxPopup> }
using DevExpress.Blazor; using Microsoft.AspNetCore.Components; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; using Volo.Abp.BlazoriseUI; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Applications.Dtos; using Volo.Abp.OpenIddict.Pro.Blazor.Pages;
namespace aa.IdentityService.Blazor.Pages.IdentityServer {
[ExposeServices(typeof(ApplicationManagement))]
[Dependency(ReplaceServices = true)]
public partial class CustomApplicationManagement { [Inject] IOrganizationUnitAppService OrganizationUnitAppService { get; set; } bool ApplicationPopup; DxPopup dxPopup; List<OrganizationUnitWithDetailsDto> organizationUnitDtoList; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); var organizationUnitResult = await OrganizationUnitAppService.GetListAllAsync(); organizationUnitDtoList = organizationUnitResult.Items.Where(u => u.ParentId == null).ToList(); } protected async override Task OpenCreateModalAsync() { Scopes = (await ScopeAppService.GetAllScopesAsync()).ToDictionary(x => x.Name, x => false); CreateInput = new ApplicationModalView(); CreateInput.ExtraProperties["NeedVAuthority"] = false; try { if (CreateValidationsRef != null) { await CreateValidationsRef.ClearAll(); } await CheckCreatePolicyAsync(); NewEntity = new CreateApplicationInput(); // Mapper will not notify Blazor that binded values are changed // so we need to notify it manually by calling StateHasChanged await InvokeAsync(async () => { StateHasChanged(); if (CreateModal != null) { await CreateModal.Show(); } }); } catch (Exception ex) { await HandleErrorAsync(ex); } } async Task OpenApplicationAsync(ApplicationDto entity) { if (dxPopup is not null) { ApplicationPopup = true; var entityDto = await AppService.GetAsync(entity.Id); EditingEntityId = entity.Id; EditingEntity = MapToEditingEntity(entityDto); EditingEntity.ExtraProperties["NeedVAuthority"] = false; EditingEntity.ExtraProperties["OrganizationUnitId"] = ""; //EditingClientModelView = ObjectMapper.Map<UpdateClientDto, UpdateClientModelView>(EditingEntity); await InvokeAsync(StateHasChanged); await dxPopup.ShowAsync(); } } protected async override Task OpenEditModalAsync(ApplicationDto entity) { await base.OpenEditModalAsync(entity); CreateInput.ClientUri = entity.ClientUri; CreateInput.LogoUri = entity.LogoUri; Scopes = (await ScopeAppService.GetAllScopesAsync()).ToDictionary(x => x.Name, x => EditingEntity.Scopes.Any(s => s == x.Name)); await InvokeAsync(StateHasChanged); } protected override UpdateApplicationInput MapToEditingEntity(ApplicationDto entityDto) { UpdateInput = ObjectMapper.Map<ApplicationDto, ApplicationModalView>(entityDto); return base.MapToEditingEntity(entityDto); ; } protected override Task OnUpdatingEntityAsync() { UpdateInput.Scopes = Scopes.Where(x => x.Value).Select(x => x.Key).ToHashSet(); UpdateInput.LogoUri = CreateInput.LogoUri; UpdateInput.ClientUri = CreateInput.ClientUri; EditingEntity = ObjectMapper.Map<ApplicationModalView, UpdateApplicationInput>(UpdateInput); return base.OnUpdatingEntityAsync(); } protected override ValueTask SetEntityActionsAsync() { EntityActions .Get<ApplicationManagement>() .Add( new EntityAction { Text = L["Application"], Visible = (data) => HasUpdatePermission, Clicked = async (data) => await OpenApplicationAsync(data.As<ApplicationDto>()) }); return base.SetEntityActionsAsync(); } bool NeedVAuthority { get => (bool)EditingEntity.ExtraProperties["NeedVAuthority"]; set => EditingEntity.ExtraProperties["NeedVAuthority"] = value; }
async Task ConfirmChange()
{
await AppService.UpdateAsync(EditingEntityId, EditingEntity);
ApplicationPopup = false;
}
}
}
Invoke method ConfirmChange()
-
0
Please try to format your code. It is unreadable. Thanks
-
0
CustomApplicationManagment.razor
@using Volo.Abp.OpenIddict.Pro.Blazor.Pages @inherits ApplicationManagement
@{ base.BuildRenderTree(__builder); }
@if (HasUpdatePermission){
<DxPopup HeaderText="@L["Application"]" @bind-Visible="ApplicationPopup" Context="DxPopupContext" @ref="dxPopup"> <BodyContentTemplate>
<DxFormLayout> <DxFormLayoutItem ColSpanMd="12" Context="item"> <DxComboBox Data="organizationUnitDtoList" FilteringMode="DataGridFilteringMode.Contains" TextFieldName="DisplayName" ValueFieldName="Id" ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" @bind-Value="@(EditingEntity.ExtraProperties["OrganizationUnitId"])"> @L["OrganizationUnit"] </DxComboBox> </DxFormLayoutItem> <DxFormLayoutItem ColSpanMd="12" Context="item"> <DxCheckBox @bind-Checked="@(NeedVAuthority)"> @L["NeedVAuthority"] </DxCheckBox> </DxFormLayoutItem> <DxFormLayoutItem ColSpanMd="12"> <div class="right-align"> <DxButton RenderStyle="ButtonRenderStyle.Primary" Text="@L["Cancel"]" Click="()=>ApplicationPopup=false" /> <DxButton RenderStyle="ButtonRenderStyle.Secondary" Text="@L["Confirm"]" Click="ConfirmChange" /> </div> </DxFormLayoutItem> </DxFormLayout> </BodyContentTemplate>
</DxPopup> }
CustomApplicationManagement.razor.cs
using DevExpress.Blazor; using Microsoft.AspNetCore.Components; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; using Volo.Abp.BlazoriseUI; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Applications.Dtos; using Volo.Abp.OpenIddict.Pro.Blazor.Pages; namespace MySoft.IdentityService.Blazor.Pages.IdentityServer { [ExposeServices(typeof(ApplicationManagement))] [Dependency(ReplaceServices = true)] public partial class CustomApplicationManagement { [Inject] IOrganizationUnitAppService OrganizationUnitAppService { get; set; } bool ApplicationPopup; DxPopup dxPopup; List<OrganizationUnitWithDetailsDto> organizationUnitDtoList; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); var organizationUnitResult = await OrganizationUnitAppService.GetListAllAsync(); organizationUnitDtoList = organizationUnitResult.Items.Where(u => u.ParentId == null).ToList(); } protected async override Task OpenCreateModalAsync() { Scopes = (await ScopeAppService.GetAllScopesAsync()).ToDictionary(x => x.Name, x => false); CreateInput = new ApplicationModalView(); CreateInput.ExtraProperties["NeedVAuthority"] = false; try { if (CreateValidationsRef != null) { await CreateValidationsRef.ClearAll(); } await CheckCreatePolicyAsync(); NewEntity = new CreateApplicationInput(); // Mapper will not notify Blazor that binded values are changed // so we need to notify it manually by calling StateHasChanged await InvokeAsync(async () => { StateHasChanged(); if (CreateModal != null) { await CreateModal.Show(); } }); } catch (Exception ex) { await HandleErrorAsync(ex); } } async Task OpenApplicationAsync(ApplicationDto entity) { if (dxPopup is not null) { ApplicationPopup = true; var entityDto = await AppService.GetAsync(entity.Id); EditingEntityId = entity.Id; EditingEntity = MapToEditingEntity(entityDto); EditingEntity.ExtraProperties["NeedVAuthority"] = false; EditingEntity.ExtraProperties["OrganizationUnitId"] = ""; //EditingClientModelView = ObjectMapper.Map<UpdateClientDto, UpdateClientModelView>(EditingEntity); await InvokeAsync(StateHasChanged); await dxPopup.ShowAsync(); } } protected async override Task OpenEditModalAsync(ApplicationDto entity) { await base.OpenEditModalAsync(entity); CreateInput.ClientUri = entity.ClientUri; CreateInput.LogoUri = entity.LogoUri; Scopes = (await ScopeAppService.GetAllScopesAsync()).ToDictionary(x => x.Name, x => EditingEntity.Scopes.Any(s => s == x.Name)); await InvokeAsync(StateHasChanged); } protected override UpdateApplicationInput MapToEditingEntity(ApplicationDto entityDto) { UpdateInput = ObjectMapper.Map<ApplicationDto, ApplicationModalView>(entityDto); return base.MapToEditingEntity(entityDto); ; } protected override Task OnUpdatingEntityAsync() { UpdateInput.Scopes = Scopes.Where(x => x.Value).Select(x => x.Key).ToHashSet(); UpdateInput.LogoUri = CreateInput.LogoUri; UpdateInput.ClientUri = CreateInput.ClientUri; EditingEntity = ObjectMapper.Map<ApplicationModalView, UpdateApplicationInput>(UpdateInput); return base.OnUpdatingEntityAsync(); } protected override ValueTask SetEntityActionsAsync() { EntityActions .Get<ApplicationManagement>() .Add( new EntityAction { Text = L["Application"], Visible = (data) => HasUpdatePermission, Clicked = async (data) => await OpenApplicationAsync(data.As<ApplicationDto>()) }); return base.SetEntityActionsAsync(); } bool NeedVAuthority { get => (bool)EditingEntity.ExtraProperties["NeedVAuthority"]; set => EditingEntity.ExtraProperties["NeedVAuthority"] = value; } async Task ConfirmChange() { await AppService.UpdateAsync(EditingEntityId, EditingEntity); ApplicationPopup = false; } } }
the AppService.UpdateAsync method can't save extra properties values
var entityDto = await AppService.GetAsync(entity.Id); The GetAsync method also can't get extra properties values
-
0
ok, I will check this asap.
-
0
hi
Can you create a new template project and reproduce the problem? (You can call application in unit test)
-
0
yes
using Volo.Abp.ObjectExtending; using Volo.Abp.Threading; namespace TestApp; public static class TestAppModuleExtensionConfigurator { private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); public static void Configure() { OneTimeRunner.Run(() => { ConfigureExistingProperties(); ConfigureExtraProperties(); }); } private static void ConfigureExistingProperties() { /* You can change max lengths for properties of the * entities defined in the modules used by your application. * * Example: Change user and role name max lengths IdentityUserConsts.MaxNameLength = 99; IdentityRoleConsts.MaxNameLength = 99; * Notice: It is not suggested to change property lengths * unless you really need it. Go with the standard values wherever possible. * * If you are using EF Core, you will need to run the add-migration command after your changes. */ } private static void ConfigureExtraProperties() { /* You can configure extra properties for the * entities defined in the modules used by your application. * * This class can be used to define these extra properties * with a high level, easy to use API. * * Example: Add a new property to the user entity of the identity module ObjectExtensionManager.Instance.Modules() .ConfigureIdentity(identity => { identity.ConfigureUser(user => { user.AddOrUpdateProperty<string>( //property type: string "SocialSecurityNumber", //property name property => { //validation rules property.Attributes.Add(new RequiredAttribute()); property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); //...other configurations for this property } ); }); }); * See the documentation for more: * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions */ ObjectExtensionManager.Instance.Modules() .ConfigureOpenIddict(openid => { openid.ConfigureApplication(app => { app.AddOrUpdateProperty<string>("Description"); }); }); } }
using Volo.Abp.ObjectExtending; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.Threading; namespace TestApp.EntityFrameworkCore; public static class TestAppEfCoreEntityExtensionMappings { private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); public static void Configure() { TestAppGlobalFeatureConfigurator.Configure(); TestAppModuleExtensionConfigurator.Configure(); OneTimeRunner.Run(() => { /* You can configure extra properties for the * entities defined in the modules used by your application. * * This class can be used to map these extra properties to table fields in the database. * * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. * USE TestAppModuleExtensionConfigurator CLASS (in the Domain.Shared project) * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES * * Example: Map a property to a table field: ObjectExtensionManager.Instance .MapEfCoreProperty<IdentityUser, string>( "MyProperty", (entityBuilder, propertyBuilder) => { propertyBuilder.HasMaxLength(128); } ); * See the documentation for more: * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities */ ObjectExtensionManager.Instance .MapEfCoreProperty<OpenIddictApplication, string>("Description"); }); } }
The test case code is as follows
using Shouldly; using System.Threading.Tasks; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Applications.Dtos; using Xunit; namespace TestApp.Samples; /* This is just an example test class. * Normally, you don't test code of the modules you are using * (like IIdentityUserAppService here). * Only test your own application services. */ public class SampleAppServiceTests : TestAppApplicationTestBase { private readonly IApplicationAppService _applicationAppService; public SampleAppServiceTests() { _applicationAppService = GetRequiredService<IApplicationAppService>(); } [Fact] public async Task Should_Set_Description_Of_An_Application() { await WithUnitOfWorkAsync(async () => { var app = new CreateApplicationInput() { ClientId = "test", DisplayName = "test" }; app.ExtraProperties["Description"] = "Description1"; await _applicationAppService.CreateAsync(app); }); var list = await _applicationAppService.GetListAsync(new() { MaxResultCount = 1 }); // list.Items[0].ExtraProperties["Description"].ShouldBe("Description1"); var app = await _applicationAppService.GetAsync(list.Items[0].Id); app.ExtraProperties["Description"].ShouldBe("Description1"); } }
The test failed as follows
TestApp.Samples.SampleAppServiceTests.Should_Set_Description_Of_An_Application 源: SampleAppServiceTests.cs 行 33 持续时间: 4.3 秒 消息: Shouldly.ShouldAssertException : app.ExtraProperties["Description"] should be "Description1" but was null 堆栈跟踪: SampleAppServiceTests.Should_Set_Description_Of_An_Application() 行 56 ExceptionDispatchInfo.Throw() TaskAwaiter.ThrowForNonSuccess(Task task) TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) TaskAwaiter.GetResult() --- End of stack trace from previous location --- ExceptionDispatchInfo.Throw() TaskAwaiter.ThrowForNonSuccess(Task task) TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) TaskAwaiter.GetResult() ExceptionDispatchInfo.Throw() TaskAwaiter.ThrowForNonSuccess(Task task) TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) TaskAwaiter.GetResult()
-
0
hi
This is an unknown problem, We will release a new 6.0 patch version.
https://github.com/abpframework/abp/pull/14306