Add a new set of API endpoints

Follow this process to generate contract, service, and controller classes for a new set of API endpoints that bind to data in a specific database table

Before you start

Define the entity

Before you start, navigate to ui/admin/metadata/entities/search in your local environment and search for the entity definition.

If no entity is defined for the database table then you need to define a new entity by inserting a new row in metadata.TEntity.

When you find the entity definition, make special note of the Component, Subcomponent, and Entity Name.

Prepare the code generator

Download the code generator - https://github.com/daniel-miller/code-generator

Open appsettings.json and update the configuration settings for your local environment. Optionally, you can create an appsettings.local.json, which is not added to source control. Your settings should look something like this:

{
  "Generator": {
    "PlatformName": "Shift",
    "TemplateFolder": "./Template",
    "OutputFolder": "../../dist/output",
    "DatabaseType": "SqlServer",
    "DatabaseConnection": "Data Source=(local); Initial Catalog=E01_Local_Shift; Integrated Security=True; Encrypt=false;"
  }
}

Make special note of the output folder. This is the directory in your local file system where the generator will create source code files.

Generate the new classes

Run the code generator. On a large database (like Shift), execution time may be a minute or two.

Open your file explorer and navigate to the output folder. You should see 3 subfolders:

  • Api: Controller classes for the API

  • Contract: Query and command classes, request and response classes, DTO classes

  • Service: Classes to read and write database entities, and adapters for entity/model conversion

Integrate the new classes

Contract code

Contract code targets .NET Standard 2.0. This maximizes its reusability, allowing it to be referenced from .NET Framework libraries and/or .NET Core libraries.

Start with Contract classes. In the output folder, open the Contract subfolder and find the component, subcomponent, and entity that you want to integrate into your project.

Copy from the output folder to the SDK project.

For example. copy File, FileActivity, and FileClaim folders

  • from Output/Contract/Content/Files

  • to code/src/library/Shift.Sdk/Contract/Content/Files

Build the solution to ensure no compiler errors.

Service code

Service code targets .NET 9.

In the output folder, open the Service subfolder. Find the component, subcomponent, and entity.

Copy from the output folder to the Service project.

For example, copy the Data folder

  • from Output/Service/Content/Files

  • to code/src/library/Shift.Service/Conent/Files

In the output folder, navigate to the Service/Orchecestration subfolder and open the TableDbContext class.

Find the entity type configuration code and copy this to TableDbContext in the Shift.Service library.

For example:

builder.ApplyConfiguration(new TFileActivityConfiguration()); 
builder.ApplyConfiguration(new TFileClaimConfiguration()); 
builder.ApplyConfiguration(new TFileConfiguration());

Find the entity property code and copy this to TableDbContext in the Shift.Service library.

For example:

internal DbSet TFileActivity { get; set; } 
internal DbSet TFileClaim { get; set; } 
internal DbSet TFile { get; set; }

Build the solution to ensure no compiler errors.

API code

API code targets .NET 9.

In the output folder, open the Api subfolder. Find the component, subcomponent, and entity.

Copy from the output folder to the Api project.

For example, copy the Data folder

  • from Output/Api/Content/Files

  • to code/src/library/Shift.Api/Conent/Files

Build the solution to ensure no compiler errors.

Optional steps

There are a few additional optional steps you should consider. These are not required, but they are recommended.

Implement default functionality for Reader:BuildQueryable

The generated code provides some guidance and advice, but the details are for you to decide. Typical improvements might include:

For example:

Remove organization identifier properties from models

Every API request is authenticated with an access key that identifies the user and the organization submitting the request. Therefore, the organization identifier is not needed in an API response, because it is redundant to the client.

Rename Identifier suffixes to Id in model property names

For example, rename FileModel.FileIdentifier to FileModel.FileId

Add navigation properties

For example, there is a one-to-many relation from TFileEntity to TFileActivity, and a one-to-many relation from TFileEntity to TFileClaim, therefore add collection properties to TFileEntity:

public ICollection<TFileActivityEntity> Activities { get; set; } = new List<TFileActivityEntity>();
public ICollection<TFileClaimEntity> Claims { get; set; } = new List<TFileClaimEntity>();

Add a corresponding property to TFileActivityEntity and TFileClaimEntity:

public TFileEntity File { get; set; } = null!;

Configure the entity relations:

builder.Entity<TFileEntity>()
    .HasMany(e => e.Activities)
    .WithOne(e => e.File)
    .HasForeignKey(e => e.FileIdentifier)
    .HasPrincipalKey(e => e.FileIdentifier);

builder.Entity<TFileEntity>()
    .HasMany(e => e.Claims)
    .WithOne(e => e.File)
    .HasForeignKey(e => e.FileIdentifier)
    .HasPrincipalKey(e => e.FileIdentifier);

Test the API

Start the Shift API and navigate to https://localhost:5000

Confirm the Swagger UI shows the new endpoints.

Open the Shift collection in Insomnia, and add requests to test and confirm the new endpoints are working.

For example:

Last updated

Was this helpful?