Skip to content

Commit

Permalink
Enhance use http proxy with http factory (#3899)
Browse files Browse the repository at this point in the history
* 2890 started to implement

* Add test for new functionality

---------

Co-authored-by: Rockford Lhotka <rocky@lhotka.net>
  • Loading branch information
StefanOssendorf and rockfordlhotka committed May 3, 2024
1 parent 8c8108a commit bba0987
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 11 deletions.
37 changes: 37 additions & 0 deletions Source/Csla.test/HttpProxy/HttpProxyExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Csla.Channels.Http;
using Csla.Configuration;
using Csla.TestHelpers;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Csla.Test.HttpProxy;

[TestClass]
public class HttpProxyExtensionsTests
{
[TestMethod]
public void UseHttpProxy_WhenConfiguringACustomHttpClientFactoryItShouldBeUsedWhenHttpProxyIsCreated()
{
bool hasBeenCalled = false;
HttpClient CustomFactory(IServiceProvider sp)
{
hasBeenCalled = true;
return new HttpClient();
}

var diContext = TestDIContextFactory.CreateContext(
o => o.DataPortal(
dp => dp.ClientSideDataPortal(
cdp => cdp.UseHttpProxy(
hp => hp.WithHttpClientFactory(CustomFactory)
)
)
)
);

_ = diContext.ServiceProvider.GetRequiredService<Csla.DataPortalClient.IDataPortalProxy>();

hasBeenCalled.Should().BeTrue();
}
}
67 changes: 67 additions & 0 deletions Source/Csla.test/HttpProxy/HttpProxyOptionsExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Csla.Channels.Http;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Csla.Test.HttpProxy;

[TestClass]
public class HttpProxyOptionsExtensionsTests
{
[TestMethod]
public void WithDataPortalUrl_ShouldSetTheDataPortalUrlAsExpected()
{
var options = new HttpProxyOptions();
options.WithDataPortalUrl("http://localhost:1337");

var expectedOptions = new HttpProxyOptions
{
DataPortalUrl = "http://localhost:1337"
};

options.Should().BeEquivalentTo(expectedOptions);
}

[TestMethod]
public void UseTextForSerialization_ShouldSetTheUseTextSerializationToTrue()
{
var options = new HttpProxyOptions();
options.UseTextForSerialization();

var expectedOptions = new HttpProxyOptions
{
UseTextSerialization = true
};

options.Should().BeEquivalentTo(expectedOptions);
}

[TestMethod]
public void UseDefaultForSerialization_ShouldSetTheUseTextSerializationToFalse()
{
var options = new HttpProxyOptions();
options.UseDefaultForSerialization();

var expectedOptions = new HttpProxyOptions
{
UseTextSerialization = false
};

options.Should().BeEquivalentTo(expectedOptions);
}

[TestMethod]
public void WithHttpClientFactory_ShouldSetTheFactoryToTheProvidedFactory()
{
var options = new HttpProxyOptions();
options.WithHttpClientFactory(httpClientFactory);

var expectedOptions = new HttpProxyOptions
{
HttpClientFactory = httpClientFactory
};

options.Should().BeEquivalentTo(expectedOptions);

static HttpClient httpClientFactory(IServiceProvider sp) => new();
}
}
4 changes: 3 additions & 1 deletion Source/Csla/DataPortalClient/HttpProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace Csla.Channels.Http
/// </summary>
public class HttpProxy : DataPortalProxy
{
private HttpClient _httpClient;

/// <summary>
/// Creates an instance of the type, initializing
/// it to use the supplied HttpClient object and options.
Expand All @@ -42,7 +44,7 @@ public HttpProxy(ApplicationContext applicationContext, HttpClient httpClient, H
/// Current options for the proxy.
/// </summary>
protected HttpProxyOptions Options { get; set; }
private HttpClient _httpClient;

private string VersionRoutingTag { get; set; }

#nullable enable
Expand Down
14 changes: 7 additions & 7 deletions Source/Csla/DataPortalClient/HttpProxyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// <summary>Implement extension methods data portal channel</summary>
//-----------------------------------------------------------------------

using System.Net.Http;
using Csla.DataPortalClient;
using Csla.Channels.Http;
using Microsoft.Extensions.DependencyInjection;

namespace Csla.Configuration
Expand All @@ -22,17 +22,17 @@ public static class HttpProxyExtensions
/// </summary>
/// <param name="config">CslaDataPortalConfiguration object</param>
/// <param name="options">Data portal proxy options</param>
public static DataPortalClientOptions UseHttpProxy(this DataPortalClientOptions config, Action<Csla.Channels.Http.HttpProxyOptions> options)
public static DataPortalClientOptions UseHttpProxy(this DataPortalClientOptions config, Action<HttpProxyOptions> options)
{
var proxyOptions = new Csla.Channels.Http.HttpProxyOptions();
var proxyOptions = new HttpProxyOptions();
options?.Invoke(proxyOptions);
config.Services.AddTransient(typeof(IDataPortalProxy),
sp =>
config.Services.AddTransient<IDataPortalProxy>(
sp =>
{
var applicationContext = sp.GetRequiredService<ApplicationContext>();
var dataPortalOptions = sp.GetRequiredService<DataPortalOptions>();
var client = sp.GetRequiredService<HttpClient>();
return new Csla.Channels.Http.HttpProxy(applicationContext, client, proxyOptions, dataPortalOptions);
var client = proxyOptions.HttpClientFactory(sp);
return new HttpProxy(applicationContext, client, proxyOptions, dataPortalOptions);
});
return config;
}
Expand Down
28 changes: 25 additions & 3 deletions Source/Csla/DataPortalClient/HttpProxyOptions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
//-----------------------------------------------------------------------
#nullable enable
//-----------------------------------------------------------------------
// <copyright file="HttpProxyOptions.cs" company="Marimer LLC">
// Copyright (c) Marimer LLC. All rights reserved.
// Website: https://cslanet.com
// </copyright>
// <summary>Options for HttpProxy</summary>
//-----------------------------------------------------------------------

using Microsoft.Extensions.DependencyInjection;
#if !NETSTANDARD2_0 && !NET6_0_OR_GREATER
using System.Net.Http;
#endif

namespace Csla.Channels.Http
{
/// <summary>
Expand All @@ -16,12 +22,28 @@ public class HttpProxyOptions
/// <summary>
/// Data portal server endpoint URL
/// </summary>
public string DataPortalUrl { get; set; }
public string DataPortalUrl { get; set; } = "";

/// <summary>
/// Gets or sets a value indicating whether to use
/// text/string serialization instead of the default
/// binary serialization.
/// </summary>
public bool UseTextSerialization { get; set; }

/// <summary>
/// Gets or sets the factory to obtain an <see cref="HttpClient"/> to make server calls.
/// </summary>
public Func<IServiceProvider, HttpClient> HttpClientFactory { get; set; } = DefaultHttpFactory;

/// <summary>
/// Default <see cref="HttpClientFactory"/> implementation.
/// </summary>
/// <param name="serviceProvider">The service provider to obtain the <see cref="HttpClient"/>.</param>
/// <returns>The <see cref="HttpClient"/>.</returns>
private static HttpClient DefaultHttpFactory(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<HttpClient>();
}
}
}
}
86 changes: 86 additions & 0 deletions Source/Csla/DataPortalClient/HttpProxyOptionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#nullable enable
//-----------------------------------------------------------------------
// <copyright file="HttpProxyOptions.cs" company="Marimer LLC">
// Copyright (c) Marimer LLC. All rights reserved.
// Website: https://cslanet.com
// </copyright>
// <summary>Extensions for HttpProxyOptions</summary>
//-----------------------------------------------------------------------

#if !NETSTANDARD2_0 && !NET6_0_OR_GREATER
using System.Net.Http;
#endif

namespace Csla.Channels.Http
{
/// <summary>
/// Provides extension methods for <see cref="HttpProxyOptions"/>.
/// </summary>
public static class HttpProxyOptionsExtensions
{
/// <summary>
/// Configures the <see cref="HttpProxyOptions.DataPortalUrl"/>.
/// </summary>
/// <param name="source">The options object.</param>
/// <param name="dataPortalUrl">The data portal server endpoint url to use.</param>
/// <returns>The options object.</returns>
public static HttpProxyOptions WithDataPortalUrl(this HttpProxyOptions source, string dataPortalUrl)
{
if (source is null)
throw new ArgumentNullException(nameof(source));
if (string.IsNullOrEmpty(dataPortalUrl))
throw new ArgumentException($"'{nameof(dataPortalUrl)}' cannot be null or empty.", nameof(dataPortalUrl));

source.DataPortalUrl = dataPortalUrl;
return source;
}

/// <summary>
/// Configures the <see cref="HttpProxyOptions.UseTextSerialization"/> to <see langword="true"/>.
/// </summary>
/// <param name="source">The options object.</param>
/// <returns>The options object.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
public static HttpProxyOptions UseTextForSerialization(this HttpProxyOptions source)
{
if (source is null)
throw new ArgumentNullException(nameof(source));

source.UseTextSerialization = true;
return source;
}

/// <summary>
/// Configures the <see cref="HttpProxyOptions.UseTextSerialization"/> to <see langword="false"/> to use the default serialization.
/// </summary>
/// <param name="source">The options object.</param>
/// <returns>The options object.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
public static HttpProxyOptions UseDefaultForSerialization(this HttpProxyOptions source)
{
if (source is null)
throw new ArgumentNullException(nameof(source));

source.UseTextSerialization = false;
return source;
}

/// <summary>
/// Configures the <see cref="HttpProxyOptions.HttpClientFactory"/> to use the provided factory instead of the default.
/// </summary>
/// <param name="source">The options object.</param>
/// <param name="factory">The factory to obtain an <see cref="HttpClient"/> for use.</param>
/// <returns>The options object.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="factory"/> is <see langword="null"/>.</exception>
public static HttpProxyOptions WithHttpClientFactory(this HttpProxyOptions source, Func<IServiceProvider, HttpClient> factory)
{
if (source is null)
throw new ArgumentNullException(nameof(source));
if (factory is null)
throw new ArgumentNullException(nameof(factory));

source.HttpClientFactory = factory;
return source;
}
}
}

0 comments on commit bba0987

Please sign in to comment.