HttpClient and HttpWebRequest cannot make empty Post request - c#

Seems HttpClient is not able to perform the following post request (it throws validation errors)
POST with URI encoded parameters
no Body but Content-Type header setted.
I'm sure this is a problem of usage of C# since I was able to perform the correct request with Postman (see the image)
The service I'm trying to authenticate against is this one Fitbit OAUTH2
I tried also HttpWebRequest, but I failed to do that even with that class, however here's also the second attemp. Seems C# is performing some action different from Postman but I have to figure out which action. Does anyone ever had a similiar issue?
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
public static class MyRequest
{
public static string Call( string uri, string headerName, string header)
{
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create( uri);
webRequest.Method = "POST";
webRequest.Headers.Add( "Authorization", $"{headerName} {header}");
webRequest.ContentType = "application/x-www-form-urlencoded";
var response = (HttpWebResponse) webRequest.GetResponse();
if(response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)
{
}
else
{
return null;
}
using ( var stream = response.GetResponseStream())
{
return stream.ToString();
}
}
}
If I use the HttpClient with the following content
content = FormUrlEncodedContet( keyValues)
the final URL do not have the #_=_ appended, and that is requested by that service otherwise it returns 401

Related

Get Request in C# Returning 401 Not Authorised

Currently trying to do a Get request as part of a c# program. The request works fine on Postman as it uses a header for authorization. However I cannot get the code working for the program to use this header correctly in its Get request. I've had a good look around and tried various bits of code I've found but haven't managed to resolve it so any help would be appreciated!
public string Connect()
{
using (WebClient wc = new WebClient())
{
string URI = "myURL.com";
wc.Headers.Add("Content-Type", "text");
wc.Headers[HttpRequestHeader.Authorization] = "Bearer OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3";//this is the entry code/key
string HtmlResult = wc.DownloadString(URI);
return HtmlResult;
}
}
Above is one method inside the class.
Below is another attempt which is an extension method that gets passed the URL:
public static string GetXml(this string destinationUrl)
{
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create(destinationUrl);
request.Method = "GET";
request.Headers[HttpRequestHeader.Authorization] = "Bearer
OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3";
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
string responseStr = new
StreamReader(responseStream).ReadToEnd();
return responseStr;
}
else
{
Console.Write(String.Format("{0}({1})",
response.StatusDescription, response.StatusCode));
}
return null;
}
Might I recommend the very handy RestSharp package (find it on Nuget).
It turns your current code into something like
public string Connect()
{
var client = new RestClient();
var request = new RestRequest("myURL.com", Method.GET);
request.AddParameter("Authorization", "Bearer OEMwNjI2ODQtMTc3OC00RkIxLTgyN0YtNzEzRkE5NzY3RTc3");
var response = client.Execute(request);
return response.Content;
}
It's much more succinct and easier to use (in my opinion) and thus lessens the likelihood of passing in or using incorrect methods.
If you're still having issues getting data back/connecting. Then using PostMan click Code in the upper right of PostMan and select the C# (RestSharp) option. Whatever is generated there matches exactly what PostMan is sending. Copy that over and you should get data back that matches your PostMan request.

C# Console Rest API header payload

I need to access a Portal which is controlled with Bearer Authentication. Client needs to obtain authentication token then add it to each request
URL ~/token
Method POST
Content-Type application/x-www-form-urlencoded
Payload grant_type=password&username=UserName&password=Password
**How do i add the payload which includes the grant type and username and password to my code **
so far my code is as follows :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
namespace ConsoleRestClient
{
class Program
{
static void Main(string[] args)
{
string URI = "https://token";
WebRequest request = WebRequest.Create(URI);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
}
}`
}
You should be sending your request with content type "application/json" and put requested login variable on the body. To give you an idea:
Headers:
Content-Type:application/json
Body:
{ "username": "MyUserName", "password": "MyPassword" }
Probably you can try adding to the request headers, by doing something like this:
string URI = "https://token";
WebRequest request = WebRequest.Create(URI);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.headers.Add(<header_name>, <header_value>);
then you read these headers on your api.

Web API: FromBody always null

I'm trying to develop a web API, and when I test the POST method, the body is always null. I have tried everything when sending the request:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:1748/api/SomeAPI");
req.Method = "post";;
var aaa = Encoding.Default.GetBytes("Test");
req.ContentType = "application/xml";
req.ContentLength = aaa.Length;
req.GetRequestStream().Write(aaa, 0, aaa.Length);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
using (System.IO.StreamReader sr = new System.IO.StreamReader(res.GetResponseStream())) {
Console.WriteLine(sr.ReadToEnd());
}
I use a breakpoint, and the API is called properly, but the body member is always null:
[HttpPost]
public void Post([FromBody]String test) {
}
try
[HttpPost]
public void SomeApi()
{
var test = HttpContext.Current.Request.Form["Test"];
}
If u send correctly the value,this will work 100%
Your Content Type is set to XML so you must pass the data as XML. This means wrapping your data in <string> element.
I would recommend using RestSharp (http://restsharp.org/) for making WebAPI calls from .Net.
var client = new RestClient("http://localhost:1748/");
var request = new RestRequest("api/SomeAPI", Method.POST);
request.AddBody("Test");
var response = client.Execute(request);
Update
I have created a sample project and it works absolutely fine:
Server side:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class HomeController : ApiController
{
[Route("api/TestAPI")]
[HttpPost]
public IHttpActionResult Post([FromBody]String test)
{
return Ok(string.Format("You passed {0}.", test));
}
}
}
Client side:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:1748/api/TestAPI");
req.Method = "post"; ;
var aaa = Encoding.Default.GetBytes("\"Test\"");
req.ContentType = "application/json";
req.ContentLength = aaa.Length;
req.GetRequestStream().Write(aaa, 0, aaa.Length);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
using (System.IO.StreamReader sr = new System.IO.StreamReader(res.GetResponseStream()))
{
Console.WriteLine(sr.ReadToEnd());
}
}
}
}
After installing the WEB API service in IIS and running the console app it prints:
"You passed Test."
Please note the quotes around the response.
If you want to use XML then you need to modify the content type and data you are sending:
var aaa = Encoding.Default.GetBytes("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Test</string>");
The response you will get is
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">You passed Test.</string>
Both samples in the debugger will have correct value passed in the test parameter.
Two things to try, 1st, try your request using a tried and tested tool like Postman. This will eliminate any chance your request is malformed in any way. 2nd, try changing your ContentType to text/plain. It's possible the request pipeline is seeing application/xml but your request body is invalid xml which really should be a bad request but is just being serialized as null.

C# WebRequest won't work with this link from LinkShare

This is driving me a bit nuts. I am trying to do something quite simple, and I have done it many times before. Just trying to call a REST API.
I am trying to call GetMessage with endpoint = "http://feed.linksynergy.com/productsearch?token=717f8c8511725ea26fd5c3651f32ab187d8db9f4b208be781c292585400e682d&keyword=DVD", and it keeps returning empty string. If I pass it any other valid URL, it will work. But if I just copy and paste the original URL into the web browser, it returns fine!
Can any smart developer tell me what's going on?
Code below. Thanks in advance.
James
public string GetMessage(string endPoint)
{
HttpWebRequest request = CreateWebRequest(endPoint);
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
string message = String.Format("POST failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}
private HttpWebRequest CreateWebRequest(string endPoint)
{
var request = (HttpWebRequest)WebRequest.Create(endPoint);
request.Method = "GET";
request.ContentLength = 0;
request.ContentType = "text/xml";
return request;
}
Not sure why your setting ContentLength/ContentType - that is generally for HTTP POST, where there is a request body for which you write data to via a stream.
This is a HTTP GET, so there is no request body. (just URI w/ query string)
This should work:
using System;
using System.IO;
using System.Net;
using System.Text;
// Create the web request
HttpWebRequest request = WebRequest.Create("http://www.someapi.com/") as HttpWebRequest;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Console application output
Console.WriteLine(reader.ReadToEnd());
}
EDIT
#Gabe is also quite right - try this on another computer, that is isn't behind any kind of firewall/proxy server.
My work PC was behind a proxy server, so in order to make REST-based HTTP calls, i needed to do this:
var proxyObject = new System.Net.WebProxy("http://myDomain:8080/", true);
System.Net.WebRequest req = System.Net.WebRequest.Create("http://www.someapi.com/");
req.Proxy = proxyObject;
proxyObject.Credentials = New System.Net.NetworkCredential("domain\username","password")

How to send an HTTPS GET Request in C#

Related: how-do-i-use-webrequest-to-access-an-ssl-encrypted-site-using-https
How to send an HTTPS GET Request in C#?
Add ?var1=data1&var2=data2 to the end of url to submit values to the page via GET:
using System.Net;
using System.IO;
string url = "https://www.example.com/scriptname.php?var1=hello";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream resStream = response.GetResponseStream();
Simple Get Request using HttpClient Class
using System.Net.Http;
class Program
{
static void Main(string[] args)
{
HttpClient httpClient = new HttpClient();
var result = httpClient.GetAsync("https://www.google.com").Result;
}
}
I prefer to use WebClient, it seems to handle SSL transparently:
http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx
Some troubleshooting help here:
https://clipperhouse.com/webclient-fiddler-and-ssl/

Categories