Table of Contents


IRIS App Architecture Decision Guide

Overview

One of the most important decisions in IRIS App development is knowing where to put your logic. Magentrix provides two paths for data access and server-side work: the REST API V3 via the Magentrix SDK, and custom C# controllers. Choosing the right path for each requirement keeps your app maintainable, secure, and performant.

This section defines the boundary between the frontend and the backend, explains when each path is appropriate, and provides a practical decision flowchart you can apply to any requirement.


The Fundamental Boundary

IRIS Apps are front-end only. This is not a guideline — it is a hard architectural constraint.

Frontend (Vue 3 — IRIS App)Backend (C# — Controllers & Classes)
Rendering and display logicBusiness rule evaluation
User interaction and input handlingCalculations and data transformation
State management within the componentMulti-step transactions
Calling the SDK to read and write dataScheduled jobs and background processing
Formatting and presenting API responsesEmail dispatch and platform API orchestration
Navigation and routingPermission elevation and system-mode operations
⚠️ Warning: Never implement business rules, validation logic, or data calculations inside Vue components. If the server data changes, front-end logic becomes stale and inconsistent. All rules must live server-side.

Data Access: Two Paths

Path 1 — Magentrix SDK via REST API V3 (Default)

The SDK wraps the REST API V3 and is your default data access layer for every IRIS App. It handles authentication, session management, token refresh, and response parsing automatically.

Use this path for:

  • Querying records with MEQL via query()
  • Retrieving a single record via retrieve()
  • Creating, updating, or deleting records via create(), edit(), delete()
  • Batch operations — arrays passed to create(), edit(), or upsert()
  • Getting the current user's context via getUserInfo()

Path 2 — Custom C# Controller via execute() (When REST API Is Insufficient)

When the REST API cannot fulfil a requirement, you build a standalone Active Controller (.ctrl file) and call it from the IRIS App using the SDK's execute() method. The controller handles the server-side logic and returns a JSON response.

Use this path only when you need:

  • Complex multi-step business logic or conditional workflows
  • Transactions that span multiple entity operations atomically
  • Operations requiring system-mode or admin privileges (DatabaseOptions { SystemMode = true })
  • Server-side scheduling via CronJob
  • Cache invalidation via CacheManager
  • Email dispatch via platform email APIs
  • Custom data aggregation not achievable with MEQL
  • Webhook endpoints receiving data from external systems
💡 Note: Always check whether the SDK's built-in methods can satisfy the requirement before building a controller. Controllers add deployment overhead — they must be published to the server and require a hard browser refresh to take effect.

Decision Matrix

RequirementUse SDKUse Controller (/acls/)
Fetch a list of records with filtersquery() with MEQL 
Fetch a single record by IDretrieve() 
Create one or many recordscreate() 
Update one or many recordsedit() 
Delete one or many recordsdelete() / deleteMany() 
Get current user infogetUserInfo() 
Count records matching a condition✅ MEQL COUNT(Id) aggregate 
Traverse a lookup relationship✅ MEQL dot notation 
Complex validation across multiple entities ✅ Controller with business logic
Atomic transaction across multiple entities ✅ Controller with Database.BeginTransaction()
Operation requiring admin privileges ✅ Controller with SystemMode = true
Schedule a background job ✅ Controller calling CronJob.RunOnce()
Send an email ✅ Controller using platform email API
Invalidate or refresh server cache ✅ Controller calling CacheManager.RefreshUserTabs()
Aggregate data not achievable with MEQL ✅ Controller using Database.QueryFlex()
Receive an inbound webhook ✅ Standalone controller endpoint

Decision Flowchart

Can the SDK's query(), retrieve(), create(),
edit(), or delete() methods fulfil this requirement?
        │
        ├── YES ──► Use the SDK. No controller needed.
        │
        └── NO
              │
              Does it require a transaction, system-mode
              privileges, scheduling, email, or caching?
                    │
                    ├── YES ──► Build a standalone controller (.ctrl)
                    │           and call it via SDK execute().
                    │
                    └── NO
                          │
                          Can MEQL aggregates or QueryFlex
                          satisfy the data requirement?
                                │
                                ├── YES ──► Use MEQL via query()
                                │           or QueryFlex in a controller.
                                │
                                └── NO ──► Build a controller with
                                           custom C# logic.

Data Flow Diagrams

Path 1 — SDK and REST API (Standard)

IRIS App (Vue 3)
    │
    │  dataService.query('SELECT Id, Name FROM Account')
    │
    ▼
Magentrix SDK
    │
    │  POST /api/3.0/query
    │  Authorization: Bearer {token}
    │
    ▼
REST API V3
    │
    │  Applies field-level security
    │  Evaluates record permissions
    │  Enriches response with metadata
    │
    ▼
IrisDataResponse { data, __permissions, __metadatas }
    │
    ▼
IRIS App renders result

Path 2 — Custom Controller (Complex Logic)

IRIS App (Vue 3)
    │
    │  dataService.execute('/acls/order/processorder', payload)
    │
    ▼
Magentrix SDK
    │
    │  POST /acls/order/processorder
    │
    ▼
Active Controller (.ctrl)
    │
    │  Validates input
    │  Runs business logic
    │  Executes transaction across multiple entities
    │  Calls CronJob / CacheManager / Email as needed
    │
    ▼
ActionResponse (JSON)
    │
    ▼
IRIS App handles result

Common Mistakes to Avoid

Building a Controller for Standard CRUD

Creating a controller just to fetch or save records adds unnecessary complexity. The SDK handles this natively with less code, automatic security enforcement, and no deployment step.

// ❌ Avoid — controller wrapping a simple query
public ActionResponse GetAccounts()
{
    var accounts = Database.Query<Account>()
        .Where(f => f.IsActive == true)
        .ToList()
    return Json(accounts, true)
}

// ✅ Correct — use the SDK directly from the IRIS App
const result = await dataService.query(
    'SELECT Id, Name FROM Account WHERE IsActive = true'
)

Putting Business Logic in Vue Components

Calculating totals, evaluating eligibility rules, or enforcing workflow conditions inside a Vue component means those rules can be bypassed and become inconsistent when data changes server-side.

// ❌ Avoid — business logic in the frontend
function calculateDiscount(account: Account): number {
    if (account.Revenue > 1000000)
        return 0.2
    if (account.Revenue > 500000)
        return 0.1
    return 0
}

// ✅ Correct — call a controller that applies the rule server-side
const result = await dataService.execute(
    '/acls/pricing/getdiscount',
    { accountId: account.Id }
)

Using execute() for Everything

The SDK's execute() method exists for calling custom controllers — not as a replacement for the standard SDK methods. Over-relying on execute() bypasses the SDK's built-in security enforcement, metadata enrichment, and error handling.


Publishing Considerations

The choice between Path 1 and Path 2 also has a deployment impact:

 SDK / REST API ChangesController Changes
Where deployedFrontend bundle onlyServer-side .ctrl file
Deploy commandmagentrix vue-run-buildmagentrix publish
Browser refresh neededStandard refreshHard refresh (Ctrl+Shift+R) required
Takes effectImmediately on next page loadAfter server compilation and hard refresh

What to Read Next

If you want to…Go to…
Start using the SDK for data operationsMagentrix SDK Reference
Learn MEQL query syntax in depthMEQL Reference
Build a custom controllerC# Controllers
Understand the REST API endpoints directlyREST API V3 Reference
Last updated on 5/14/2026

Attachments