static void

WebAPI HttpClient

Microsoft.AspNet.WebApi.Client package

Pattern

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri(idsJson);
    // Add an Accept header for JSON format.
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
    using (var response = client.PutAsJsonAsync("api/messages/", message).Result)
    {
        if (response.IsSuccessStatusCode)
        {
            var result = response.Content.ReadAsAsync<OperationResult>().Result;
            return result;
        }
        throw new InvalidOperationException("Error: " + response.StatusCode + ": " + response.ReasonPhrase);
    }
}

Configuration

Configure the client (for authentication etc)

var handler = new WebRequestHandler
{
    AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
};
var c = new HttpClient(handler);

You have to drop to lower level than "PostAsJsonAsync" for some config

var jsonMediaTypeFormatter = new JsonMediaTypeFormatter();
jsonMediaTypeFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
var response = client.PutAsync("api/message/", message,
                        jsonMediaTypeFormatter, CancellationToken.None).Result;

Json.Net can be configured globally:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = { new StringEnumConverter() }
};

Authentication

Windows credentials.

var handler = new HttpClientHandler { UseDefaultCredentials = true };
 
using (var client = new HttpClient(handler))
{
    var response = client.GetAsync("http://localhost:2893/api/product/1").Result;
    response.EnsureSuccessStatusCode();
    var product = response.Content.ReadAsAsync<Product>().Result;
}

Basic authentication

var clientHandler = new HttpClientHandler
                        {
                            Credentials =
                                new System.Net.NetworkCredential(userName, password)
                        };
using (var client = new HttpClient(clientHandler))
{
    var response = client.GetAsync("http://localhost:2893/api/other/1").Result;
    if (response.IsSuccessStatusCode)
    {
        var result = response.Content.ReadAsStringAsync();
    }
}

Testing

For testing, use an in-memory HttpServer, and the HttpClient must be constructed with the server.

var config = new HttpConfiguration();
config.Routes.MapHttpRoute("Default", "api/{controller}/{id}");
var testingHandler = new TestDelegatingHandler<OperationResult>(httpResponseMessageFunc);
var server = new HttpServer(config, testingHandler);
var client = new HttpClient(server);

Here's the delegating handler:

internal class TestDelegatingHandler<T> : DelegatingHandler
{
    private readonly Func<HttpRequestMessage, HttpResponseMessage> _httpResponseMessageFunc;
 
    /// <summary>
    /// Simple: new TestDelegatingHandler&lt;Result&gt;(new Result())
    /// </summary>
    public TestDelegatingHandler(T value)
        : this(HttpStatusCode.OK, value)
    {
    }
 
    /// <summary>
    /// new TestDelegatingHandler&lt;Result&gt;(HttpStatusCode.BadRequest, new Result())
    /// </summary>
    public TestDelegatingHandler(HttpStatusCode statusCode, T value)
    {
        _httpResponseMessageFunc = request => request.CreateResponse(statusCode, value);
    }
 
    /// <summary>
    /// new TestDelegatingHandler&lt;Result&gt;(request =&gt; request.CreateResponse(HttpStatusCode.Created, new Result(true)))
    /// </summary>
    public TestDelegatingHandler(Func<HttpRequestMessage, HttpResponseMessage> httpResponseMessageFunc)
    {
        _httpResponseMessageFunc = httpResponseMessageFunc;
    }
 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return Task.Factory.StartNew(() => _httpResponseMessageFunc(request));
    }
}

Build it simply or with a func:

var t1 = new TestDelegatingHandler<Result>(new Result(true));
var t2 = new TestDelegatingHandler<Result>(request => request.CreateResponse(HttpStatusCode.Created, new Result(true)));
 

Self-hosted test

var config = new HttpSelfHostConfiguration("http://localhost:9090/");
 
config.Routes.MapHttpRoute(
    "API Default", "api/{controller}/{id}",
    new { id = RouteParameter.Optional });
 
using (var server = new HttpSelfHostServer(config))
{
    server.OpenAsync().Wait();
    RunClient();
}