Open Closed

How to Add extended property of tenant and view it in another tab in create tenant Modal #7925


User avatar
0
nabass created

How to get extended property from tenant

Check the docs before asking a question: https://abp.io/docs/latest Check the samples to see the basic tasks: https://abp.io/docs/latest/samples The exact solution to your question may have been answered before, and please first use the search on the homepage. Provide us with the following info: 🧐 Hint: If you are using the ABP Studio, you can see all the information about your solution from the configuration window, which opens when you right-click on the solution and click on the Solution Configuration button.

  • ABP Framework version: vX.X.X
  • UI Type: Angular / MVC / Blazor WASM / Blazor Server
  • Database System: EF Core (SQL Server, Oracle, MySQL, PostgreSQL, etc..) / MongoDB
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes/no
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

11 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi see https://abp.io/docs/latest/framework/architecture/modularity/extending/module-entity-extensions

    view it in another tab in create tenant Modal

    you need to override the CreateModalModel

    move these code to a new tab

    you can download saas module to get CreateModalModel page code

    Here is the document about how to override page. https://abp.io/docs/latest/framework/ui/mvc-razor-pages/customization-user-interface

  • User Avatar
    0
    nabass created

    hi i followed the document but nothing changes 1- source code of tenant page doesn't have tabs despite the view has 2 tabs ( Basic info && Database Connection String)

    2- section (Completely Overriding a Razor Page) into document i found there is no need to inherit just use AbpPageModel if i create all logic in cs file here is my final code:=>

    public class MyCreateModalModel : AbpPageModel
    {
        protected ITenantAppService TenantAppService { get; }
        public MyCreateModalModel(ITenantAppService tenantAppService) //: base(tenantAppService)
        {
            TenantAppService = tenantAppService;
        }
    
        [BindProperty]
        public TenantInfoModel Tenant { get; set; }
    
        public virtual Task<IActionResult> OnGetAsync()
        {
            Tenant = new TenantInfoModel();
            return Task.FromResult<IActionResult>(Page());
        }
    
        public virtual async Task<IActionResult> OnPostAsync()
        {
            ValidateModel();
    
            var input = ObjectMapper.Map<TenantInfoModel, TenantCreateDto>(Tenant);
            await TenantAppService.CreateAsync(input);
    
            return NoContent();
        }
    
        public class TenantInfoModel : ExtensibleObject
        {
            [Required]
            [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
            [Display(Name = "DisplayName:TenantName")]
            public string Name { get; set; }
    
            [Required]
            [EmailAddress]
            [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxAdminEmailAddressLength))]
            public string AdminEmailAddress { get; set; }
    
            [Required]
            [DataType(DataType.Password)]
            [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxPasswordLength))]
            public string AdminPassword { get; set; }
        }
    }
    

    and this is my html code: =>

    @using Microsoft.Extensions.Localization
    @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
    @using Volo.Abp.Localization
    @using Volo.Abp.ObjectExtending
    @using Volo.Abp.TenantManagement.Localization
    @model Horizon.HorizonERP.Web.Pages.TenantManagement.Tenants.MyCreateModalModel
    @using Volo.Abp.Data
    @using Volo.Abp.TenantManagement;
    @inject IHtmlLocalizer<AbpTenantManagementResource> L
    @inject IStringLocalizerFactory StringLocalizerFactory
    @{
        Layout = null;
    }
    <form method="post" asp-page="/TenantManagement/Tenants/MyCreateModal">
        <abp-modal>
            <abp-modal-header title="@L["NewTenant"].Value"></abp-modal-header>
            <abp-modal-body>
                <abp-tabs>
                    <abp-tab title="Main Info">
                        <abp-input asp-for="Tenant.Name" />
                        <abp-input asp-for="Tenant.AdminEmailAddress" />
                        <div class="mb-3">
                            <label class="form-label">@L["DisplayName:AdminPassword"].Value</label>
                            <span> * </span>
                            <div class="input-group">
                                <input type="password" class="form-control" maxlength="@TenantConsts.MaxPasswordLength" asp-for="Tenant.AdminPassword" />
                                <button class="btn btn-secondary" type="button" id="PasswordVisibilityButton">
                                    <i class="fa fa-eye-slash" aria-hidden="true"></i>
                                </button>
                            </div>
                            <span asp-validation-for="Tenant.AdminPassword"></span>
                        </div>
                    </abp-tab>
                    <abp-tab title="Extra">
                        @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<MyCreateModalModel.TenantInfoModel>())
                        {
                            if (!propertyInfo.Name.EndsWith("_Text"))
                            {
                                if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
                                {
                                    if (propertyInfo.Type.IsEnum)
                                    {
                                        Model.Tenant.ExtraProperties.ToEnum(propertyInfo.Name, propertyInfo.Type);
                                    }
                                    <abp-select asp-for="Tenant.ExtraProperties[propertyInfo.Name]"
                                                label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
                                                autocomplete-api-url="@propertyInfo.Lookup.Url"
                                                autocomplete-selected-item-name="@Model.Tenant.GetProperty(propertyInfo.Name+"_Text")"
                                                autocomplete-selected-item-value="@Model.Tenant.GetProperty(propertyInfo.Name)"
                                                autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
                                                autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
                                                autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
                                                autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
                                }
                                else
                                {
                                    <abp-input type="@propertyInfo.GetInputType()"
                                               asp-for="Tenant.ExtraProperties[propertyInfo.Name]"
                                               label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
                                               asp-format="@propertyInfo.GetInputFormatOrNull()"
                                               value="@propertyInfo.GetInputValueOrNull(Model.Tenant.GetProperty(propertyInfo.Name))" />
                                }
                            }
                        }
                    </abp-tab>
                </abp-tabs>
            </abp-modal-body>
            <abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
        </abp-modal>
    </form>
    
    

    but final result is the same nothing changed so did i miss logic or registration or code line i must put anything ??

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    it works for me

    @page
    @using Microsoft.Extensions.Localization
    @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
    @using Volo.Abp.Data
    @using Volo.Abp.Localization
    @using Volo.Abp.ObjectExtending
    @using Volo.Saas
    @using Volo.Saas.Host.Pages.Saas.Host.Tenants
    @using Volo.Saas.Localization
    @model CreateModalModel
    @inject IStringLocalizer<SaasResource> L
    @inject IStringLocalizerFactory StringLocalizerFactory
    @{
    Layout = null;
    }
    <form method="post" asp-page="/Saas/Host/Tenants/CreateModal">
        <abp-modal>
            <abp-modal-header title="@L["NewTenant"].Value"></abp-modal-header>
            <abp-modal-body>
                <abp-tabs>
                    <abp-tab title="Main Info">
                        <abp-input asp-for="Tenant.Name" />
                        <abp-input asp-for="Tenant.AdminEmailAddress" />
                        <div class="mb-3">
                            <label class="form-label">@L["DisplayName:AdminPassword"].Value</label>
                            <span> * </span>
                            <div class="input-group">
                                <input type="password" class="form-control" maxlength="@TenantConsts.MaxPasswordLength" asp-for="Tenant.AdminPassword" />
                                <button class="btn btn-secondary" type="button" id="PasswordVisibilityButton">
                                    <i class="fa fa-eye-slash" aria-hidden="true"></i>
                                </button>
                            </div>
                            <span asp-validation-for="Tenant.AdminPassword"></span>
                        </div>
                    </abp-tab>
                    <abp-tab title="Extra">
                        @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<CreateModalModel.TenantInfoModel>())
                        {
                        if (!propertyInfo.Name.EndsWith("_Text"))
                        {
                        if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
                        {
                        if (propertyInfo.Type.IsEnum)
                        {
                        Model.Tenant.ExtraProperties.ToEnum(propertyInfo.Name, propertyInfo.Type);
                        }
                        <abp-select asp-for="Tenant.ExtraProperties[propertyInfo.Name]"
                                    label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
                                    autocomplete-api-url="@propertyInfo.Lookup.Url"
                                    autocomplete-selected-item-name="@Model.Tenant.GetProperty(propertyInfo.Name+"_Text")"
                                    autocomplete-selected-item-value="@Model.Tenant.GetProperty(propertyInfo.Name)"
                                    autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
                                    autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
                                    autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
                                    autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
                        }
                        else
                        {
                        <abp-input type="@propertyInfo.GetInputType()"
                                   asp-for="Tenant.ExtraProperties[propertyInfo.Name]"
                                   label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
                                   asp-format="@propertyInfo.GetInputFormatOrNull()"
                                   value="@propertyInfo.GetInputValueOrNull(Model.Tenant.GetProperty(propertyInfo.Name))" />
                        }
                        }
                        }
                    </abp-tab>
                </abp-tabs>
            </abp-modal-body>
            <abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
        </abp-modal>
    </form>
    
    

  • User Avatar
    0
    nabass created

    hi i moved page into same path as you

    and final result is

    steps what i did is: 1- get the application contract tenant source to use it's Dto within cs file

    2- copy html code that you used 3- change namespace of cs file to (namespace Horizon.HorizonERP.Web.Pages.Sass.Host.Tenants)

    so what i miss ?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    You should use the same cshtml file name

  • User Avatar
    0
    nabass created

    wow it works thank you lian :)

  • User Avatar
    0
    nabass created

    sorry i noticed that where is Database Connection strings tab ??

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    HI,

    i just copy the code you provided

    https://abp.io/support/questions/7925/How-to-Add-extended-property-of-tenant-and-view-it-in-another-tab-in-create-tenant-Modal#answer-3a15170e-c56b-d5fd-eed1-ed4cefe85aed

  • User Avatar
    0
    nabass created

    Please Still Has the same Issue that The Database Connection String Tab not exist on the custom tenant screen, although i already have licenses but i cant get the source of this Page "/Saas/Host/Tenants/CreateModal" from github Please could you provide me the original source code of this Page.

    appreciate your Quick response.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    sure, please email me. i will share it with you.

    shiwei.liang@volosoft.com

    BTW, you can download it via ABP CLI abp get-source Volo.Saas

  • User Avatar
    0
    nabass created

    thanks for efforts it works well thank you again

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.3.0-preview. Updated on May 12, 2025, 05:22