Power Pages è la soluzione di Microsoft Power Platform per costruire siti web esterni (rivolti a clienti, partner o cittadini) che leggono e scrivono dati direttamente in Microsoft Dataverse. Il motore di rendering delle pagine è Liquid, un linguaggio di template open source (nato in Ruby) eseguito server-side: consente di interrogare Dataverse e di iniettare dati e logica di presentazione nell’HTML prima che la pagina raggiunga il browser.
Liquid: cos’è e dove vive
Liquid usa tre costrutti principali:
- Output
{{ ... }}per stampare valori (es.{{ user.fullname }}). - Tag
{% ... %}per la logica (cicli, condizioni, query). - Filtri
{{ value | filter }}per trasformare l’output (es.| date: 'dd/MM/yyyy').
Liquid si scrive dentro i web template (componenti riutilizzabili di markup), nei content snippet, oppure nel campo Copy delle web page. I web template si compongono tramite ereditarietà: un template figlio dichiara {% extends 'Layout' %} e riempie i block definiti dal genitore. Questo pattern è centrale per costruire layout coerenti e header/footer condivisi.
Oggetti di contesto
Liquid espone oggetti globali che riflettono lo stato della sessione e del sito: user (il contatto autenticato o vuoto se anonimo), page, website, request, settings, sitemarkers e snippets. Sono la via idiomatica per personalizzare i contenuti in base a chi sta navigando.
Interrogare Dataverse con i Liquid tag
Per portare dati Dataverse in pagina esistono tag dedicati:
entitylist/entityview: caricano una list configurata nell’app di gestione (colonne, viste, filtri, paging) e permettono di renderizzarla con markup custom invece del componente low-code standard.entityform/webform: incorporano un basic form o un multistep form progettato nel design studio.fetchxml: esegue una query FetchXML arbitraria per scenari non coperti dalle viste predefinite. Esempio:
{% fetchxml myquery %}
<fetch top="5">
<entity name="contact">
<attribute name="fullname" />
</entity>
</fetch>
{% endfetchxml %}
{% for c in myquery.results.entities %}
{{ c.fullname }}
{% endfor %}
Esiste anche l’oggetto entities['nome_tabella'][guid] per leggere un singolo record per ID.
Componenti low-code vs Liquid custom
La scelta architetturale ricorrente all’esame è: usare List e Form low-code oppure scrivere Liquid?
- List e Basic/Multistep Form (low-code): si configurano nel design studio, offrono search, paging, sort, azioni CRUD, validazioni e integrazione automatica con le table permission. Vanno preferiti quando lo scenario è coperto out-of-the-box: massimizzano manutenibilità e riducono codice.
- Liquid custom (entitylist/fetchxml): da scegliere quando servono layout, aggregazioni o markup non ottenibili dai componenti standard — ad esempio una vista a card, un raggruppamento particolare o dati combinati da più tabelle. Il costo è maggiore complessità e responsabilità sul rendering.
Regola pratica: low-code prima, Liquid quando il low-code non basta.
Il ruolo delle table permission
Punto cruciale e sempre presente: Liquid non aggira la sicurezza. Ogni query (entitylist, fetchxml, entities[...]) rispetta le table permission configurate e i web role assegnati al contatto. Se un utente non ha permessi di lettura su una tabella, la query Liquid non restituirà quei record, indipendentemente da come è scritto il template. Per esporre dati occorre creare la table permission corretta (scope: Global, Contact, Account, Self) e collegarla al web role appropriato.
Inoltre le table permission richiedono le column permission per governare l’accesso a singoli campi.
Liquid è server-side, non JavaScript
Liquid viene valutato una sola volta, sul server, al momento della generazione della pagina. Non reagisce a eventi del browser, non aggiorna il DOM e non gestisce interattività client (validazioni dinamiche, chiamate on-click, aggiornamenti live). Per quella logica servono JavaScript lato client e le Web API di Power Pages (chiamate REST verso Dataverse). Liquid e JavaScript sono complementari, non alternativi.
Trappole tipiche d’esame
- Scenario: una pagina Liquid con
fetchxmlnon mostra alcuni record ai clienti. → Risposta giusta: mancano/insufficienti le table permission per il web role; Liquid rispetta sempre la sicurezza, non la aggira. - Scenario: serve validazione dinamica di un campo mentre l’utente digita. → Risposta giusta: usare JavaScript + Web API, non Liquid (che è server-side e non reattivo).
- Scenario: elenco di record con paging, ricerca e azioni CRUD standard. → Risposta giusta: usare un List (basic form/multistep) low-code, non Liquid custom.
- Scenario: layout a card personalizzato con dati aggregati da più tabelle. → Risposta giusta: entitylist/fetchxml in un web template, quando i componenti low-code non coprono il requisito.
- Scenario: personalizzare il contenuto in base all’utente autenticato. → Risposta giusta: usare l’oggetto
usere le condizioni Liquid{% if user %}, ricordando che per gli anonimiuserè vuoto.