I have two problems. I am trying to interact with a Web API that is wanting a HTTP PUT. I am trying to pass the parameters as part of the querystring. Unfortunately, I am not really sure how to do that. Do I include them in with the first parameter of the PutAsync method as shown below?
The other question I have is I am unsure what needs to be coded for the HTTPContent object when using the PutAsync method. I am trying to pass the parameters in the querystring instead of other methods that might be used. Most of the examples that I can find are passing the data as json.
using (var apiManagementSystem = new HttpClient())
{
apiManagementSystem.BaseAddress = new Uri("https://thedomain.com/api/");
apiManagementSystem.DefaultRequestHeaders.Clear();
apiManagementSystem.DefaultRequestHeaders.Add("SessionID", _sessionID);
HttpContent httpContent = new /* What do I do Here? */
responseMessage = apiManagementSystem.PutAsync("Product/someID?available=N", httpContent).Result;
}
My finished url should be something like this.
https://thedomain.com/api/Product/someID?available=N
This API that I am communicating with is a Rest API
Related
I have some C# code that does the following post request:
string postData = newFormUrlEncodedContent(params).ReadAsStringAsync().Result;
var postContent = new StringContent(postData, UTF8Encoding.UTF8, "application/x-www-form-urlencoded");
var responseMessage = httpClient.PostAsync(url, postContent).Result;
I would like to do the equivalent in Python using the Requests library. This is what I have:
headers = {'content-type':'application/x-www-form-urlencoded'}
postContent = requests.post(url, params=params, headers=headers, cookies=previousResponse.cookies)
But postContent.status_code for the Python code is 404, whereas the C# request returns 200. It's possible that there's something wrong with the params since I retrieve those via some Regex matching from a previous request, but that seems to be working.
Edit: I think setting the params parameter is for get requests, not post requests. Also I believe Requests takes care of form encoding:
Typically, you want to send some form-encoded data — much like an HTML form. To do this, simply pass a dictionary to the data argument. Your dictionary of data will automatically be form-encoded when the request is made
So now I have:
postContent = requests.post(url, data = params, cookies = previousResponse.cookies)
Now postContent.status_code == 500. The stack trace says the data is invalid at the root level. I will look into it.
In the past I made a class that shunk the request on an endpoint. Now, I create a dll that include this method, this is the code that I'm trying to convert on this library:
using (var client = new HttpClient())
{
string requestJson = JsonConvert.SerializeObject(data);
client.DefaultRequestHeaders.Add("token", token);
byte[] responseArray = client. 'there is no upload data method
// the bottom code is of the old method
byte[] responseArray = client.UploadData(requestURI, method, Encoding.UTF8.GetBytes(requestJson));
return Encoding.ASCII.GetString(responseArray);
}
In the not portable library System.Net I can call client.UploadData, but here I see only : postAsync and putAsync, there is a method that independent from the put or post request allow me to send the data from the client to the server? Thanks in advance.
In your old code you used some method passed in method parameter to send data with UploadData method, and it was probably POST or PUT. If you do not specify the method for UploadData, POST is being used. So you should use PostAsyncor PutAsync, based on you current code and the value of method parameter you pass to UploadData.
The simplest way would be to use something like this:
using(var client = new HttpClient())
{
var response = await client.PostAsJsonAsync(requestUrl, data);
return await response.Content.ReadAsStringAsync();
}
The code for PUT would be the same, but with PutAsJsonAsync
In an HTTP request PUT and POST are the correct ways to transmit data to a server, it does not make sense to send data independently of these methods. When you are using a client such as that available in System.Net this is merely being abstracted away from you.
I have a web api developed and deployed. It works with unit test and using fiddler. However, if i create a separate project and try to post data to it, it sends back a 400 Bad Request error. I am looking for a way to post this custom object using a client being written in C#. Unlike WCF there is no matadata to create proxy of these objects from and then instantiate and pass it on to calling methods. How do you pass a custom object like Customer as a parameter to a method?
URL would be http://host/directory/api/customer/AddNewCustomer
and method definition is like
[HttpPost]
public bool AddNewCustomer(Customer customerObj)
EDIT
Following is my client code
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://host/directory/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.Timeout = TimeSpan.FromSeconds(30.0);
// strong typed instance
var values = new JObject();
values.Add("FirstName", "John");
values.Add("LastName", "Doe");
HttpContent content = new StringContent(values.ToString(), Encoding.UTF8,"application/json");
var response = client.PostAsJsonAsync("api/customer/AddNewCustomer", content).Result;
After trying many solutions, usign fiddler i came to know that content object was not set. This is strange but that was the case. So i tried passing JObject directly wihout casting it to HttpContent and it worked
// strong typed instance
var values = new JObject();
values.Add("FirstName", "John");
values.Add("LastName", "Doe");
// this is not set!!!
HttpContent content = new StringContent(values.ToString(), Encoding.UTF8,"application/json");
var response = client.PostAsJsonAsync("api/customer/AddNewCustomer", values).Result;
Ideally Customer would be in a separate class library of models and you could share that dll between projects. But any object with the same property names will work because web API will serialized them to Json or xml and make the mappings automatically.
I'm currently using the System.Net.Http.HttpClient for cross platform support.
I read that it is not a good practice to instantiate a HttpClient object for each request and that you should reuse it whenever possible.
Now I have a problem while writing a client library for a service. Some API calls need to have a specific header, some MUST not include this specific header.
It seems that I can only manipulate the "DefaultRequestHeaders" which will be send with each request.
Is there an option when actually making the request with e.g. "client.PostAsync()" to modify the headers only for the specific request?
(Info: Requests can be multi threaded).
Thanks in advance!
Yes, you can create a new HttpRequestMessage, set all the properties you need to, and then pass it to SendAsync.
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://example.org"),
Method = HttpMethod.Post,
Content = new StringContent("Here is my content")
}
request.Headers.Accept.Add(...); // Set whatever headers you need to
var response = await client.SendAsync(request);
Use HttpContent.Headers. Simply create HttpContent instance with required headers and pass it to PostAsync method.
I have created a simple web api controller in mvc4 containing 4 methods (one for each CRUD operation). I'm able to use fiddler to test that the methods in my controller work.
I'm now trying to make a unit test to prove that these work. I've managed to serialize my client side object into json format, but now how do I use this string of json to actually invoke my methods?
If it helps, I am using Json.NET to serialize my client object - although I don't think this extention actually handles the delivery and retreival of it to the server.
Your unit tests should be written against the controller - so you don't need to make an actual HTTP request to unit test your Web API code, you just call the methods.
From a design perspective, if you want a restful Web API, the client should be able to send a standard HTTP message without having to serialize the request.
This is the kind of approach I have used to post an object to a restful Web API:
HttpResponseMessage response;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://url_to_service");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseTask = client.PostAsJsonAsync("api/resource/somethingelse", someObjectToPost).Result;
responseTask.Wait();
response = responseTask.Result;
if (response.IsSuccessStatusCode)
{
var contentTask = response.Content.ReadAsAsync<SomeResponseType>();
contentTask.Wait();
SomeResponseType responseContent = contentTask.Result;
}
else
{
//Handle error.
}
In this case, someObjectToPost is your client-side object, though you can leave it to Web API to serialize it for you. In the above example I am assuming the reponse is of fictional type SomeResponseType - you can also use ReadAsStringAsync if the response is expected to be plain text.
The code presented here by nick_w is correct. You need to use HttpClient object. And as Steve Fenton mentioned, to create unit test you don't want to do it - rather test directly against controller. But for the functional test you can do it. I've done same thing. I've created helper class so I need only to call one of Http helper methods, depending if it is GET or POST, etc. that I do. This helper uses generic types so it operates with any types that being passed.