From 2a2a4be3c40273b0562f639dbd12cd855ea7ed7d Mon Sep 17 00:00:00 2001 From: sbohmig <58512481+sbohmig@users.noreply.github.com> Date: Thu, 5 Dec 2019 09:19:19 +0100 Subject: [PATCH 1/3] IDisposable implemented. Web proxy parameter. Constants made public for external use. IList instead of IEnumerable --- .../TranslateClient.cs | 260 ++++++++++-------- 1 file changed, 140 insertions(+), 120 deletions(-) diff --git a/CognitiveServices.Translator.Client/TranslateClient.cs b/CognitiveServices.Translator.Client/TranslateClient.cs index 4c599de..66f90fb 100644 --- a/CognitiveServices.Translator.Client/TranslateClient.cs +++ b/CognitiveServices.Translator.Client/TranslateClient.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -10,123 +11,142 @@ namespace CognitiveServices.Translator { - /// - /// Translate using cognitive service from Microsoft - /// - /// - /// https://docs.microsoft.com/en-us/azure/cognitive-services/translator/quickstarts/csharp - public class TranslateClient : ITranslateClient - { - private const int MaxNumberOfRequestContent = 25; - private const int MaxNumberOfCharacterPerRequest = 5_000; - private const string UriExtensionPath = "translate"; - - private readonly CognitiveServicesConfig _cognitiveServiceConfig = new CognitiveServicesConfig(); - private readonly HttpClient _httpClient; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The cognitive service configuration. - public TranslateClient(CognitiveServicesConfig cognitiveServiceConfig) - { - _cognitiveServiceConfig = cognitiveServiceConfig; - - // In Core 2.1, we can use what is described in: https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.1 - // Otherwise, maybe use RestSharp? - _httpClient = new HttpClient - { - BaseAddress = new Uri(Constants.TranslatorApiBasePath) - }; - } - - /// - /// Translates the content. - /// - /// The content. (Max.: 25 items) - /// The options. - /// - /// The translated content - /// - public IList Translate(IEnumerable content, RequestParameter options) - { - return TranslateAsync(content, options).Result; - } - - /// - /// Translates the content. - /// - /// The content. (Max.: 25 items) - /// The options. - /// - /// The translated content - /// - public IList Translate(RequestContent content, RequestParameter options) - { - return TranslateAsync(new[] { content }, options).Result; - } - - /// - /// Translates the content. - /// - /// The content. (Max.: 25 items) - /// The options. - /// - /// The translated content - /// - public async Task> TranslateAsync(IEnumerable content, RequestParameter options) - { - if (content.Count() > MaxNumberOfRequestContent) - throw new Exception($"Maximum amount of text to be translated have been reached (Max: {MaxNumberOfRequestContent})"); - else if (string.Join(string.Empty, content).Length > MaxNumberOfCharacterPerRequest) - throw new Exception($"Maximum length of all the text to be translated is {MaxNumberOfCharacterPerRequest} characters."); - - var qs = options.ToQueryString(); - - using (var request = new HttpRequestMessage(HttpMethod.Post, $"{UriExtensionPath}?{qs}")) - { - var requestBody = JsonConvert.SerializeObject(content.ToList()); - - // For the request, don't forget the request header stuff. - request.Content = new StringContent(requestBody, Encoding.UTF8, Constants.RequestMediaType); - // Todo We should be alternating between the subscription key. When we detect it's not working. - request.Headers.Add(Constants.RequestHeaderSubscriptionKey, _cognitiveServiceConfig.SubscriptionKey); - - using (var response = await _httpClient.SendAsync(request).ConfigureAwait(false)) - { - if (response.IsSuccessStatusCode) - { - var responseBody = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject>(responseBody); - - return result; - } - else - { - var message = $"Problem happened during translation. " + - $"Status code: {response.StatusCode}, " + - $"Reason: {response.ReasonPhrase}"; - - var exception = new TranslateException(message); - exception.ParseResponseError(response); - throw exception; - } - } - } - } - - /// - /// Translates the content. - /// - /// The content. (Max.: 25 items) - /// The options. - /// - /// The translated content - /// - public Task> TranslateAsync(RequestContent content, RequestParameter options) - { - return TranslateAsync(new[] { content }, options); - } - } + /// + /// Translate using cognitive service from Microsoft + /// + /// + /// https://docs.microsoft.com/en-us/azure/cognitive-services/translator/quickstarts/csharp + public class TranslateClient : ITranslateClient, IDisposable + { + private const string UriExtensionPath = "translate"; + + private readonly CognitiveServicesConfig _cognitiveServiceConfig = new CognitiveServicesConfig(); + private HttpClient _httpClient; + + + + public const int MaxNumberOfRequestContent = 25; + public const int MaxNumberOfCharacterPerRequest = 5_000; + + + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The cognitive service configuration. + public TranslateClient(CognitiveServicesConfig cognitiveServiceConfig, IWebProxy proxy = null) + { + _cognitiveServiceConfig = cognitiveServiceConfig; + + + proxy = proxy ?? WebRequest.DefaultWebProxy; + var handler = new HttpClientHandler() + { + Proxy = proxy, + UseProxy = proxy != WebRequest.DefaultWebProxy + }; + + + // In Core 2.1, we can use what is described in: https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.1 + // Otherwise, maybe use RestSharp? + _httpClient = new HttpClient(handler, true); + _httpClient.BaseAddress = new Uri(Constants.TranslatorApiBasePath); + } + + /// + /// Translates the content. + /// + /// The content. (Max.: 25 items) + /// The options. + /// + /// The translated content + /// + public IList Translate(IEnumerable content, RequestParameter options) + { + return TranslateAsync(content, options).Result; + } + + /// + /// Translates the content. + /// + /// The content. (Max.: 25 items) + /// The options. + /// + /// The translated content + /// + public IList Translate(RequestContent content, RequestParameter options) + { + return TranslateAsync(new[] { content }, options).Result; + } + + /// + /// Translates the content. + /// + /// The content. (Max.: 25 items) + /// The options. + /// + /// The translated content + /// + public async Task> TranslateAsync(IEnumerable content, RequestParameter options) + { + if (content.Count() > MaxNumberOfRequestContent) + throw new Exception($"Maximum amount of text to be translated have been reached (Max: {MaxNumberOfRequestContent})"); + else if (string.Join(string.Empty, content).Length > MaxNumberOfCharacterPerRequest) + throw new Exception($"Maximum length of all the text to be translated is {MaxNumberOfCharacterPerRequest} characters."); + + var qs = options.ToQueryString(); + + using (var request = new HttpRequestMessage(HttpMethod.Post, $"{UriExtensionPath}?{qs}")) + { + var requestBody = JsonConvert.SerializeObject(content.ToList()); + + // For the request, don't forget the request header stuff. + request.Content = new StringContent(requestBody, Encoding.UTF8, Constants.RequestMediaType); + // Todo We should be alternating between the subscription key. When we detect it's not working. + request.Headers.Add(Constants.RequestHeaderSubscriptionKey, _cognitiveServiceConfig.SubscriptionKey); + + using (var response = await _httpClient.SendAsync(request).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var responseBody = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject>(responseBody); + return result; + } + else + { + var message = $"Problem happened during translation. " + + $"Status code: {response.StatusCode}, " + + $"Reason: {response.ReasonPhrase}"; + + var exception = new TranslateException(message); + exception.ParseResponseError(response); + throw exception; + } + } + } + } + + /// + /// Translates the content. + /// + /// The content. (Max.: 25 items) + /// The options. + /// + /// The translated content + /// + public Task> TranslateAsync(RequestContent content, RequestParameter options) + { + return TranslateAsync(new[] { content }, options); + } + + + public void Dispose() + { + _httpClient?.Dispose(); + _httpClient = null; + } + + } } From 27efddf141229916b8ae9fe40aed4708c7ca00d2 Mon Sep 17 00:00:00 2001 From: sbohmig <58512481+sbohmig@users.noreply.github.com> Date: Thu, 5 Dec 2019 09:24:31 +0100 Subject: [PATCH 2/3] Update RequestParameter.cs --- .../Translate/RequestParameter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CognitiveServices.Translator.Client/Translate/RequestParameter.cs b/CognitiveServices.Translator.Client/Translate/RequestParameter.cs index 47fb69f..62ac336 100644 --- a/CognitiveServices.Translator.Client/Translate/RequestParameter.cs +++ b/CognitiveServices.Translator.Client/Translate/RequestParameter.cs @@ -40,7 +40,7 @@ public RequestParameter() /// A string specifying the category (domain) of the translation. This parameter /// is used to get translations from a customized system built with Microsoft Translator Hub. Default value is: general. /// - public string Category => "general"; + public string Category { get; set; } = "general"; /// /// Specifies how profanities should be treated in translations. Possible values From 253b07d35fb5412a8f70fa2b40dbd22423142ea5 Mon Sep 17 00:00:00 2001 From: sbohmig <58512481+sbohmig@users.noreply.github.com> Date: Thu, 5 Dec 2019 09:26:46 +0100 Subject: [PATCH 3/3] Added custom field at the discretion of user. Accept if you feel like it. Could also be handled by user with a derived class obviously. --- .../Translate/RequestContent.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CognitiveServices.Translator.Client/Translate/RequestContent.cs b/CognitiveServices.Translator.Client/Translate/RequestContent.cs index cc97a5d..ffeada0 100644 --- a/CognitiveServices.Translator.Client/Translate/RequestContent.cs +++ b/CognitiveServices.Translator.Client/Translate/RequestContent.cs @@ -25,5 +25,12 @@ public string Text _text = value; } } + + + /// + /// User optional key + /// + public int Key { get; set; } + } }