如何用C#通过SOAP/REST API停用并激活Salesforce自定义触发器
Hey there! I’ve tackled exactly this scenario before—here’s a practical, step-by-step solution using C# with Salesforce’s REST API to safely toggle your trigger’s activation status. This works perfectly for Developer Edition orgs, and includes error handling to ensure you don’t leave triggers inactive accidentally:
First, make sure you have these set up:
- A Salesforce Connected App with API access (enable OAuth2, grant
Full AccessorModify All Datapermissions) - Your org’s instance URL, connected app credentials (client ID/secret), and a user account with permissions to modify Apex triggers
- A C# project (Console App, ASP.NET, etc.) with
System.Net.HttpandSystem.Text.Jsonpackages installed (or use the official Salesforce.NET SDK if you prefer)
First, we need to get an OAuth2 access token to make API calls. Here’s a reusable method:
using System.Net.Http; using System.Threading.Tasks; using System.Collections.Generic; using System.Net.Http.Headers; public async Task<string> GetSalesforceAuthToken(string instanceUrl, string clientId, string clientSecret, string username, string password) { var tokenEndpoint = $"{instanceUrl}/services/oauth2/token"; var formData = new Dictionary<string, string> { {"grant_type", "password"}, {"client_id", clientId}, {"client_secret", clientSecret}, {"username", username}, {"password", password} // Don't forget to append your Salesforce security token here! }; using var httpClient = new HttpClient(); var response = await httpClient.PostAsync(tokenEndpoint, new FormUrlEncodedContent(formData)); response.EnsureSuccessStatusCode(); var tokenResponse = await response.Content.ReadAsAsync<dynamic>(); return tokenResponse.access_token; }
Next, we’ll query the ApexTrigger object to find our target trigger, then update its IsActive field to false:
public async Task DeactivateTrigger(string instanceUrl, string accessToken, string triggerDeveloperName) { // Query the active trigger to get its ID var queryEndpoint = $"{instanceUrl}/services/data/v59.0/query?q=SELECT+Id+FROM+ApexTrigger+WHERE+DeveloperName='{triggerDeveloperName}'+AND+Status='Active'"; using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var queryResponse = await httpClient.GetAsync(queryEndpoint); queryResponse.EnsureSuccessStatusCode(); var queryResult = await queryResponse.Content.ReadAsAsync<dynamic>(); if (queryResult.totalSize == 0) { throw new Exception($"Trigger {triggerDeveloperName} not found or already inactive."); } var triggerId = queryResult.records[0].Id; // Update trigger to inactive var updateEndpoint = $"{instanceUrl}/services/data/v59.0/sobjects/ApexTrigger/{triggerId}"; var updateBody = new { IsActive = false }; var updateResponse = await httpClient.PatchAsync(updateEndpoint, new StringContent( System.Text.Json.JsonSerializer.Serialize(updateBody), System.Text.Encoding.UTF8, "application/json")); updateResponse.EnsureSuccessStatusCode(); Console.WriteLine($"Trigger {triggerDeveloperName} deactivated successfully."); }
This is where you run your custom org tasks—like bulk contact updates, data migrations, or any process that needs the trigger disabled. Wrap this in error handling to ensure we can recover the trigger status if something goes wrong:
private void ExecuteOrgOperations() { // Replace this with your actual org-specific logic Console.WriteLine("Running org operations..."); // Example: Bulk update Contact records, run a custom Apex class, etc. }
Once your operations are done, re-enable the trigger using a similar method to deactivation:
public async Task ReactivateTrigger(string instanceUrl, string accessToken, string triggerDeveloperName) { // Query the inactive trigger to get its ID var queryEndpoint = $"{instanceUrl}/services/data/v59.0/query?q=SELECT+Id+FROM+ApexTrigger+WHERE+DeveloperName='{triggerDeveloperName}'+AND+Status='Inactive'"; using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var queryResponse = await httpClient.GetAsync(queryEndpoint); queryResponse.EnsureSuccessStatusCode(); var queryResult = await queryResponse.Content.ReadAsAsync<dynamic>(); if (queryResult.totalSize == 0) { throw new Exception($"Trigger {triggerDeveloperName} not found or already active."); } var triggerId = queryResult.records[0].Id; // Update trigger to active var updateEndpoint = $"{instanceUrl}/services/data/v59.0/sobjects/ApexTrigger/{triggerId}"; var updateBody = new { IsActive = true }; var updateResponse = await httpClient.PatchAsync(updateEndpoint, new StringContent( System.Text.Json.JsonSerializer.Serialize(updateBody), System.Text.Encoding.UTF8, "application/json")); updateResponse.EnsureSuccessStatusCode(); Console.WriteLine($"Trigger {triggerDeveloperName} reactivated successfully."); }
Put it all together with robust error handling to guarantee the trigger gets reactivated even if your operations fail:
public async Task RunTriggerToggleWorkflow() { // Replace these values with your org's details string instanceUrl = "https://your-dev-ed.my.salesforce.com"; string clientId = "YOUR_CONNECTED_APP_CLIENT_ID"; string clientSecret = "YOUR_CONNECTED_APP_CLIENT_SECRET"; string username = "your-username@example.com"; string password = "your-password+security-token"; string targetTrigger = "UpdateContactData"; string accessToken = string.Empty; try { // Authenticate accessToken = await GetSalesforceAuthToken(instanceUrl, clientId, clientSecret, username, password); // Deactivate trigger await DeactivateTrigger(instanceUrl, accessToken, targetTrigger); // Run org operations ExecuteOrgOperations(); // Reactivate trigger await ReactivateTrigger(instanceUrl, accessToken, targetTrigger); } catch (Exception ex) { Console.WriteLine($"Error occurred: {ex.Message}"); // Attempt to reactivate the trigger even if something fails if (!string.IsNullOrEmpty(accessToken)) { try { await ReactivateTrigger(instanceUrl, accessToken, targetTrigger); Console.WriteLine("Trigger reactivated as part of error recovery."); } catch (Exception recoveryEx) { Console.WriteLine($"Failed to recover trigger status: {recoveryEx.Message}"); } } } }
- API Version: Replace
v59.0with the latest API version supported by your org (check Setup > API > API Versions) - Managed Packages: If your trigger is in a managed package, add
AND NamespacePrefix='YOUR_PACKAGE_NAMESPACE'to your SOQL query - Permissions: Ensure your user has
Modify All DataorAuthor Apex+Customize Applicationpermissions to modify triggers - SOAP API Alternative: If you prefer SOAP, use the
update()call on theApexTriggerobject—just generate the WSDL for your org and use it in your C# project
内容的提问来源于stack exchange,提问作者Shripal Gandhi

