I'm trying to connect to a 3rd party WebApi and have created several unit tests to determine the functionality of said WebApi. My initial test used System.Net and did something like the following ...
var request = (HttpWebRequest)WebRequest.Create(commonUrl +
"api/controller/action?value=" + value);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = 0;
request.Method = "POST";
var response = (HttpWebResponse)request.GetResponse();
This returns an expected response and everything is ok, however I was later asked to use System.Net.Http instead so attempting to something like the following ...
HttpClient client = new HttpClient() { BaseAddress = new Uri(commonUrl) };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(
"application/x-www-form-urlencoded"));
var postData = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("value", value)
};
var response = client.PostAsync("api/controller/action",
new FormUrlEncodedContent(postData)).Result;
Unfortunately though, the response StatusCode comes back with System.Net.HttpStatusCode.NotFound Any idea why this is happening?
Thanks in advance
Related
I'm consuming a Web API of an internal system in the company.
It's getting a payload in JSON format and returning a response with data in JSON format.
When sending the request with Postman, it returns the expected response (StatusCode=200 + a response text in JSON format). That means that everything is OK with the web service.
Now I have to develop an application in C# to send this HTTP request.
The problem is, that I receive as response content "OK" and not the expected JSON response gotten with Postman.
public HttpWebResponse SendRequest(string url, string checkOutFolder, string drawingNo, string login, string password)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "GET";
request.Accept = "application/json";
string payload = GeneratePayLoad(checkOutFolder, drawingNo);
string header = CreateAuthorization(login, password);
request.Headers[HttpRequestHeader.Authorization] = header;
request.ServicePoint.Expect100Continue = false;
var type = request.GetType();
var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request);
var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false);
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(payload);
}
// Response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string responseContent = rd.ReadToEnd();
Console.WriteLine(responseContent);
}
return response;
}
Has anyone already experiences something similar.
Can you help me?
EDIT
Following your suggestions
1) Changed the method to POST -> result is still the same
2) Used Postman's code generator and RestSharp -> result is still the same
public void Request(string url, string checkOutFolder, string drawingNo, string login, string password)
{
var client = new RestClient(url);
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Basic **********");
var body = GeneratePayLoad(checkOutFolder, drawingNo);
request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = client.Execute(request);
Console.WriteLine(response.Content);
}
Changed to HttpClient -> result still the same
using (var client = new HttpClient())
{
string uri = "******************";
string path = "destinationpath";
var endpoint = new Uri(uri);
string payload = GeneratePayLoad(path, "100-0000947591");
//FormUrlEncodedContent form = new FormUrlEncodedContent(payload);
var stringContent = new StringContent(payload);
var payload2 = new StringContent(payload, Encoding.UTF8, "application/json");
var byteArray = Encoding.ASCII.GetBytes("*******");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(client.DefaultRequestHeaders.Authorization.ToString()));
var result = client.PostAsync(endpoint, stringContent).Result.Content.ReadAsStringAsync().Result;
Console.WriteLine("test");
}
Wrote a Python code using requests Package -> delivers the same as Postman. So the problem is in the C# code.
Does anyone have an idea what is going on?
SOLVED
The issue was on the payload generation!
The request needs to be an HTTP POST and not HTTP GET because it contains JSON payload.
request.Method = "GET"; should be request.Method = "POST";
That would be one of the issue(s). I am not sure if there is something else that is wrong, but try changing the request method to POST and try again.
I've got a section of code to do a call to an external webapi using WebRequest. I'm trying to update it to use RestSharp instead. What am I missing here to make the conversion? The closest question here to give any sort of idea what might be going on is found in Calling webapi method gives 404. The "answer" was a missing accepted content type. I've verified through the RestClient the types are present (and appear valid).
Common request JSON
var statusRequest = #"
{
""auth"": {
""type"": ""basic""
},
""requestId"": ""15"",
""method"": {
""name"": ""getStatus"",
""params"": {
""showAllStatus"": ""0""
}
}
}
";
WebRequest code
var webRequest = WebRequest.Create("https://service.url/api/status") as HttpWebRequest;
webRequest.Method = "POST";
var username = "user";
var password = "pass";
var encoded = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1")
.GetBytes(username + ":" + password));
webRequest.Headers.Add("Authorization", "Basic " + encoded);
var requestWriter = new StreamWriter(webRequest.GetRequestStream());
webRequest.ContentType = "APPLICATION/JSON; CHARSET=UTF-8";
requestWriter.Write(statusRequest);
requestWriter.Close();
var responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
var responseData = responseReader.ReadToEnd();
responseReader.Close();
Should convert to RestSharp as
var client = new RestClient("https://service.url");
client.Authenticator = new HttpBasicAuthenticator("user", "pass");
var request = new RestRequest("api/status", Method.Post);
request.RequestFormat = DataFormat.Json;
request.AddJsonBody(statusRequest);
client.BuildUri(request);
var response = await client.GetAsync(request);
EDIT: Make the RestRequest a POST
Please read the docs.
Also, you are calling GetAsync. Even if you set the request method to Method.Post, calling GetAsync will override it.
This will work:
var request = new RestRequest("api/status")
.AddStringBody(statusRequest, DataFormat.Json);
var response = await client.PostAsync(request);
How exactly do I use the enhanced AMD through Twilio? I understand that it can only be done through the REST API (no TwiML) but I'm having a hard time seeing the connection between a standard call and the answering machine detection.
I've read through this page a few times, but I still don't understand. So here is the standard c# code for placing a call through the REST API:
TwilioClient.Init(AccountSid, AuthToken);
var to = new PhoneNumber("+14155551212");
var from = new PhoneNumber("+15017250604");
var call = CallResource.Create(to, from, url: new Uri("http://demo.twilio.com/docs/voice.xml"));
And here is my c# translated code from the aforementioned link:
using (var client = new HttpClient())
{
var byteArray = Encoding.ASCII.GetBytes($#"{AccountSid}:{AuthToken}");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
var requestContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("To", "+15017250604"),
new KeyValuePair<string, string>("From", "+15017250604"),
new KeyValuePair<string, string>("MachineDetection", "DetectMessageEnd"),
new KeyValuePair<string, string>("Url", Url.Action("PostTransfer"))
});
var response = client.PostAsync(_amdRequest, requestContent);
var responseContent = response.Result.Content;
}
So what am I missing? I'm sure it's something simple, but I'm not seeing how the enhanced AMD knows what call to listen to, and what the order of events here should be. And finally, how am I supposed to see the results?
EDIT:
So to be crystal clear, here is my code as it currently sits:
TwilioClient.Init(AccountSid, AuthToken);
var toPhone = new PhoneNumber(to);
var fromPhone = new PhoneNumber(from);
var call = CallResource.Create(toPhone, fromPhone, url: new Uri("http://demo.twilio.com/docs/voice.xml"));
using (var client = new HttpClient())
{
var byteArray = Encoding.ASCII.GetBytes($#"{AccountSid}:{AuthToken}");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
var requestContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("To", to),
new KeyValuePair<string, string>("From", from),
new KeyValuePair<string, string>("MachineDetection", "DetectMessageEnd"),
new KeyValuePair<string, string>("Url", Url.Action("PostTransfer"))
});
var response = client.PostAsync(_amdRequest, requestContent);
var responseContent = response.Result.Content;
}
And elsewhere in my code is a function called "PostTransfer" that gets the "AnsweredBy" parameter and does some stuff after the call is placed. Should this be working? Because it isn't. The call goes through and I can hear Twilio's example file play, but it never gets to the "PostTransfer" function.
Twilio developer evangelist here.
You look like you're making a call with detection successfully. You're making a call from your Twilio number to a users number.
You see the results of the answering machine detection when Twilio has decided on whether it is a machine or a human, at which point it makes a webhook request to your URL that you send as part of making the call.
When Twilio makes the webhook, it will include an extra parameter: AnsweredBy. When you set MachineDetection to DetectMessageEnd the values of AnsweredBy can be: machine_end_beep, machine_end_silence, machine_end_other, human, fax, and unknown. You can then read this value and decide what to do with the call at this point.
Does that help at all?
Can you try HttpWebRequest instead? here is an example how to do it,
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
request.Headers.Add("Authorization", string.Format("Bearer {0}",AccessToken));
request.ContentType = "application/json;charset=utf-8";
request.ContentLength = body.Length;
request.Accept = "application/json"
if (!string.IsNullOrWhiteSpace(body))
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] bytes = encoding.GetBytes(body);
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
// Send the data.
requestStream.Write(bytes, 0, bytes.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (callback != null)
{
var reader = new StreamReader(response.GetResponseStream());
callback(reader.ReadToEnd());
}
}
I am trying to convert a curl request to c# request but it is not working
curl request
curl -X GET "http://www1.bloomingdales.com/shop/search?keyword=lace%2Btop"
The above curl request works fine
C# request
public lib_check ()
{
string url_1 = "http://www1.bloomingdales.com/shop/search/Pageindex%2CProductsperpage/1%2C180?keyword=women%20tank%20top";
Console.Write (url+"request started");
var request = (HttpWebRequest)WebRequest.Create(url_1);
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
var json = reader.ReadToEnd ();
console.write( json);
}
}
But the above c# request throws 403 forbidden error
How to fix c# request and make request working to get 200 response?
I guess the reason why it's forbidden because you didn't construct the necessary header that the site is expecting. You need to construct those headers and you can check it in developer tools in chrome. See code below.
string url_1 = #"http://www1.bloomingdales.com/shop/search/Pageindex%2CProductsperpage/1%2C180?keyword=women%20tank%20top";
var request = (HttpWebRequest)WebRequest.Create(url_1);
request.Method = "GET";
request.Accept = "text/html";
request.UserAgent = ".NET Framework Test Client"; // Some server prevent script like this so they validate some user-agents
request.MaximumAutomaticRedirections = int.MaxValue;
request.Timeout = 50000;
var response = request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
var json = reader.ReadToEnd();
Console.Write(json);
}
To see what are the headers needed by the server; try requesting the url in browser first while dev tools are active.
Update : If this doesn't work well due to timeout issue it better to handle it asynchronously.
var handler = new HttpClientHandler
{
AllowAutoRedirect = true,
CookieContainer = new CookieContainer(),
UseCookies = true,
AutomaticDecompression = DecompressionMethods.Deflate
};
var client = new HttpClient(handler)
{
Timeout = new TimeSpan(0, 3, 0)
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html"));
client.DefaultRequestHeaders.ExpectContinue = false;
client.DefaultRequestHeaders.Add("Accept-Language", "en-US, en");
var result = client.GetAsync("http://www1.bloomingdales.com/shop/search/Pageindex%2CProductsperpage/1%2C180?keyword=women%20tank%20top").Result;
var content = result.Content.ReadAsStringAsync().Result;
Console.Write(content);
I noticed the result is not json but a page. May be because it's not API. Adjust the code as needed but the bare bone was already there.
I'm working with JSON and C# ( HttpWebRequest ). Basically I have application to download a JSON from and API REST, but the problem is when I download it, the JSON comes missing some data, it seems that is cutting some data, with wrong structure. If I use a software which does the same thing that I'm developing, this problem doesn't happen. I'm sure that is something with my code, if I'm missing something. Here is my code:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("MyURL");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
string authInfo = "user" + ":" + "pass";
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
httpWebRequest.Headers["Authorization"] = "Basic " + authInfo;
// Create the HttpContent for the form to be posted.
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var sr = new StreamReader(httpResponse.GetResponseStream(), Encoding.UTF8))
{
StreamWriter sw = new StreamWriter(#"C:\test\Stores.txt");
sw.Write(sr.ReadToEnd());
}
You can try this.its works in my code.
public static async Task MethodName()
{
using (HttpClientHandler handler = new HttpClientHandler() { UseCookies = false })
{
using (HttpClient httpClient = new HttpClient(handler))
{
httpClient.DefaultRequestHeaders.Authorization = Program.getAuthenticationHeader();
string filterQuery = Program.getURI().ToString();
using (HttpResponseMessage httpResponse = await httpClient.GetAsync(filterQuery).ConfigureAwait(false))
{
var streamContent = await httpResponse.Content.ReadAsStreamAsync();
FileStream fs = new FileStream("C:\test\Stores.Json", FileMode.Create);
streamContent.CopyTo(fs);
streamContent.Close();
fs.Close();
}
}
}
}
This can be an issue with your Http request (GET).
Step 1 - If you have a working software with the API, use Fiddler to analyse what is the http GET request it sends. You need to check the header info as well.
Step 2 - Compare the Http request with the HttpRequest you have created. There can be missing parameters etc.