Extending the Domain Model
Let's customize the model so we can update the information we need to properly track the status and location of members.
In this section, you'll learn how to:
- Extend an Existing Entity
- Create a Reference List
- Create a Migration Class
- Update front-end configurations to fit extended model
Let's dive right into the code!
Extending an Existing Entity
Navigate to the backend > Shesha.Membership.sln folder in your project directory.
Adding a Table Prefix
The concept of a table prefix on the backend is often associated with database management systems, where it involves adding a specific string or identifier to the names of database tables. This is typically done to avoid naming conflicts and to organize tables based on certain criteria.
- Navigate to
Shesha.Membership.Domain>Domain>Properties>AssemblyInfo.cs - Modify the table prefix attribute tag to be
[assembly: TablePrefix("Mem_")], instead of[assembly: TablePrefix("Membership_")]
Note: While short prefixes offer these advantages, it's also crucial to strike a balance. The prefix should be long enough to be meaningful and avoid potential conflicts, but not so long that it becomes burdensome. A well-chosen, concise prefix enhances the overall quality and maintainability of the codebase.
Create a Reference List
- Create a folder called Enums in the project called Shesha.Membership.Domain.
- Right click on the Enums folder, Add --> Class.
- Give your class the name of:
RefListMembershipStatuses.cs, and click on Add. - Add the below code:
using Shesha.Domain.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Shesha.Membership.Domain.Enums
{
/// <summary>
/// Statuses for a Members Membership
/// </summary>
[ReferenceList("Mem", "MembershipStatuses")]
public enum RefListMembershipStatuses : long
{
/// <summary>
/// Membership status is still being processed
/// </summary>
[Description("In Progress")]
InProgress = 1,
/// <summary>
/// Membership status is active
/// </summary>
[Description("Active")]
Active = 2,
/// <summary>
/// Membership status is cancelled
/// </summary>
[Description("Cancelled")]
Cancelled = 3
}
}
Create a New Entity
- Navigate to
Shesha.Membership.Domain-->Domain - Right click on the
Domainfolder, Add --> Class - Give your class the name of:
Member.cs, and click on Add- This is where we will be adding properties we want as an addition to the Person table.
This is how your class should be constructed:
using Shesha.Domain.Attributes;
using Shesha.Domain;
using System;
using Shesha.Membership.Domain.Domain.Enums;
namespace Shesha.Membership.Domain.Domain
{
/// <summary>
/// A person within the application that is a Member
/// </summary>
[Entity(TypeShortAlias = "Mem.Member")]
public class Member : Person
{
/// <summary>
/// The membership number for the Member
/// </summary>
public virtual string MembershipNumber { get; set; }
/// <summary>
/// The date when the Members membership started
/// </summary>
public virtual DateTime? MembershipStartDate { get; set; }
/// <summary>
/// The date when the Members membership ended
/// </summary>
public virtual DateTime? MembershipEndDate { get; set; }
/// <summary>
/// Identification document for the Member
/// </summary>
public virtual StoredFile IdDocument { get; set; }
/// <summary>
/// The status of the membership
/// </summary>
[ReferenceList("Mem", "MembershipStatuses")]
public virtual RefListMembershipStatuses? MembershipStatus { get; set; }
}
}
Create a Migration Class
- Navigate to
Shesha.Membership.Domain-->Migrations - Right click on the
Migrationsfolder, Add --> Class - Create a new migration class with a file name following this format: M[YEAR][MONTH][DAY][HOUR][MINUTE][SECONDS].cs e.g. M20231124085300.cs for 24 November 2023 08:53:00.
- Add the below code:
using FluentMigrator;
using Shesha.FluentMigrator;
using System;
namespace Shesha.Membership.Domain.Migrations
{
// <summary>
/// Adding the Members table
/// </summary>
[Migration(20231124085300)]
public class M20231124085300 : Migration
{
/// <summary>
/// Code to execute when executing the migrations
/// </summary>
public override void Up()
{
Alter.Table("Core_Persons")
.AddColumn("Mem_MembershipNumber").AsString().Nullable()
.AddForeignKeyColumn("Mem_IdDocumentId", "Frwk_StoredFiles").Nullable()
.AddColumn("Mem_MembershipStartDate").AsDateTime().Nullable()
.AddColumn("Mem_MembershipEndDate").AsDateTime().Nullable()
.AddColumn("Mem_MembershipStatusLkp").AsInt64().Nullable();
}
/// <summary>
/// Code to execute when rolling back the migration
/// </summary>
public override void Down()
{
throw new NotImplementedException();
}
}
}
You can check out Fluent Migrator for more options about database migrations.
- You can run your application by going to the menu and selecting
Debug-->Start Debuggingor by clickingF5 - The application should open in your browser on the default Swagger API page.
- Search and navigate to the
Memberendpoints that have been dynamically created by Shesha.

Read more about dynamic APIs here
Updating Configurations
Now that we have fully extended our domain model, it is time to go back and update our views so that we can reference our newly created fields in the Member entity.
This can be done by updating the Model Type property in all our views from Shesha.Domain.Person (Shesha.Core.Person) to Shesha.Membership.Domain.Member (Mem.Member), changing CRUD endpoints to point to the relevant model type, and adding the following fields:
- MembershipNumber -
Textfield:string - MembershipStatus -
RadioButton:RefListMembershipStatuses - MembershipStartDate -
Datefield:DateTime - MembershipEndDate -
Datefield:DateTime - IdDocument -
File:StoredFile
Create View
- Navigate to the
member-createform designer - Select
Settingsand change theEntitytoShesha.Membership.Domain.Member (Mem.Member)
With the addition of properties to our entity, to facilitate for an overall cleaner and more manageable UI, we are going to be utilizing a wizard component for properly separating the different sections of information required for the member registration.
You can find more information about implementation of the wizard component here
- Search and drag in a
wizardcomponent from theBuilder Widgets - Drag in all the existing components onto the
wizardcomponent's draggable area

Configure Wizard Stepsto rename the defaultStep 1and add an additional step to the wizard:- Biographical Information
- Membership Information

-
Update the
Membership Informationstep'sDonebutton to the following:- After Done Action:
Execute Script>
- After Done Action:
(function () {
const PATH = `/api/dynamic/Shesha.Membership/Member/Create`;
http.post(`${PATH}`, data).then(onSuccess).catch(onError);
})();
function onSuccess(resp) {
// Navigate to details view of the created member
window.location.href = `/dynamic/Shesha.Membership/member-details?id=${resp.data.result.id}`;
}
function onError(_e) {
message.error(`Failed to create member: ${_e}`, 10);
}
- While on the
Biographical Informationstep of the wizard, search and drag in theFilecomponent from theBuilder Widgets.
You can find more information about implementation of the file component here
-
Configure the
Filecomponent with the following:- Property Name :
idDocument - Label :
Id Document - Owner Id: leave empty
- Property Name :
-
While on the
Biographical Informationstep of the wizard, search and drag in theEntity Pickercomponent from theBuilder Widgets.
You can find more information about implementation of the entity picker component here
- Configure the
Entity Pickercomponent with the following:
- Property Name :
address - Label :
Address - Entity Type:
Shesha.Domain.Address (Shesha.Core.Address)
Configure Columnsof the wizard to include the following columns:
- addressLine1
- suburb
- town

One of the Entity Picker components many benefits is that it provides the flexibility to allow the addition of a new record, should the address entry not exist in any of the existing records brought back from the backend. To tap into the full functionality, we need to go create a form that will allow us to enter the details of the new address entry.
In another tab, go create a new form with the following information:
- Module:
Shesha - Template:
blank-view - Name:
address-create - Label:
Address Create - Description:
This create view is used to create a new address - Model Type:
Shesha.Domain.Address (Shesha.Core.Address)
Once on the form designer, on the Data Panel, drag and drop properties onto the Edit Area and autocomplete or change the labels accordingly:
- addressLine1
- suburb
- town

Save your form and head back to the member-create form designer
- Select the
Entity Pickercomponent -- >Allow New Record - Populate the
Dialogue Settingswith the following:
- Title:
Add Address - Modal Form:
address-create - Show Modal Buttons:
true
-
Click on the
nextbutton on theWizardcomponent to go to the next step. -
On the
Data Panel, drag and drop properties onto theEdit Areaand autocomplete or change the labels accordingly:- membershipNumber
- membershipStartDate
- membershipEndDate
- membershipStatus

-
Add additional validations on the
membershipStartDateandmembershipEndDateproperties by selecting the respectiveDateFieldcomponents and configure the following:- Disabled Date Mode:
Function Template - Disabled Date Template:
Disable Past Dates
- Disabled Date Mode:
- Save your form
Table View
- Navigate to the
members-tableform designer - Select
Settingsand change theEntitytoShesha.Membership.Domain.Member (Mem.Member)

- Select the
Datatable Contextcomponent and change theEntity TypetoShesha.Membership.Domain.Member (Mem.Member)

- Select the
Datatablecomponent >Customize Columnsto add the relevant columns

- Select the
Button Groupcomponent on thetoolbarto customize theCreate Memberbutton - Update the
Create Memberbutton configurations by seeting theButton Typeproperty toNone.
This is because we will be using the default wizard buttons that were configured on the member-create.

- Save your form
Details View
- Navigate to the
member-detailsform designer - Select
Settingsand change theEntitytoShesha.Membership.Domain.Member (Mem.Member)
With the addition of properties to our entity, to facilitate for an overall cleaner and more manageable UI, we are going to be utilizing a tab component for properly separating the different sections of the membership information.
You can find more information about implementation of the tab component here
- Search and drag in a
tabcomponent from theBuilder Widgetsonto thedetailspanel - Drag in all the existing components onto the
tabcomponent's draggable area

Configure Tab Panesto rename the defaultTab 1and add an additional tab.

- While on the
Biographical Informationtab, search and drag in theFilecomponent from theBuilder Widgets.
You can find more information about implementation of the file component here
-
Configure the
Filecomponent with the following:- Property Name :
idDocument - Label :
Id Document - Owner Id:
{data.id} - Owner Type:
Shesha.Membership.Domain.Domain.Member
- Property Name :
- Viewing the details of a foreign key on a details view can be achieved in a number of ways:
For the purposes of this tutorial, we are going to be utilizing the Entity Reference component
- While on the
Biographical Informationtab, search and drag in theEntity Referencecomponent from theBuilder Widgets.
You can find more information about implementation of the entity reference component here
-
Configure the
Entity Referencecomponent with the following:- Property Name :
address - Label :
Address - Get Entity Url :
/api/dynamic/Shesha/Address/Get - Entity Type :
Shesha.Domain.Address (Shesha.Core.Address) - Display Property :
fullAddress - Entity Reference Type:
Modal Dialog Box - Form Selection Mode:
Name - Form:
address-create - Dialog Settings:
- Title:
Address - Show Modal Buttons:
true - Submit Http Verb:
PUT - Handle Success:
Designer Form-->Refresh
- Title:
- Property Name :
This will render the address details on a dialog and allow for editing and updating the address entry on the rendered dialog
-
Click on the
Membership Informationtab on thetab panelto go to the next tab. -
On the
Data Panel, drag and drop properties onto theEdit Areaand autocomplete or change the labels accordingly:- membershipNumber
- membershipStartDate
- membershipEndDate
- membershipStatus
To further personalize the membership details view, let's make some changes to our header section.
- Select the
textcomponent used for the title and change thecontentproperty to{{fullName}} - {{membershipNumber}}

- Search and drag in the
Reference List Statuscomponent from theBuilder Widgetsnext to thetexttitle component
You can find more information about implementation of the reference list status component here

-
Configure the
Reference List Statuscomponent with the following:- Property Name :
membershipStatus - Reference List:
MembershipStatuses
- Property Name :
-
Save your form
Let's test out our new changes!
- Using the main menu, navigate to the
members-tableand refresh your page to make sure your changes have taken effect. - Register a new member!
