IPowerPortalsProService
The IPowerPortalsProService interface provides methods for performing CRUD operations, executing queries, managing relationships, and retrieving metadata from Dataverse. It is the primary service for server-side data access in PowerPortalsPro.
Note
In most cases you do not need to call
IPowerPortalsProServicedirectly. TheRecordContext,MainContext, and grid components handle data operations automatically. Use this service for custom logic that falls outside the standard component workflow.
Server and Client Implementations
IPowerPortalsProService ships with two implementations registered automatically by the framework — your component code is identical against both, and the runtime injects whichever one matches the active render context:
- Server implementation (
PowerPortalsPro.Web.Server, registered byAddPowerPortalsProWebServer) — runs in-process, talks to Dataverse directly throughIOrganizationService, and applies yourITablePermissionHandler/ITableRecordPermissionHandlerinterceptors before any read or write. Selected when the page renders underInteractiveServerRenderModeor static SSR. - Client implementation (
PowerPortalsPro.Web.Client, registered byAddPowerPortalsProWebClient) — runs in the browser under WebAssembly, has no Dataverse SDK at all, and instead JSON-serializes each call out to the corresponding server-side HTTP endpoint (/api/table/{name},/api/retrieveMultiple, etc.). Permission handlers still apply because the request lands back on the server's endpoint. See the Client API page for the wire format and the routes the client implementation calls.
Because the contract is identical, the same component works under any interactivity mode (Server, WebAssembly, or Auto). Code that calls _powerPortalsProService.RetrieveRecordAsync(...) in a Server-rendered page does an in-process Dataverse call; the same line in a WASM-rendered page issues an HTTP request — no branching required.
Injecting the Service
Inject IPowerPortalsProService into any Blazor component or service via constructor or property injection.
// usePowerPortalsPro() returns the typed client the framework dispatches
// every CRUD call through. The `ppp` object exposes retrieve / create /
// update / delete / associate / executeMultiple / metadata / file methods
// against the configured Dataverse environment.
import { usePowerPortalsPro } from '@powerportalspro/react';
function MyComponent() {
const { ppp } = usePowerPortalsPro();
// ...
}[Inject]
private IPowerPortalsProService _powerPortalsProService { get; set; } = null!;Retrieving a Record
Use RetrieveRecordAsync to fetch a single record by table name and ID. Optionally specify which columns to return; if omitted, all columns are returned.
// Retrieve all columns
const account = await ppp.retrieveRecordAsync('account', accountId);
// Retrieve specific columns only
const account = await ppp.retrieveRecordAsync('account', accountId, [
'name', 'telephone1', 'address1_city',
]);// Retrieve all columns
var account = await _powerPortalsProService.RetrieveRecordAsync("account", accountId);
// Retrieve specific columns only
var account = await _powerPortalsProService.RetrieveRecordAsync("account", accountId,
new[] { "name", "telephone1", "address1_city" });Querying Multiple Records
Use RetrieveRecordsAsync with a FetchXML query string to retrieve multiple records with filtering, sorting, and linked entity support.
const fetchXml = `<fetch>
<entity name='contact'>
<attribute name='fullname' />
<attribute name='emailaddress1' />
<filter>
<condition attribute='parentcustomerid' operator='eq' value='...' />
</filter>
<order attribute='fullname' />
</entity>
</fetch>`;
const response = await ppp.retrieveRecordsAsync(fetchXml);
for (const record of response.tableRecords) {
// Process each record
}var fetchXml = @"<fetch>
<entity name='contact'>
<attribute name='fullname' />
<attribute name='emailaddress1' />
<filter>
<condition attribute='parentcustomerid' operator='eq' value='...' />
</filter>
<order attribute='fullname' />
</entity>
</fetch>";
var response = await _powerPortalsProService.RetrieveRecordsAsync(fetchXml);
foreach (var record in response.TableRecords)
{
// Process each record
}Creating a Record
Use CreateRecordAsync to create a new record in Dataverse. The response contains the ID of the newly created record.
// TableRecord uses a `properties` map of typed ColumnValue objects keyed
// by column name. The createTableRecord helper builds the wire shape and
// stamps a temp `_idForCreate` so cross-record references can resolve
// inside a single Create + Associate batch before the server assigns the
// real id.
import { createTableRecord } from '@powerportalspro/react';
const newContact = createTableRecord('contact', {
firstname: { type: 'string', value: 'John' },
lastname: { type: 'string', value: 'Doe' },
});
const response = await ppp.createRecordAsync(newContact);
const newRecordId = response.id;var newContact = new TableRecord { TableName = "contact" };
newContact["firstname"] = new StringValue("John");
newContact["lastname"] = new StringValue("Doe");
var response = await _powerPortalsProService.CreateRecordAsync(newContact);
var newRecordId = response.Id;Updating a Record
Use UpdateRecordAsync to update an existing record. Only the properties set on the TableRecord are sent to Dataverse.
const recordToUpdate = createTableRecord('contact', {
telephone1: { type: 'string', value: '555-1234' },
}, { id: contactId });
await ppp.updateRecordAsync(recordToUpdate);var recordToUpdate = new TableRecord
{
TableName = "contact",
Id = contactId
};
recordToUpdate["telephone1"] = new StringValue("555-1234");
await _powerPortalsProService.UpdateRecordAsync(recordToUpdate);Deleting a Record
Use DeleteRecordAsync to delete a record by table name and ID.
await ppp.deleteRecordAsync('contact', contactId);await _powerPortalsProService.DeleteRecordAsync("contact", contactId);Associating Records
Use AssociateAsync and DisassociateAsync to manage many-to-many relationships between records.
// Associate
const account = { tableName: 'account', id: accountId };
const regions = [
{ tableName: 'ppp_region', id: regionId1 },
{ tableName: 'ppp_region', id: regionId2 },
];
await ppp.associateAsync(account, 'ppp_Account_ppp_Region_ppp_Region', regions);
// Disassociate
await ppp.disassociateAsync(account, 'ppp_Account_ppp_Region_ppp_Region', regions);// Associate
var account = new TableRecordReference("account", accountId);
var regions = new List<TableRecordReference>
{
new TableRecordReference("ppp_region", regionId1),
new TableRecordReference("ppp_region", regionId2),
};
await _powerPortalsProService.AssociateAsync(account, "ppp_Account_ppp_Region_ppp_Region", regions);
// Disassociate
await _powerPortalsProService.DisassociateAsync(account, "ppp_Account_ppp_Region_ppp_Region", regions);Executing Requests
Use ExecuteAsync for a single request or ExecuteMultipleAsync to execute multiple requests in a single database transaction. If any request in a transactional batch fails, all changes are rolled back.
// Execute multiple requests in a single transaction. Each request is a tagged-union object discriminated by `type`.
const requests = [
{ type: 'create', record: contact },
{ type: 'update', record: account },
];
const responses = await ppp.executeMultipleAsync(requests, { returnResponses: true });// Execute multiple requests in a single transaction
var requests = new List<OrganizationRequest>
{
new CreateRequest(contact),
new UpdateRequest(account),
};
var responses = await _powerPortalsProService.ExecuteMultipleAsync(requests, returnResponses: true);Retrieving Metadata
Use RetrieveTableMetadataAsync and RetrieveViewMetadataAsync to retrieve table and view metadata. For cached access, prefer ITableMetadataCache and IViewMetadataCache instead.
const tableMetadata = await ppp.retrieveTableMetadataAsync('contact');
const viewMetadata = await ppp.retrieveViewMetadataAsync(viewId);var tableMetadata = await _powerPortalsProService.RetrieveTableMetadataAsync("contact");
var viewMetadata = await _powerPortalsProService.RetrieveViewMetadataAsync(viewId);Working with Files
Use GetFileInfoAsync to retrieve file or image metadata and optionally the binary content from a file or image column.
// Get file metadata only
const fileInfo = await ppp.getFileInfoAsync('contact', contactId, 'ppp_contract');
// Get file metadata and binary content
const fileWithData = await ppp.getFileInfoAsync(
'contact', contactId, 'ppp_contract', { includeData: true },
);
const bytes = fileWithData.fileData;// Get file metadata only
var fileInfo = await _powerPortalsProService.GetFileInfoAsync("contact", contactId, "ppp_contract");
// Get file metadata and binary content
var fileWithData = await _powerPortalsProService.GetFileInfoAsync("contact", contactId, "ppp_contract", includeData: true);
var bytes = fileWithData.FileData;IPowerPortalsProService Interface
Methods
Name | Parameters | Type | Description |
|---|---|---|---|
AssociateAsync | TableRecordReference record string relationshipName IEnumerable<TableRecordReference> relatedRecords EntityRole? role | Task<AssociateResponse> | Associates a record with one or more related records via a many-to-many relationship. |
ClearAllCachesAsync | Task<IReadOnlyList<CacheClearResult>> | Clears every server-side Services.IClearableCache (table / view / privilege metadata, per-user privileges, environment-file settings) and rebuilds the localized-strings cache atomically — readers continue to see the previously loaded data until the new state is fully populated. Lazy caches refill on the next request that needs them. | |
ClearCacheAsync | string name | Task<CacheClearResult> | Clears one named cache. Returns null when no registered cache matches name (case-insensitive); failures are wrapped in the result rather than thrown. Same auth gate as IPowerPortalsProService.ClearAllCachesAsync. |
CreateFileArchiveAsync | CreateFileArchiveRequest request | Task<FileArchiveResult> | Builds an archive (currently zip; future formats live behind the CreateFileArchiveRequest.Format enum) containing every record's file payload for the named table / column pair. Uses the same per-record permission chain as String,System.Boolean) — unauthorized / missing rows are silently dropped from the archive. Duplicate filenames are disambiguated by suffixing |
CreateRecordAsync | TableRecord record | Task<CreateResponse> | Creates a new record in Dataverse. |
DeleteRecordAsync | string tableLogicalName Guid id | Task<DeleteResponse> | Deletes a record from Dataverse by table name and record ID. |
DisassociateAsync | TableRecordReference record string relationshipName IEnumerable<TableRecordReference> relatedRecords EntityRole? role | Task<DisassociateResponse> | Removes an association between a record and one or more related records via a many-to-many relationship. |
DownloadLocalizationSourceAsync | string sourceId string culture | Task<LocalizationDownload> | Downloads the keys one source contributed to one culture during the most recent warmup, as JSON in the same nested-object shape consumer |
DownloadMergedLocalizationsAsync | string culture | Task<LocalizationDownload> | Downloads the merged localization keys for one culture — the post-merge winning value for every key the cache has stored, regardless of which source originally supplied it. Use this for a complete-snapshot reference (everything the portal will actually serve for that culture) rather than the per-source view above. |
ExecuteAsync | OrganizationRequest request | Task<OrganizationResponse> | Executes a single organization request against Dataverse. |
ExecuteMultipleAsync | IEnumerable<OrganizationRequest> requests bool returnResponses | Task<List<OrganizationResponse>> | Executes multiple organization requests in a single database transaction. If any request fails, all changes in the batch are rolled back. |
GetCacheNamesAsync | Task<IReadOnlyList<string>> | Returns the names of every server-side Services.IClearableCache, suitable for an admin UI that wants to render per-cache clear buttons. Same auth gate as IPowerPortalsProService.ClearAllCachesAsync applies on the HTTP endpoint. | |
GetFileInfoAsync | string tableName Guid recordId string columnName bool includeData | Task<FileInfo> | Retrieves file information and optionally the binary content from a file or image column in Dataverse. |
GetFileInfosAsync | string tableName IEnumerable<Guid> recordIds string columnName bool includeData | Task<IEnumerable<FileInfo>> | Batched retrieval of file information for many records of the same table / column in a single round trip. Internally fans the per-record fetches out in parallel and returns the combined list. The same per-record permission-handler chain runs as for the single-record call; failed lookups are dropped from the response rather than failing the whole batch. Used by FileGrid's 'Download All' / 'Download Selected' so the client can build a zip without firing N HTTP requests. |
GetLocalizationOverviewAsync | Task<LocalizationOverview> | Returns an admin-facing snapshot of the string-localization pipeline: the static configuration that drove the warmup plus the per-source load records produced by the most recent warmup. Backs the | |
GetMergedLocalizationEntriesAsync | string culture | Task<IReadOnlyList<MergedLocalizationEntry>> | Returns the merged localization keys for one culture as a structured list — every key the cache will serve, its winning post-merge value, and which source supplied that value. Same data as DownloadMergedLocalizationsAsync(System.String) but per-key annotated with its origin (file / web resource / Dataverse metadata) so an admin can inspect provenance in a grid. Entries are sorted by key. |
GetOrganizationSettingsAsync | Task<OrganizationSettings> | Retrieves the organization-wide settings sourced from the Dataverse
| |
GetTablePermissionsForCurrentUserAsync | string tableLogicalName | Task<TableSecurityPermission> | Returns the current user's combined table-level Models.TableSecurityPermission mask for tableLogicalName — the bitwise union of Read / Create / Write / Delete / Append / AppendTo flags any registered |
GetTranslationAvailabilityAsync | Task<TranslationAvailability> | Returns whether the localization-translation feature is usable in the current environment: whether the Azure translation service is configured, whether the translation managed solution is installed, and the candidate target languages (the portal's supported cultures annotated with Azure-translatability). Backs the | |
RetrieveRecordAsync | string tableLogicalName Guid id IEnumerable<string> columns | Task<TableRecord> | Retrieves a single record from Dataverse by table name and record ID. |
RetrieveRecordsAsync | string fetchXml | Task<RetrieveRecordsResponse> | Retrieves multiple records from Dataverse using a FetchXML query. Supports filtering, sorting, paging, linked entities, and aggregate queries. |
RetrieveTableMetadataAsync | string tableLogicalName | Task<TableMetadata> | Retrieves table metadata from Dataverse, including column definitions, relationships, and display configuration. |
RetrieveViewMetadataAsync | Guid viewId | Task<ViewMetadata> | Retrieves view metadata from Dataverse, including the view's FetchXML query, columns, and display configuration. |
RetrieveViewsForTableAsync | string tableLogicalName | Task<IEnumerable<ViewMetadata>> | Retrieves every view metadata record for a table. Used by grids that need to enumerate the available views (view-picker, default-view resolution, etc.). The server-side implementation reads from the in-process |
TranslateLocalizationFileAsync | TranslationRequest request | Task<TranslationResult> | Machine-translates an uploaded localization file into one or more target languages via Azure Translator, reusing the Dataverse translation memory and reporting how many strings were freshly translated versus reused. Returns one file per target language plus a zip of all. |
UpdateRecordAsync | TableRecord record | Task<UpdateResponse> | Updates an existing record in Dataverse. Only the properties set on the record are sent to Dataverse. |
AssociateAsyncstring relationshipName
IEnumerable<TableRecordReference> relatedRecords
EntityRole? role
ClearAllCachesAsyncServices.IClearableCache (table / view / privilege metadata, per-user privileges, environment-file settings) and rebuilds the localized-strings cache atomically — readers continue to see the previously loaded data until the new state is fully populated. Lazy caches refill on the next request that needs them. ClearCacheAsyncnull when no registered cache matches name (case-insensitive); failures are wrapped in the result rather than thrown. Same auth gate as IPowerPortalsProService.ClearAllCachesAsync.CreateFileArchiveAsyncCreateFileArchiveRequest.Format enum) containing every record's file payload for the named table / column pair. Uses the same per-record permission chain as String,System.Boolean) — unauthorized / missing rows are silently dropped from the archive. Duplicate filenames are disambiguated by suffixing CreateRecordAsyncDeleteRecordAsyncGuid id
DisassociateAsyncstring relationshipName
IEnumerable<TableRecordReference> relatedRecords
EntityRole? role
DownloadLocalizationSourceAsyncstring culture
DownloadMergedLocalizationsAsyncExecuteAsyncExecuteMultipleAsyncbool returnResponses
GetCacheNamesAsyncServices.IClearableCache, suitable for an admin UI that wants to render per-cache clear buttons. Same auth gate as IPowerPortalsProService.ClearAllCachesAsync applies on the HTTP endpoint.GetFileInfoAsyncGuid recordId
string columnName
bool includeData
GetFileInfosAsyncIEnumerable<Guid> recordIds
string columnName
bool includeData
GetLocalizationOverviewAsyncGetMergedLocalizationEntriesAsyncDownloadMergedLocalizationsAsync(System.String) but per-key annotated with its origin (file / web resource / Dataverse metadata) so an admin can inspect provenance in a grid. Entries are sorted by key.GetOrganizationSettingsAsync-
DefaultCurrency — the org's base currency, used by create-mode editors (MoneyEdit ) to render the right symbol on brand-new records. -
BlockedFileExtensions +MaxUploadFileSizeInBytes — file-upload constraints clients mirror to reject invalid files before the round-trip.
GetTablePermissionsForCurrentUserAsyncModels.TableSecurityPermission mask for tableLogicalName — the bitwise union of Read / Create / Write / Delete / Append / AppendTo flags any registered GetTranslationAvailabilityAsyncRetrieveRecordAsyncGuid id
IEnumerable<string> columns
RetrieveRecordsAsyncRetrieveTableMetadataAsyncRetrieveViewMetadataAsyncRetrieveViewsForTableAsyncTranslateLocalizationFileAsyncUpdateRecordAsync