I have been following the guide on how to customize the app modules with the intention of extending module entities with new properties and exposing these with a modified service/controller .
I have extended OrganizationUnit from a module with the following properties: and then mapped these new properties to the same database table as OrganizationUnit by updating DbContext.OnModelCreating and EfCoreEntityExtensionMappings and and Dto Extensions and created a database-migration
And here is user interface for inserting new organization unit and its work fine
Summary To summarize, I wish to achieve the following:
How do I add new method from applications services and controllers in a way that enables me to get list of UnitCategory as dropdown list? I have implemented the following based on the solution #438 :
public interface IAppOrganizationUnitAppService : IOrganizationUnitAppService
{
Task<PagedResultDto<LookupDto>> GetUnitCategoryLookupAsync(LookupRequestDto input);
}
[RemoteService(IsEnabled = false)] // If you use dynamic controller feature you can disable remote service. Prevent creating duplicate controller for the application service.
[Dependency(ReplaceServices = true)]
[ExposeServices( typeof(OrganizationUnitAppService),typeof(IAppOrganizationUnitAppService))]
public class AppOrganizationUnitAppService : OrganizationUnitAppService, IAppOrganizationUnitAppService
{
private readonly IMODRepository<OrganizationUnitCategory, Guid> _unitCategoryRepository;
public AppOrganizationUnitAppService(
OrganizationUnitManager organizationUnitManager,
IdentityUserManager userManager,
IOrganizationUnitRepository organizationUnitRepository,
IIdentityUserRepository identityUserRepository,
IIdentityRoleRepository identityRoleRepository,
IMODRepository<OrganizationUnitCategory, Guid> unitCategoryRepository)
:base(organizationUnitManager,userManager, organizationUnitRepository, identityUserRepository, identityRoleRepository)
{
_unitCategoryRepository = unitCategoryRepository;
}
public async Task<PagedResultDto<LookupDto>> GetUnitCategoryLookupAsync(LookupRequestDto input)
{
var query = _unitCategoryRepository.AsQueryable()
.WhereIf(!string.IsNullOrWhiteSpace(input.Filter), x => x.ArabicName != null && x.ArabicName.Contains(input.Filter));
var lookupData = await query.PageBy(input.SkipCount, input.MaxResultCount).ToDynamicListAsync<OrganizationUnitCategory>();
var totalCount = query.Count();
return new PagedResultDto<LookupDto>
{
TotalCount = totalCount,
Items = ObjectMapper.Map<List<OrganizationUnitCategory>, List<LookupDto>>(lookupData)
};
}
}
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(OrganizationUnitController), typeof(IAppOrganizationUnitAppService))]
[RemoteService(true, Name = "AbpIdentity")]
[Route("api/identity/organization-units", Order = 0)]
[ControllerName("OrganizationUnit")]
[Area("identity")]
public class AppOrganizationUnitController : OrganizationUnitController, IAppOrganizationUnitAppService
{
public AppOrganizationUnitController(IOrganizationUnitAppService organizationUnitAppService)
: base(organizationUnitAppService)
{
}
[HttpGet]
[Route("Unit-Category-lookup")]
public Task<PagedResultDto<LookupDto>> GetUnitCategoryLookupAsync(LookupRequestDto input)
{
return ((IAppOrganizationUnitAppService)OrganizationUnitAppService).GetUnitCategoryLookupAsync(input);
}
}
However when I attempt to start the HttpApi.Host project I now get the following exception:
- ABP Framework version: v3.2.0
- UI type: Angular
- Tiered (MVC) or Identity Server Seperated (Angular): Identity Server Seperated (Angular)
- Exception message and stack trace:
- Steps to reproduce the issue:
7 Answer(s)
-
0
hi
In the current version, there's automatic way of making a combobox for navigation property. But it's in our roadmap.
AppOrganizationUnitController has not been registered
this exception is weird! becauseAppOrganizationUnitController
is derived fromOrganizationUnitController
which is derived fromAbpController
. so it must be already registered to the DI system.public class OrganizationUnitController : AbpController, IOrganizationUnitAppService, IApplicationService, IRemoteService
did you create the controller in
*.HttpApi
-
0
Yes I created the controller in
*.HttpApi
-
0
I guess you don't need to put
GetUnitCategoryLookupAsync
intoAppOrganizationUnitController
. You can create a new controller. Can you try it. -
0
Hi, I have created this controller only to inlcude
GetUnitCategoryLookupAsync
and I need it to be appear under the same path in swagger. If I put it under a new controller, it will create it under a new path ,and I guess combobox won't appear in UI !!I am really stuck with this issue. I would be appreciative if you could help me with it.
-
0
there won't be a combobox even if you implement this. As I mentioned, this feature will come in the next releases. (4.1) what you can do is; you can replace the New Organisation razor page.
This document explains how to customize UI => https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface
If you create your own view in the
Pages/Identity/OrganizationUnits
directory (as embedded resource) it'll overwrite the existing pageCreate
CreateModal.cshtml
file in your web project underPages/Identity/OrganizationUnits/CreateModal.cshtml
Add the below code to your
CreateModal.cshtml
and make your customizationsCreateModal.cshtml
@page @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @using Volo.Abp.Identity.Localization @using Volo.Abp.Identity.Web.Pages.Identity.OrganizationUnits @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending @model CreateModalModel @inject IHtmlLocalizer<IdentityResource> L @inject IStringLocalizerFactory StringLocalizerFactory @{ Layout = null; } <form asp-page="/Identity/OrganizationUnits/CreateModal" autocomplete="off"> <abp-modal> <abp-modal-header title="@L["NewOrganizationUnit"].Value"></abp-modal-header> <abp-modal-body> <abp-input asp-for="OrganizationUnit.ParentId"/> <abp-input asp-for="OrganizationUnit.DisplayName"/> @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<CreateModalModel.OrganizationUnitInfoModel>()) { if (propertyInfo.Type.IsEnum) { <abp-select asp-for="OrganizationUnit.ExtraProperties[propertyInfo.Name]" label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> </abp-select> } else { <abp-input type="@propertyInfo.GetInputType()" asp-for="OrganizationUnit.ExtraProperties[propertyInfo.Name]" label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)" asp-format="@propertyInfo.GetInputFormatOrNull()" value="@propertyInfo.GetInputValueOrNull(Model.OrganizationUnit.ExtraProperties[propertyInfo.Name])"/> } } </abp-modal-body> <abp-modal-footer buttons="@(AbpModalButtons.Cancel | AbpModalButtons.Save)"></abp-modal-footer> </abp-modal> </form>
CreateModal.cshtml.cs
public class CreateModalModel : IdentityPageModel { [BindProperty] public OrganizationUnitInfoModel OrganizationUnit { get; set; } protected IOrganizationUnitAppService OrganizationUnitAppService { get; } public CreateModalModel(IOrganizationUnitAppService organizationUnitAppService) { OrganizationUnitAppService = organizationUnitAppService; OrganizationUnit = new OrganizationUnitInfoModel(); } public virtual Task OnGetAsync(Guid? parentId) { OrganizationUnit.ParentId = parentId; return Task.CompletedTask; } public virtual async Task<IActionResult> OnPostAsync() { ValidateModel(); var input = ObjectMapper.Map<OrganizationUnitInfoModel, OrganizationUnitCreateDto>(OrganizationUnit); await OrganizationUnitAppService.CreateAsync(input); return NoContent(); } public class OrganizationUnitInfoModel : ExtensibleObject { [HiddenInput] public Guid? ParentId { get; set; } [Required] public string DisplayName { get; set; } } }
-
0
Hi,
Unfortunately, We are not using Razor UI for our project. We are using angular. I dont think it will be an easy task to replace organization unit component using the Replaceable Component Api. Is it?
-
0
If you are using Angular then check out https://docs.abp.io/en/commercial/latest/ui/angular/dynamic-form-extensions