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

Add CancellationToken and .ConfigureAwait(false) #251

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Salesforce.Chatter.Models;
Expand All @@ -20,7 +20,7 @@ public class ChatterClientTests
private static string _password = ConfigurationManager.AppSettings["Password"];

private AuthenticationClient _auth;
private ChatterClient _chatterClient;
private IChatterClient _chatterClient;

[TestFixtureSetUp]
public void Init()
Expand All @@ -39,7 +39,7 @@ public void Init()
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)(SecurityProtocolTypeTls12 | SecurityProtocolTypeTls11);

_auth = new AuthenticationClient();
_auth.UsernamePasswordAsync(_consumerKey, _consumerSecret, _username, _password, TokenRequestEndpointUrl).Wait();
_auth.UsernamePasswordAsync(_consumerKey, _consumerSecret, _username, _password, TokenRequestEndpointUrl, CancellationToken.None).Wait();

_chatterClient = new ChatterClient(_auth.InstanceUrl, _auth.AccessToken, _auth.ApiVersion);
}
Expand Down Expand Up @@ -226,7 +226,7 @@ public async Task Chatter_Get_Users_IsNotNull()
}

#region private functions
private async Task<FeedItem> postFeedItem(ChatterClient chatter)
private async Task<FeedItem> postFeedItem(IChatterClient chatter)
{
var me = await chatter.MeAsync<UserDetail>();
var id = me.id;
Expand Down
76 changes: 39 additions & 37 deletions src/ChatterToolkitForNET/ChatterClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Salesforce.Chatter.Models;
using Salesforce.Common;
Expand All @@ -8,7 +9,8 @@ namespace Salesforce.Chatter
{
public class ChatterClient : IChatterClient, IDisposable
{
private readonly JsonHttpClient _jsonHttpClient;
private readonly IJsonHttpClient _jsonHttpClient;
private readonly JsonHttpClient _fullJsonHttpClient;
private readonly string _itemsOrElements;

public ChatterClient(string instanceUrl, string accessToken, string apiVersion)
Expand All @@ -18,105 +20,105 @@ public ChatterClient(string instanceUrl, string accessToken, string apiVersion)

public ChatterClient(string instanceUrl, string accessToken, string apiVersion, HttpClient httpClient)
{
_jsonHttpClient = new JsonHttpClient(instanceUrl, apiVersion, accessToken, httpClient);
_jsonHttpClient = _fullJsonHttpClient = new JsonHttpClient(instanceUrl, apiVersion, accessToken, httpClient);

// A change in endpoint for feed item was introduced in v31 of the API.
_itemsOrElements = float.Parse(_jsonHttpClient.GetApiVersion().Substring(1)) > 30 ? "feed-elements" : "feed-items";
_itemsOrElements = float.Parse(_fullJsonHttpClient.GetApiVersion().Substring(1)) > 30 ? "feed-elements" : "feed-items";
}

public Task<T> FeedsAsync<T>()
public Task<T> FeedsAsync<T>(CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>("chatter/feeds");
return _jsonHttpClient.HttpGetAsync<T>("chatter/feeds", token);
}

public Task<T> MeAsync<T>()
public Task<T> MeAsync<T>(CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>("chatter/users/me");
return _jsonHttpClient.HttpGetAsync<T>("chatter/users/me", token);
}

public Task<T> PostFeedItemAsync<T>(FeedItemInput feedItemInput, string userId)
public Task<T> PostFeedItemAsync<T>(FeedItemInput feedItemInput, string userId, CancellationToken token)
{
// Feed items not available post v30.0
if (float.Parse(_jsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
if (float.Parse(_fullJsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
{
return _jsonHttpClient.HttpPostAsync<T>(feedItemInput, "chatter/feed-elements");
return _jsonHttpClient.HttpPostAsync<T>(feedItemInput, "chatter/feed-elements", token);
}

return _jsonHttpClient.HttpPostAsync<T>(feedItemInput, string.Format("chatter/feeds/news/{0}/{1}", userId, _itemsOrElements));
return _jsonHttpClient.HttpPostAsync<T>(feedItemInput, string.Format("chatter/feeds/news/{0}/{1}", userId, _itemsOrElements), token);
}

public Task<T> PostFeedItemToObjectAsync<T>(ObjectFeedItemInput envelope)
public Task<T> PostFeedItemToObjectAsync<T>(ObjectFeedItemInput envelope, CancellationToken token)
{
return _jsonHttpClient.HttpPostAsync<T>(envelope, "chatter/feed-elements/");
return _jsonHttpClient.HttpPostAsync<T>(envelope, "chatter/feed-elements/", token);
}

public Task<T> PostFeedItemWithAttachmentAsync<T>(ObjectFeedItemInput envelope, byte[] fileContents, string fileName)
public Task<T> PostFeedItemWithAttachmentAsync<T>(ObjectFeedItemInput envelope, byte[] fileContents, string fileName, CancellationToken token)
{
return _jsonHttpClient.HttpBinaryDataPostAsync<T>("chatter/feed-elements/", envelope, fileContents, "feedElementFileUpload", fileName);
return _jsonHttpClient.HttpBinaryDataPostAsync<T>("chatter/feed-elements/", envelope, fileContents, "feedElementFileUpload", fileName, token);
}

public Task<T> PostFeedItemCommentAsync<T>(FeedItemInput envelope, string feedId)
public Task<T> PostFeedItemCommentAsync<T>(FeedItemInput envelope, string feedId, CancellationToken token)
{
if (float.Parse(_jsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
if (float.Parse(_fullJsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
{
return _jsonHttpClient.HttpPostAsync<T>(envelope, string.Format("chatter/{0}/{1}/capabilities/comments/items", _itemsOrElements, feedId));
return _jsonHttpClient.HttpPostAsync<T>(envelope, string.Format("chatter/{0}/{1}/capabilities/comments/items", _itemsOrElements, feedId), token);
}

return _jsonHttpClient.HttpPostAsync<T>(envelope, string.Format("chatter/{0}/{1}/comments", _itemsOrElements, feedId));
return _jsonHttpClient.HttpPostAsync<T>(envelope, string.Format("chatter/{0}/{1}/comments", _itemsOrElements, feedId), token);
}

public Task<T> LikeFeedItemAsync<T>(string feedId)
public Task<T> LikeFeedItemAsync<T>(string feedId, CancellationToken token)
{
if (float.Parse(_jsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
if (float.Parse(_fullJsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
{
return _jsonHttpClient.HttpPostAsync<T>(null, string.Format("chatter/{0}/{1}/capabilities/chatter-likes/items", _itemsOrElements, feedId));
return _jsonHttpClient.HttpPostAsync<T>(null, string.Format("chatter/{0}/{1}/capabilities/chatter-likes/items", _itemsOrElements, feedId), token);
}

return _jsonHttpClient.HttpPostAsync<T>(null, string.Format("chatter/{0}/{1}/likes", _itemsOrElements, feedId));
return _jsonHttpClient.HttpPostAsync<T>(null, string.Format("chatter/{0}/{1}/likes", _itemsOrElements, feedId), token);
}

public Task<T> ShareFeedItemAsync<T>(string feedId, string userId)
public Task<T> ShareFeedItemAsync<T>(string feedId, string userId, CancellationToken token)
{
var sharedFeedItem = new SharedFeedItemInput { SubjectId = userId };

if (float.Parse(_jsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
if (float.Parse(_fullJsonHttpClient.GetApiVersion().Substring(1)) > 30.0)
{
sharedFeedItem.OriginalFeedElementId = feedId;
return _jsonHttpClient.HttpPostAsync<T>(sharedFeedItem, "chatter/feed-elements");
return _jsonHttpClient.HttpPostAsync<T>(sharedFeedItem, "chatter/feed-elements", token);
}

sharedFeedItem.OriginalFeedItemId = feedId;
return _jsonHttpClient.HttpPostAsync<T>(sharedFeedItem, string.Format("chatter/feeds/user-profile/{0}/{1}", userId, _itemsOrElements));
return _jsonHttpClient.HttpPostAsync<T>(sharedFeedItem, string.Format("chatter/feeds/user-profile/{0}/{1}", userId, _itemsOrElements), token);
}

public Task<T> GetMyNewsFeedAsync<T>(string query = "")
public Task<T> GetMyNewsFeedAsync<T>(string query = "", CancellationToken token = default(CancellationToken))
{
var url = string.Format("chatter/feeds/news/me/{0}", _itemsOrElements);

if (!string.IsNullOrEmpty(query))
url += string.Format("?q={0}", query);

return _jsonHttpClient.HttpGetAsync<T>(url);
return _jsonHttpClient.HttpGetAsync<T>(url, token);
}

public Task<T> GetGroupsAsync<T>()
public Task<T> GetGroupsAsync<T>(CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>("chatter/groups");
return _jsonHttpClient.HttpGetAsync<T>("chatter/groups", token);
}

public Task<T> GetGroupFeedAsync<T>(string groupId)
public Task<T> GetGroupFeedAsync<T>(string groupId, CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>(string.Format("chatter/feeds/record/{0}/{1}", _itemsOrElements, groupId));
return _jsonHttpClient.HttpGetAsync<T>(string.Format("chatter/feeds/record/{0}/{1}", _itemsOrElements, groupId), token);
}

public Task<T> GetUsersAsync<T>()
public Task<T> GetUsersAsync<T>(CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>("chatter/users");
return _jsonHttpClient.HttpGetAsync<T>("chatter/users", token);
}

public Task<T> GetTopicsAsync<T>()
public Task<T> GetTopicsAsync<T>(CancellationToken token)
{
return _jsonHttpClient.HttpGetAsync<T>("connect/topics");
return _jsonHttpClient.HttpGetAsync<T>("connect/topics", token);
}

public void Dispose()
Expand Down
21 changes: 12 additions & 9 deletions src/ChatterToolkitForNET/IChatterClient.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
using System.Threading;
using System.Threading.Tasks;
using Salesforce.Chatter.Models;

namespace Salesforce.Chatter
{
public interface IChatterClient
{
Task<T> FeedsAsync<T>();
Task<T> MeAsync<T>();
Task<T> PostFeedItemAsync<T>(FeedItemInput feedItemInput, string userId);
Task<T> PostFeedItemCommentAsync<T>(FeedItemInput envelope, string feedId);
Task<T> LikeFeedItemAsync<T>(string feedId);
Task<T> ShareFeedItemAsync<T>(string feedId, string userId);
Task<T> GetMyNewsFeedAsync<T>(string query = "");
Task<T> GetGroupsAsync<T>();
Task<T> GetGroupFeedAsync<T>(string groupId);
Task<T> FeedsAsync<T>(CancellationToken token = default(CancellationToken));
Task<T> MeAsync<T>(CancellationToken token = default(CancellationToken));
Task<T> PostFeedItemAsync<T>(FeedItemInput feedItemInput, string userId, CancellationToken token = default(CancellationToken));
Task<T> PostFeedItemCommentAsync<T>(FeedItemInput envelope, string feedId, CancellationToken token = default(CancellationToken));
Task<T> LikeFeedItemAsync<T>(string feedId, CancellationToken token = default(CancellationToken));
Task<T> ShareFeedItemAsync<T>(string feedId, string userId, CancellationToken token = default(CancellationToken));
Task<T> GetMyNewsFeedAsync<T>(string query = "", CancellationToken token = default(CancellationToken));
Task<T> GetGroupsAsync<T>(CancellationToken token = default(CancellationToken));
Task<T> GetGroupFeedAsync<T>(string groupId, CancellationToken token = default(CancellationToken));
Task<T> GetUsersAsync<T>(CancellationToken token = default(CancellationToken));
Task<T> GetTopicsAsync<T>(CancellationToken token = default(CancellationToken));
}
}
6 changes: 3 additions & 3 deletions src/CommonLibrariesForNET.FunctionalTests/CommonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class CommonTests
private static string _username = ConfigurationManager.AppSettings["Username"];
private static string _password = ConfigurationManager.AppSettings["Password"];

private AuthenticationClient _auth;
private JsonHttpClient _jsonHttpClient;
private IAuthenticationClient _auth;
private IJsonHttpClient _jsonHttpClient;

[TestFixtureSetUp]
public void Init()
Expand Down Expand Up @@ -173,7 +173,7 @@ public async Task Upsert_New_CheckReturnInclude()
public async Task BadTokenHandling()
{
var badToken = "badtoken";
var serviceHttpClient = new JsonHttpClient(_auth.InstanceUrl, _auth.ApiVersion, badToken, new HttpClient());
IJsonHttpClient serviceHttpClient = new JsonHttpClient(_auth.InstanceUrl, _auth.ApiVersion, badToken, new HttpClient());

const string query = "SELECT count() FROM Account";

Expand Down
4 changes: 2 additions & 2 deletions src/CommonLibrariesForNET.UnitTests/BulkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public async void Requests_CheckHttpRequestMessage_HttpGetXml()
Assert.AreEqual(r.Headers.GetValues("X-SFDC-Session").First(), "accessToken");
}, new object()));

using (var httpClient = new XmlHttpClient("http://localhost:1899", "v32", "accessToken", client))
using (IXmlHttpClient httpClient = new XmlHttpClient("http://localhost:1899", "v32", "accessToken", client))
{
await httpClient.HttpGetAsync<object>("brad");
}
Expand Down Expand Up @@ -57,7 +57,7 @@ public async void Requests_CheckHttpRequestMessageAndResponseDeserialization_Htt

}, testObject)); // pass in the object to be returned (Same object roundtripped here for simplicity)

using (var httpClient = new XmlHttpClient("http://localhost:1899", "v32", "accessToken", client))
using (IXmlHttpClient httpClient = new XmlHttpClient("http://localhost:1899", "v32", "accessToken", client))
{
var result = await httpClient.HttpPostAsync<SerializerTest>(testObject, "brad");
Assert.AreEqual(testObject.TestField, result.TestField);
Expand Down
14 changes: 7 additions & 7 deletions src/CommonLibrariesForNET.UnitTests/CommonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public async Task Auth_UsernamePassword_Check()
Assert.AreEqual(r.Content.ToString(), "System.Net.Http.FormUrlEncodedContent");
}));

using (var auth = new AuthenticationClient(client))
using (IAuthenticationClient auth = new AuthenticationClient(client))
{
await auth.UsernamePasswordAsync(consumerKey, consumerSecret, username, password);

Expand All @@ -58,7 +58,7 @@ public async Task Requests_CheckHttpRequestMessage_HttpGet()
Assert.AreEqual(r.Headers.Authorization.ToString(), "Bearer accessToken");
}));

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpGetAsync<object>("wade");
}
Expand All @@ -78,7 +78,7 @@ public async Task Requests_CheckHttpRequestMessage_HttpGet_WithNode()
Assert.AreEqual(r.Headers.Authorization.ToString(), "Bearer accessToken");
}));

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpGetAsync<object>("wade");
}
Expand All @@ -98,7 +98,7 @@ public async Task Requests_CheckHttpRequestMessage_HttpPost()
Assert.AreEqual(r.Headers.Authorization.ToString(), "Bearer accessToken");
}));

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpPostAsync<object>(null, "wade");
}
Expand All @@ -118,7 +118,7 @@ public async Task Requests_CheckHttpRequestMessage_HttpPatch()
Assert.AreEqual(r.Headers.Authorization.ToString(), "Bearer accessToken");
}));

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpPatchAsync(null, "wade");
}
Expand All @@ -138,7 +138,7 @@ public async Task Requests_CheckHttpRequestMessage_HttpDelete()
Assert.AreEqual(r.Headers.Authorization.ToString(), "Bearer accessToken");
}));

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpDeleteAsync("wade");
}
Expand All @@ -155,7 +155,7 @@ public async Task Requests_CheckCustomRequestsHeaders()

client.DefaultRequestHeaders.Add("headername", "headervalue");

using (var httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
using (IJsonHttpClient httpClient = new JsonHttpClient("http://localhost:1899", "v36", "accessToken", client))
{
await httpClient.HttpGetAsync<object>("wade");
}
Expand Down
Loading