sendwithus C# Client
none
Target framework is .NET Standard 2.0
With one exception, this client covers all of the sendwithus API calls documented at: https://www.sendwithus.com/docs/api#overview
The exception is the Multi-Langauge API calls; those API calls are not supported in this client. If you require support for the Multi-Language API, please contact sendwithus: https://www.sendwithus.com/contact
If you are using Visual Studio 2015:
- In the Solution Explorer window, right click on your solution and select "Manage NuGet Packages for Solution..."
- Search for "SendwithusClient"
- Be sure to use the one that's by sendwithus. There's another one called SendWithUs.Client by Mimeo, but that is not supported by sendwithus
- Select the "SendwithusClient" package and choose "Install" for your solution/project.
using sendwithus;
// Set the API Key
SendwithusClient.ApiKey = <your_api_key> // Test or Production
// Configure API settings (optional)
SendwithusClient.SetTimeoutInMilliseconds(your_preferred_timeout); // Default is 30000 (30s). This is the timeout for an individual API call attempt
SendwithusClient.RetryCount = your_preferred_retryCount; // Default is 3. This is the number of times that each API call will be retried if it fails due to a potentially transient event
SendwithusClient.RetryIntervalMilliseconds = your_preferred_retryInterval; // Default is 100ms. This is the amount of time to wait between retry attempts.
The API will perform a retry in the following cases:
Retry Causes | Exception Thrown |
---|---|
API Call Timeout | TaskCanceledException |
Received HTTP Status 502: BadGateway | SendwithusException |
Received HTTP Status 503: ServiceUnavailable | SendwithusException |
Received HTTP Status 505: GatewayTimeout | SendwithusException |
A SendwithusException is a regular Exception with a StatusCode property added
All exceptions will be part of an AggregateException, regardless of whether a retry was attempted or not.
Some examples:
- An API call that fails with a status code 403: Forbidden (not a retriable status code) will throw an AggregateException with one InnerException of type SendwithusException
- An API call that repeatedly times out will throw an AggregateException with InnerExceptions of type TaskCanceledException
- An API call that times out once, then fails with a status code of 503: Service Unavailable, and then fails again with a status code 400: Bad Request will throw an AggregateException with InnerExceptions, in order, of: { TaskCanceledException, SendwithusException, SendwithusException}
The API Client will also throw the following other exceptions:
- An InvalidOperationException will be thrown when adding a new API call to a queue of Batched API calls when the limit of maximum API calls per batch has already been met
try
{
var templates = await Template.GetTemplatesAsync();
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
try
{
var response = await Template.GetTemplateAsync(templateId);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
try
{
var template = await Template.GetTemplateVersionsAsync(templateId);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US";
try
{
var template = await Template.GetTemplateAsync(templateId, locale);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US";
try
{
var templateVersions = await Template.GetTemplateVersionsAsync(templateId, locale);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var versionId = "ver_ET3j2snkKhqsjRjtK6bXJE";
try
{
var templateVersion = await Template.GetTemplateVersionAsync(templateId, versionId);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US";
var versionId = "ver_ET3j2snkKhqsjRjtK6bXJE";
try
{
var templateVersion = await Template.GetTemplateVersionAsync(templateId, locale, versionId);
}
catch (AggregateException exception)
{
// Exception handling
}
Note: at least one of "html" or "text" must be specified in the updated template version object
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var versionId = "ver_ET3j2snkKhqsjRjtK6bXJE";
var updatedTemplateVersion = new TemplateVersion();
var templateVersionName = "New Version";
var templateSubject = "edited!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>UPDATE</h1></body></html>"; // optional
updatedTemplateVersion.text = "sometext"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
try
{
var templateVersion = await Template.UpdateTemplateVersionAsync(templateId, versionId, updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US"
var versionId = "ver_ET3j2snkKhqsjRjtK6bXJE";
var updatedTemplateVersion = new TemplateVersion();
var templateVersionName = "New Version";
var templateSubject = "edited!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>UPDATE</h1></body></html>"; // optional
updatedTemplateVersion.text = "sometext"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
try
{
var templateVersion = await Template.UpdateTemplateVersionAsync(templateId, versionId, updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateVersionName = "New Template Version";
var templateSubject = "New Version!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>NEW TEMPLATE VERSION</h1></body></html>"; // optional
updatedTemplateVersion.text = "some text"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
updatedTemplateVersion.locale = "en-US"; // optional
try
{
var template = await Template.CreateTemplateAsync(updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "fr-FR";
var templateVersionName = "Published French Version";
var templateSubject = "Ce est un nouveau modèle!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>Nouveau modèle!</h1></body></html>"; // optional
updatedTemplateVersion.text = "un texte"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
try
{
var template = await Template.AddLocaleToTemplate(templateId, locale, updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
NOTE – At least one of html or text must be specified
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var templateVersionName = "New Template Version";
var templateSubject = "New Version!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>NEW TEMPLATE VERSION</h1></body></html>"; // optional
updatedTemplateVersion.text = "some text"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
try
{
var templateVersion = await Template.CreateTemplateVersion(templateId, updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
NOTE – At least one of html or text must be specified
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US";
var templateVersionName = "New Template Version";
var templateSubject = "New Version!";
var updatedTemplateVersion = new TemplateVersion(templateVersionName, templateSubject);
updatedTemplateVersion.html = "<html><head></head><body><h1>NEW TEMPLATE VERSION</h1></body></html>"; // optional
updatedTemplateVersion.text = "some text"; // optional
updatedTemplateVersion.preheader = "some preheader"; // optional
try
{
var templateVersion = await Template.CreateTemplateVersion(templateId, locale, updatedTemplateVersion);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
try
{
var genericApiCallStatus = await Template.DeleteTemplate(templateId);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
var locale = "en-US";
try
{
var genericApiCallStatus = await Template.DeleteTemplate(templateId, locale);
}
catch (AggregateException exception)
{
// Exception handling
}
We validate all HTML content
Example with only the required parameters:
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
// Construct the template data
// The content of the template data is all optional and is based on the template being used
var templateData = new Dictionary<string, object>();
templateData.Add("first_name", "Chuck");
templateData.Add("last_name", "Norris");
templateData.Add("img", "http://placekitten.com/50/60");
var link = new Dictionary<string, string>();
link.Add("url", "https://www.sendwithus.com");
link.Add("text", "sendwithus!");
templateData.Add("link", link);
// Construct the recipient
var recipient = new EmailRecipient(DEFAULT_RECIPIENT_EMAIL_ADDRESS);
// Construct the email object
var email = new Email(templateId, templateData, recipient);
// Send the email
try
{
var emailResponse = await email.Send();
}
catch (AggregateException exception)
{
// Exception handling
}
Example with all parameters:
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
// Construct the template data
// The content of the template data is all optional and is based on the template being used
var templateData = new Dictionary<string, object>();
templateData.Add("first_name", "Chuck");
templateData.Add("last_name", "Norris");
templateData.Add("img", "http://placekitten.com/50/60");
var link = new Dictionary<string, string>();
link.Add("url", "https://www.sendwithus.com");
link.Add("text", "sendwithus!");
templateData.Add("link", link);
// Construct the recipient
var recipient = new EmailRecipient(DEFAULT_RECIPIENT_EMAIL_ADDRESS);
// Construct the email object
var email = new Email(templateId, templateData, recipient);
email.cc.Add(new EmailRecipient("[email protected]", "CC One"));
email.cc.Add(new EmailRecipient("[email protected]", "CC Two"));
email.bcc.Add(new EmailRecipient("[email protected]", "BCC One"));
email.bcc.Add(new EmailRecipient("[email protected]", "BCC Two"));
email.sender.address = "[email protected]";
email.sender.reply_to = "[email protected]";
email.sender.name = "Company";
email.tags.Add("tag1");
email.tags.Add("tag2");
email.tags.Add("tag3");
email.headers.Add("X-HEADER-ONE", "header-value");
email.inline.id = "cat.png";
email.inline.data = "{BASE_64_ENCODED_FILE_DATA}";
email.files.Add(new EmailFileData("doc.txt", "{BASE_64_ENCODED_FILE_DATA}"));
email.files.Add(new EmailFileData("stuff.zip", "{BASE_64_ENCODED_FILE_DATA}"));
email.version_name = "this version";
email.locale = "en-US";
email.esp_account = "esp_EsgkbqQdDg7F3ncbz9EHW7";
// Send the email
try
{
var emailResponse = await email.Send();
}
catch (AggregateException exception)
{
// Exception handling
}
var logId = "log_88be2c0f8b5c6d3933dd578b6a0f13e5";
try
{
var log = await Log.GetLogAsync(logId);
}
catch (AggregateException exception)
{
// Exception handling
}
var logId = "log_88be2c0f8b5c6d3933dd578b6a0f13e5";
try
{
var logEvents = await Log.GetLogEventsAsync(logId);
}
catch (AggregateException exception)
{
// Exception handling
}
var logId = "log_88be2c0f8b5c6d3933dd578b6a0f13e5";
try
{
var logResendResponse = await Log.ResendLogAsync(logId);
}
catch (AggregateException exception)
{
// Exception handling
}
try
{
var snippets = await Snippet.GetSnippetsAsync();
}
catch (AggregateException exception)
{
// Exception handling
}
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
try
{
var snippets = await Snippet.GetSnippetAsync(snippetId);
}
catch (AggregateException exception)
{
// Exception handling
}
var snippetName = "My First Snippet";
var snippetBody = "<h1>Welcome!</h1>";
try
{
var snippetResponse = await Snippet.CreateSnippetAsync(snippetName, snippetBody);
}
catch (AggregateException exception)
{
// Exception handling
}
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
var snippetName = "Updated Snippet";
var snippetBody = "<h1>Welcome Again!</h1>";
try
{
var response = await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
}
catch (AggregateException exception)
{
// Exception handling
}
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
try
{
var genericApiCallStatus = await Snippet.DeleteSnippetAsync(snippetId);
}
catch (AggregateException exception)
{
// Exception handling
}
var templateId = "tem_SxZKpxJSHPbYDWRSQnAQUR";
// Create the template data
var templateData = new Dictionary<string, object>();
templateData.Add("amount", "$12.00");
// Create the render object
var renderTemplate = new Render(templateId, templateData);
renderTemplate.version_id = "ver_ET3j2snkKhqsjRjtK6bXJE"; // optional. Can use either version_id or version_name to specify a version, but not both
renderTemplate.locale = "en-US"; // optional
renderTemplate.strict = true; // optional. Strict defaults to false if not set
try
{
var renderTemplateResponse = await renderTemplate.RenderTemplateAsync();
}
catch (AggregateException exception)
{
// Exception handling
}
GET /customers/[email protected]
var customerEmailAddress = "[email protected]";
try
{
var customerResponse = await Customer.GetCustomerAsync(customerEmailAddress);
}
catch (AggregateException exception)
{
// Exception handling
}
If a Customer already exists with the specified email address, then a data merge is performed. Merge operations will:
- replace existing attributes with new values
- add any new attributes to the Customer Merge operations will never remove attributes from a Customer. Note that customer data can only be simple data types like strings and integers.
// Build the customer
var customer = new Customer("[email protected]");
customer.data.Add("first_name", "Matt"); // optional
customer.data.Add("city", "San Francisco"); // optional
customer.locale = "en-US"; // optional
// Make the API call
try
{
var genericApiCallStatus = await Customer.CreateOrUpdateCustomerAsync(customer);
}
catch (AggregateException exception)
{
// Exception handling
}
var customerEmailAddress = "[email protected]";
try
{
var genericApiCallStatus = await Customer.DeleteCustomerAsync(customerEmailAddress);
}
catch (AggregateException exception)
{
// Exception handling
}
GET /customers/[email protected]/logs?count={count}&created_lt={timestamp}&created_gt={timestamp}
With no query parameters to filter the logs:
var customerEmailAddress = "[email protected]";
try
{
var customerEmailLogsResponse = await Customer.GetCustomerEmailLogsAsync(customerEmailAddress);
}
catch (AggregateException exception)
{
// Exception handling
}
With all query parameters to filter the logs:
var customerEmailAddress = "[email protected]";
var queryStartTime = 123456789;
var queryEndTime = 987654321;
// Build the query parameters. All of these are optional
var queryParameters = new Dictionary<string, object>();
queryParameters.Add("count", 2);
queryParameters.Add("created_gt", queryStartTime);
queryParameters.Add("created_lt", queryEndTime);
// Make the API call
try
{
var customerEmailLogsResponse = await Customer.GetCustomerEmailLogsAsync(customerEmailAddress, queryParameters);
}
catch (AggregateException exception)
{
// Exception handling
}
This will add the specified customer to the first step of the specified drip campaign. If the first step has a delay on it, then it will send the first email once that delay has elapsed.
var dripCampaignId = "dc_VXKGx85NmwHnRv9FZv88TW";
// Build the drip campaign object
var recipient = new EmailRecipient("[email protected]", "John"); // The email name is optional
var dripCampaign = new DripCampaign(recipient);
dripCampaign.cc.Add(new EmailRecipient("[email protected]", "Suzy Smith")); // Optional
dripCampaign.cc.Add(new EmailRecipient("[email protected]", "Joe")); // Optional
dripCampaign.bcc.Add(new EmailRecipient("[email protected]", "Fake Name")); // Optional
dripCampaign.bcc.Add(new EmailRecipient("[email protected]", "Matt Damon")); // Optional
dripCampaign.sender.address = "[email protected]"; // Optional
dripCampaign.sender.name = "Company"; // Optional
dripCampaign.sender.reply_to = "[email protected]"; // Optional
dripCampaign.tags.Add("tag1"); // Optional
dripCampaign.tags.Add("tag2"); // Optional
dripCampaign.tags.Add("tag3"); // Optional
dripCampaign.locale = "en-US"; // Optional
dripCampaign.esp_account = "esp_1a2b3c4d5e"; // Optional
dripCampaign.email_data.Add("amount", "$12.00"); // Optional
// Make the API call
try
{
var response = await dripCampaign.ActivateAsync(dripCampaignId);
}
catch (AggregateException exception)
{
// Exception handling
}
var dripCampaignId = "dc_VXKGx85NmwHnRv9FZv88TW";
var customerEmailAddress = "[email protected]";
try
{
var dripCampaignResponse = await DripCampaign.DeactivateAsync(dripCampaignId, customerEmailAddress);
}
catch (AggregateException exception)
{
// Exception handling
}
If a user unsubscribes, changes email addresses, or cancels, call this endpoint to remove the specified email address from all active drip campaigns.
var customerEmailAddress = "[email protected]";
try
{
var dripCampaignDeactivateAllResponse = await DripCampaign.DeactivateFromAllCampaignsAsync(customerEmailAddress);
}
catch (AggregateException exception)
{
// Exception handling
}
try
{
var dripCampaignDetails = await DripCampaign.GetDripCampaignsAsync();
}
catch (AggregateException exception)
{
// Exception handling
}
var dripCampaignId = "dc_VXKGx85NmwHnRv9FZv88TW";
try
{
var dripCampaignDetails = await DripCampaign.GetDripCampaignAsync(dripCampaignId);
}
catch (AggregateException exception)
{
// Exception handling
}
The sendwithus batch endpoint enables multiple API calls to be made in a single HTTP request. NOTE – Batch sizes over 10 requests are not recommended.
- By default, batch API calls are limited to 10 per batch.
- Any additional calls beyond 10 will throw an InvalidOperationException.
- This limit can be increased by calling BatchApiRequest.OverrideMaximumBatchRequests(int newMaximum)
The process to making a batch API call is:
- Call BatchApiRequest.StartNewBatchRequest()
- After making this call, all subsequent API calls will queued up in a new batch request.
- Make all the API calls as you normally would. Instead of being sent, these calls will be queued.
- Call BatchApiRequest.SendBatchApiRequest(). This will send the batch request with all of the queued requests, clear the queue, return the response (which will contain the response for each API call in the queue), and exit batch mode.
- After this call, all subsequent API calls will be sent out as soon as they are called, instead of being queued.
- Access the response to each batch command by calling
Additional Features:
- PauseBatchRequest() and ResumeBatchRequest(): Respectively exist and then re-enter batch mode without clearing the list of batched calls. Allows other API calls to be sent immediately (not batched) while building a list of batched API calls.
- AbortBatchRequest(): Allows a batch API calls can be aborted without sending any of the batched calls. This will exit batch mode and clear the list of batched API calls.
Example using 5 commands:
// Start the batch request
BatchApiRequest.StartNewBatchRequest();
// Make the API calls to be batched
var customerEmailAddress = "[email protected]";
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
var snippetName = "Updated Snippet";
var snippetBody = "<h1>Welcome Again!</h1>";
try
{
// Discard the response to the API calls as it will just be an empty object (since the requests aren't actually sent yet)
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
await DripCampaign.GetDripCampaignsAsync();
await Customer.DeleteCustomerAsync(customerEmailAddress);
// Make the batch API Request
var batchResponses = await BatchApiRequest.SendBatchApiRequest();
// Get the response to the individual API calls
var snippets = response[0].GetBody<List<Snippet>>();
var logs = response[1].GetBody<List<Log>>();
var snippetResponse = response[2].GetBody<SnippetResponse>();
var dripCampaignDetails = response[3].GetBody<List<DripCampaignDetails>>();
var genericApiCallStatus = response[4].GetBody<GenericApiCallStatus>();
}
catch (AggregateException exception)
{
// Exception handling
}
catch (InvalidOperationException exception)
{
// Exception handling
}
Example sending 11 commands without overriding the limit (to show when the exception is thrown):
var customerEmailAddress = "[email protected]";
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
var snippetName = "Updated Snippet";
var snippetBody = "<h1>Welcome Again!</h1>";
// Start the batch request
BatchApiRequest.StartNewBatchRequest();
// Make the API calls to be batched
try
{
// Make the first 10 API calls
// Discard the response to the API calls as it will just be an empty object (since the requests aren't actually sent yet)
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
await DripCampaign.GetDripCampaignsAsync();
await Customer.DeleteCustomerAsync(customerEmailAddress);
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
await DripCampaign.GetDripCampaignsAsync();
await Customer.DeleteCustomerAsync(customerEmailAddress);
// Make the 11th API call. This is when the InvalidOperationException will be thrown
await Snippet.GetSnippetsAsync();
// Make the batch API Request. This won't be reached.
var batchResponses = await BatchApiRequest.SendBatchApiRequest();
// Handle the responses
}
catch (AggregateException exception)
{
// Exception handling
}
catch (InvalidOperationException exception)
{
// Exception handling
}
Example sending 12 commands after overriding the limit:
var customerEmailAddress = "[email protected]";
var snippetId = "snp_bn8c87iXuFWdtYLGJrBAWW";
var snippetName = "Updated Snippet";
var snippetBody = "<h1>Welcome Again!</h1>";
// Start the batch request
BatchApiRequest.StartNewBatchRequest();
// Override the maximum number of API calls that can be included in this batch
BatchApiRequest.OverrideMaximumBatchRequests(12);
// Make the API calls to be batched
try
{
// Make the first 10 API calls
// Discard the response to the API calls as it will just be an empty object (since the requests aren't actually sent yet)
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
await DripCampaign.GetDripCampaignsAsync();
await Customer.DeleteCustomerAsync(customerEmailAddress);
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
await Snippet.UpdateSnippetAsync(snippetId, snippetName, snippetBody);
await DripCampaign.GetDripCampaignsAsync();
await Customer.DeleteCustomerAsync(customerEmailAddress);
// Make the 11th and 12th API calls. This is when the InvalidOperationException will be thrown
await Snippet.GetSnippetsAsync();
await Log.GetLogsAsync();
// Make the batch API Request.
var batchResponses = await BatchApiRequest.SendBatchApiRequest();
// Handle the responses
}
catch (AggregateException exception)
{
// Exception handling
}
catch (InvalidOperationException exception)
{
// Exception handling
}
finally
{
// Return the max batch request limit to its default value (optional)
BatchApiRequest.SetMaximumBatchRequestsToDefault();
}
Example pausing and resuming a batch request
// Start the batch request
BatchApiRequest.StartNewBatchRequest();
try
{
// Make the API call to be batched
await Template.GetTemplatesAsync();
// Pause the batch request
BatchApiRequest.PauseBatchRequest();
// Make another API call which will be sent immediately
var snippets = await Snippet.GetSnippetsAsync();
// Resume the batch request and add another API call to it
BatchApiRequest.ResumeBatchRequest();
await Customer.GetCustomerAsync('foo@bar.com');
// Make the final batch request, containing the Get Templates and Get Customer API calls
var batchResponses = await BatchApiRequest.SendBatchApiRequest();
}
catch (AggregateException exception)
{
Assert.Fail(exception.ToString());
}
catch (InvalidOperationException exception)
{
// Exception handling
}
Example aborting a batch request
// Start the batch request
BatchApiRequest.StartNewBatchRequest();
try
{
// Make the API call to be batched
await Template.GetTemplatesAsync();
// Abort the batch request
BatchApiRequest.AbortBatchRequest();
// Make another API call which will be sent immediately
var snippets = await Snippet.GetSnippetsAsync();
// For demonstration, make the aborted batch API Reqeust anyways
// This will be an empty request as the list of batched API calls was cleared by the Abort call
var batchResponses = await BatchApiRequest.SendBatchApiRequest();
}
catch (AggregateException exception)
{
Assert.Fail(exception.ToString());
}
catch (InvalidOperationException exception)
{
// Exception handling
}
The build version is set by the Sendwithus_csharp/appveyor.yml file. It is set so that the 3rd digit in the build number is automatically incremented whenever a new build is made. To change the major or minor build revision, simply edit the line at the top of the file accordingly:
# version format
version: 1.0.{build}
The way the version settings for the final package are set is:
- "version" variable set in appveyor.yml file, as shown above
- appveyor.yml sets the C# project's "assembly_version", "assembly_file_version", and "assembly_informational_version" to this "version"
- the sendwithus_csharp/Sendwithus/SendwithusClient.nuspec sets the NuGet version to the assembly version
This project uses AppVeyor for its CI. AppVeyor is configured to automatically run all of the unit tests whenever a new commit is pushed to GitHub, regardless of the branch. All of the AppVeyor settings are configured in the Sendwithus_csharp/appveyor.yml file. All unused settings are simply commented out, so all available settings can be identified in that file.
The appveyor.yml file is configured to automatically deploy new commits to NuGet. It is configured so that only new commits on the master branch will be deployed. Therefore, please develop all features on a feature branch and only integrate with master when ready for deployment. This setting can be changed under the "build:" settings in the appveyor.yml file. It is also possible to manually build and deploy the solution from www.appveyor.com.
Settings for the NuGet deployment can be edited in the sendwithus_csharp/Sendwithus/SendwithusClient.nuspec file.
The project is CLS compliant, so the package can be used in any .NET language that supports CLS compliant packages. For example, this includes VB.NET and might also include F# and Visual C++. The lattter two haven't been tested, but support for VB.NET has been. To add the package to a solution in a different language, simply follow the same procedure that you would for C#:
- In the Solution Explorer window, right click on your solution and select "Manage NuGet Packages for Solution..."
- Search for "SendwithusClient"
- Be sure to use the one that's by sendwithus. There's another one called SendWithUs.Client by Mimeo, but that is not supported by sendwithus and might not be CLS compliant.
- Select the "SendwithusClient" package and choose "Install" for your solution/project.
The tests are run using Visual Studio's standard unit-testing libaries and built in test runner. Simply select "Test->Run->All Tests" to run the unit tests.
Sendwithus' API typically sends responses back in these ranges:
- 2xx – Successful Request
- 4xx – Failed Request (Client error)
- 5xx – Failed Request (Server error)
If you're receiving an error in the 400 response range follow these steps:
- Double check the data and ID's getting passed to sendwithus
- Ensure your API key is correct
- Make sure there's no extraneous spaces in the id's getting passed