From 2068ea9b1754b0e611a6420fa090ec0b37087e3e Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Tue, 7 Mar 2017 17:00:49 -0800 Subject: [PATCH 1/7] Adding a way to initialize ServiceClient using provided HttpClient. Added tests --- .../Fakes/FakeServiceClient.cs | 4 + .../ServiceClientTests.cs | 17 +- .../SvcClientWithHttpClientTests.cs | 51 ++++++ .../SvcClients/ContosoServiceClient.cs | 167 ++++++++++++++++++ .../ServiceClient.cs | 46 ++++- 5 files changed, 278 insertions(+), 7 deletions(-) create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs index b745a789087af..95663a238dea4 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs @@ -18,6 +18,10 @@ public FakeServiceClient() // Prevent base constructor from executing } + public FakeServiceClient(HttpClient httpClient) + : base(httpClient) + { } + public FakeServiceClient(HttpClientHandler httpMessageHandler, params DelegatingHandler[] handlers) : base(httpMessageHandler, handlers) { diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs index b083817db0ed6..4098491df7fb0 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs @@ -10,6 +10,7 @@ using Xunit; using System.Net.Http.Headers; using System.Diagnostics; +using Microsoft.Rest.ClientRuntime.Tests.SvcClients; namespace Microsoft.Rest.ClientRuntime.Tests { @@ -109,6 +110,16 @@ public void RetryHandlerRetriesWith500Errors() Assert.Equal(2, attemptsFailed); } + [Fact] + public void FakeSvcClientWithHttpClient() + { + HttpClient hc = new HttpClient(new ContosoMessageHandler()); + var fakeClient = new FakeServiceClient(hc); + HttpResponseMessage response = fakeClient.DoStuffSync("Hello"); + string responseContent = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Contoso Rocks", responseContent); + } + [Fact] public void RetryHandlerRetriesWith500ErrorsAndSucceeds() { @@ -214,7 +225,7 @@ public void AddUserAgentInfoWithVersion() Assert.True(testProduct.Product.Name.Equals(testProductName)); Assert.True(testProduct.Product.Version.Equals(testProductVersion)); } - + #if NET451 [Fact] public void VerifyOsInfoInUserAgent() @@ -230,6 +241,10 @@ public void VerifyOsInfoInUserAgent() Assert.NotEmpty(osProduct.Product.Name); Assert.NotEmpty(osProduct.Product.Version); } + + + + #endif } } \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs new file mode 100644 index 0000000000000..04d141d546a97 --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs @@ -0,0 +1,51 @@ +using Microsoft.Rest.ClientRuntime.Tests.SvcClients; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Rest.ClientRuntime.Tests +{ + public class SvcClientWithHttpClientTests + { + [Fact] + public void InitializeServiceClientWithHttpClient() + { + HttpClient hc = new HttpClient(); + ContosoServiceClient contosoClient = new ContosoServiceClient(hc); + HttpResponseMessage response = contosoClient.DoSyncWork(); + Assert.NotNull(response); + } + + [Fact] + public void GetInitializedHttpClient() + { + ContosoServiceClient contosoClient = new ContosoServiceClient(null); + HttpResponseMessage response = contosoClient.DoSyncWork(); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.NotNull(response); + } + + [Fact] + public void InitializeMessageHandlerPostContructor() + { + HttpClient hc = new HttpClient(new ContosoMessageHandler()); + ContosoServiceClient contosoClient = new ContosoServiceClient(hc); + HttpResponseMessage response = contosoClient.DoSyncWork("Hello"); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Contoso Rocks", cont); + } + + [Fact] + public void ProvideHttpClientAfterInitialization() + { + DelegatingHandler[] handlers = new ContosoMessageHandler[] { new ContosoMessageHandler() }; + ContosoServiceClient contosoClient = new FabricamServiceClient(new HttpClientHandler(), handlers); + HttpResponseMessage response = contosoClient.DoSyncWork(); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Delayed User Provided HttpClient after initialization", cont); + } + } +} diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs new file mode 100644 index 0000000000000..d3b52ebd459fa --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Rest.ClientRuntime.Tests.SvcClients +{ + /// + /// Customized client that emulates how partners will use Customized code to extend + /// generated client. + /// + public class ContosoServiceClient : ServiceClient + { + HttpClient _httpClient; + /// + /// Constructor that accepts HttpClient + /// + /// + public ContosoServiceClient(HttpClient httpClient) : base (httpClient) + { + + } + + public ContosoServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + : base(rootHandler, handlers) + { } + + /// + /// Some task emulating getting response back + /// + /// + /// + public HttpResponseMessage DoSyncWork(string content = null) + { + return Task.Factory.StartNew(() => + { + return DoStuff(content); + }).Unwrap().GetAwaiter().GetResult(); + } + + + /// + /// Creates request and sends + /// + /// string value + /// + private async Task DoStuff(string content = null) + { + // Construct URL + string url = "http://www.microsoft.com"; + + // Create HTTP transport objects + HttpRequestMessage _httpRequest = null; + + _httpRequest = new HttpRequestMessage(); + _httpRequest.Method = HttpMethod.Get; + _httpRequest.RequestUri = new Uri(url); + + // Set content + if (content != null) + { + _httpRequest.Content = new StringContent(content); + } + + // Set Headers + _httpRequest.Headers.Add("x-ms-version", "2013-11-01"); + + return await this.HttpClient.SendAsync(_httpRequest, new CancellationToken()).ConfigureAwait(false); + } + + protected override void Dispose(bool disposing) + { + _httpClient.Dispose(); + base.Dispose(disposing); + } + } + + public class FabricamServiceClient : ContosoServiceClient + { + private HttpClient _httpClient; + public FabricamServiceClient(HttpClient httpClient) : base(httpClient) + { + + } + + public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + : base(rootHandler, handlers) + { } + + /// + /// The idea is to have customized client override Get in the child class inheriting ServiceClient + /// And provide an instance of HttpClient. + /// This is yet another way for anyone to use their own HttpClient and override default existing client + /// + public override HttpClient HttpClient + { + get + { + if (_httpClient == null) + { + _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); + } + + return _httpClient; + } + + protected set + { + base.HttpClient = value; + } + } + } + + /// + /// Custom message handler + /// + public class ContosoMessageHandler : DelegatingHandler + { + public ContosoMessageHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + /// + /// Returns Contoso Rocks response + /// + /// HttpRequestMessage object + /// CancellationToken + /// + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent("Contoso Rocks"); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } + + /// + /// Yet another delegating handler for tests + /// + public class DelayedHandler : DelegatingHandler + { + string _handlerData; + private DelayedHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + public DelayedHandler(string handlerData) + : this() + { + _handlerData = handlerData; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent(_handlerData); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } +} diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs index 35bdb9f55eb80..739b7ed6ae8fe 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs @@ -26,6 +26,7 @@ public abstract class ServiceClient : IDisposable private const string FXVERSION = "FxVersion"; private const string OSNAME = "OSName"; private const string OSVERSION = "OSVersion"; + private HttpClient _httpClient; /// /// Indicates whether the ServiceClient has been disposed. @@ -42,6 +43,7 @@ public abstract class ServiceClient : IDisposable /// private string _fxVersion; + #region NET45 specific code #if NET45 /// /// Indicates OS Name @@ -114,6 +116,7 @@ private string ReadHKLMRegistry(string path, string key) catch { return ""; } } #endif + #endregion /// /// Gets the AssemblyInformationalVersion if available @@ -196,7 +199,7 @@ private string FrameworkVersion /// pipeline). /// protected HttpClientHandler HttpClientHandler { get; set; } - + /// /// Initializes a new instance of the ServiceClient class. /// @@ -209,6 +212,19 @@ protected ServiceClient() { } + /// + /// Initializes a new instance of the ServiceClient class. + /// + /// HttpClient + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "The created objects should be disposed on caller's side")] + protected ServiceClient(HttpClient httpClient) + { + InitializeHttpClient(httpClient, CreateRootHandler()); + } + /// /// Initializes a new instance of the ServiceClient class. /// @@ -253,7 +269,7 @@ protected static HttpClientHandler CreateRootHandler() /// /// Gets the HttpClient used for making HTTP requests. /// - public HttpClient HttpClient { get; protected set; } + public virtual HttpClient HttpClient { get; protected set; } /// /// Gets the UserAgent collection which can be augmented with custom @@ -344,6 +360,17 @@ protected virtual void Dispose(bool disposing) "CA2000:Dispose objects before losing scope", Justification = "We let HttpClient instance dispose")] protected void InitializeHttpClient(HttpClientHandler httpClientHandler, params DelegatingHandler[] handlers) + { + InitializeHttpClient(null, httpClientHandler, handlers); + } + + /// + /// Initialize service client with provided HttpClient + /// + /// HttpClient + /// HttpClientHandler + /// List of handlers from top to bottom (outer handler is the first in the list) + protected void InitializeHttpClient(HttpClient httpClient, HttpClientHandler httpClientHandler, params DelegatingHandler[] handlers) { HttpClientHandler = httpClientHandler; DelegatingHandler currentHandler = new RetryDelegatingHandler(); @@ -360,16 +387,23 @@ protected void InitializeHttpClient(HttpClientHandler httpClientHandler, params { handler = handler.InnerHandler as DelegatingHandler; } + handler.InnerHandler = currentHandler; currentHandler = handlers[i]; } } - var newClient = new HttpClient(currentHandler, false); + if (httpClient == null) + { + HttpClient = new HttpClient(currentHandler, false); + } + else + { + HttpClient = httpClient; + } + FirstMessageHandler = currentHandler; - HttpClient = newClient; - Type type = this.GetType(); - SetUserAgent(type.FullName, ClientVersion); + SetUserAgent(this.GetType().FullName, ClientVersion); } /// From 5ad8dbb0c9824b880075a2d2255ccd745e8a1ead Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Tue, 7 Mar 2017 21:57:46 -0800 Subject: [PATCH 2/7] Rearranged files, added license headers --- ....cs => CustomClientWithHttpClientTests.cs} | 15 ++-- .../ContosoServiceClient.cs | 80 ++----------------- .../CustomClients/FabrikamServiceClient.cs | 71 ++++++++++++++++ .../ServiceClientTests.cs | 15 ++-- 4 files changed, 91 insertions(+), 90 deletions(-) rename src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/{SvcClientWithHttpClientTests.cs => CustomClientWithHttpClientTests.cs} (85%) rename src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/{SvcClients => CustomClients}/ContosoServiceClient.cs (58%) create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs similarity index 85% rename from src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs rename to src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs index 04d141d546a97..410acb8eb01b6 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClientWithHttpClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs @@ -1,14 +1,13 @@ -using Microsoft.Rest.ClientRuntime.Tests.SvcClients; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Xunit; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. namespace Microsoft.Rest.ClientRuntime.Tests { - public class SvcClientWithHttpClientTests + using Microsoft.Rest.ClientRuntime.Tests.CustomClients; + using System.Net.Http; + using Xunit; + + public class CustomClientWithHttpClientTests { [Fact] public void InitializeServiceClientWithHttpClient() diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs similarity index 58% rename from src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs rename to src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs index d3b52ebd459fa..4e831e68380d3 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/SvcClients/ContosoServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Rest.ClientRuntime.Tests.SvcClients + +namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients { + using System; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + /// /// Customized client that emulates how partners will use Customized code to extend /// generated client. @@ -77,43 +75,7 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } } - - public class FabricamServiceClient : ContosoServiceClient - { - private HttpClient _httpClient; - public FabricamServiceClient(HttpClient httpClient) : base(httpClient) - { - - } - - public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) - : base(rootHandler, handlers) - { } - - /// - /// The idea is to have customized client override Get in the child class inheriting ServiceClient - /// And provide an instance of HttpClient. - /// This is yet another way for anyone to use their own HttpClient and override default existing client - /// - public override HttpClient HttpClient - { - get - { - if (_httpClient == null) - { - _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); - } - - return _httpClient; - } - - protected set - { - base.HttpClient = value; - } - } - } - + /// /// Custom message handler /// @@ -138,30 +100,4 @@ protected override async Task SendAsync(HttpRequestMessage return await Task.Run(() => response); } } - - /// - /// Yet another delegating handler for tests - /// - public class DelayedHandler : DelegatingHandler - { - string _handlerData; - private DelayedHandler() : base() - { - InnerHandler = new HttpClientHandler(); - } - - public DelayedHandler(string handlerData) - : this() - { - _handlerData = handlerData; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - StringContent contosoContent = new StringContent(_handlerData); - HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); - response.Content = contosoContent; - return await Task.Run(() => response); - } - } } diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs new file mode 100644 index 0000000000000..884551f11f6e3 --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + public class FabricamServiceClient : ContosoServiceClient + { + private HttpClient _httpClient; + public FabricamServiceClient(HttpClient httpClient) : base(httpClient) + { } + + public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + : base(rootHandler, handlers) + { } + + /// + /// The idea is to have customized client override Get in the child class inheriting ServiceClient + /// and provide an instance of HttpClient. + /// This is yet another way for anyone to use their own HttpClient and override default existing client + /// without using the overloaded ServiceClient(HttpClient) constructor + /// + public override HttpClient HttpClient + { + get + { + if (_httpClient == null) + { + _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); + } + + return _httpClient; + } + + protected set + { + base.HttpClient = value; + } + } + } + + + /// + /// Yet another delegating handler for tests + /// + public class DelayedHandler : DelegatingHandler + { + string _handlerData; + private DelayedHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + public DelayedHandler(string handlerData) + : this() + { + _handlerData = handlerData; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent(_handlerData); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } +} \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs index 4098491df7fb0..afe10e76f6446 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs @@ -1,16 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using Microsoft.Rest.ClientRuntime.Tests.CustomClients; +using Microsoft.Rest.ClientRuntime.Tests.Fakes; +using Microsoft.Rest.TransientFaultHandling; using System; using System.Linq; using System.Net; using System.Net.Http; -using Microsoft.Rest.ClientRuntime.Tests.Fakes; -using Microsoft.Rest.TransientFaultHandling; -using Xunit; using System.Net.Http.Headers; -using System.Diagnostics; -using Microsoft.Rest.ClientRuntime.Tests.SvcClients; +using Xunit; namespace Microsoft.Rest.ClientRuntime.Tests { @@ -115,7 +114,7 @@ public void FakeSvcClientWithHttpClient() { HttpClient hc = new HttpClient(new ContosoMessageHandler()); var fakeClient = new FakeServiceClient(hc); - HttpResponseMessage response = fakeClient.DoStuffSync("Hello"); + HttpResponseMessage response = fakeClient.DoStuffSync(); string responseContent = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); Assert.Equal("Contoso Rocks", responseContent); } @@ -241,10 +240,6 @@ public void VerifyOsInfoInUserAgent() Assert.NotEmpty(osProduct.Product.Name); Assert.NotEmpty(osProduct.Product.Version); } - - - - #endif } } \ No newline at end of file From 956a2ea21c8c2a1b5f037876271020fd7d859c29 Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Wed, 8 Mar 2017 15:35:21 -0800 Subject: [PATCH 3/7] Fixed failing test for Operational Insights. Cleaned up test code for service client tests --- .../CustomClients/ContosoServiceClient.cs | 7 ------ .../CustomClients/FabrikamServiceClient.cs | 11 +++++++--- .../ServiceClient.cs | 22 +++++++++---------- .../Microsoft.Rest.ClientRuntime/project.json | 2 +- .../OperationalInsights.Test/project.json | 9 +++++--- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs index 4e831e68380d3..1e0a79102e980 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -12,7 +12,6 @@ namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients /// public class ContosoServiceClient : ServiceClient { - HttpClient _httpClient; /// /// Constructor that accepts HttpClient /// @@ -68,12 +67,6 @@ private async Task DoStuff(string content = null) return await this.HttpClient.SendAsync(_httpRequest, new CancellationToken()).ConfigureAwait(false); } - - protected override void Dispose(bool disposing) - { - _httpClient.Dispose(); - base.Dispose(disposing); - } } /// diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs index 884551f11f6e3..1bcb775d35379 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs @@ -34,11 +34,16 @@ public override HttpClient HttpClient return _httpClient; } - - protected set + } + + protected override void Dispose(bool disposing) + { + if(_httpClient != null) { - base.HttpClient = value; + _httpClient.Dispose(); } + + base.Dispose(disposing); } } diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs index 739b7ed6ae8fe..d2acfe27e2c07 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs @@ -1,18 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Reflection; -using Microsoft.Rest.TransientFaultHandling; -#if NET45 -using Microsoft.Win32; -#endif namespace Microsoft.Rest { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Reflection; + using Microsoft.Rest.TransientFaultHandling; +#if NET45 + using Microsoft.Win32; +#endif + /// /// ServiceClient is the abstraction for accessing REST operations and their payload data types.. /// @@ -26,7 +27,6 @@ public abstract class ServiceClient : IDisposable private const string FXVERSION = "FxVersion"; private const string OSNAME = "OSName"; private const string OSVERSION = "OSVersion"; - private HttpClient _httpClient; /// /// Indicates whether the ServiceClient has been disposed. diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json index 0bb77c8791928..37220fea58ea0 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json @@ -1,5 +1,5 @@ { - "version": "2.3.5", + "version": "2.3.6", "copyright": "Copyright (c) Microsoft Corporation", "title": "Client Runtime Library for Microsoft AutoRest Generated Clients", "description": "Infrastructure for error handling, tracing, and HttpClient pipeline configuration. Required by client libraries generated using AutoRest. \nSupported Platforms:\n - Portable Class Libraries\n - .NET Framework 4.5\n - Windows 8\n - Windows Phone 8.1\n - DotNet Core", diff --git a/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json b/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json index 9dfc405110a0e..879405fd5bf72 100644 --- a/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json +++ b/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json @@ -22,7 +22,7 @@ "netcoreapp1.0": { "imports": ["dnxcore50", "portable-net45+win8"], "dependencies": { - "System.Diagnostics.Tracing": "4.1.0" + "System.Diagnostics.Tracing": "4.3.0" } } }, @@ -31,10 +31,13 @@ "type": "platform", "version": "1.0.0" }, - "Microsoft.Rest.ClientRuntime.Azure.TestFramework": "[1.4.0-preview,2.0.0)", + "Microsoft.Azure.Management.OperationalInsights": { + "target": "project", + "type": "build" + }, + "Microsoft.Rest.ClientRuntime.Azure.TestFramework": "[1.6.0,2.0.0)", "Microsoft.Rest.ClientRuntime.Azure": "[3.3.3,4.0.0)", "Microsoft.Azure.ResourceManager": "1.0.0-preview", - "Microsoft.Azure.Management.OperationalInsights": "[1.0.0-preview, 2.0.0)", "xunit": "2.2.0-beta2-build3300", "dotnet-test-xunit": "2.2.0-preview2-build1029" } From 6f9654481a458a0d350e550e63313e32772466c8 Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Thu, 9 Mar 2017 13:32:27 -0800 Subject: [PATCH 4/7] Adding missing license headers --- .../CustomClients/ContosoServiceClient.cs | 4 +++- .../CustomClients/FabrikamServiceClient.cs | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs index 1e0a79102e980..f6933644d5daf 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -1,4 +1,6 @@ - +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients { using System; diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs index 1bcb775d35379..97c712d5c0ddb 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs @@ -10,10 +10,20 @@ namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients public class FabricamServiceClient : ContosoServiceClient { private HttpClient _httpClient; + + /// + /// Constructor for FabricamServiceClient + /// + /// HttpClient object public FabricamServiceClient(HttpClient httpClient) : base(httpClient) { } - public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + /// + /// Constructor + /// + /// HttpClientHandler + /// DelegatingHandler + public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) : base(rootHandler, handlers) { } From c40834d9a48e7b66c3a417d63f4a753b7fe75058 Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Thu, 9 Mar 2017 16:11:58 -0800 Subject: [PATCH 5/7] Reverted HttpClient back to original (removing virtual). Adjusted tests accordingly --- .../CustomClientWithHttpClientTests.cs | 2 +- .../CustomClients/ContosoServiceClient.cs | 32 ++++++- .../CustomClients/FabrikamServiceClient.cs | 86 ------------------- .../Microsoft.Rest.ClientRuntime.Tests.xproj | 3 + .../ServiceClient.cs | 2 +- 5 files changed, 36 insertions(+), 89 deletions(-) delete mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs index 410acb8eb01b6..0fb80b72e420b 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs @@ -41,7 +41,7 @@ public void InitializeMessageHandlerPostContructor() public void ProvideHttpClientAfterInitialization() { DelegatingHandler[] handlers = new ContosoMessageHandler[] { new ContosoMessageHandler() }; - ContosoServiceClient contosoClient = new FabricamServiceClient(new HttpClientHandler(), handlers); + ContosoServiceClient contosoClient = new ContosoServiceClient(); HttpResponseMessage response = contosoClient.DoSyncWork(); string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); Assert.Equal("Delayed User Provided HttpClient after initialization", cont); diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs index f6933644d5daf..5ae7a93667c90 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -14,6 +14,11 @@ namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients /// public class ContosoServiceClient : ServiceClient { + public ContosoServiceClient():base() + { + HttpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); + } + /// /// Constructor that accepts HttpClient /// @@ -39,7 +44,6 @@ public HttpResponseMessage DoSyncWork(string content = null) return DoStuff(content); }).Unwrap().GetAwaiter().GetResult(); } - /// /// Creates request and sends @@ -95,4 +99,30 @@ protected override async Task SendAsync(HttpRequestMessage return await Task.Run(() => response); } } + + /// + /// Yet another delegating handler for tests + /// + public class DelayedHandler : DelegatingHandler + { + string _handlerData; + private DelayedHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + public DelayedHandler(string handlerData) + : this() + { + _handlerData = handlerData; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent(_handlerData); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } } diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs deleted file mode 100644 index 97c712d5c0ddb..0000000000000 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients -{ - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; - - public class FabricamServiceClient : ContosoServiceClient - { - private HttpClient _httpClient; - - /// - /// Constructor for FabricamServiceClient - /// - /// HttpClient object - public FabricamServiceClient(HttpClient httpClient) : base(httpClient) - { } - - /// - /// Constructor - /// - /// HttpClientHandler - /// DelegatingHandler - public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) - : base(rootHandler, handlers) - { } - - /// - /// The idea is to have customized client override Get in the child class inheriting ServiceClient - /// and provide an instance of HttpClient. - /// This is yet another way for anyone to use their own HttpClient and override default existing client - /// without using the overloaded ServiceClient(HttpClient) constructor - /// - public override HttpClient HttpClient - { - get - { - if (_httpClient == null) - { - _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); - } - - return _httpClient; - } - } - - protected override void Dispose(bool disposing) - { - if(_httpClient != null) - { - _httpClient.Dispose(); - } - - base.Dispose(disposing); - } - } - - - /// - /// Yet another delegating handler for tests - /// - public class DelayedHandler : DelegatingHandler - { - string _handlerData; - private DelayedHandler() : base() - { - InnerHandler = new HttpClientHandler(); - } - - public DelayedHandler(string handlerData) - : this() - { - _handlerData = handlerData; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - StringContent contosoContent = new StringContent(_handlerData); - HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); - response.Content = contosoContent; - return await Task.Run(() => response); - } - } -} \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj index a00304d6ebbe4..9ae90b04a0bf0 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj @@ -17,5 +17,8 @@ + + + \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs index d2acfe27e2c07..3eac71849a39b 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs @@ -269,7 +269,7 @@ protected static HttpClientHandler CreateRootHandler() /// /// Gets the HttpClient used for making HTTP requests. /// - public virtual HttpClient HttpClient { get; protected set; } + public HttpClient HttpClient { get; protected set; } /// /// Gets the UserAgent collection which can be augmented with custom From 592251ad5980608b061d49a1b11d57e0b59d7c8a Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Tue, 7 Mar 2017 17:00:49 -0800 Subject: [PATCH 6/7] Adding a way to initialize ServiceClient using provided HttpClient in constructor. Added tests Fixed failing test for Operational Insights. Cleaned up test code for service client tests Adding missing license headers. --- .../CustomClientWithHttpClientTests.cs | 50 ++++++++++ .../CustomClients/ContosoServiceClient.cs | 98 +++++++++++++++++++ .../CustomClients/FabrikamServiceClient.cs | 86 ++++++++++++++++ .../Fakes/FakeServiceClient.cs | 4 + .../ServiceClientTests.cs | 20 +++- .../ServiceClient.cs | 66 ++++++++++--- .../Microsoft.Rest.ClientRuntime/project.json | 2 +- .../OperationalInsights.Test/project.json | 9 +- 8 files changed, 310 insertions(+), 25 deletions(-) create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs create mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs new file mode 100644 index 0000000000000..410acb8eb01b6 --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Rest.ClientRuntime.Tests +{ + using Microsoft.Rest.ClientRuntime.Tests.CustomClients; + using System.Net.Http; + using Xunit; + + public class CustomClientWithHttpClientTests + { + [Fact] + public void InitializeServiceClientWithHttpClient() + { + HttpClient hc = new HttpClient(); + ContosoServiceClient contosoClient = new ContosoServiceClient(hc); + HttpResponseMessage response = contosoClient.DoSyncWork(); + Assert.NotNull(response); + } + + [Fact] + public void GetInitializedHttpClient() + { + ContosoServiceClient contosoClient = new ContosoServiceClient(null); + HttpResponseMessage response = contosoClient.DoSyncWork(); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.NotNull(response); + } + + [Fact] + public void InitializeMessageHandlerPostContructor() + { + HttpClient hc = new HttpClient(new ContosoMessageHandler()); + ContosoServiceClient contosoClient = new ContosoServiceClient(hc); + HttpResponseMessage response = contosoClient.DoSyncWork("Hello"); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Contoso Rocks", cont); + } + + [Fact] + public void ProvideHttpClientAfterInitialization() + { + DelegatingHandler[] handlers = new ContosoMessageHandler[] { new ContosoMessageHandler() }; + ContosoServiceClient contosoClient = new FabricamServiceClient(new HttpClientHandler(), handlers); + HttpResponseMessage response = contosoClient.DoSyncWork(); + string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Delayed User Provided HttpClient after initialization", cont); + } + } +} diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs new file mode 100644 index 0000000000000..f6933644d5daf --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients +{ + using System; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Customized client that emulates how partners will use Customized code to extend + /// generated client. + /// + public class ContosoServiceClient : ServiceClient + { + /// + /// Constructor that accepts HttpClient + /// + /// + public ContosoServiceClient(HttpClient httpClient) : base (httpClient) + { + + } + + public ContosoServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + : base(rootHandler, handlers) + { } + + /// + /// Some task emulating getting response back + /// + /// + /// + public HttpResponseMessage DoSyncWork(string content = null) + { + return Task.Factory.StartNew(() => + { + return DoStuff(content); + }).Unwrap().GetAwaiter().GetResult(); + } + + + /// + /// Creates request and sends + /// + /// string value + /// + private async Task DoStuff(string content = null) + { + // Construct URL + string url = "http://www.microsoft.com"; + + // Create HTTP transport objects + HttpRequestMessage _httpRequest = null; + + _httpRequest = new HttpRequestMessage(); + _httpRequest.Method = HttpMethod.Get; + _httpRequest.RequestUri = new Uri(url); + + // Set content + if (content != null) + { + _httpRequest.Content = new StringContent(content); + } + + // Set Headers + _httpRequest.Headers.Add("x-ms-version", "2013-11-01"); + + return await this.HttpClient.SendAsync(_httpRequest, new CancellationToken()).ConfigureAwait(false); + } + } + + /// + /// Custom message handler + /// + public class ContosoMessageHandler : DelegatingHandler + { + public ContosoMessageHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + /// + /// Returns Contoso Rocks response + /// + /// HttpRequestMessage object + /// CancellationToken + /// + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent("Contoso Rocks"); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } +} diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs new file mode 100644 index 0000000000000..97c712d5c0ddb --- /dev/null +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + public class FabricamServiceClient : ContosoServiceClient + { + private HttpClient _httpClient; + + /// + /// Constructor for FabricamServiceClient + /// + /// HttpClient object + public FabricamServiceClient(HttpClient httpClient) : base(httpClient) + { } + + /// + /// Constructor + /// + /// HttpClientHandler + /// DelegatingHandler + public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) + : base(rootHandler, handlers) + { } + + /// + /// The idea is to have customized client override Get in the child class inheriting ServiceClient + /// and provide an instance of HttpClient. + /// This is yet another way for anyone to use their own HttpClient and override default existing client + /// without using the overloaded ServiceClient(HttpClient) constructor + /// + public override HttpClient HttpClient + { + get + { + if (_httpClient == null) + { + _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); + } + + return _httpClient; + } + } + + protected override void Dispose(bool disposing) + { + if(_httpClient != null) + { + _httpClient.Dispose(); + } + + base.Dispose(disposing); + } + } + + + /// + /// Yet another delegating handler for tests + /// + public class DelayedHandler : DelegatingHandler + { + string _handlerData; + private DelayedHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + public DelayedHandler(string handlerData) + : this() + { + _handlerData = handlerData; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent(_handlerData); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } +} \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs index b745a789087af..95663a238dea4 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Fakes/FakeServiceClient.cs @@ -18,6 +18,10 @@ public FakeServiceClient() // Prevent base constructor from executing } + public FakeServiceClient(HttpClient httpClient) + : base(httpClient) + { } + public FakeServiceClient(HttpClientHandler httpMessageHandler, params DelegatingHandler[] handlers) : base(httpMessageHandler, handlers) { diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs index b083817db0ed6..afe10e76f6446 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/ServiceClientTests.cs @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using Microsoft.Rest.ClientRuntime.Tests.CustomClients; +using Microsoft.Rest.ClientRuntime.Tests.Fakes; +using Microsoft.Rest.TransientFaultHandling; using System; using System.Linq; using System.Net; using System.Net.Http; -using Microsoft.Rest.ClientRuntime.Tests.Fakes; -using Microsoft.Rest.TransientFaultHandling; -using Xunit; using System.Net.Http.Headers; -using System.Diagnostics; +using Xunit; namespace Microsoft.Rest.ClientRuntime.Tests { @@ -109,6 +109,16 @@ public void RetryHandlerRetriesWith500Errors() Assert.Equal(2, attemptsFailed); } + [Fact] + public void FakeSvcClientWithHttpClient() + { + HttpClient hc = new HttpClient(new ContosoMessageHandler()); + var fakeClient = new FakeServiceClient(hc); + HttpResponseMessage response = fakeClient.DoStuffSync(); + string responseContent = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + Assert.Equal("Contoso Rocks", responseContent); + } + [Fact] public void RetryHandlerRetriesWith500ErrorsAndSucceeds() { @@ -214,7 +224,7 @@ public void AddUserAgentInfoWithVersion() Assert.True(testProduct.Product.Name.Equals(testProductName)); Assert.True(testProduct.Product.Version.Equals(testProductVersion)); } - + #if NET451 [Fact] public void VerifyOsInfoInUserAgent() diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs index 35bdb9f55eb80..d2acfe27e2c07 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs @@ -1,18 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Reflection; -using Microsoft.Rest.TransientFaultHandling; -#if NET45 -using Microsoft.Win32; -#endif namespace Microsoft.Rest { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Reflection; + using Microsoft.Rest.TransientFaultHandling; +#if NET45 + using Microsoft.Win32; +#endif + /// /// ServiceClient is the abstraction for accessing REST operations and their payload data types.. /// @@ -42,6 +43,7 @@ public abstract class ServiceClient : IDisposable /// private string _fxVersion; + #region NET45 specific code #if NET45 /// /// Indicates OS Name @@ -114,6 +116,7 @@ private string ReadHKLMRegistry(string path, string key) catch { return ""; } } #endif + #endregion /// /// Gets the AssemblyInformationalVersion if available @@ -196,7 +199,7 @@ private string FrameworkVersion /// pipeline). /// protected HttpClientHandler HttpClientHandler { get; set; } - + /// /// Initializes a new instance of the ServiceClient class. /// @@ -209,6 +212,19 @@ protected ServiceClient() { } + /// + /// Initializes a new instance of the ServiceClient class. + /// + /// HttpClient + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Microsoft.Reliability", + "CA2000:Dispose objects before losing scope", + Justification = "The created objects should be disposed on caller's side")] + protected ServiceClient(HttpClient httpClient) + { + InitializeHttpClient(httpClient, CreateRootHandler()); + } + /// /// Initializes a new instance of the ServiceClient class. /// @@ -253,7 +269,7 @@ protected static HttpClientHandler CreateRootHandler() /// /// Gets the HttpClient used for making HTTP requests. /// - public HttpClient HttpClient { get; protected set; } + public virtual HttpClient HttpClient { get; protected set; } /// /// Gets the UserAgent collection which can be augmented with custom @@ -344,6 +360,17 @@ protected virtual void Dispose(bool disposing) "CA2000:Dispose objects before losing scope", Justification = "We let HttpClient instance dispose")] protected void InitializeHttpClient(HttpClientHandler httpClientHandler, params DelegatingHandler[] handlers) + { + InitializeHttpClient(null, httpClientHandler, handlers); + } + + /// + /// Initialize service client with provided HttpClient + /// + /// HttpClient + /// HttpClientHandler + /// List of handlers from top to bottom (outer handler is the first in the list) + protected void InitializeHttpClient(HttpClient httpClient, HttpClientHandler httpClientHandler, params DelegatingHandler[] handlers) { HttpClientHandler = httpClientHandler; DelegatingHandler currentHandler = new RetryDelegatingHandler(); @@ -360,16 +387,23 @@ protected void InitializeHttpClient(HttpClientHandler httpClientHandler, params { handler = handler.InnerHandler as DelegatingHandler; } + handler.InnerHandler = currentHandler; currentHandler = handlers[i]; } } - var newClient = new HttpClient(currentHandler, false); + if (httpClient == null) + { + HttpClient = new HttpClient(currentHandler, false); + } + else + { + HttpClient = httpClient; + } + FirstMessageHandler = currentHandler; - HttpClient = newClient; - Type type = this.GetType(); - SetUserAgent(type.FullName, ClientVersion); + SetUserAgent(this.GetType().FullName, ClientVersion); } /// diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json index 0bb77c8791928..37220fea58ea0 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/project.json @@ -1,5 +1,5 @@ { - "version": "2.3.5", + "version": "2.3.6", "copyright": "Copyright (c) Microsoft Corporation", "title": "Client Runtime Library for Microsoft AutoRest Generated Clients", "description": "Infrastructure for error handling, tracing, and HttpClient pipeline configuration. Required by client libraries generated using AutoRest. \nSupported Platforms:\n - Portable Class Libraries\n - .NET Framework 4.5\n - Windows 8\n - Windows Phone 8.1\n - DotNet Core", diff --git a/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json b/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json index 9dfc405110a0e..879405fd5bf72 100644 --- a/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json +++ b/src/ResourceManagement/OperationalInsights/OperationalInsights.Test/project.json @@ -22,7 +22,7 @@ "netcoreapp1.0": { "imports": ["dnxcore50", "portable-net45+win8"], "dependencies": { - "System.Diagnostics.Tracing": "4.1.0" + "System.Diagnostics.Tracing": "4.3.0" } } }, @@ -31,10 +31,13 @@ "type": "platform", "version": "1.0.0" }, - "Microsoft.Rest.ClientRuntime.Azure.TestFramework": "[1.4.0-preview,2.0.0)", + "Microsoft.Azure.Management.OperationalInsights": { + "target": "project", + "type": "build" + }, + "Microsoft.Rest.ClientRuntime.Azure.TestFramework": "[1.6.0,2.0.0)", "Microsoft.Rest.ClientRuntime.Azure": "[3.3.3,4.0.0)", "Microsoft.Azure.ResourceManager": "1.0.0-preview", - "Microsoft.Azure.Management.OperationalInsights": "[1.0.0-preview, 2.0.0)", "xunit": "2.2.0-beta2-build3300", "dotnet-test-xunit": "2.2.0-preview2-build1029" } From 0efd55022ee63e9ba6656908fb48b392e93f378c Mon Sep 17 00:00:00 2001 From: shahabhijeet Date: Thu, 9 Mar 2017 16:11:58 -0800 Subject: [PATCH 7/7] Reverted HttpClient back to original (removing virtual). Adjusted tests accordingly --- .../CustomClientWithHttpClientTests.cs | 2 +- .../CustomClients/ContosoServiceClient.cs | 32 ++++++- .../CustomClients/FabrikamServiceClient.cs | 86 ------------------- .../Microsoft.Rest.ClientRuntime.Tests.xproj | 3 + .../ServiceClient.cs | 2 +- 5 files changed, 36 insertions(+), 89 deletions(-) delete mode 100644 src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs index 410acb8eb01b6..0fb80b72e420b 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClientWithHttpClientTests.cs @@ -41,7 +41,7 @@ public void InitializeMessageHandlerPostContructor() public void ProvideHttpClientAfterInitialization() { DelegatingHandler[] handlers = new ContosoMessageHandler[] { new ContosoMessageHandler() }; - ContosoServiceClient contosoClient = new FabricamServiceClient(new HttpClientHandler(), handlers); + ContosoServiceClient contosoClient = new ContosoServiceClient(); HttpResponseMessage response = contosoClient.DoSyncWork(); string cont = response.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); Assert.Equal("Delayed User Provided HttpClient after initialization", cont); diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs index f6933644d5daf..5ae7a93667c90 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/ContosoServiceClient.cs @@ -14,6 +14,11 @@ namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients /// public class ContosoServiceClient : ServiceClient { + public ContosoServiceClient():base() + { + HttpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); + } + /// /// Constructor that accepts HttpClient /// @@ -39,7 +44,6 @@ public HttpResponseMessage DoSyncWork(string content = null) return DoStuff(content); }).Unwrap().GetAwaiter().GetResult(); } - /// /// Creates request and sends @@ -95,4 +99,30 @@ protected override async Task SendAsync(HttpRequestMessage return await Task.Run(() => response); } } + + /// + /// Yet another delegating handler for tests + /// + public class DelayedHandler : DelegatingHandler + { + string _handlerData; + private DelayedHandler() : base() + { + InnerHandler = new HttpClientHandler(); + } + + public DelayedHandler(string handlerData) + : this() + { + _handlerData = handlerData; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + StringContent contosoContent = new StringContent(_handlerData); + HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); + response.Content = contosoContent; + return await Task.Run(() => response); + } + } } diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs deleted file mode 100644 index 97c712d5c0ddb..0000000000000 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/CustomClients/FabrikamServiceClient.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -namespace Microsoft.Rest.ClientRuntime.Tests.CustomClients -{ - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; - - public class FabricamServiceClient : ContosoServiceClient - { - private HttpClient _httpClient; - - /// - /// Constructor for FabricamServiceClient - /// - /// HttpClient object - public FabricamServiceClient(HttpClient httpClient) : base(httpClient) - { } - - /// - /// Constructor - /// - /// HttpClientHandler - /// DelegatingHandler - public FabricamServiceClient(HttpClientHandler rootHandler, DelegatingHandler[] handlers) - : base(rootHandler, handlers) - { } - - /// - /// The idea is to have customized client override Get in the child class inheriting ServiceClient - /// and provide an instance of HttpClient. - /// This is yet another way for anyone to use their own HttpClient and override default existing client - /// without using the overloaded ServiceClient(HttpClient) constructor - /// - public override HttpClient HttpClient - { - get - { - if (_httpClient == null) - { - _httpClient = new HttpClient(new DelayedHandler("Delayed User Provided HttpClient after initialization")); - } - - return _httpClient; - } - } - - protected override void Dispose(bool disposing) - { - if(_httpClient != null) - { - _httpClient.Dispose(); - } - - base.Dispose(disposing); - } - } - - - /// - /// Yet another delegating handler for tests - /// - public class DelayedHandler : DelegatingHandler - { - string _handlerData; - private DelayedHandler() : base() - { - InnerHandler = new HttpClientHandler(); - } - - public DelayedHandler(string handlerData) - : this() - { - _handlerData = handlerData; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - StringContent contosoContent = new StringContent(_handlerData); - HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); - response.Content = contosoContent; - return await Task.Run(() => response); - } - } -} \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj index a00304d6ebbe4..9ae90b04a0bf0 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime.Tests/Microsoft.Rest.ClientRuntime.Tests.xproj @@ -17,5 +17,8 @@ + + + \ No newline at end of file diff --git a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs index d2acfe27e2c07..3eac71849a39b 100644 --- a/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs +++ b/src/ClientRuntime/Microsoft.Rest.ClientRuntime/ServiceClient.cs @@ -269,7 +269,7 @@ protected static HttpClientHandler CreateRootHandler() /// /// Gets the HttpClient used for making HTTP requests. /// - public virtual HttpClient HttpClient { get; protected set; } + public HttpClient HttpClient { get; protected set; } /// /// Gets the UserAgent collection which can be augmented with custom