Skip to content

Commit

Permalink
[#3] - Added two constructor overloads of HalClient, so that IJsonHtt…
Browse files Browse the repository at this point in the history
…pClient can be passed in. This should allow developers to provide their own implementation of IJsonHttpClient rather than use the default one.
  • Loading branch information
eoin55 committed Mar 6, 2016
1 parent 483c878 commit 91e6a20
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 10 deletions.
54 changes: 49 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ Install-Package HoneyBear.HalClient
### 2) Create an instance of HalClient
`HalClient` has a dependency on `HttpClient`. This can be provided in the constructor:
```cs
var client = new HalClient(new HttpClient { BaseAddress = new Uri("https://api.retail.com/") });
var halClent = new HalClient(new HttpClient { BaseAddress = new Uri("https://api.retail.com/") });
```
Or accessed via a public property:
```cs
var client = new HalClient();
client.HttpClient.BaseAddress = new Uri("https://api.retail.com/");
var halClent = new HalClient();
halClent.HttpClient.BaseAddress = new Uri("https://api.retail.com/");
```

#### (Optional) Custom serializer settings
HalClient uses the default JsonMediaTypeFormatter for handling serialization and deserialization. If you need to change any of the settings (for handling null values, missing properties, custom date formats and so on), you can build a custom MediaTypeFormatter by subclassing JsonMediaTypeFormatter, and then passing it in to the HalClient constructor:
HalClient uses the default JsonMediaTypeFormatter for handling deserialization of responses. If you need to change any of the settings (for handling null values, missing properties, custom date formats and so on), you can build a custom MediaTypeFormatter by subclassing JsonMediaTypeFormatter, and then passing it in to the HalClient constructor:
```cs
public class CustomMediaTypeFormatter : JsonMediaTypeFormatter
{
Expand All @@ -59,7 +59,51 @@ public class CustomMediaTypeFormatter : JsonMediaTypeFormatter
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/hal+json"));
}

var client = new HalClient(new HttpClient { BaseAddress = new Uri("https://api.retail.com/") }, new List<MediaTypeFormatter> { new CustomMediaTypeFormatter() });
var halClent = new HalClient(new HttpClient { BaseAddress = new Uri("https://api.retail.com/") }, new List<MediaTypeFormatter> { new CustomMediaTypeFormatter() });
```

### (Optional) Override default implementation of IJsonHttpClient
By default, `HalClient` uses a internal implementation of `IJsonHttpClient`, which uses `HttpClient` to perform HTTP requests (GET, POST, PUT and DELETE). In some cases, it may be preferable to provide your own implementation of `IJsonHttpClient`. For example, if you want to specify a different `MediaTypeFormatter` for serializing POST and PUT requests:

```cs
public class CustomJsonHttpClient : IJsonHttpClient
{
private readonly CustomMediaTypeFormatter _formatter;

public CustomJsonHttpClient(HttpClient client, CustomMediaTypeFormatter formatter)
{
HttpClient = client;
_formatter = formatter;
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/hal+json"));
}

public HttpClient HttpClient { get; }

public Task<HttpResponseMessage> GetAsync(string uri)
=> HttpClient.GetAsync(uri);

public Task<HttpResponseMessage> PostAsync<T>(string uri, T value)
=> HttpClient.PostAsync(uri, value, _formatter);

public Task<HttpResponseMessage> PutAsync<T>(string uri, T value)
=> HttpClient.PutAsync(uri, value, _formatter);

public Task<HttpResponseMessage> DeleteAsync(string uri)
=> HttpClient.DeleteAsync(uri);
}
```

```cs
var jsonClient = new CustomJsonHttpClient(new HttpClient(), new CustomMediaTypeFormatter());
var halClent = new HalClient(jsonClient);
```

or

```cs
var jsonClient = new CustomJsonHttpClient(new HttpClient(), new CustomMediaTypeFormatter());
var formatters = new List<MediaTypeFormatter> { new CustomMediaTypeFormatter() };
var halClent = new HalClient(jsonClient, formatters);
```

## Usage Examples
Expand Down
25 changes: 23 additions & 2 deletions Src/HoneyBear.HalClient/HalClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,31 @@ public HalClient()

}

internal HalClient(IJsonHttpClient client)
/// <summary>
/// Creates an instance of the <see cref="HalClient"/> class.
/// </summary>
/// <param name="client">The implementation of <see cref="IJsonHttpClient"/> to use.</param>
/// <param name="formatters">
/// Specifies the list of <see cref="MediaTypeFormatter"/>s to use.
/// Default is <see cref="HalJsonMediaTypeFormatter"/>.
/// </param>
public HalClient(
IJsonHttpClient client,
ICollection<MediaTypeFormatter> formatters)
{
_client = client;
_formatters = _defaultFormatters;
_formatters = formatters == null || !formatters.Any() ? _defaultFormatters : formatters;
}

/// <summary>
/// Creates an instance of the <see cref="HalClient"/> class.
/// </summary>
/// <param name="client">The implementation of <see cref="IJsonHttpClient"/> to use.</param>
public HalClient(
IJsonHttpClient client)
: this(client, _defaultFormatters)
{

}

/// <summary>
Expand Down
38 changes: 36 additions & 2 deletions Src/HoneyBear.HalClient/Http/IJsonHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,46 @@

namespace HoneyBear.HalClient.Http
{
internal interface IJsonHttpClient
/// <summary>
/// Provides a wrapper for <see cref="System.Net.Http.HttpClient"/> that processes JSON HTTP requests and responses.
/// </summary>
public interface IJsonHttpClient
{
/// <summary>
/// A getter for the wrapped instance of <see cref="System.Net.Http.HttpClient"/>.
/// </summary>
HttpClient HttpClient { get; }

/// <summary>
/// Send a GET request to the specified Uri as an asynchronous operation.
/// </summary>
/// <param name="uri">The Uri the request is sent to.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.</returns>
Task<HttpResponseMessage> GetAsync(string uri);

/// <summary>
/// Send a POST request to the specified Uri as an asynchronous operation.
/// </summary>
/// <typeparam name="T"/>
/// <param name="uri">The Uri the request is sent to.</param>
/// <param name="value">The HTTP request content sent to the server.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.</returns>
Task<HttpResponseMessage> PostAsync<T>(string uri, T value);

/// <summary>
/// Send a PUT request to the specified Uri as an asynchronous operation.
/// </summary>
/// <typeparam name="T"/>
/// <param name="uri">The Uri the request is sent to.</param>
/// <param name="value">The HTTP request content sent to the server.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.</returns>
Task<HttpResponseMessage> PutAsync<T>(string uri, T value);

/// <summary>
/// Send a DELETE request to the specified Uri as an asynchronous operation.
/// </summary>
/// <param name="uri">The Uri the request is sent to.</param>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.</returns>
Task<HttpResponseMessage> DeleteAsync(string uri);
}
}
}
2 changes: 1 addition & 1 deletion Src/HoneyBear.HalClient/Http/JsonHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace HoneyBear.HalClient.Http
{
internal class JsonHttpClient : IJsonHttpClient
internal sealed class JsonHttpClient : IJsonHttpClient
{
public JsonHttpClient(HttpClient client)
{
Expand Down

0 comments on commit 91e6a20

Please sign in to comment.