Skip to content

Commit 6f1c953

Browse files
authored
Minor but breaking changes (#15)
* Minor but breaking changes A quick internet search reveals that the two properties that derive from ServiceClient are the now-deprecated Video API and sunsetting Emotion API, so should mostly go unnoticed. * Fix protected object name `UrlReqeust` to `UrlRequest` * Expose the HttpClient instance to a derived class, giving it a chance to dispose it * Beef up error handling to allow both old/new styles of error JSON. * Better messages in exceptions * Fix comments based on CR * Fix comments based on CR (2)
1 parent 10b0875 commit 6f1c953

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

ClientLibrary/ClientException.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public ClientException(string message, string errorCode, HttpStatusCode httpStat
120120
/// <param name="error">The error entity.</param>
121121
/// <param name="httpStatus">The http status.</param>
122122
public ClientException(ClientError error, HttpStatusCode httpStatus)
123+
: base(error?.Message)
123124
{
124125
this.Error = error;
125126
this.HttpStatus = httpStatus;

ClientLibrary/ServiceClient.cs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//
1+
//
22
// Copyright (c) Microsoft. All rights reserved.
33
// Licensed under the MIT license.
44
//
@@ -47,7 +47,7 @@ namespace Microsoft.ProjectOxford.Common
4747
{
4848
public abstract class ServiceClient : IDisposable
4949
{
50-
protected class UrlReqeust
50+
protected class UrlRequest
5151
{
5252
public string url { get; set; }
5353
}
@@ -71,7 +71,7 @@ public class WrappedClientError
7171
ContractResolver = s_defaultResolver
7272
};
7373

74-
private readonly HttpClient _httpClient;
74+
protected HttpClient HttpClient { get; }
7575

7676
private readonly bool _ownHttpClient;
7777

@@ -99,7 +99,7 @@ protected ServiceClient(HttpClient httpClient) : this(httpClient, false)
9999
/// <param name="ownHttpClient">True if this object owns the HttpClient, false if the caller owns it.</param>
100100
private ServiceClient(HttpClient httpClient, bool ownHttpClient)
101101
{
102-
_httpClient = httpClient;
102+
HttpClient = httpClient;
103103
_ownHttpClient = ownHttpClient;
104104
}
105105

@@ -121,7 +121,7 @@ protected virtual void Dispose(bool disposing)
121121

122122
if (disposing && _ownHttpClient)
123123
{
124-
_httpClient.Dispose();
124+
HttpClient.Dispose();
125125
}
126126

127127
_disposed = true;
@@ -150,7 +150,7 @@ protected virtual void Dispose(bool disposing)
150150

151151
#region the JSON client
152152
/// <summary>
153-
/// Helper method executing a GET REST request.
153+
/// Helper method executing a POST REST request.
154154
/// </summary>
155155
/// <typeparam name="TRequest">Type of request.</typeparam>
156156
/// <typeparam name="TResponse">Type of response.</typeparam>
@@ -165,18 +165,16 @@ protected Task<TResponse> PostAsync<TRequest, TResponse>(string apiUrl, TRequest
165165
}
166166

167167
/// <summary>
168-
/// Helper method executing a POST REST request.
168+
/// Helper method executing a GET REST request.
169169
/// </summary>
170-
/// <typeparam name="TRequest">Type of request.</typeparam>
171170
/// <typeparam name="TResponse">Type of response.</typeparam>
172171
/// <param name="apiUrl">API URL relative to the apiRoot</param>
173-
/// <param name="requestBody">Content of the HTTP request.</param>
174172
/// <param name="cancellationToken">Async cancellation token</param>
175173
/// <returns>TResponse</returns>
176174
/// <exception cref="ClientException">Service exception</exception>
177-
protected Task<TResponse> GetAsync<TRequest, TResponse>(string apiUrl, TRequest requestBody, CancellationToken cancellationToken)
175+
protected Task<TResponse> GetAsync<TResponse>(string apiUrl, CancellationToken cancellationToken)
178176
{
179-
return SendAsync<TRequest, TResponse>(HttpMethod.Get, apiUrl, requestBody, cancellationToken);
177+
return SendAsync<Object, TResponse>(HttpMethod.Get, apiUrl, null, cancellationToken);
180178
}
181179

182180
/// <summary>
@@ -211,7 +209,7 @@ protected Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, stri
211209
}
212210
}
213211

214-
var task = _httpClient.SendAsync(request, cancellationToken)
212+
var task = HttpClient.SendAsync(request, cancellationToken)
215213
.ContinueWith(t => GetContent(t.Result)
216214
.ContinueWith(u => GetResponse<TResponse>(t.Result, u.Result)));
217215

@@ -230,7 +228,7 @@ private Task<string> GetContent(HttpResponseMessage response)
230228
return response.Content.ReadAsStringAsync();
231229
}
232230
}
233-
else if (response.Content != null && response.Content.Headers.ContentType.MediaType.Contains("application/json"))
231+
else if (response.Content != null && response.Content.Headers.ContentType?.MediaType.Contains("application/json") == true)
234232
{
235233
return response.Content.ReadAsStringAsync();
236234
}
@@ -251,13 +249,20 @@ private TResponse GetResponse<TResponse>(HttpResponseMessage response, string re
251249
}
252250
else
253251
{
254-
if (response.Content != null && response.Content.Headers.ContentType.MediaType.Contains("application/json"))
252+
if (response?.Content?.Headers?.ContentType?.MediaType.Contains("application/json") == true)
255253
{
254+
// Some of the endpoints return an top-level 'error' field (WrappedClientError) whereas some will simply
255+
// return the plain ClientError.
256256
var wrappedClientError = JsonConvert.DeserializeObject<WrappedClientError>(responseContent);
257257
if (wrappedClientError?.Error != null)
258258
{
259259
throw new ClientException(wrappedClientError.Error, response.StatusCode);
260260
}
261+
var clientError = JsonConvert.DeserializeObject<ClientError>(responseContent);
262+
if (clientError != null)
263+
{
264+
throw new ClientException(clientError, response.StatusCode);
265+
}
261266
}
262267

263268
response.EnsureSuccessStatusCode();

0 commit comments

Comments
 (0)