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<Result>(new Result())
/// </summary>
public TestDelegatingHandler(T value)
: this(HttpStatusCode.OK, value)
{
}
/// <summary>
/// new TestDelegatingHandler<Result>(HttpStatusCode.BadRequest, new Result())
/// </summary>
public TestDelegatingHandler(HttpStatusCode statusCode, T value)
{
_httpResponseMessageFunc = request => request.CreateResponse(statusCode, value);
}
/// <summary>
/// new TestDelegatingHandler<Result>(request => 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();
}
- You need to create ApiControllers in the same project.
- You need Visual Studio to Run As Admin so you can use the localhost port.