Getting an error issuing a post request in c# - c#

I want to issue a post request in a c# app to https://www.inventor-s-hub.xyz:8000/v8
but I keep getting this error --> System.Net.WebException: the remote name couldn't be resolved 'www.inventor-s-hub.xyz'
I have a node.js server running on the port at that domain which works fine if you navigate to it from a browser.
This is the method that I am calling later on in the app which issues a post request:
Using System.Net.Http;
public async void PostToServer(string name)
{
using (HttpClient client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "name", name},
{ "id", "1" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://www.inventor-s-hub.xyz:8000/v8", content);
}
}
I've searched the web but couldn't really find anything relevant, I don't think I am running a proxy on the machine I am issuing the request from.
From the server, I am just sending a 200 status.

Try this sample:
public static async PostToServer(string name)
{
var values = new Dictionary<string, string>
{
{ "name", name},
{ "id", "1" }
};
HttpClient client = new HttpClient();
var content = new FormUrlEncodedContent(values);
HttpResponseMessage response = await client.PostAsync(new Uri("https://www.inventor-s-hub.xyz:8000/v8"), content );
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}

Related

C# HttpClient.SendAsync causes error, cannot send a content-body with this verb-type

I am getting error cannot send a content-body with this verb-type. I am calling a GET Endpoint from a C# VSTO desktop application. What am I doing wrong.
public static string GetCentralPath(LicenseMachineValidateRequestDTO licenseMachine)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Properties.Settings.Default.Properties["JWT"].DefaultValue.ToString());
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{Constants.URL.APIBase}licensemachine/GetCentralPath"),
Content = new StringContent(JsonConvert.SerializeObject(licenseMachine), Encoding.UTF8, "application/json"),
};
using (HttpResponseMessage response = client.SendAsync(request).GetAwaiter().GetResult()) // Causing ERROR
{
var result = GetStringResultFromHttpResponseMessage(response, true);
if (string.IsNullOrEmpty(result))
return null;
return JsonConvert.DeserializeObject<string>(result);
}
}
}
The end point looks like the following:
[HttpGet("GetCentralPath")]
public async Task<IActionResult> GetCentralPath(LicenseMachineValidateRequestDTO dto)
{
// Some code
}
fix the action, you cannot send body data with get, see this post
HTTP GET with request body
[HttpPost("GetCentralPath")]
public async Task<IActionResult> GetCentralPath(LicenseMachineValidateRequestDTO dto)
and fix request , replace Method = HttpMethod.Get with Post, this is what generates an error
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{Constants.URL.APIBase}licensemachine/GetCentralPath"),
Content = new StringContent(JsonConvert.SerializeObject(licenseMachine), Encoding.UTF8, "application/json"),
};

Consuming a Web API in Xamarin

I've created a Web API in ASP.NET that is hosted on a web server. This Web API accesses a table in SQL Server where I have a table called Products with Id, ProductName, Description and Price, I did the tests via Postman and it is working correctly, but when I try to consume the method to bring a specific product via Xamarin application, I get the following error message in break mode:
System.Net.Http.HttpRequestException: Timeout exceeded getting exception details
public class DataService
{
public async Task<List<Product>> GetProductAsync(string ProductName)
{
using (var client = new HttpClient())
{
string url = "http://ProductsAPI.hostname.com/api";
try
{
var uri = url + "/" + ProductName.ToString();
HttpResponseMessage response = await client.GetAsync(uri);
var ProductJsonString = awaitresponse.Content.ReadAsStringAsync();
var Product = JsonConvert.DeserializeObject<List<Product>>(ProductJsonString);
return Product;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
Here's what I've used in the past:
public string GetAPIJsonAsync(string URL)
{
using (WebClient wc = new WebClient())
{
return wc.DownloadString(URL);
}
}
This would return the raw JSON to whoever called it, and I would then convert it to the desirable object.
If you increase the timeout of the HttpClient, does it return more information?
Also, try Refit It does all the work for you, including deserializing into json.
This Works Perfectly for me
public static async Task<List<BranchMasterModel>> GetBranchList(int city)
{
var client = new HttpClient(new NativeMessageHandler());
client.BaseAddress = new Uri(UrlAdd);//("http://192.168.101.119:8475/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "AuthToken"));
var result = await client.GetAsync("api/Master/V2/Branch/"+city);
string branch = await result.Content.ReadAsStringAsync();
var branches = JsonConvert.DeserializeObject<List<BranchMasterModel>>(branch);
return branches;
}

Testing REST API endpoints

I have a number of REST api endpoints that I am calling via ajax from a web client, and I want to write some automated tests to insure that they work properly outside of a web browser.
I am writing them as unit tests Tests and here is what I have so far:
[TestClass]
public class ApiTests
{
string local_host_address = "http://localhost:1234//";
public async Task<string> Post(string path, IEnumerable<KeyValuePair<string, string>> parameters)
{
using (var client = new HttpClient())
{
client.Timeout = new TimeSpan(0,0,5);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response_message = await client.PostAsync(local_host_address + path, new FormUrlEncodedContent(parameters));
var response = await response_message.Content.ReadAsStringAsync();
if (response_message.IsSuccessStatusCode)
{
return response;
}
else
{
throw new Exception("Request failed");
}
}
}
[TestMethod]
[TestCategory("ApiTests")]
public void TestLogon()
{
var parameters = new Dictionary<string, string>();
parameters["email"] = "bob#aol.com";
parameters["password"] = "rosebud";
Task.Run( () =>
{
var output = Post("Default.aspx/Logon", parameters);
Console.WriteLine(output.Result);
}).Wait();
}
}
...pretty basic, it just tries to call a specific endpoint, and return the results. Problem is, this call returns the basic default.aspx web page body, not the results generated by default.aspx/logon. I am doing something wrong, but I have been over it with a debugger and I cannot see my error. The default.aspx/logon endpoint exists and it works perfectly when I access it via website. Am I missing or overlooking something?
-TTM
SOLUTION:
Bruno's alteration of my code snippet works quite nicely. Anyone else trying to solve the problem of testing a REST endpoint can just put that into a unit test and pass in a POCO and it will return the JSON response.
You are sending the body as FormUrlEncoded although you marked your request as application/json.
If your API is REST and takes JSON, instead of taking the Dictionary, you could deserialize an object (e.g. with Newtonsoft.Json):
public async Task<string> Post<T>(string path, T data)
{
using (var client = new HttpClient())
{
client.Timeout = new TimeSpan(0, 0, 5);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = JsonConvert.SerializeObject(data);
var response_message = await client.PostAsync(local_host_address + path, new StringContent(json, Encoding.UTF8, "application/json");
var response = await response_message.Content.ReadAsStringAsync();
if (response_message.IsSuccessStatusCode)
{
return response;
}
else
{
throw new Exception("Request failed");
}
}
}

Send request as Json on UWP

I have deployed an AzureML published experiment with deployed web service. I tried to use the sample code provided in the configuration page, but universal apps do not implement Http.Formatting yet, thus I couldn't use postasjsonasync.
I tried to follow the sample code as much as possible, but I'm getting statuscode of 415 "Unsupported Media Type", What's the mistake I'm doing?
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
// client.BaseAddress = uri;
var scoreRequest = new
{
Inputs = new Dictionary<string, StringTable>() {
{
"dataInput",
new StringTable()
{
ColumnNames = new [] {"Direction", "meanX", "meanY", "meanZ"},
Values = new [,] { { "", x.ToString(), y.ToString(), z.ToString() }, }
}
},
},
GlobalParameters = new Dictionary<string, string>() { }
};
var stringContent = new StringContent(scoreRequest.ToString());
HttpResponseMessage response = await client.PostAsync(uri, stringContent);
Many Thanks
You'll need to serialize the object to a JSON string (I recommend using NewtonSoft.Json to make it easier) and set the content type accordingly. Here's an implementation I'm using in my UWP apps (note that _client is an HttpClient):
public async Task<HttpResponseMessage> PostAsJsonAsync<T>(Uri uri, T item)
{
var itemAsJson = JsonConvert.SerializeObject(item);
var content = new StringContent(itemAsJson);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return await _client.PostAsync(uri, content);
}

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