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()
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;
}
}
}
@using Volo.Abp.OpenIddict.Pro.Blazor.Pages
@{ 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" />
</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 {
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;
}
}
}
Invoke method ConfirmChange()
Hi.
Can you check this? : https://support.abp.io/QA/Questions/1999/Blazor-Server-App-deploy-on-IIS-Get-Authorization-Error-after-sigin
it works well. Thank you very much.
1, I create microservice temeplate with abp suite 2, Publish it with dotnet publish, and get Application below. 3, Set up docker and DbMigrator 4, Add authserver.pfx 5, Deploy it on iis 6, open blazor 7, login 8,select an item and some error exist 9, i checked log and get the code Volo.Authorization:010001
it happened when i deploy it on windows server 2019. but with the same step it worked well on my personal equipment.