Post call for xml content using HttpClient - c#

How to make xml content compatible with HttpClient's PostAsync operation for the content and where do you specify the headers for Content-Type = application/xml.
Error -> Cannot convert string to HttpContent
public async Task GetCustomersAsync(string firstname, string lastname)
{
using (var client = new HttpClient())
{
var content = "<soapenv:Envelope xmlns:xsi...";
var response = await client.PostAsync("https://domain.com/scripts/WebObj.exe/Client.woa/2/ws/ABC", content);
var responseString = await response.Content.ReadAsStringAsync();
}
}

My guess is what you want to do is the following:
public async Task<string> GetCustomersAsync(string firstname, string lastname)
{
using (var client = new HttpClient())
{
var content = new StringContent("<soapenv:Envelope xmlns:xsi...", Encoding.UTF8, "application/xml");;
var response = await client.PostAsync("https://example.com/scripts/WebObj.exe/Client.woa/2/ws/ABC", content);
return await response.Content.ReadAsStringAsync();
}
}
OR
using (var request = new HttpRequestMessage { RequesteUri = new Uri("POST_URL"), Method = HttpMethod.Post })
{
var content = new StringContent("<soapenv:Envelope xmlns:xsi...");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml");
}
You can refer here to more information about other Content types that can be created and passed.

To specifically request xml content in response you must define the content type in the header of the content. The MediaTypeHeaderValue is parsed and set in the ContentType property of the content Headers. Here is a complete example of the code;
using (var client = new HttpClient())
{
var content = new StringContent(messageToPOST, Encoding.UTF8, "text/xml");
content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/xml");
response = await client.PostAsync(_uri, content);
responseMsg = await response.Content.ReadAsStringAsync();
}
The responseMsg property returned by the request as the response can be parsed as a string and otherwise converted to and validated as xml using an expression such as
XDocument xdoc = XDocument.Parse(responseMsg);
string xmlAsString = xdoc.ToString();

Related

HttpClient request no response

I am not getting any response - no error, no bad request status, etc. - when I send a post request to this API route. postData is simply a JSON object. The funny thing here is this: When i send post data as a string instead of an object, I can get a response.
View the code below:
[HttpPost]
[Route("api/updateStaffs/")]
public async Task<object> UpdateStaff([FromBody] object postData)
{
string _apiUrl = "http://localhost:5000/system/getToken";
string _baseAddress = "http://localhost:5000/system/getToken";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = await client.PostAsync(_apiUrl, new StringContent(postData.ToString(), Encoding.UTF8, "application/json"));
if (responseMessage.IsSuccessStatusCode)
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = responseMessage.Content;
return ResponseMessage(response);
}
}
return NotFound();
}
No response:
var postData = new {
user = "test"
pass = "hey"
};
var responseMessage = await client.PostAsync(_apiUrl, new StringContent(postData.ToString(), Encoding.UTF8, "application/json"));
OR
var responseMessage = await client.PostAsync(_apiUrl, new StringContent("{}", Encoding.UTF8, "application/json"));
Will get response:
var responseMessage = await client.PostAsync(_apiUrl, new StringContent("blahblah", Encoding.UTF8, "application/json"));
The receiving API is a third-party application so I am unable to verify if this error is on the other end.
Thanks.
If you dont want to use PostAsJsonAsync
You need to serialize your anonymous type to JSON, the most common tool for this is Json.NET
var jsonData = JsonConvert.SerializeObject(postData);
Then you need to construct a content object to send this data, here we can use ByteArrayContent but you can use a different type
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var byteContent = new ByteArrayContent(buffer);
Then send the request
var responseMessage = await client.PostAsync(_apiUrl, byteContent);
Figured out the issue. Have to use HttpVersion10 instead of HttpVersion11.

c# redirect post request

Trying to make a post request from one application to another using the same Form Data parameters that the first one received.
both application controller currently have same method:
public async Task<ActionResult> TestSet()
{
var inputString = Request.Form["inputString"];
var inputFile = Request.Files[0];
var resultString = await _service.Set(inputString, inputFile.FileName, inputFile.ContentType, inputFile.InputStream);
return new MyJsonResult(new
{
fileName = resultString
});
}
which return json string:
{"fileName": "someFileName.png"}
Trying to make the first method to be something like this
public async Task<ActionResult> TestSet()
{
var inputString = Request.Form["inputString"];
var inputFile = Request.Files[0];
if (!string.IsNullOrEmpty(_redirectUrl))
{
using (var client = new HttpClient())
{
HttpContent content = GetContentSomehow(this.Request); // this i have an issue with
var response = await client.PostAsync(_redirectUrl, content);
var responseString = await response.Content.ReadAsStringAsync();
return new MyJsonResult(responseString);
}
}
var resultString = await _service.Set(inputString, inputFile.FileName, inputFile.ContentType, inputFile.InputStream);
return new MyJsonResult(new
{
fileName = resultString
});
}
This could help to get ByteArrayContent for File only.
And this would probably work to get the non-file parameters into StringContent, but how to get both of them into single Content?
var jsonString = JsonConvert.SerializeObject(Request.Form.ToDictionary());
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
Solved this issue by cominig StringContent and StreamContent into MultipartFormDataContent
public static MultipartFormDataContent GetMultipartFormData(HttpRequestBase req)
{
var formData = new MultipartFormDataContent();
//formData.Headers.ContentType.MediaType = "multipart/form-data";
foreach (var row in req.Form.ToDictionary())
{
formData.Add(new StringContent(row.Value), row.Key);
}
var file = req.Files[0];
StreamContent fileStreamContent = new StreamContent(file.InputStream);
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
formData.Add(fileStreamContent, file.FileName, file.FileName);
return formData;
}

How to send image in HttpClient SendRequestAsync

I am using Windows.Web.Http instead of System and I am trying to send an image.
My sample code:
Dictionary<string, object> requestDictionary;
HttpClient httpClient = new HttpClient();
HttpRequestMessage re = new HttpRequestMessage();
HttpResponseMessage response;
re.Method = HttpMethod.Post;
re.RequestUri = url;
string content_type = "application/json";
string req_data = JsonConvert.SerializeObject(requestDictionary);
re.Content = new HttpStringContent(req_data, UnicodeEncoding.Utf8, content_type);
response = await httpClient.SendRequestAsync(re);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
httpClient.Dispose();
httpClient=null;
In this case my requestDictionary will be some thing like
requestDictionary.Add("Image", filename);
requestDictionary.Add("description", some_description);
Someone please help me to achieve this.
By using .Net 4.5 (or by adding the Microsoft.Net.Http package from NuGet) there is an easier way to do this:
private string Upload(string actionUrl, string paramString, byte[] paramFileBytes)
{
HttpContent stringContent = new StringContent(paramString);
HttpContent bytesContent = new ByteArrayContent(paramFileBytes);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(stringContent, "paramter");
formData.Add(bytesContent, "image");
var response = client.PostAsync(actionUrl, formData).Result;
if (!response.IsSuccessStatusCode)
{
return null;
}
return response.Content.ReadAsStringAsync().Result;
}
}
If you prefer to use a stream instead of a byte-array you can easily do this, by just using new StreamContent() instead of new ByteArrayContent().

A method was called at an unexpected time in HttpClient MultipartFormDataContent

I have to post the multipart data to the server but I am getting below error
I am using the below code
public async static Task<string> HttpImagePostMethod(byte[] wInputData, string Uri, string path)
{
string result = string.Empty;
try
{
#region For Https (Secure) Api having SSL
var filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
var client = new System.Net.Http.HttpClient(new WinRtHttpClientHandler(filter));
#endregion
MultipartFormDataContent requestContent = new MultipartFormDataContent();
// StreamContent content = new StreamContent(wInputData);
var content = new ByteArrayContent(wInputData);
content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
requestContent.Add(content, "file", path);
requestContent.Headers.Add("X-API-Key", UrlFactory.X_API_Key_Value);
requestContent.Add(new StringContent("144"), "type");
HttpResponseMessage aResp = await client.PostAsync(UrlFactory.BaseUrl + Uri, requestContent);
if (aResp.IsSuccessStatusCode)
{
result = await aResp.Content.ReadAsStringAsync();
}
else
{
result = await aResp.Content.ReadAsStringAsync();
}
}
catch (Exception ex)
{
result = string.Empty;
}
return result;
}
I am getting error at this line
HttpResponseMessage aResp = await client.PostAsync(UrlFactory.BaseUrl + Uri, requestContent);
Due to this line
requestContent.Headers.Add("X-API-Key", UrlFactory.X_API_Key_Value);
Myself Answer this question maybe helpful to my other friends...
HttpRequestMessage httpRequest = new HttpRequestMessage();
httpRequest.Method = HttpMethod.Post;
httpRequest.RequestUri = new System.Uri(UrlFactory.BaseUrl + Uri);
httpRequest.Content = requestContent;
httpRequest.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
httpRequest.Headers.TryAddWithoutValidation("X-API-Key", UrlFactory.X_API_Key_Value);
Client(HttpClient) shouldn't contain any header, we declaring header in HttpRequestMessage
As the error message says, you're trying to set a header on the content but it doesn't belong there; your API token is a property of the request itself and not of its content.
Try adding that header to client.DefaultRequestHeaders instead.

Troubleshooting HTTPClient asynchronous POST and reading results

I have a problem post string to form and read. Problem is they get away but need to do so sophisticated and it was very fast. Absolutely perfect multithreaded or asynchronous. Thank you very for your help.
This is my code.
private static void AsyncDown()
{
const string url = "http://whois.sk-nic.sk/index.jsp";
const string req = "PREM-0001";
var client = new HttpClient();
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("text", "PREM-0001")
};
FormUrlEncodedContent content = new FormUrlEncodedContent(pairs);
HttpResponseMessage response = client.PostAsync("http://whois.sk-nic.sk/index.jsp", content).Result;
if (response.IsSuccessStatusCode)
{
HttpContent stream = response.Content;
Task<string> data = stream.ReadAsStringAsync();
}
}
Taking a rough stab in the dark at what your problem is, I'd guess that you're having trouble reading the response of your call.
When the content is POSTed to the server,
HttpResponseMessage response
= client.PostAsync("http://whois.sk-nic.sk/index.jsp", content).Result;
if (response.IsSuccessStatusCode)
{
HttpContent stream = response.Content;
Task<string> data = stream.ReadAsStringAsync();
}
It does so asynchronously, so the code will continue execution even though the result is not (most likely) available yet. Checking response.IsSuccessStatusCode will thus not give you the behavior you're expecting.
Change your calls to look like this by adding the await keyword:
HttpResponseMessage response
= await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
Then, change the reading of the stream to use await as well:
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
}
EDIT: got some await objects mixed up and have corrected the code listing.
edit 2: here is the complete LINQPad script that I used to successfully download an HTML page from the given URL.
var client = new HttpClient();
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("text", "PREM-0001")
};
FormUrlEncodedContent content = new FormUrlEncodedContent(pairs);
HttpResponseMessage response = await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
//data.Dump(); //uncomment previous if using LINQPad
}
Maybe the site has changed since last post but now the request parameter name is whois not text. If this was the case a year ago too that's why it didn't work.
Today site responds to get too, i.e. http://whois.sk-nic.sk/index.jsp?whois=PREM-0001
Full code with get:
private async Task<string> Get(string code)
{
using (var client = new HttpClient())
{
var requestUri = String.Format("http://whois.sk-nic.sk/index.jsp?whois={0}", code);
var data = await client.GetStringAsync(requestUri);
return data;
}
}
Full code with post:
private async Task<string> Post()
{
using (var client = new HttpClient())
{
var postData = new KeyValuePair<string, string>[]
{
new KeyValuePair<string, string>("whois", "PREM-0001"),
};
var content = new FormUrlEncodedContent(postData);
var response = await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
if (!response.IsSuccessStatusCode)
{
var message = String.Format("Server returned HTTP error {0}: {1}.", (int)response.StatusCode, response.ReasonPhrase);
throw new InvalidOperationException(message);
}
var data = await response.Content.ReadAsStringAsync();
return data;
}
}
Or a parser could be used because I guess extracting the returned values is the final goal:
private void HtmlAgilityPack(string code)
{
var requestUri = String.Format("http://whois.sk-nic.sk/index.jsp?whois={0}", code);
var request = new HtmlWeb();
var htmlDocument = request.Load(requestUri);
var name = htmlDocument.DocumentNode.SelectSingleNode("/html/body/table[1]/tr[5]/td/table/tr[2]/td[2]").InnerText.Trim();
var organizations = htmlDocument.DocumentNode.SelectSingleNode("/html/body/table[1]/tr[5]/td/table/tr[3]/td[2]").InnerText.Trim();
}

Categories