Waarom consoletoepassingen voor Dynamics 365?
Consoletoepassingen zijn krachtige tools om beheertaken te automatiseren, gegevens in bulk te verwerken en geplande jobs uit te voeren op Dynamics 365-omgevingen. In tegenstelling tot plugins, die binnen de uitvoeringspipeline van het platform draaien, draaien console-apps extern. Ze kunnen dus bewerkingen uitvoeren die binnen de normale uitvoeringscontext onpraktisch of onmogelijk zouden zijn. Lees meer over de Dataverse Web API en de Organization Service.
Veelvoorkomende scenario's
- Datamigratie: Records in bulk importeren en exporteren tussen systemen
- Gepland onderhoud: Oude records opruimen, rollups herberekenen
- Rapportage-exports: Volgens planning CSV- of Excel-exports genereren
- Synchronisatie voor integraties: Gegevens synchroniseren met externe systemen
- Omgevingsbeheer: Uitrol en configuratie van solutions automatiseren
- Testautomatisering: Testgegevens aanmaken, integratietests uitvoeren
Uw project opzetten
Het project aanmaken
Maak in Visual Studio een nieuwe consoletoepassing op .NET Framework 4.6.2. Die frameworkversie sluit aan bij de vereisten van de Dynamics 365 SDK.
// Visual Studio → New Project → Console App (.NET Framework)
// Target Framework: .NET Framework 4.6.2
// Project Name: D365AutomationConsole
Vereiste NuGet-pakketten
Installeer de volgende NuGet-pakketten om verbinding te maken met Dynamics 365:
Install-Package Microsoft.CrmSdk.CoreAssemblies
Install-Package Microsoft.CrmSdk.XrmTooling.CoreAssembly
Install-Package Microsoft.CrmSdk.Deployment
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
Authenticatiemethoden
Authenticatie met een connection string
De eenvoudigste aanpak gebruikt een connection string met de CrmServiceClient.
using Microsoft.Xrm.Tooling.Connector;
var connectionString = @"
AuthType=OAuth;
Url=https://yourorg.crm.dynamics.com;
AppId=51f81489-12ee-4a9e-aaae-a2591f45987d;
RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97;
LoginPrompt=Auto";
var client = new CrmServiceClient(connectionString);
if (client.IsReady)
{
Console.WriteLine("Connected to: " + client.ConnectedOrgFriendlyName);
IOrganizationService service = client.OrganizationServiceProxy;
// Use service for operations
}
else
{
Console.WriteLine("Connection failed: " + client.LastCrmError);
}Zet geen gebruikersnamen en wachtwoorden in connection strings
Dit voorbeeld meldt interactief aan (LoginPrompt=Auto) en bewaart nooit een wachtwoord. Aanmelden met gebruikersnaam en wachtwoord (ROPC) wordt geblokkeerd door meervoudige verificatie en voorwaardelijke toegang en laat referenties in platte tekst achter, dus gebruik het niet. Gebruik voor onbemande jobs de aanpak met client secret of certificaat hieronder en bewaar het geheim in Azure Key Vault.
Client-ID en secret (aanbevolen voor automatisering)
Gebruik voor onbewaakte automatisering een app-registratie in Microsoft Entra ID met client credentials.
var connectionString = @"
AuthType=ClientSecret;
Url=https://yourorg.crm.dynamics.com;
ClientId=your-app-registration-client-id;
ClientSecret=your-client-secret";
var client = new CrmServiceClient(connectionString);Belangrijk: maak in Dynamics 365 een applicatiegebruiker (Application User) aan voor de app-registratie en geef die de gepaste beveiligingsrollen.
Authenticatie met certificaten
Gebruik certificaatauthenticatie voor de hoogste beveiliging in productie.
var connectionString = @"
AuthType=Certificate;
Url=https://yourorg.crm.dynamics.com;
ClientId=your-app-registration-client-id;
Thumbprint=your-certificate-thumbprint;
StoreName=My;
StoreLocation=CurrentUser";
var client = new CrmServiceClient(connectionString);Veelvoorkomende bewerkingen
CRUD-bewerkingen
Voer Create-, Retrieve-, Update- en Delete-bewerkingen uit met de Organization Service.
// Create
var account = new Entity("account");
account["name"] = "Contoso Ltd";
account["telephone1"] = "+1-555-0123";
Guid accountId = service.Create(account);
Console.WriteLine($"Created account: {accountId}");
// Retrieve
var retrieved = service.Retrieve("account", accountId,
new ColumnSet("name", "telephone1", "accountnumber"));
Console.WriteLine($"Retrieved: {retrieved["name"]}");
// Update
var updateAccount = new Entity("account", accountId);
updateAccount["accountnumber"] = "ACC-001";
service.Update(updateAccount);
Console.WriteLine("Account updated");
// Delete
service.Delete("account", accountId);
Console.WriteLine("Account deleted");Gegevens opvragen
Gebruik QueryExpression of FetchXML om gegevens op te halen uit Dynamics 365.
var query = new QueryExpression("contact")
{
ColumnSet = new ColumnSet("fullname", "emailaddress1", "parentcustomerid"),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression("statecode", ConditionOperator.Equal, 0),
new ConditionExpression("emailaddress1", ConditionOperator.NotNull)
}
},
Orders = { new OrderExpression("fullname", OrderType.Ascending) },
TopCount = 100
};
// Add linked entity for account name
var accountLink = query.AddLink("account", "parentcustomerid", "accountid", JoinOperator.LeftOuter);
accountLink.Columns.AddColumn("name");
accountLink.EntityAlias = "parentaccount";
var results = service.RetrieveMultiple(query);
foreach (var contact in results.Entities)
{
var accountName = contact.GetAttributeValue<AliasedValue>("parentaccount.name")?.Value;
Console.WriteLine($"{contact["fullname"]} - {accountName ?? "No Account"}");
}Bulkbewerkingen
Gebruik ExecuteMultipleRequest voor efficiënte bulkbewerkingen.
public void BulkCreateContacts(IOrganizationService service, List<Entity> contacts)
{
var batchSize = 100;
var batches = contacts
.Select((contact, index) => new { contact, index })
.GroupBy(x => x.index / batchSize)
.Select(g => g.Select(x => x.contact).ToList())
.ToList();
int totalCreated = 0;
foreach (var batch in batches)
{
var multipleRequest = new ExecuteMultipleRequest
{
Settings = new ExecuteMultipleSettings
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
foreach (var contact in batch)
{
multipleRequest.Requests.Add(new CreateRequest { Target = contact });
}
var response = (ExecuteMultipleResponse)service.Execute(multipleRequest);
int successCount = response.Responses.Count(r => r.Fault == null);
totalCreated += successCount;
// Log any failures
foreach (var item in response.Responses.Where(r => r.Fault != null))
{
Console.WriteLine($"Error at index {item.RequestIndex}: {item.Fault.Message}");
}
Console.WriteLine($"Batch complete: {successCount}/{batch.Count} created");
}
Console.WriteLine($"Total created: {totalCreated}/{contacts.Count}");
}Best practice:
Groepeer bewerkingen in batches van 100 tot 500 voor optimale prestaties. Vang gedeeltelijke fouten netjes op.
Console-apps inplannen
Voer consoletoepassingen volgens planning uit met Windows Task Scheduler of Azure Functions.
Windows Task Scheduler
Gebruik in on-premises scenario's Windows Task Scheduler om console-apps op vaste tijdstippen uit te voeren.
Azure Functions
Zet de logica van de console-app voor automatisering in de cloud om naar Azure Functions met timertriggers.
Foutafhandeling en logging
Voorzie robuuste foutafhandeling en logging voor automatisering in productie.
public void ProcessRecord(IOrganizationService service, Guid recordId)
{
try
{
var record = service.Retrieve("account", recordId, new ColumnSet(true));
// Process record
}
catch (FaultException<OrganizationServiceFault> ex)
{
// Dynamics 365 specific error
Console.WriteLine($"D365 Error: {ex.Detail.Message}");
Console.WriteLine($"Error Code: {ex.Detail.ErrorCode}");
if (ex.Detail.InnerFault != null)
{
Console.WriteLine($"Inner Error: {ex.Detail.InnerFault.Message}");
}
}
catch (TimeoutException ex)
{
Console.WriteLine($"Timeout: {ex.Message}");
// Implement retry logic
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
throw;
}
}Best practices:
- Gebruik try-catch-blokken rond alle API-bewerkingen
- Log fouten naar bestanden, het Event Log of Application Insights
- Voorzie retrylogica voor tijdelijke fouten
- Verstuur meldingen bij kritieke fouten
- Houd uitvoeringsstatistieken bij voor monitoring
Beveiligingsoverwegingen
Belangrijke aandachtspunten:
- Zet nooit inloggegevens hardcoded in de broncode
- Gebruik Azure Key Vault voor het beheer van secrets
- Gebruik serviceaccounts met minimale rechten (least privilege)
- Vernieuw secrets en certificaten regelmatig
- Schakel auditlogging in voor geautomatiseerde bewerkingen
Conclusie
Consoletoepassingen zijn een krachtige manier om Dynamics 365-taken te automatiseren die verder gaan dan wat met plugins of Power Automate kan. Van datamigratie tot gepland onderhoud: console-apps bieden volledige SDK-toegang met de flexibiliteit van externe uitvoering.
Besteed aandacht aan degelijke authenticatie, foutafhandeling en beveiliging, zodat uw automatisering betrouwbaar en onbewaakt in productie kan draaien.