issue with post with string containg & in c# - c#

i am trying to make a post to url which should look like below image in body of fiddler.
correct post from fiddler
ISSUE HAPPENING : when i post it spilt from & (ampersand) and create separate entries for key value in body of fiddler.
my post in fiddler
what should i do to appear in single key value pair?
i am trying to post following data :
responseData = "paymentid=100131806470125606&result=NOT+CAPTURED&auth=138601&ref=806420053674&tranid=131806429899386&postdate=0305&trackid=100001182618838&udf1=1&udf2=2&udf3=3&udf4=4&udf5=5&amt=5190.0&authRespCode=51"
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string HtmlResult = wc.UploadString("https://example.com/test.php", "authRespCode=1&responseData = " + responseData);
}

You can use HttpUtility.ParseQueryString:
var res = HttpUtility.ParseQueryString(responseData);
then you can access you parameters like so:
res["paymentid"]
etc...

adding this line solved my problem :
responseData = responseData.Replace("&", "&");
responseData = HttpUtility.UrlEncode(responseData);
Complete code :
string responseData = Utilitycl.GetHtmlInputValue(getString, "responseData", Utilitycl.ELEMENTTYPE.INPUT);
responseData = responseData.Replace("&", "&");
responseData = HttpUtility.UrlEncode(responseData);
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string HtmlResult = wc.UploadString("https://example.com/test.php", "authRespCode=1&responseData = " + responseData);
}

You will need to escape your URI string:
string HtmlResult = wc.UploadString("https://example.com/test.php", "authRespCode=1&responseData = " + Uri.EscapeUriString(responseData));

Related

Publish article for Apple news API using C# - (401) Unauthorized

I am working on posting article using Apple news API.
I created new account and also created new channel.
Below is the code snippet which I am using.
string channel_id = "{Channel_Id}";
string api_key_id = "{Key_Id}";
string api_key_secret = "{Secret}";
var path = "https://news-api.apple.com/channels/" + channel_id + "/articles";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.ContentType = "multipart/form-data";
httpWebRequest.Method = "POST";
httpWebRequest.Accept = "application/json";
httpWebRequest.Host = "news-api.apple.com";
httpWebRequest.UseDefaultCredentials = true;
httpWebRequest.PreAuthenticate = true;
httpWebRequest.ProtocolVersion = HttpVersion.Version11;
httpWebRequest.KeepAlive = true;
string appleDate = String.Format("{0}Z", DateTime.UtcNow.ToString("s"));
string credentials = String.Format("{0}:{1}", "Content-Disposition", "form-data; ");
credentials += String.Format("{0}:{1}", "filename", "article.json; ");
credentials += String.Format("{0}:{1}", "name", "article.json; ");
credentials += String.Format("{0}","HHMAC; ");
credentials += String.Format("{0}={1}", "key", api_key_id + "; ");
string decodedSecret = base64Decode(api_key_secret);
string canonical_request = path + "POST" + appleDate ;
string hash = Class1.HmacSha256Digest(canonical_request, decodedSecret);
string Encodedhash = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(hash));
credentials += String.Format("{0}={1}", "signature", Encodedhash + "; ");
credentials += String.Format("{0}={1}", "date", appleDate + "; ");
httpWebRequest.Headers.Add("Authorization", credentials);
using (StreamReader r = new StreamReader(Directory.GetCurrentDirectory() + ("/article.json")))
{
string json = r.ReadToEnd();
dynamic jsonObj = JsonConvert.DeserializeObject(json);
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(json);
Stream newStream = httpWebRequest.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Here is base64Decode function
public static string base64Decode(string data)
{
var base64EncodedBytes = System.Convert.FromBase64String(data);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
Here is class to convert Sha256Digest
public static class Class1
{
public static string HmacSha256Digest(this string message, string secret)
{
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] keyBytes = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
System.Security.Cryptography.HMACSHA256 cryptographer = new System.Security.Cryptography.HMACSHA256(keyBytes);
byte[] bytes = cryptographer.ComputeHash(messageBytes);
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
}
Whenever I am trying to post the API I am getting below error message:
"'The remote server returned an error: (401) Unauthorized".
When I am trying to post the API request using Postman then I am getting below error message:
{
"errors": [
{
"code": "WRONG_SIGNATURE"
}
]
}
Is there anything incorrect to generate Signature ?
I researched few articles but unable to find any solution.
Please guide me to find out the solution on this.
I don't have time to go through the entirety of your code and suggest you start with a simpler Channel Data request before attempting to POST json, but a potential couple of bits I noticed:
You use ASCII encoding where you should be using UTF8 throughout.
You strip hyphens from the Base64 but Apple only strips returns and
whitespace
The cannonical request should be written: "POST[url][date][contentType]" where url = "https://news-api.apple.com/channels/[channelID]/articles", date is in the format "yyyy-MM-dd'T'HH:mm:ss'Z'" and content-type = "multipart/form-data; boundary=[boundary]" where boundary is any string used to divide the content.
See also my tips on using Python, most importantly ensure you are using the path to a folder containing article.json (not the path to a file). And finally here is my own translation of the Python into Swift.

Unable to Post on Pinterest using their API

I'm receiving a 400 Bad Request error message when posting a pin on Pinterest. It works using Postman, but doesn't work programmatically. Using C#, has anyone been able to successfully post a pin on Pinterest without using the pinsharp wrapper?
private void postPinterest(string messages, string id, string usertoken, string image, string boardname, string username)
{
string link = null;
boardname = boardname.Replace(" ", "-");
string board = username + "/" + boardname;
string url = "https://api.pinterest.com/v1/pins?access_token=" + usertoken;
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrEmpty(board))
sb.Append("&board=" + HttpUtility.UrlEncode(board));
if (!string.IsNullOrEmpty(messages))
sb.Append("&note=" + HttpUtility.UrlEncode(messages));
if (!string.IsNullOrEmpty(link))
sb.Append("&image_url=" + HttpUtility.UrlEncode(link));
string postdata = sb.ToString().Substring(1);
PostData(url, postdata);
}
private object PostData(string url, string postdata)
{
object json=null;
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
// req.Accept = "application/json";
using (var stream = req.GetRequestStream())
{
byte[] bindata = Encoding.ASCII.GetBytes(postdata);
stream.Write(bindata, 0, bindata.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string response = new StreamReader(resp.GetResponseStream()).ReadToEnd();
json = JsonConvert.DeserializeObject<dynamic>(response);
return json;
}
catch (WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
return json;
}
}
}
}
return json;
}
EDIT:
It doesn't work using the JSON format or x-www-form-urlencoded format.
I changed the content type to application/x-www-form-urlencoded and now I'm receiving the error message below. I receive 400 Bad Request error using JSON format:
"{\n \"message\": \"405: Method Not Allowed\",\n \"type\": \"http\"\n}"
The problem is the the parameter that you are posting.
In the Api i could find board as a parameter but both note and image comes under field parameter which specifies the return type JSON.
As per documentation on this page you can post in this format
https://api.pinterest.com/v1/boards/anapinskywalker/wanderlust/pins/?
access_token=abcde&
limit=2&
fields=id,link,counts,note
So I tried the following and its getting response
https://api.pinterest.com/v1/boards/?access_token="YourTokenWithoutQuotes"&fields=id%2Ccreator
Would suggest you to first test the Api you are hitting putting a breakpoint inside the PostData function and check if the passed url is in the correct format and compare it with Pininterest API Explorer.
As you might have already received authorization code and access token so I am assuming your post function should be working fine.
public string postPinterest(string access_token,string boardname,string note,string image_url)
{
public string pinSharesEndPoint = "https://api.pinterest.com/v1/pins/?access_token={0}";
var requestUrl = String.Format(pinSharesEndPoint, accessToken);
var message = new
{
board = boardname,
note = note,
image_url = image_url
};
var requestJson = new JavaScriptSerializer().Serialize(message);
var client = new WebClient();
var requestHeaders = new NameValueCollection
{
{"Content-Type", "application/json" },
{"x-li-format", "json" }
};
client.Headers.Add(requestHeaders);
var responseJson = client.UploadString(requestUrl, "POST", requestJson);
var response = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(responseJson);
return response;
}

Set a body for WebClient when making a Post Request

So I have an api that I want to call to. The first call is an ahoy call and in the body of the request I need to send the ship_type, piratename and my piratepass. I then want to read the response which has my treasure booty that i will use for later.
I'm able to do this with web request. but i feel like there is a better way to do it with webclient.
(way I currently do it in webrequest)
//Credentials for the Pirate api
string piratename = "IvanTheTerrible";
string piratepass= "YARRRRRRRR";
string URI = "https://www.PiratesSuperSecretHQ.com/sandyShores/api/respectmyauthority";
WebRequest wr = WebRequest.Create(URI);
wr.Method = "POST";
wr.ContentType = "application/x-www-form-urlencoded";
string bodyData = "ship_type=BattleCruiser&piratename=" + piratename + "&piratepass=" + piratepass;
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] byte1 = encoder.GetBytes(bodyData);
wr.ContentLength = byte1.Length;
//writes the body to the request
Stream newStream = wr.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();
WebResponse wrep = wr.GetResponse();
string result;
using (var reader = new StreamReader(wrep.GetResponseStream()))
{
result = reader.ReadToEnd(); // do something fun...
}
Thanks in advance either way.
You can do with this simple code
Uri uri = new Uri("yourUri");
string data = "yourData";
WebClient client = new WebClient();
var result = client.UploadString(uri, data);
Remember that you can use UploadStringTaskAsync if you want to be async
You can try like below as well:
public String wcPost(){
Map<String, String> bodyMap = new HashMap();
bodyMap.put("key1","value1");
WebClient client = WebClient.builder()
.baseUrl("domainURL")
.build();
String responseSpec = client.post()
.uri("URI")
.headers(h -> h.setBearerAuth("token if any"))
.body(BodyInserters.fromValue(bodyMap))
.exchange()
.flatMap(clientResponse -> {
if (clientResponse.statusCode().is5xxServerError()) {
clientResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
return clientResponse.bodyToMono(String.class);
}
else
return clientResponse.bodyToMono(String.class);
})
.block();
return responseSpec;
}

Is it required to encode values when using UploadString with C# WebClient?

I have code like the following to do a POST to a server:
string URI = "http://mydomain.com/foo";
string myParameters =
"&token=1234" +
"&text=" + HttpUtility.UrlEncode(someVariable);
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string HtmlResult = wc.UploadString(URI, myParameters);
}
Is it required to UrlEncode the parameters like I'm doing or does UploadString handle that automatically under the covers? I don't want to risk any type of double encoding.
Yes, it is required to encode them if you use the UploadString method.
But you could use a more intelligent overload for your case (UploadValues):
string URI = "http://mydomain.com/foo";
var values = new NameValueCollection
{
{ "token", "1234" },
{ "text", someVariable },
};
using (var wc = new WebClient())
{
byte[] result = wc.UploadValues(URI, values);
string htmlResult = Encoding.UTF8.GetString(result);
}
Now you no longer need to worry about any encodings. The WebClient will take them into account when sending the request. Also you will notice that I have removed the application/x-www-form-urlencoded you were adding because when you use the UploadValues method this Content-Type header will automatically be added to the request.

How to fill forms and submit with Webclient in C#

I'm new at using the the libraries WebClient, HttpResponse and HttpRequest in C#, so bear with me, if my question is confusing to read.
I need to build a WinForm based on C# which can open a URL, which is secured with the basic authorization. I did this with adding this to the header, like this:
using (WebClient wc = new WebClient())
{
wc.Headers.Add(HttpRequestHeader.Authorization, "Basic " +
Convert.ToBase64String(
Encoding.ASCII.GetBytes(username + ":" + password)));
}
So far, so good! Now I would like to fill a form with a number, and I find the source-code from the site, and discover that the name is "number". So I write this:
NameValueCollection formData = new NameValueCollection();
formData["number"] = number
byte[] responseBytes = wc.UploadValues(theurl, "POST", formData);
string response = Encoding.ASCII.GetString(responseBytes);
textBox_HTML.Text = response;
But how do I submit this? I will like to receive my "search-results"...
You should probably be using HttpWebRequest for this. Here's a simple example:
var strId = UserId_TextBox.Text;
var strName = Name_TextBox.Text;
var encoding=new ASCIIEncoding();
var postData="userid="+strId;
postData += ("&username="+strName);
byte[] data = encoding.GetBytes(postData);
var myRequest =
(HttpWebRequest)WebRequest.Create("http://localhost/MyIdentity/Default.aspx");
myRequest.Method = "POST";
myRequest.ContentType="application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
var newStream=myRequest.GetRequestStream();
newStream.Write(data,0,data.Length);
newStream.Close();
var response = myRequest.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
var result = responseReader.ReadToEnd();
responseReader.Close();
response.Close();
Try this:
using System.Net;
using System.Collections.Specialized;
NameValueCollection values = new NameValueCollection();
values.Add("TextBox1", "value1");
values.Add("TextBox2", "value2");
values.Add("TextBox3", "value3");
string Url = urlvalue.ToLower();
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] result = client.UploadValues(Url, "POST", values);
string ResultAuthTicket = System.Text.Encoding.UTF8.GetString(result);
}
I have found a solution to my problem. First of all I was confused about some of the basics in http-communication. This was caused by a python-script i wrote, which have a different approach with the communication.
I solved it with generating the POST-data from scratch and open the uri, which was contained in the form-action.
BFree's answer works great. One thing I would note, though, is that the data concatenation should really be url-encoded, otherwise you'd have trouble with things like "=" and "&" signs within the data.
The VB.NET version, urlencoded and with UTF-8 support, is below (note that url-encoding requires a reference to System.Web.dll, which only worked for me after I switched from .NET 4 Compact Framework to the regular .NET 4 Framework).
Imports System.Web
Imports System.Net
Imports System.IO
Public Class WebFormSubmitter
Public Shared Function submit(ByVal address As String,
ByVal values As Dictionary(Of String, String)) As String
Dim encoding As New UTF8Encoding
Dim postData As String = getPostData(values:=values)
Dim data() As Byte = encoding.GetBytes(postData)
Dim request = CType(WebRequest.Create(address), HttpWebRequest)
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = data.Length
Dim newStream = request.GetRequestStream()
newStream.Write(data, 0, data.Length)
newStream.Close()
Dim response = request.GetResponse()
Dim responseStream = response.GetResponseStream()
Dim responseReader = New StreamReader(responseStream)
Return responseReader.ReadToEnd()
End Function
Private Shared Function getPostData(ByVal values As Dictionary(Of String, String)) As String
Dim postDataPairList As New List(Of String)
For Each anEntry In values
postDataPairList.Add(anEntry.Key & "=" & HttpUtility.UrlEncode(anEntry.Value))
Next
Return String.Join(separator:="&", values:=postDataPairList)
End Function
End Class
Posting a form with System.Net.Http.HttpClient and reading the response as string:
var formData = new Dictionary<string, string>();
formData.Add("number", number);
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var httpResponse = await httpClient.PostAsync(theurl, content);
var responseString = await httpResponse.Content.ReadAsStringAsync();
}
You submitted it already with UploadValues. The question is: what is your "result-search"? What does the page return? HTML? If so - the HTML Agility Pack is the easiest way to parse html.

Categories