I am using the extremely awesome HttpClient provided in the WCF REST Starter Kit. I have the following method that is working against the HelloTxt API:
public UserValidateResponse Validate()
{
HttpClient client = new HttpClient(baseUrl);
HttpMultipartMimeForm form = new HttpMultipartMimeForm();
form.Add("app_key", this.AppKey);
form.Add("user_key", this.UserKey);
HttpResponseMessage response = client.Post("user.validate", form.CreateHttpContent());
return response.Content.ReadAsXmlSerializable<UserValidateResponse>();
}
I have a nice generic GetRequest method that looks like this:
public T GetRequest<T>(string query)
{
HttpClient client = new HttpClient(baseUrl);
client.DefaultHeaders.UserAgent.AddString(@"http://www.simply-watches.co.uk/");
HttpResponseMessage response = client.Get(query);
response.EnsureStatusIsSuccessful();
T data = default(T);
try
{
data = response.Content.ReadAsXmlSerializable<T>();
return data;
}
catch (Exception ex)
{
Console.Write(String.Format("{0}: {1}", ex.Message, ex.InnerException.Message));
}
return data;
}
The benefit of which is that you can pass it T as the response type as per this random example:
public List<User> GetUsers(int deptid)
{
string query = String.Format("department.getUsers?api_key={0}&dept_id={1}", this.APIKey, deptId);
return GetRequest<List<User>>(query);
}
I now want to the same generic style POST method, rather than GET and I'm sure I can use the HttpContentExtensions, but I can't figure out how to transform the request into a HttpMultipartMimeForm. this is what I have so far:
public T PostRequest<K, T>(string query, K request)
{
HttpClient client = new HttpClient(baseUrl);
// the following line doesn't work! Any suggestions?
HttpContent content = HttpContentExtensions.CreateDataContract<K>(request, Encoding.UTF8, "application/x-www-form-urlencoded", typeof(HttpMultipartMimeForm));
HttpResponseMessage response = client.Post(query, content);
response.EnsureStatusIsSuccessful();
T data = default(T);
try
{
data = response.Content.ReadAsXmlSerializable<T>();
return data;
}
catch (Exception ex)
{
Console.Write(String.Format("{0}: {1}", ex.Message, ex.InnerException.Message));
}
return data;
}
It would be called like this:
UserValidateResponse response = PostRequest<UserValidateRequest, UserValidateResponse>("user.validate", new UserValidateRequest(this.AppKey, this.UserKey));
It is to work against this API: http://hellotxt.com/developers/documentation. Any suggestions are extremely welcome! I could define a different form for each POST, but it would be nice to do this generically.
HttpClient is used to send an HTTP request, using a URL. HttpClient can be used to make Web API requests from the console Application, Winform Application, Web form Application, Windows store Application, etc.
An HTTP Client. An HttpClient can be used to send requests and retrieve their responses. An HttpClient is created through a builder . The builder can be used to configure per-client state, like: the preferred protocol version ( HTTP/1.1 or HTTP/2 ), whether to follow redirects, a proxy, an authenticator, etc.
The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.
I answered my own question on this. The code can be seen in my .NET wrapper for the HelloTxt API - HelloTxt.NET, and as per my comment above, uses reflection to work out the request object properties, and populates a HttpMultipartMimeForm()
with the values, whilst checking the Required
data annotions on the class properties.
The code in question is:
/// <summary>
/// Generic post request.
/// </summary>
/// <typeparam name="K">Request Type</typeparam>
/// <typeparam name="T">Response Type</typeparam>
/// <param name="query">e.g. user.validate</param>
/// <param name="request">The Request</param>
/// <returns></returns>
public T PostRequest<K, T>(string query, K request)
{
using (var client = GetDefaultClient())
{
// build form data post
HttpMultipartMimeForm form = CreateMimeForm<K>(request);
// call method
using (HttpResponseMessage response = client.Post(query, form.CreateHttpContent()))
{
response.EnsureStatusIsSuccessful();
return response.Content.ReadAsXmlSerializable<T>();
}
}
}
/// <summary>
/// Builds a HttpMultipartMimeForm from a request object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="request"></param>
/// <returns></returns>
public HttpMultipartMimeForm CreateMimeForm<T>(T request)
{
HttpMultipartMimeForm form = new HttpMultipartMimeForm();
Type type = request.GetType();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
foreach (Attribute attribute in property.GetCustomAttributes(true))
{
RequiredAttribute requiredAttribute = attribute as RequiredAttribute;
if (requiredAttribute != null)
{
if (!requiredAttribute.IsValid(property.GetValue(request, null)))
{
//Console.WriteLine("{0} [type = {1}] [value = {2}]", property.Name, property.PropertyType, property.GetValue(property, null));
throw new ValidationException(String.Format("{0} [type = {1}] requires a valid value", property.Name, property.PropertyType));
}
}
}
if (property.PropertyType == typeof(FileInfo))
{
FileInfo fi = (FileInfo)property.GetValue(request, null);
HttpFormFile file = new HttpFormFile();
file.Content = HttpContent.Create(fi, "application/octet-stream");
file.FileName = fi.Name;
file.Name = "image";
form.Files.Add(file);
}
else
{
form.Add(property.Name, String.Format("{0}", property.GetValue(request, null)));
}
}
return form;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With