Cannot submit form data via POST API call - c#

I'm trying to make a POST API call to update a product on Prisync with multipart/formdata text field.
The call responses success on POSTMAN:
but it returns 400 Bad request error in .NET code:
Can you please let me know what's wrong here?
Here is my code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
namespace PrisyncPost
{
class Program
{
static string apikey = "luan.t44#gmail.com";
static string apitoken = "3a3206b37763722c0fc6431b713d9239";
static void Main(string[] args)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://prisync.com/api/v2/edit/product/id/10117217");
httpWebRequest.Method = "POST";
httpWebRequest.Headers["apikey"] = apikey;
httpWebRequest.Headers["apitoken"] = apitoken;
httpWebRequest.ContentType = "multipart/form-data; boundary=&";
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent("test test test"), "name");
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
foreach (var item in form)
streamWriter.Write(item);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
}
}

Related

c# Json Post throws 404 bad request error

I am new to JSON and C# and trying for a POST request and reading the response.
I am writing the Content Type correctly, url I am trying to send to the server is also correct. Probably my code is just incorrect and I will appreciate for any helps on this.
Below is my code but I keep getting 400 bad request.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Text;
using System.IO;
using System.Diagnostics;
public class Server
{
public void ServerStart()
{
try{
string webAddr="https://localhost:61000/users/login";
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{ \"userName\" : \"laborel\", \"userPassword\" : \"dGVzdG5ldFBDMSEu\" }";
streamWriter.Write(json);
streamWriter.Flush();
}
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
byte[] responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
}
}catch(WebException ex){
Console.WriteLine(ex.Message);
System.Windows.Forms.MessageBox.Show(string.Format ("Exception Occurred: {0}",ex.Message));
}
}
}
One thing byte[] responseText = streamReader.ReadToEnd(); is not right, where I am not sure what should bet the responseText
Could some one point me out on how can we create a function which accepts the webaddress and the json string as input and returns the response text
Following would work string responseText = streamReader.ReadToEnd();

Authenticate login in website using certificate C#

I'm doing some research, and I want to logging into the ecac site using my company's certificate ... using Chrome I can access the system without any problem because chrome asks for the certificate to authenticate the login. I tried to implement a small test crawler, where I put my certificate in the request, but, the government website always returns error ... So I tried to use selenium with the chrome driver to login, but with that it is necessary that I select the certificate manually, and my idea is to do this automatically.
My test source is:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace TestCrawler
{
class Program
{
static void Main(string[] args)
{
string host = #"https://cav.receita.fazenda.gov.br/autenticacao/login";
string certName = #"certificado.pfx";
string password = #"senha";
try
{
X509Certificate2 certificate = new X509Certificate2(certName, password);
ServicePointManager.CheckCertificateRevocationList = false;
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
ServicePointManager.Expect100Continue = true;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.PreAuthenticate = true;
req.AllowAutoRedirect = true;
req.ClientCertificates.Add(certificate);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string postData = "login-form-type=cert";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);
req.ContentLength = postBytes.Length;
Stream postStream = req.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while (line != null)
{
Console.WriteLine(line);
line = reader.ReadLine();
}
}
stream.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
When analyzing the source of the ecac site, I have identified that in the login button by the certificate, a JS code is executed
onclick="javascript:document.loginCert.submit(); return false;
My another test:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
namespace TestCrawler
{
class Program
{
private static string host = #"https://cav.receita.fazenda.gov.br/";
private static string certName = #"certificado.pfx";
private static string password = #"senha";
static async void Login()
{
X509Certificate2 certificate = new X509Certificate2(certName, password);
var handler = new WebRequestHandler();
handler.ClientCertificates.Add(certificate);
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri(host);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html"));
// New code:
using (HttpResponseMessage response = await client.GetAsync("autenticacao/Login/Certificado"))
{
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
}
}
}
}
static void Main(string[] args)
{
Login();
Console.ReadLine();
}
}
}

C# Console Application httpWebRequest

Im trying to create a very simple c# console application to post some data to a web api. However whatever I do I get an error on the response like:
responseText "{\"info\":{\"status\":\"failed\",\"error\":{\"code\":1000,\"message\":\"Invalid argument from request\"}}}" string
The api http://www.detrack.com/api-documentation/ is looking for a post like
https://app.detrack.com/api/v1/deliveries/view/all.json?key=dab13cc0094620102d89f06c0e464b7de0782bb979258d3a&json={"date":"2014-08-29"}
I know using this in chrome advanced rest application extension returns a valid result. But When I try the same via this console code. I get an error!.
Here is the code I have in my console application.
using System;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://app.detrack.com/api/v1/deliveries/view/all.json?key=dab13cc0094620102d89f06c0e464b7de0782bb979258d3a&");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "json={\"date\":\"2014-08-28\"}";
Console.WriteLine(json);
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
Console.ReadKey();
}
}
}
}
Any help/guidance would be really appreciated
brendan
So I'm looking at this:
string json = "json={\"date\":\"2014-08-28\"}";
And according to the brief description on detrack that is not what you want. They're expecting valid json and that isn't. Here's what you should be considering valid json:
string json = "{\"date\":\"2014-08-28\"}";
Be warned I don't know about your escaping of quotes. I would serialize that differently; either a strongly typed class or an anonymous class. Anon would look like this:
string json = JsonConvert.DeserializeObject(new { date = "2014-08-28" });
Setting aside any concerns about time, timezones, utc, etc, that will serialize your structures correctly. Here's a scratchy program from linqpad:
void Main()
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(new { date = "2014-08-28"});
Console.WriteLine(json);
}
>>> {"date":"2014-08-28"}
You can try the (untested!) code below.
using System;
using System.Net;
using System.IO;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
var webAddr = "https://app.detrack.com/api/v1/deliveries/create.json";
var httpWebRequest = (HttpWebRequest) WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
string postData = "key=dab13cc0094620102d89f06c0e464b7de0782bb979258d3a&json={""date"":""2014-08-28""}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
httpWebRequest.ContentLength = byteArray.Length;
using(var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(byteArray, 0, byteArray.Length);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using(var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
MessageBox.Show(result);
}
}
}
}

Call to OData service from C#

I use the code below to call an OData service (which is the working service from Odata.org) from C# and I don't get any result.The error is in the response.GetResponseStream().
Here is the error :
Length = 'stream.Length' threw an exception of type 'System.NotSupportedException'
I want to call to the service and parse the data from it, what is the simpliest way to do that?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using System.IO;
using System.Xml;
namespace ConsoleApplication1
{
public class Class1
{
static void Main(string[] args)
{
Class1.CreateObject();
}
private const string URL = "http://services.odata.org/OData/OData.svc/Products?$format=atom";
private static void CreateObject()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "GET";
request.ContentType = "application/xml";
request.Accept = "application/xml";
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
XmlTextReader reader = new XmlTextReader(stream);
}
}
}
}
}
I ran your code on my machine, and it executed fine, I was able to traverse all XML elements retrieved by the XmlTextReader.
var request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "GET";
request.ContentType = "application/xml";
request.Accept = "application/xml";
using (var response = request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
var reader = new XmlTextReader(stream);
while (reader.Read())
{
Console.WriteLine(reader.Value);
}
}
}
But as #qujck suggested, take a look at HttpClient. It's much easier to use.
If you're running .NET 4.5 then take a look at HttpClient (MSDN)
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(endpoint);
Stream stream = await response
.Content.ReadAsStreamAsync().ConfigureAwait(false);
response.EnsureSuccessStatusCode();
See here and here for complete examples

POST Querystring using WebClient

I want to execute a QueryString using WebClient but using the POST Method
That is what I got so far
CODE:
using (var client = new WebClient())
{
client.QueryString.Add("somedata", "value");
client.DownloadString("uri");
}
It is working but unfortunately it is using GET not POST and the reason I want it to use POST is that I am doing a web scraping and this is how the request is made as I see in WireShark. [IT USES POST AS A METHOD BUT NO POST DATA ONLY THE QUERY STRING.]
In answer to your specific question:
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] response = client.UploadData("your url", "POST", new byte[] { });
//get the response as a string and do something with it...
string s = System.Text.Encoding.Default.GetString(response);
But using WebClient can be a PITA since it doesn't accept cookies nor allow you to set a timeout.
this will help you, use WebRequest instead of WebClient.
using System;
using System.Net;
using System.Threading;
using System.IO;
using System.Text;
class ThreadTest
{
static void Main()
{
WebRequest req = WebRequest.Create("http://www.yourDomain.com/search");
req.Proxy = null;
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string reqString = "searchtextbox=webclient&searchmode=simple";
byte[] reqData = Encoding.UTF8.GetBytes(reqString);
req.ContentLength = reqData.Length;
using (Stream reqStream = req.GetRequestStream())
reqStream.Write(reqData, 0, reqData.Length);
using (WebResponse res = req.GetResponse())
using (Stream resSteam = res.GetResponseStream())
using (StreamReader sr = new StreamReader(resSteam))
File.WriteAllText("SearchResults.html", sr.ReadToEnd());
System.Diagnostics.Process.Start("SearchResults.html");
}
}

Categories

Resources