Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strongly typed #211

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
ed82d9f
Add an overloaded RequestAsync to accept JArray and also refactor it …
Jericho Feb 1, 2016
eb5a119
Reformat
Jericho Feb 1, 2016
0b66b5c
Strongly typed GlobalStats
Jericho Feb 2, 2016
40fadc9
Strongly typed GlobalSuppressions
Jericho Feb 3, 2016
4659022
Strongly typed UnsubscribeGroups
Jericho Feb 3, 2016
602a9b4
Strongly typed 'Suppression'
Jericho Feb 4, 2016
fb10162
Add overload Client.Post method to accept a JArray
Jericho Feb 5, 2016
35880a9
Strongly typed Bounces
Jericho Feb 15, 2016
8e5f0d4
Strongly typed custom fields
Jericho Feb 15, 2016
b4e1f67
Display the underlying error message when exception occurs
Jericho Feb 15, 2016
5e6b31c
Added missing reference to system serialization
Jericho Feb 16, 2016
68da11f
Strongly typed Lists
Jericho Feb 16, 2016
3a01e79
Added strongly typed Custom Fields
Jericho Feb 16, 2016
ede9da5
Merge pull request #1 from sendgrid/master
Jericho Feb 17, 2016
be134ae
Add an overloaded RequestAsync to accept JArray and also refactor it …
Jericho Feb 1, 2016
7dcfd55
Reformat
Jericho Feb 1, 2016
b9ffdea
Strongly typed GlobalStats
Jericho Feb 2, 2016
017895a
Strongly typed GlobalSuppressions
Jericho Feb 3, 2016
356dc2f
Strongly typed UnsubscribeGroups
Jericho Feb 3, 2016
3a22e63
Strongly typed 'Suppression'
Jericho Feb 4, 2016
3310daa
Add overload Client.Post method to accept a JArray
Jericho Feb 5, 2016
b15c283
Strongly typed Bounces
Jericho Feb 15, 2016
431ab71
Strongly typed custom fields
Jericho Feb 15, 2016
de04c00
Display the underlying error message when exception occurs
Jericho Feb 15, 2016
0285525
Added missing reference to system serialization
Jericho Feb 16, 2016
8c18087
Strongly typed Lists
Jericho Feb 16, 2016
0f32188
Added strongly typed Custom Fields
Jericho Feb 16, 2016
adc84b8
Merge branch 'strongly_typed' of https://github.com/Jericho/sendgrid-…
Jericho Feb 17, 2016
7134d77
Strongly typed Segments
Jericho Feb 17, 2016
158d23b
Replace 'new JArray(...)' with JArray.FromObject(...)'
Jericho Feb 17, 2016
a41801b
Stringly typed Contacts
Jericho Feb 20, 2016
3e776ea
Strongly typed Templates and Template Versions
Jericho Feb 25, 2016
b4d66aa
Add cancellation token to async methods
Jericho Feb 29, 2016
b5ccd02
Configure the 'Example' project to be built
Jericho Mar 1, 2016
23964af
Add 3 missing files
Jericho Mar 1, 2016
8f3deb4
Merge branch 'strongly_typed' of https://github.com/Jericho/sendgrid-…
Jericho Mar 1, 2016
a59cd03
Get rid of Visual Studio warning: CS4014 Because this call is not awa…
Jericho Mar 1, 2016
d443120
Strongly typed Categories and User
Jericho Mar 1, 2016
595b03a
Merge branch 'strongly_typed' of https://github.com/Jericho/sendgrid-…
Jericho Mar 1, 2016
29dad31
Strongly typed Categories and User
Jericho Mar 1, 2016
9b3b281
Merge branch 'strongly_typed' of https://github.com/Jericho/sendgrid-…
Jericho Mar 1, 2016
b3426fb
ConfigureAwait(false)
Jericho Mar 4, 2016
60bc811
Strongly typed Api Keys
Jericho Mar 18, 2016
f853d70
Add .editorconfig file
Jericho Mar 18, 2016
edd4ca2
Revert changes I did not intend to commit
Jericho Mar 18, 2016
a015d29
Strongly typed campaigns
Jericho Mar 23, 2016
6e00d13
Fix unit tests
Jericho Mar 24, 2016
18d6856
Implement IDisposable interface
Jericho Apr 10, 2016
0448307
Get rid of the 'The method '...' does not need to use async/await" wa…
Jericho May 10, 2016
83cce39
Fix parameters in XML documentation that do not match the name of the…
Jericho May 10, 2016
6fe8609
Fix bug: Segments.GetRecipientsAsync ignores the segmentId
Jericho May 10, 2016
7eeeb4a
Remove redundant empty parentheses
Jericho May 10, 2016
4be377d
Convert fields to readonly
Jericho May 10, 2016
2461764
Remove redundant comma in array initializer
Jericho May 10, 2016
ec39dfa
Fix the SendGridMessage constructor that ignored the 'header' parameter
Jericho May 10, 2016
8d011fe
Merge branch 'strongly_typed' of https://github.com/Jericho/sendgrid-…
Jericho May 10, 2016
6876a8a
Restore Apikeys.cs which was overwritten in the last merge
Jericho May 10, 2016
3fa56fb
Misc
Jericho May 10, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Strongly typed UnsubscribeGroups
Also allow the HttpClient to be injected (this is useful for mocking and for using Fiddler)
  • Loading branch information
Jericho committed Feb 17, 2016
commit 356dc2fae5ad5e945c63d43675ded3e13674991e
99 changes: 55 additions & 44 deletions SendGrid/Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,47 @@
using SendGrid.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Mail;
using System.Net.Security;

namespace Example
{
internal class Program
{
private static void Main()
{
// Do you want to proxy requests through fiddler?
var useFiddler = false;

if (useFiddler)
{
// This is necessary to ensure HTTPS traffic can be proxied through Fiddler without any certificate validation error.
// This is fine for testing but not advisable in production
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
}

// Direct all traffic through fiddler running on the local machine
var httpClient = new HttpClient(
new HttpClientHandler()
{
Proxy = new WebProxy("http://localhost:8888"),
UseProxy = useFiddler
}
);

// Test sending email
var to = "example@example.com";
var from = "example@example.com";
var fromName = "Jane Doe";
SendEmail(to, from, fromName);
// Test viewing, creating, modifying and deleting API keys through our v3 Web API
ApiKeys();
UnsubscribeGroups();
Suppressions();
GlobalSuppressions();
GlobalStats();
ApiKeys(httpClient);
UnsubscribeGroups(httpClient);
Suppressions(httpClient);
GlobalSuppressions(httpClient);
GlobalStats(httpClient);
}

private static void SendAsync(SendGrid.SendGridMessage message)
Expand Down Expand Up @@ -62,10 +83,10 @@ private static void SendEmail(string to, string from, string fromName)
SendAsync(myMessage);
}

private static void ApiKeys()
private static void ApiKeys(HttpClient httpClient)
{
String apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey);
var client = new SendGrid.Client(apiKey: apiKey, httpClient: httpClient);

// GET API KEYS
HttpResponseMessage responseGet = client.ApiKeys.Get().Result;
Expand Down Expand Up @@ -102,48 +123,38 @@ private static void ApiKeys()
Console.ReadKey();
}

private static void UnsubscribeGroups()
private static void UnsubscribeGroups(HttpClient httpClient)
{
String apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey);
Console.WriteLine("\n***** UNSUBSCRIBE GROUPS *****");

var apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey: apiKey, httpClient: httpClient);

// CREATE A NEW SUPPRESSION GROUP
var newGroup = client.UnsubscribeGroups.CreateAsync("New group", "This is a new group for testing purposes", false).Result;
Console.WriteLine("Unique ID of the new suppresion group: {0}", newGroup.Id);

// UPDATE A SUPPRESSION GROUP
var updatedGroup = client.UnsubscribeGroups.UpdateAsync(newGroup.Id, "This is the updated name").Result;
Console.WriteLine("Suppresion group {0} updated", updatedGroup.Id);

// GET UNSUBSCRIBE GROUPS
HttpResponseMessage responseGet = client.UnsubscribeGroups.Get().Result;
Console.WriteLine(responseGet.StatusCode);
Console.WriteLine(responseGet.Content.ReadAsStringAsync().Result);
Console.WriteLine("These are your current Unsubscribe Groups. Press any key to continue.");
Console.ReadKey();
var groups = client.UnsubscribeGroups.GetAllAsync().Result;
Console.WriteLine("There are {0} suppresion groups", groups.Length);

// GET A PARTICULAR UNSUBSCRIBE GROUP
int unsubscribeGroupID = 69;
HttpResponseMessage responseGetUnique = client.UnsubscribeGroups.Get(unsubscribeGroupID).Result;
Console.WriteLine(responseGetUnique.StatusCode);
Console.WriteLine(responseGetUnique.Content.ReadAsStringAsync().Result);
Console.WriteLine("This is an Unsubscribe Group with ID: " + unsubscribeGroupID.ToString() + ".\n\nPress any key to continue.");
Console.ReadKey();

// POST UNSUBSCRIBE GROUP
HttpResponseMessage responsePost = client.UnsubscribeGroups.Post("C Sharp Unsubscribes", "Testing the C Sharp Library", false).Result;
var rawString = responsePost.Content.ReadAsStringAsync().Result;
dynamic jsonObject = JObject.Parse(rawString);
var unsubscribeGroupId = jsonObject.id.ToString();
Console.WriteLine(responsePost.StatusCode);
Console.WriteLine(responsePost.Content.ReadAsStringAsync().Result);
Console.WriteLine("Unsubscribe Group created.\n\nPress any key to continue.");
Console.ReadKey();
var group = client.UnsubscribeGroups.GetAsync(newGroup.Id).Result;
Console.WriteLine("Retrieved unsubscribe group {0}: {1}", group.Id, group.Name);

// DELETE UNSUBSCRIBE GROUP
Console.WriteLine("Deleting Unsubscribe Group, please wait.");
HttpResponseMessage responseDelete = client.UnsubscribeGroups.Delete(unsubscribeGroupId).Result;
Console.WriteLine(responseDelete.StatusCode);
HttpResponseMessage responseFinal = client.UnsubscribeGroups.Get().Result;
Console.WriteLine(responseFinal.StatusCode);
Console.WriteLine(responseFinal.Content.ReadAsStringAsync().Result);
Console.WriteLine("Unsubscribe Group Deleted.\n\nPress any key to end.");
client.UnsubscribeGroups.DeleteAsync(newGroup.Id).Wait();
Console.WriteLine("Suppression group {0} deleted", newGroup.Id);

Console.WriteLine("\n\nPress any key to continue");
Console.ReadKey();
}

private static void Suppressions()
private static void Suppressions(HttpClient httpClient)
{
String apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey);
Expand Down Expand Up @@ -179,17 +190,17 @@ private static void Suppressions()
Console.ReadKey();
}

private static void GlobalSuppressions()
private static void GlobalSuppressions(HttpClient httpClient)
{
Console.WriteLine("\n***** GLOBAL SUPPRESSION *****");

var apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey);
var client = new SendGrid.Client(apiKey: apiKey, httpClient: httpClient);

// ADD EMAILS TO THE GLOBAL SUPPRESSION LIST
var emails = new[] { "example@example.com", "example2@example.com" };
client.GlobalSuppressions.AddAsync(emails).Wait();
Console.WriteLine("\nThe following emails have been added to the global suppression list: {0}", string.Join(", ", emails));
Console.WriteLine("The following emails have been added to the global suppression list: {0}", string.Join(", ", emails));
Console.WriteLine("Is {0} unsubscribed (should be true): {1}", emails[0], client.GlobalSuppressions.IsUnsubscribedAsync(emails[0]).Result);
Console.WriteLine("Is {0} unsubscribed (should be true): {1}", emails[1], client.GlobalSuppressions.IsUnsubscribedAsync(emails[1]).Result);

Expand All @@ -206,12 +217,12 @@ private static void GlobalSuppressions()
Console.ReadKey();
}

private static void GlobalStats()
private static void GlobalStats(HttpClient httpClient)
{
Console.WriteLine("\n***** GLOBAL STATS *****");

var apiKey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY", EnvironmentVariableTarget.User);
var client = new SendGrid.Client(apiKey);
var client = new SendGrid.Client(apiKey: apiKey, httpClient: httpClient);

// Global Stats provide all of your user’s email statistics for a given date range.
var startDate = new DateTime(2015, 11, 01);
Expand Down
94 changes: 47 additions & 47 deletions SendGrid/SendGrid/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,44 @@ namespace SendGrid
public class Client
{
private string _apiKey;
public APIKeys ApiKeys;
public UnsubscribeGroups UnsubscribeGroups;
public Suppressions Suppressions;
public GlobalSuppressions GlobalSuppressions;
public GlobalStats GlobalStats;
public string Version;
private Uri _baseUri;
private HttpClient _httpClient;
private const string MediaType = "application/json";
private enum Methods
{
GET, POST, PATCH, DELETE
}

public APIKeys ApiKeys { get; private set; }
public UnsubscribeGroups UnsubscribeGroups { get; private set; }
public Suppressions Suppressions { get; private set; }
public GlobalSuppressions GlobalSuppressions { get; private set; }
public GlobalStats GlobalStats { get; private set; }
public string Version { get; private set; }

/// <summary>
/// Create a client that connects to the SendGrid Web API
/// </summary>
/// <param name="apiKey">Your SendGrid API Key</param>
/// <param name="baseUri">Base SendGrid API Uri</param>
public Client(string apiKey, string baseUri = "https://api.sendgrid.com/")
public Client(string apiKey, string baseUri = "https://api.sendgrid.com/", HttpClient httpClient = null)
{
_baseUri = new Uri(baseUri);
_apiKey = apiKey;

Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
ApiKeys = new APIKeys(this);
UnsubscribeGroups = new UnsubscribeGroups(this);
Suppressions = new Suppressions(this);
GlobalSuppressions = new GlobalSuppressions(this);
GlobalStats = new GlobalStats(this);

_httpClient = httpClient ?? new HttpClient();
_httpClient.BaseAddress = _baseUri;
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", string.Format("sendgrid/{0};csharp", Version));
}

/// <summary>
Expand Down Expand Up @@ -78,50 +88,40 @@ private async Task<HttpResponseMessage> RequestAsync(Methods method, string endp
/// <returns>An asyncronous task</returns>
private async Task<HttpResponseMessage> RequestAsync(Methods method, string endpoint, StringContent content)
{
using (var client = new HttpClient())
try
{
try
var methodAsString = "";
switch (method)
{
client.BaseAddress = _baseUri;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "sendgrid/" + Version + ";csharp");

var methodAsString = "";
switch (method)
{
case Methods.GET: methodAsString = "GET"; break;
case Methods.POST: methodAsString = "POST"; break;
case Methods.PATCH: methodAsString = "PATCH"; break;
case Methods.DELETE: methodAsString = "DELETE"; break;
default:
var message = "{\"errors\":[{\"message\":\"Bad method call, supported methods are GET, POST, PATCH and DELETE\"}]}";
var response = new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)
{
Content = new StringContent(message)
};
return response;
}

var postRequest = new HttpRequestMessage()
{
Method = new HttpMethod(methodAsString),
RequestUri = new Uri(_baseUri + endpoint),
Content = content
};
return await client.SendAsync(postRequest);

case Methods.GET: methodAsString = "GET"; break;
case Methods.POST: methodAsString = "POST"; break;
case Methods.PATCH: methodAsString = "PATCH"; break;
case Methods.DELETE: methodAsString = "DELETE"; break;
default:
var message = "{\"errors\":[{\"message\":\"Bad method call, supported methods are GET, POST, PATCH and DELETE\"}]}";
var response = new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)
{
Content = new StringContent(message)
};
return response;
}
catch (Exception ex)

var httpRequest = new HttpRequestMessage()
{
var message = string.Format(".NET {0}, raw message: \n\n{1}", (ex is HttpRequestException) ? "HttpRequestException" : "Exception", ex.Message);
var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(message)
};
return response;
}
Method = new HttpMethod(methodAsString),
RequestUri = new Uri(_baseUri + endpoint),
Content = content
};
return await _httpClient.SendAsync(httpRequest);
}
catch (Exception ex)
{
var message = string.Format(".NET {0}, raw message: \n\n{1}", (ex is HttpRequestException) ? "HttpRequestException" : "Exception", ex.Message);
var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(message)
};
return response;
}
}

Expand Down
19 changes: 19 additions & 0 deletions SendGrid/SendGrid/Model/SuppressionGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Newtonsoft.Json;

namespace SendGrid.Model
{
public class SuppressionGroup
{
[JsonProperty("id")]
public int Id { get; set; }

[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("description")]
public string Description { get; set; }

[JsonProperty("is_default")]
public bool IsDefault { get; set; }
}
}
3 changes: 1 addition & 2 deletions SendGrid/SendGrid/Resources/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ public async Task<bool> IsUnsubscribedAsync(string email)
/// <returns>https://sendgrid.com/docs/API_Reference/Web_API_v3/Suppression_Management/global_suppressions.html</returns>
public async Task AddAsync(IEnumerable<string> emails)
{
var receipient_emails = new JArray(emails.ToArray());
var data = new JObject(new JProperty("recipient_emails", receipient_emails));
var data = new JObject(new JProperty("recipient_emails", new JArray(emails.ToArray())));
var response = await _client.Post(_endpoint, data);
response.EnsureSuccess();
}
Expand Down
Loading