### Create Dataverse Entity Record using IOrganizationService Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Creates a new 'account' entity record in Dataverse using the standard IOrganizationService interface. Requires an initialized ServiceClient. Input is a ServiceClient and an Entity object, output is the Guid of the created record or an exception. Handles basic entity attribute types. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk; using System; // Method 1: Using IOrganizationService interface public Guid CreateAccountStandard(ServiceClient serviceClient) { var account = new Entity("account"); account["name"] = "Contoso Corporation"; account["accountnumber"] = "ACC-12345"; account["telephone1"] = "555-1234"; account["revenue"] = new Money(1000000.00m); account["primarycontactid"] = new EntityReference("contact", Guid.Parse("12345678-1234-1234-1234-123456789012")); account["donotbulkemail"] = true; account["createdon"] = DateTime.UtcNow; try { Guid accountId = serviceClient.Create(account); Console.WriteLine($"Created account with ID: {accountId}"); return accountId; } catch (Exception ex) { Console.WriteLine($"Create failed: {ex.Message}"); throw; } } ``` -------------------------------- ### Assign Entities and Send Emails in Dataverse using C# Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Provides C# code examples for assigning Dataverse entities to users and sending emails. It utilizes extension methods for assignment and email sending, as well as the standard SendEmailRequest. Dependencies include Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Crm.Sdk.Messages. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using System; public void AssignAndSendEmail(ServiceClient serviceClient) { Guid accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); Guid userId = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"); Guid emailId = Guid.Parse("FFFFFFFF-EEEE-DDDD-CCCC-BBBBBBBBBBBB"); // Assign entity to user bool assignSuccess = serviceClient.AssignEntityToUser( userId: userId, entityName: "account", entityId: accountId ); Console.WriteLine($"Assignment {(assignSuccess ? "successful" : "failed")}"); // Send email using extension method bool emailSent = serviceClient.SendSingleEmail( emailid: emailId, token: "batch-token" ); Console.WriteLine($"Email send {(emailSent ? "successful" : "failed")}"); // Send email using standard request var sendEmailRequest = new SendEmailRequest { EmailId = emailId, IssueSend = true, TrackingToken = "" }; var sendEmailResponse = (SendEmailResponse)serviceClient.Execute(sendEmailRequest); Console.WriteLine("Email sent via standard request"); } ``` -------------------------------- ### Create Dataverse Entity Record using Extension Method Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Creates a new 'account' entity record using a simplified extension method with automatic type handling. Requires an initialized ServiceClient. Input is a ServiceClient, entity name, and a dictionary of fields, output is the Guid of the created record or an exception. Allows specifying solution, duplicate detection, and plugin bypass. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using System; using System.Collections.Generic; // Method 2: Using simplified extension method public Guid CreateAccountExtension(ServiceClient serviceClient) { var fields = new Dictionary { { "name", new DataverseDataTypeWrapper("Contoso Corporation", DataverseFieldType.String) }, { "accountnumber", new DataverseDataTypeWrapper("ACC-12345", DataverseFieldType.String) }, { "telephone1", new DataverseDataTypeWrapper("555-1234", DataverseFieldType.String) }, { "revenue", new DataverseDataTypeWrapper(1000000.00m, DataverseFieldType.Money) }, { "primarycontactid", new DataverseDataTypeWrapper( Guid.Parse("12345678-1234-1234-1234-123456789012"), DataverseFieldType.Lookup, "contact") }, { "donotbulkemail", new DataverseDataTypeWrapper(true, DataverseFieldType.CrmBoolean) } }; try { Guid accountId = serviceClient.CreateNewRecord( entityName: "account", valueArray: fields, applyToSolution: "MySolution", // Optional: add to solution enabledDuplicateDetection: true, // Optional: enable dup detection bypassPluginExecution: false // Optional: skip plugins (requires privilege) ); Console.WriteLine($"Created account with ID: {accountId}"); return accountId; } catch (Exception ex) { Console.WriteLine($"Create failed: {ex.Message}"); throw; } } ``` -------------------------------- ### Direct HTTP Operations with Dataverse ServiceClient Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates how to perform standard HTTP operations (GET, POST, PATCH, DELETE) against Dataverse entities using the ServiceClient. This includes retrieving, creating, updating, and deleting records, along with setting custom headers and content types. ```APIDOC ## GET /api/data/v9.x/accounts/{accountId} ### Description Retrieves a specific account record from Dataverse. ### Method GET ### Endpoint `/api/data/v9.x/accounts/{accountId}` ### Parameters #### Path Parameters - **accountId** (Guid) - Required - The unique identifier of the account to retrieve. #### Query Parameters - **$select** (string) - Optional - Comma-separated list of properties to retrieve. ### Request Example ```csharp var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); string getQuery = $"accounts({accountId})?$select=name,telephone1,revenue"; var getResponse = serviceClient.ExecuteWebRequest(method: HttpMethod.Get, queryString: getQuery, body: null); ``` ### Response #### Success Response (200) - **content** (string) - The JSON representation of the account data. #### Response Example ```json { "@odata.etag": "...", "name": "Example Account", "telephone1": "555-1234", "revenue": 1000000.00 } ``` ## POST /api/data/v9.x/accounts ### Description Creates a new account record in Dataverse. ### Method POST ### Endpoint `/api/data/v9.x/accounts` ### Parameters #### Request Body - **name** (string) - Required - The name of the account. - **telephone1** (string) - Optional - The primary phone number. - **revenue** (double) - Optional - The annual revenue. - **accountnumber** (string) - Optional - The account number. ### Request Example ```csharp var accountData = new { name = "HTTP API Account", telephone1 = "555-1234", revenue = 1000000.00, accountnumber = "HTTP-001" }; string jsonBody = JsonSerializer.Serialize(accountData); var postResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: "accounts", body: jsonBody, customHeaders: new Dictionary> { { "Prefer", new List { "return=representation" } }, { "MSCRM.SuppressDuplicateDetection", new List { "false" } } }, contentType: "application/json" ); ``` ### Response #### Success Response (201 Created) - **Location** (string) - The URL of the newly created account. #### Response Example ```json { "@odata.context": "...", "accountid": "..." } ``` ## PATCH /api/data/v9.x/accounts/{accountId} ### Description Updates an existing account record in Dataverse. ### Method PATCH ### Endpoint `/api/data/v9.x/accounts/{accountId}` ### Parameters #### Path Parameters - **accountId** (Guid) - Required - The unique identifier of the account to update. #### Request Body - **telephone1** (string) - Optional - The primary phone number to update. - **websiteurl** (string) - Optional - The website URL to update. ### Request Example ```csharp var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); var updateData = new { telephone1 = "555-9999", websiteurl = "https://www.contoso.com" }; string updateJson = JsonSerializer.Serialize(updateData); var patchResponse = serviceClient.ExecuteWebRequest( method: new HttpMethod("PATCH"), queryString: $"accounts({accountId})", body: updateJson, contentType: "application/json" ); ``` ### Response #### Success Response (204 No Content) No content is returned on successful update. ## DELETE /api/data/v9.x/accounts/{accountId} ### Description Deletes a specific account record from Dataverse. ### Method DELETE ### Endpoint `/api/data/v9.x/accounts/{accountId}` ### Parameters #### Path Parameters - **accountId** (Guid) - Required - The unique identifier of the account to delete. ### Request Example ```csharp var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); var deleteResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Delete, queryString: $"accounts({accountId})", body: null ); ``` ### Response #### Success Response (204 No Content) No content is returned on successful deletion. ``` -------------------------------- ### Execute HTTP Operations (C#) Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Performs direct HTTP requests (GET, POST, PATCH, DELETE) against the Dataverse Web API using the ServiceClient. Supports custom headers and content types. Demonstrates creating, retrieving, updating, and deleting account records. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading; public void ExecuteHttpOperations(ServiceClient serviceClient) { // GET request - Retrieve account var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); string getQuery = $"accounts({accountId})?$select=name,telephone1,revenue"; var getResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Get, queryString: getQuery, body: null, customHeaders: null ); if (getResponse.IsSuccessStatusCode) { string content = getResponse.Content.ReadAsStringAsync().Result; Console.WriteLine($"Account data: {content}"); } // POST request - Create account var accountData = new { name = "HTTP API Account", telephone1 = "555-1234", revenue = 1000000.00, accountnumber = "HTTP-001" }; string jsonBody = JsonSerializer.Serialize(accountData); var postResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: "accounts", body: jsonBody, customHeaders: new Dictionary> { { "Prefer", new List { "return=representation" } }, { "MSCRM.SuppressDuplicateDetection", new List { "false" } } }, contentType: "application/json" ); if (postResponse.IsSuccessStatusCode) { var locationHeader = postResponse.Headers.Location; Console.WriteLine($"Created account at: {locationHeader}"); } // PATCH request - Update account var updateData = new { telephone1 = "555-9999", websiteurl = "https://www.contoso.com" }; string updateJson = JsonSerializer.Serialize(updateData); var patchResponse = serviceClient.ExecuteWebRequest( method: new HttpMethod("PATCH"), queryString: $"accounts({accountId})", body: updateJson, customHeaders: null, contentType: "application/json" ); Console.WriteLine($"Update status: {patchResponse.StatusCode}"); // DELETE request var deleteResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Delete, queryString: $"accounts({accountId})", body: null, customHeaders: null ); Console.WriteLine($"Delete status: {deleteResponse.StatusCode}"); } ``` -------------------------------- ### Advanced Web API Operations with Cancellation Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt This section demonstrates how to perform Web API operations with support for cancellation tokens, allowing you to abort long-running requests, for example, due to a timeout. ```APIDOC ## GET /api/data/v9.x/accounts ### Description Retrieves a list of accounts with cancellation support, including setting preferences like maximum page size. ### Method GET ### Endpoint `/api/data/v9.x/accounts` ### Parameters #### Query Parameters - **$select** (string) - Optional - Comma-separated list of properties to retrieve. - **$top** (int) - Optional - The maximum number of records to return. #### Request Headers - **Prefer** (string) - Optional - Controls server behavior, e.g., `odata.maxpagesize=500` to limit page size. ### Request Example ```csharp var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(30)); // Timeout after 30 seconds try { var response = serviceClient.ExecuteWebRequest( method: HttpMethod.Get, queryString: "accounts?$select=name&$top=1000", body: null, customHeaders: new Dictionary> { { "Prefer", new List { "odata.maxpagesize=500" } } }, cancellationToken: cancellationTokenSource.Token ); Console.WriteLine($"Request completed: {response.StatusCode}"); } catch (OperationCanceledException) { Console.WriteLine("Request was cancelled due to timeout"); } ``` ### Response #### Success Response (200 OK) - **value** (array) - An array of account objects. #### Response Example ```json { "@odata.context": "...", "value": [ { "@odata.etag": "...", "name": "Account 1" }, { "@odata.etag": "...", "name": "Account 2" } ] } ``` #### Error Response (499 Client Closed Request) This status code may be returned if the operation is cancelled by the client. ``` -------------------------------- ### Connect to Dataverse with ConnectionOptions Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates establishing a ServiceClient connection using strongly-typed ConnectionOptions. Supports client secret and external token management authentication types. Requires Microsoft.PowerPlatform.Dataverse.Client NuGet package. Input is ConnectionOptions object, output is a ready ServiceClient instance or an exception. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.PowerPlatform.Dataverse.Client.Model; using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; public async Task ConnectWithOptionsAsync() { // Client secret authentication with ConnectionOptions var connectionOptions = new ConnectionOptions { AuthenticationType = AuthenticationType.ClientSecret, ServiceUri = new Uri("https://contoso.crm.dynamics.com"), ClientId = "51f81489-12ee-4a9e-aaae-a2591f45987d", ClientSecret = "your-client-secret", RequireNewInstance = true, SkipDiscovery = true }; // External token provider pattern var tokenProviderOptions = new ConnectionOptions { AuthenticationType = AuthenticationType.ExternalTokenManagement, ServiceUri = new Uri("https://contoso.crm.dynamics.com"), AccessTokenProviderFunctionAsync = async (resourceUri) => { // Custom token acquisition logic var token = await AcquireTokenFromCustomSourceAsync(resourceUri); return token; } }; try { var serviceClient = new ServiceClient(connectionOptions); if (serviceClient.IsReady) { Console.WriteLine("Connection established successfully"); Console.WriteLine($"Auth Type: {serviceClient.ActiveAuthenticationType}"); return serviceClient; } else { throw new Exception($"Connection failed: {serviceClient.LastError}"); } } catch (Exception ex) { Console.WriteLine($"Connection error: {ex.Message}"); throw; } } private async Task AcquireTokenFromCustomSourceAsync(string resourceUri) { // Implement custom token acquisition logic return await Task.FromResult("your-access-token"); } ``` -------------------------------- ### Replace IOverrideAuthHookWrapper with Constructor Function Pointer Source: https://github.com/microsoft/powerplatform-dataverseserviceclient/blob/master/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt This change replaces the IOverrideAuthHookWrapper with a new constructor that accepts a function pointer. This function, named FunctionName, takes an InstanceUri string and returns an access token, allowing for more flexible authentication processor association at the instance level. ```csharp /* The new constructor accepts a function pointer: string FunctionName(string InstanceUri) */ // Example usage (conceptual): // var serviceClient = new CdsServiceClient(new Uri("https://yourorg.crm.dynamics.com"), (instanceUri) => GetAccessToken(instanceUri)); ``` -------------------------------- ### PowerShell: Connect to Dataverse and Manage Records Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates connecting to Dataverse using client secrets or federated identity credentials, creating, retrieving, updating, and deleting account records. It also shows how to query records using FetchXML and execute batch operations. ```powershell # Install the PowerShell module Install-Module -Name Microsoft.PowerPlatform.Dataverse.Client.PowerShell # Import the module Import-Module Microsoft.PowerPlatform.Dataverse.Client.PowerShell # Connection using client secret $connectionString = "AuthType=ClientSecret;" + "Url=https://contoso.crm.dynamics.com;" + "ClientId=51f81489-12ee-4a9e-aaae-a2591f45987d;" + "ClientSecret=your-client-secret" $conn = Connect-PowerPlatformDataverse -ConnectionString $connectionString # Check connection status if ($conn.IsReady) { Write-Host "Connected to: $($conn.ConnectedOrgFriendlyName)" Write-Host "Organization ID: $($conn.ConnectedOrgId)" Write-Host "Version: $($conn.ConnectedOrgVersion)" Write-Host "User: $($conn.OAuthUserId)" } # Connection using Federated Identity Credential (Azure DevOps) $conn = Connect-PowerPlatformDataverse ` -ServerUrl "contoso.crm.dynamics.com" ` -TenantId "12345678-1234-1234-1234-123456789012" ` -ClientId "87654321-4321-4321-4321-210987654321" ` -ServiceConnectionId "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" ` -ConnectionTimeoutInSeconds 180 # Create a new account record $accountFields = @{ "name" = "PowerShell Account" "telephone1" = "555-1234" "accountnumber" = "PS-001" "revenue" = 1000000.00 "donotbulkemail" = $true } $accountId = New-DataverseRecord -EntityLogicalName "account" -Fields $accountFields Write-Host "Created account with ID: $accountId" # Retrieve a record $account = Get-DataverseRecord ` -EntityLogicalName "account" ` -Id $accountId ` -Fields @("name", "telephone1", "revenue", "createdon") Write-Host "Account Name: $($account.Attributes['name'])" Write-Host "Phone: $($account.Attributes['telephone1'])" Write-Host "Revenue: $($account.Attributes['revenue'].Value)" # Update a record $updateFields = @{ "telephone1" = "555-9999" "websiteurl" = "https://www.contoso.com" "revenue" = 1500000.00 } Set-DataverseRecord ` -EntityLogicalName "account" ` -Id $accountId ` -Fields $updateFields Write-Host "Account updated successfully" # Query records using FetchXML $fetchXml = @" "@ $accounts = Get-DataverseRecords -FetchXml $fetchXml Write-Host "Found $($accounts.Count) accounts" foreach ($acc in $accounts) { Write-Host "- $($acc.Attributes['name']): $($acc.Attributes['revenue'].Value)" } # Delete a record Remove-DataverseRecord -EntityLogicalName "account" -Id $accountId Write-Host "Account deleted" # Execute batch operations $batchId = New-DataverseBatch -BatchName "PowerShellBatch" -ReturnResults $true # Add operations to batch for ($i = 1; $i -le 10; $i++) { $fields = @{ "name" = "Batch Account $i" "accountnumber" = "BATCH-$($i.ToString('D4'))" } New-DataverseRecord -EntityLogicalName "account" -Fields $fields -BatchId $batchId } # Execute the batch $results = Invoke-DataverseBatch -BatchId $batchId Write-Host "Batch completed. Success count: $($results.Responses.Count)" # Access connection properties Write-Host "Max Retry Count: $($conn.MaxRetryCount)" Write-Host "Retry Pause Time: $($conn.RetryPauseTime)" Write-Host "Auth Type: $($conn.ActiveAuthenticationType)" Write-Host "Tenant ID: $($conn.TenantId)" Write-Host "Environment ID: $($conn.EnvironmentId)" # Configure advanced settings $conn.MaxRetryCount = 5 $conn.RetryPauseTime = [TimeSpan]::FromSeconds(3) $conn.SessionTrackingId = [Guid]::NewGuid() # Impersonation $conn.CallerId = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" # Perform operations as impersonated user $conn.CallerId = [Guid]::Empty # Reset # Dispose connection when done $conn.Dispose() ``` -------------------------------- ### Query Dataverse Records using QueryExpression, FetchXML, and Extensions (C#) Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Executes queries against Dataverse using three different methods: QueryExpression for structured queries, FetchXML for XML-based queries, and an extension method for simplified dictionary-based parameters. Supports filtering and sorting. Requires the Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Xrm.Sdk.Query namespaces. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk.Query; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using System; using System.Collections.Generic; using System.Linq; public void QueryAccountsMultipleMethods(ServiceClient serviceClient) { // Method 1: QueryExpression var query = new QueryExpression("account") { ColumnSet = new ColumnSet("name", "telephone1", "revenue"), Criteria = new FilterExpression(LogicalOperator.And) { Conditions = { new ConditionExpression("revenue", ConditionOperator.GreaterThan, 500000), new ConditionExpression("statecode", ConditionOperator.Equal, 0) } }, Orders = { new OrderExpression("name", OrderType.Ascending) } }; var results = serviceClient.RetrieveMultiple(query); Console.WriteLine($"QueryExpression found {results.Entities.Count} records"); foreach (var entity in results.Entities) { Console.WriteLine($"- {entity.GetAttributeValue("name")}: " + $"{entity.GetAttributeValue("revenue")?.Value:C}"); } // Method 2: FetchXML string fetchXml = @" "; var fetchResults = serviceClient.GetEntityDataByFetchSearchEC(fetchXml); Console.WriteLine($"FetchXML found {fetchResults.Entities.Count} records"); // Method 3: Extension method with dictionary parameters var searchParams = new Dictionary { { "statecode", "0" }, { "telephone1", "555%" } // LIKE query }; var fieldList = new List { "name", "telephone1", "revenue", "createdon" }; var dictResults = serviceClient.GetEntityDataBySearchParams( entityName: "account", searchParameters: searchParams, searchOperator: LogicalSearchOperator.And, fieldList: fieldList ); Console.WriteLine($"Extension method found {dictResults.Count} records"); foreach (var record in dictResults) { var accountId = record.Key; var fields = record.Value; Console.WriteLine($"Account {accountId}: {fields["name"]}"); } } ``` -------------------------------- ### Execute Dataverse Workflows using C# Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates how to execute Dataverse workflows on entities using both extension methods and the standard OrganizationRequest in C#. It requires the Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Crm.Sdk.Messages namespaces. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using System; public void ExecuteWorkflowOperations(ServiceClient serviceClient) { Guid accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); // Execute workflow using extension method Guid asyncOperationId = serviceClient.ExecuteWorkflowOnEntity( workflowName: "Account Approval Workflow", id: accountId ); Console.WriteLine($"Workflow started. Async Operation ID: {asyncOperationId}"); // Execute workflow using standard OrganizationRequest var executeWorkflowRequest = new ExecuteWorkflowRequest { WorkflowId = Guid.Parse("99999999-8888-7777-6666-555555555555"), EntityId = accountId }; var workflowResponse = (ExecuteWorkflowResponse)serviceClient.Execute(executeWorkflowRequest); Console.WriteLine($"Workflow instance ID: {workflowResponse.Id}"); } ``` -------------------------------- ### Dataverse Queue and User Operations in C# Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Illustrates C# methods for adding entities to Dataverse queues, retrieving the current user's ID, and executing custom actions. This snippet relies on the Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Xrm.Sdk namespaces. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk; using System; public void QueueAndUserOperations(ServiceClient serviceClient) { Guid entityId = Guid.Parse("12345678-1234-1234-1234-123456789012"); Guid workingUserId = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"); // Add entity to queue bool queueSuccess = serviceClient.AddEntityToQueue( entityId: entityId, entityName: "incident", queueName: "Support Queue", workingUserId: workingUserId, setWorkingByUser: true ); Console.WriteLine($"Queue operation {(queueSuccess ? "successful" : "failed")}"); // Get current user ID Guid currentUserId = serviceClient.GetMyUserId(); Console.WriteLine($"Current user ID: {currentUserId}"); // Execute custom action var customActionRequest = new OrganizationRequest("new_CustomAction"); customActionRequest["Target"] = new EntityReference("account", entityId); customActionRequest["InputParameter"] = "value"; var customActionResponse = serviceClient.Execute(customActionRequest); Console.WriteLine("Custom action executed"); } ``` -------------------------------- ### Execute Dataverse Requests via Web API using C# Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates how to execute Dataverse requests, such as WhoAmIRequest, specifically using the Web API endpoint with the ServiceClient in C#. This approach is an alternative to the default SOAP endpoint and requires the Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Xrm.Sdk namespaces. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using System; // Execute with Web API instead of SOAP public void ExecuteWithWebApi(ServiceClient serviceClient) { var request = new WhoAmIRequest(); // Execute using Web API endpoint var response = (WhoAmIResponse)serviceClient.ExecuteOrganizationRequest( req: request, logMessageTag: "WhoAmI Request", useWebAPI: true ); Console.WriteLine($"User ID: {response.UserId}"); Console.WriteLine($"Business Unit: {response.BusinessUnitId}"); Console.WriteLine($"Organization: {response.OrganizationId}"); } ``` -------------------------------- ### Retrieve and Update Account Entity in C# Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt This C# code demonstrates retrieving an account record from Dataverse, performing a standard update, and then executing a partial update using an extension method. It includes error handling and uses the ServiceClient for Dataverse interactions. Dependencies include Microsoft.PowerPlatform.Dataverse.Client and Microsoft.Xrm.Sdk. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using System; using System.Collections.Generic; public void RetrieveAndUpdateAccount(ServiceClient serviceClient, Guid accountId) { try { // Retrieve with specific columns var columnSet = new ColumnSet("name", "telephone1", "revenue", "statuscode"); Entity account = serviceClient.Retrieve("account", accountId, columnSet); Console.WriteLine($"Retrieved: {account["name"]}"); Console.WriteLine($"Phone: {account.GetAttributeValue("telephone1")}"); Console.WriteLine($"Revenue: {account.GetAttributeValue("revenue")?.Value}"); // Method 1: Standard update account["telephone1"] = "555-9999"; account["websiteurl"] = "https://www.contoso.com"; account["revenue"] = new Money(1500000.00m); serviceClient.Update(account); Console.WriteLine("Account updated successfully"); // Method 2: Extension method update var updateFields = new Dictionary { { "telephone1", new DataverseDataTypeWrapper("555-8888", DataverseFieldType.String) }, { "emailaddress1", new DataverseDataTypeWrapper("info@contoso.com", DataverseFieldType.String) }, { "revenue", new DataverseDataTypeWrapper(2000000.00m, DataverseFieldType.Money) } }; bool updateSuccess = serviceClient.UpdateEntity( entityName: "account", keyFieldName: "accountid", id: accountId, fieldList: updateFields, applyToSolution: "", enabledDuplicateDetection: false, bypassPluginExecution: false ); if (updateSuccess) { Console.WriteLine("Extension method update successful"); } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); throw; } } // Update state and status public void DeactivateAccount(ServiceClient serviceClient, Guid accountId) { bool success = serviceClient.UpdateStateAndStatusForEntity( entName: "account", id: accountId, stateCode: "1", // Inactive statusCode: "2" // Inactive status ); Console.WriteLine($"Deactivation {(success ? "successful" : "failed")}"); } ``` -------------------------------- ### Paginate Dataverse Records using FetchXML (C#) Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Retrieves multiple pages of records from Dataverse using FetchXML with pagination parameters. This method allows for efficient retrieval of large datasets by processing records in chunks. It requires a ServiceClient and utilizes out parameters for paging cookies and more records indicator. ```csharp // Advanced query with paging public void QueryWithPaging(ServiceClient serviceClient) { string fetchXml = @" "; int pageNumber = 1; string pagingCookie = null; bool moreRecords = true; while (moreRecords) { var results = serviceClient.GetEntityDataByFetchSearch( fetchXml: fetchXml, pageCount: 100, pageNumber: pageNumber, pageCookie: pagingCookie, outPageCookie: out string newCookie, isMoreRecords: out moreRecords ); Console.WriteLine($"Page {pageNumber}: {results.Count} records"); pagingCookie = newCookie; pageNumber++; if (pageNumber > 10) break; // Safety limit } } ``` -------------------------------- ### Use Dataverse Request Builder for Granular Control Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Illustrates the use of the Request Builder pattern for creating and retrieving Dataverse entities with granular control. This includes setting custom headers, request IDs, correlation IDs, and impersonating users for specific operations. The builder pattern simplifies complex request construction. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using System; using System.Threading; using System.Threading.Tasks; public async Task UseRequestBuilderAsync(ServiceClient serviceClient) { Guid targetUserId = Guid.Parse("12345678-1234-1234-1234-123456789012"); Guid aadObjectId = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"); var entity = new Microsoft.Xrm.Sdk.Entity("account"); entity["name"] = "Request Builder Account"; var requestBuilder = serviceClient.CreateRequestBuilder(); // Build request with custom headers and impersonation Guid accountId = await requestBuilder .WithRequestId(Guid.NewGuid()) // For tracing .WithCorrelationId(Guid.NewGuid()) // For telemetry correlation .WithHeader("CustomHeader", "CustomValue") .WithCrmUserId(targetUserId) // Impersonate CRM user .WithUserObjectId(aadObjectId) // Impersonate AAD user .CreateAsync(entity, System.Threading.CancellationToken.None); Console.WriteLine($"Created account with request builder: {accountId}"); // Retrieve with builder var retrievedEntity = await requestBuilder .WithRequestId(Guid.NewGuid()) .RetrieveAsync("account", accountId, new Microsoft.Xrm.Sdk.Query.ColumnSet("name", "createdon"), System.Threading.CancellationToken.None); } ``` -------------------------------- ### Execute Dataverse Batch Operations (C#) Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt This C# code demonstrates how to execute multiple Dataverse operations (create, update, delete) as a single batch request using the ServiceClient. It covers creating the batch, adding operations with specific parameters, executing the batch, and processing the responses, including error handling. Batch operations require the ServiceClient to have batch operations available and are useful for improving performance and reducing API call overhead. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.PowerPlatform.Dataverse.Client.Extensions; using Microsoft.Xrm.Sdk; using System; using System.Collections.Generic; public void ExecuteBatchOperations(ServiceClient serviceClient) { if (!serviceClient.IsBatchOperationsAvailable) { Console.WriteLine("Batch operations not available"); return; } // Step 1: Create a batch request Guid batchId = serviceClient.CreateBatchOperationRequest( batchName: "BulkAccountUpdate", returnResults: true, // Return results from operations continueOnError: true // Continue if individual operations fail ); Console.WriteLine($"Created batch with ID: {batchId}"); try { // Step 2: Add operations to the batch using batchId parameter // Create multiple accounts for (int i = 1; i <= 5; i++) { var fields = new Dictionary { { "name", new DataverseDataTypeWrapper($"Batch Account {i}", DataverseFieldType.String) }, { "accountnumber", new DataverseDataTypeWrapper($"BATCH-{i:D4}", DataverseFieldType.String) }, { "telephone1", new DataverseDataTypeWrapper($"555-{i:D4}", DataverseFieldType.String) } }; serviceClient.CreateNewRecord("account", fields, batchId: batchId); } // Update existing accounts var existingAccountIds = new List { Guid.Parse("12345678-1234-1234-1234-123456789012"), Guid.Parse("87654321-4321-4321-4321-210987654321") }; foreach (var accountId in existingAccountIds) { var updateFields = new Dictionary { { "telephone1", new DataverseDataTypeWrapper("555-BATCH", DataverseFieldType.String) }, { "description", new DataverseDataTypeWrapper("Updated via batch", DataverseFieldType.String) } }; serviceClient.UpdateEntity("account", "accountid", accountId, updateFields, batchId: batchId); } // Delete an account Guid accountToDelete = Guid.Parse("11111111-2222-3333-4444-555555555555"); serviceClient.DeleteEntity("account", accountToDelete, batchId: batchId); // Step 3: Execute the batch Console.WriteLine("Executing batch..."); var executeMultipleResponse = serviceClient.ExecuteBatch(batchId); // Step 4: Process results Console.WriteLine($"Batch completed. Faults: {executeMultipleResponse.IsFaulted}"); for (int i = 0; i < executeMultipleResponse.Responses.Count; i++) { var response = executeMultipleResponse.Responses[i]; if (response.Fault != null) { Console.WriteLine($"Request {i} failed: {response.Fault.Message}"); } else { Console.WriteLine($"Request {i} succeeded"); if (response.Response != null) { // Handle specific response types if (response.Response is Microsoft.Xrm.Sdk.Messages.CreateResponse createResp) { Console.WriteLine($" Created entity ID: {createResp.id}"); } } } } // Alternative: Retrieve as parsed dictionary var dictResults = serviceClient.RetrieveBatchResponse(batchId); Console.WriteLine($"Dictionary results count: {dictResults.Count}"); } finally { // Step 5: Clean up batch from memory serviceClient.ReleaseBatchInfoById(batchId); Console.WriteLine("Batch released from memory"); } } // Get batch by name instead of ID public void ExecuteBatchByName(ServiceClient serviceClient) { string batchName = "MyNamedBatch"; Guid batchId = serviceClient.CreateBatchOperationRequest(batchName, returnResults: true); // Add operations... // Retrieve batch by name Guid retrievedBatchId = serviceClient.GetBatchOperationIdRequestByName(batchName); if (retrievedBatchId == batchId) { serviceClient.ExecuteBatch(retrievedBatchId); } } ``` -------------------------------- ### Execute Custom API Calls (C#) Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Demonstrates executing both bound and unbound custom API actions against the Dataverse Web API. This requires constructing the correct query string and JSON body for the action parameters. The response content is then processed. ```csharp // Execute custom action via Web API public void ExecuteCustomAction(ServiceClient serviceClient) { var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); // Bound action (bound to entity) var actionParameters = new { InputParameter = "value", AnotherParameter = 123 }; string actionJson = JsonSerializer.Serialize(actionParameters); var actionResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: $"accounts({accountId})/Microsoft.Dynamics.CRM.new_CustomAction", body: actionJson, customHeaders: null, contentType: "application/json" ); if (actionResponse.IsSuccessStatusCode) { string result = actionResponse.Content.ReadAsStringAsync().Result; Console.WriteLine($"Action result: {result}"); } // Unbound action (global) var unboundResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: "new_GlobalCustomAction", body: actionJson, customHeaders: null, contentType: "application/json" ); } ``` -------------------------------- ### Connect to Dataverse with ServiceClient and Connection String Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt Establishes an authenticated connection to Microsoft Dataverse using the ServiceClient class and a connection string. It supports various authentication types like OAuth (with user credentials, client secrets, or certificates). The snippet demonstrates checking the connection status and retrieving basic organization and user details upon successful connection. ```csharp using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Extensions.Logging; using System; // OAuth with user credentials string connString = "AuthType=OAuth;" + "Url=https://contoso.crm.dynamics.com;" + "UserName=user@contoso.com;" + "Password=yourpassword;" + "ClientId=51f81489-12ee-4a9e-aaae-a2591f45987d;" + "RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97"; // Client secret authentication string clientSecretConn = "AuthType=ClientSecret;" + "Url=https://contoso.crm.dynamics.com;" + "ClientId=51f81489-12ee-4a9e-aaae-a2591f45987d;" + "ClientSecret=your-client-secret"; // Certificate authentication string certConn = "AuthType=Certificate;" + "Url=https://contoso.crm.dynamics.com;" + "ClientId=51f81489-12ee-4a9e-aaae-a2591f45987d;" + "CertificateThumbprint=ABCDEF1234567890;" + "CertificateStoreName=My"; try { using (var serviceClient = new ServiceClient(clientSecretConn)) { if (serviceClient.IsReady) { Console.WriteLine($"Connected to: {serviceClient.ConnectedOrgFriendlyName}"); Console.WriteLine($"Organization ID: {serviceClient.ConnectedOrgId}"); Console.WriteLine($"Version: {serviceClient.ConnectedOrgVersion}"); Console.WriteLine($"User ID: {serviceClient.OAuthUserId}"); } else { Console.WriteLine($"Connection failed: {serviceClient.LastError}"); Console.WriteLine($"Exception: {serviceClient.LastException?.Message}"); } } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } ``` -------------------------------- ### Executing Custom Actions via Web API Source: https://context7.com/microsoft/powerplatform-dataverseserviceclient/llms.txt This section covers executing both bound and unbound custom actions against the Dataverse Web API. Learn how to structure the request body and specify the correct endpoint for custom logic execution. ```APIDOC ## POST /api/data/v9.x/accounts/{accountId}/Microsoft.Dynamics.CRM.new_CustomAction ### Description Executes a bound custom action on a specific account record. ### Method POST ### Endpoint `/api/data/v9.x/accounts/{accountId}/Microsoft.Dynamics.CRM.new_CustomAction` ### Parameters #### Path Parameters - **accountId** (Guid) - Required - The unique identifier of the account to bind the action to. #### Request Body - **InputParameter** (string) - Example input parameter for the custom action. - **AnotherParameter** (int) - Example numeric parameter. ### Request Example ```csharp var accountId = Guid.Parse("12345678-1234-1234-1234-123456789012"); var actionParameters = new { InputParameter = "value", AnotherParameter = 123 }; string actionJson = JsonSerializer.Serialize(actionParameters); var actionResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: $"accounts({accountId})/Microsoft.Dynamics.CRM.new_CustomAction", body: actionJson, contentType: "application/json" ); ``` ### Response #### Success Response (200 OK) - **result** (string) - The result returned by the custom action. #### Response Example ```json { "result": "Success" } ``` ## POST /api/data/v9.x/new_GlobalCustomAction ### Description Executes an unbound (global) custom action. ### Method POST ### Endpoint `/api/data/v9.x/new_GlobalCustomAction` ### Parameters #### Request Body - **InputParameter** (string) - Example input parameter for the custom action. - **AnotherParameter** (int) - Example numeric parameter. ### Request Example ```csharp var actionParameters = new { InputParameter = "value", AnotherParameter = 123 }; string actionJson = JsonSerializer.Serialize(actionParameters); var unboundResponse = serviceClient.ExecuteWebRequest( method: HttpMethod.Post, queryString: "new_GlobalCustomAction", body: actionJson, contentType: "application/json" ); ``` ### Response #### Success Response (200 OK) - **result** (string) - The result returned by the custom action. #### Response Example ```json { "result": "Success" } ``` ``` -------------------------------- ### Fix ExecuteCdsWebRequest Bug with ClientSecretAuth Types Source: https://github.com/microsoft/powerplatform-dataverseserviceclient/blob/master/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt Addresses an issue in the ExecuteCdsWebRequest method that prevented connections using clientSecretAuth types from functioning correctly. This fix ensures seamless integration when client secrets are used for authentication. ```csharp /* No specific code snippet provided, but the fix addresses the ExecuteCdsWebRequest method for clientSecretAuth types. */ ```