POSTing JSON to URL via WebClient in C# - c#

I have some JavaScript code that I need to convert to C#. My JavaScript code POSTs some JSON to a web service that's been created. This JavaScript code works fine and looks like the following:
var vm = { k: "1", a: "2", c: "3", v: "4" };
$.ajax({
url: "http://www.mysite.com/1.0/service/action",
type: "POST",
data: JSON.stringify(vm),
contentType: "application/json;charset=utf-8",
success: action_Succeeded,
error: action_Failed
});
function action_Succeeded(r) {
console.log(r);
}
function log_Failed(r1, r2, r3) {
alert("fail");
}
I'm trying to figure out how to convert this to C#. My app is using .NET 2.0. From what I can tell, I need to do something like the following:
using (WebClient client = new WebClient())
{
string json = "?";
client.UploadString("http://www.mysite.com/1.0/service/action", json);
}
I'm a little stuck at this point. I'm not sure what json should look like. I'm not sure if I need to set the content type. If I do, I'm not sure how to do that. I also saw UploadData. So, I'm not sure if I'm even using the right method. In a sense, the serialization of my data is my problem.
Can someone tell me what I'm missing here?
Thank you!

The question is already answered but I think I've found the solution that is simpler and more relevant to the question title, here it is:
var cli = new WebClient();
cli.Headers[HttpRequestHeader.ContentType] = "application/json";
string response = cli.UploadString("http://some/address", "{some:\"json data\"}");
PS: In the most of .net implementations, but not in all WebClient is IDisposable, so of cource it is better to do 'using' or 'Dispose' on it. However in this particular case it is not really necessary.

The following example demonstrates how to POST a JSON via WebClient.UploadString Method:
var vm = new { k = "1", a = "2", c = "3", v= "4" };
using (var client = new WebClient())
{
var dataString = JsonConvert.SerializeObject(vm);
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
client.UploadString(new Uri("http://www.contoso.com/1.0/service/action"), "POST", dataString);
}
Prerequisites: Json.NET library

You need a json serializer to parse your content, probably you already have it,
for your initial question on how to make a request, this might be an idea:
var baseAddress = "http://www.example.com/1.0/service/action";
var http = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
string parsedContent = <<PUT HERE YOUR JSON PARSED CONTENT>>;
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(parsedContent);
Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
var response = http.GetResponse();
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();
hope it helps,

Related

Trying to use Google TTS using HttpWebRequest but it doesn't work

I'm trying to use Google's TTS to convert a text to speech and I want to use HttpWebRequest for this, as I want to avoid any third-party clients. (This is because I'm practicing calling Web API's.) So I have this code:
HttpWebRequest requestVoices = (HttpWebRequest)WebRequest.Create($"https://texttospeech.googleapis.com/v1/voices?key={bearerKey}");
using StreamReader streamReader = new(requestVoices.GetResponse().GetResponseStream());
var voiceList = GoogleVoices.LoadFromJson(streamReader.ReadToEnd()).Sort();
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "Speaking.json"), voiceList.SaveAsJson());
This works fine. I get a list of all voices, ordered by gender, then name. So, being ambitious, I want to generate a sound file, using this configuration:
var sound = new SpeechConfig()
{
Input = new SpeechConfig.InputConfig(){Text = "Hello, World!"},
AudioConfig = new SpeechConfig.AudioSpeechConfig()
{
AudioEncoding = "MP3",
EffectsProfileId = new List<string>(){ "large-home-entertainment-class-device" },
Pitch = 0.0,
SpeakingRate = 1.0
},
Voice = new SpeechConfig.VoiceConfig()
{
Name = "en-IN",
LanguageCode = "en-IN-Wavenet-D"
}
};
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "Speak.json"), sound.SaveAsJson());
And to check if it generates proper JSON, this is what gets written to that file:
{
"AudioConfig": {
"AudioEncoding": "MP3",
"EffectsProfileId": [
"large-home-entertainment-class-device"
],
"Pitch": 0.0,
"SpeakingRate": 1.0
},
"Input": {
"Text": "Hello, World!"
},
"Voice": {
"LanguageCode": "en-IN-Wavenet-D",
"Name": "en-IN"
}
}
So, that looks good too. So now I need to call the TTS API, using this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://texttospeech.googleapis.com/v1/text:synthesize/");
request.Headers.Add("Authorization", $"Bearer {bearerKey}");
request.Headers.Add("Content-Type", "application/json; charset=utf-8");
request.Method = "POST";
request.ContentType = "application/json";
using (StreamWriter streamWriter = new(request.GetRequestStream()))
{
streamWriter.Write(sound.SaveAsJson());
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string soundFileName= Path.Combine(Environment.CurrentDirectory, "Sound.mp3");
var soundFile = File.Create(soundFileName);
response.GetResponseStream().CopyTo(soundFile);
soundFile.Close();
But nothing gets written and I get the error: Unhandled exception. System.Net.WebException: The remote server returned an error: (401) Unauthorized. at System.Net.HttpWebRequest.GetResponse() at Program.<Main>$(String[] args)...
Now, I know the bearer key is correct as I get a list of voices.
Using Google gives me way too many results, most of which use third-party libraries or talk about the "Translate" API. So that's not very useful. So I used OpenAI (ChatGPT) to give me an example, which wasn't much different, but used this as url: "https://texttospeech.googleapis.com/v1/text:synthesize?key=YOUR_API_KEY&input.text=" + textToSynthesize;
Well, that doesn't work either. So, I tried this as something suggested it:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("Authorization", "Bearer $(gcloud auth print-access-token)");
request.Headers.Add("X-goog-api-key", $"{bearerKey}");
Still no luck. And there are no restrictions on this API key, except it's less than an hour old. Could it be that I just have to wait longer? Or am I doing something wrong? I must be doing something wrong, I think. I get the list of voices, but not the sound.
What am I doing wrong?
And I'm an idiot! :D This part:
"Voice": {
"LanguageCode": "en-IN-Wavenet-D",
"Name": "en-IN"
}
should be:
"Voice": {
"LanguageCode": "en-IN",
"Name": "en-IN-Wavenet-D"
}
Also, the JSON is case-sensitive...
Working code:
public async Task Speak(string filename, string bearerKey, string text)
{
string url = $"https://texttospeech.googleapis.com/v1/text:synthesize?key={bearerKey}";
var client = new HttpClient();
var context = new StringContent(Sound(text).SaveAsJson(), Encoding.UTF8, "application/json");
using HttpResponseMessage response = await client.PostAsync(url, context);
var result = AudioContent.LoadFromJson(await response.Content.ReadAsStringAsync());
File.WriteAllBytes(filename, System.Convert.FromBase64String(result.Content));
}
And yes, decided to use HttpClient() as it was easier. This method is part of a class that holds the voice data. Sound is created by:
public SpeechConfig Sound(string text) =>
new()
{
Input = new SpeechConfig.InputConfig()
{
Text = text
},
AudioConfig = new SpeechConfig.AudioSpeechConfig()
{
AudioEncoding = "MP3",
EffectsProfileId = new List<string>() { "large-home-entertainment-class-device" },
Pitch = Value.Pitch,
SpeakingRate = Value.SpeakingRate
},
Voice = new SpeechConfig.VoiceConfig()
{
Name = Value.Selection.Name,
LanguageCode = Value.Selection.LanguageCode
}
};
In the same class.

Calling PayU rest api (create order) returns html instead of json response

I'm trying to post an order to PayU payment gateway, using Rest Client tools like post man also I got the same issue.
I'm trying to post using C#, the order created successfully but the response is not as expected, it should be a json object contains the inserted order id and the redirect url , but the current is html response!
C# Code response :
My C# Code using restsharp library :
public IRestResponse<CreateOrderResponseDTO> CreateOrder(CreateOrderDTO orderToCreate)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var actionUrl = "/api/v2_1/orders/";
var client = new RestClient(_baseUrl);
var request = new RestRequest(actionUrl, Method.POST)
{
RequestFormat = DataFormat.Json
};
request.AddJsonBody(orderToCreate);
request.AddHeader("authorization", $"Bearer {_accessToken}");
request.AddHeader("Content-Type", "application/json");
var response = client.Execute<CreateOrderResponseDTO>(request);
if (response.StatusCode == HttpStatusCode.OK)
{
return response;
}
throw new Exception("order not inserted check the data.");
}
My C# Code using built in WebRequest also returns same html :
public string Test(string url, CreateOrderDTO order)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + _accessToken);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(new JavaScriptSerializer().Serialize(order));
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
Can anyone advise what I missed here ?
In postman, the solution is turning off redirects, like on the image below:
After some tries I found that PayU rest api returns 302 (found) also ResponseUri not OK 200 as expected.
by default rest client automatically redirect to this url so I received the html content of the payment page.
The solution is :
client.FollowRedirects = false;
Hope this useful to anyone.
Also, I would like to add that the above answer by Mohammad is correct as to get the response URL we need to set AllowAutoRedirect to false. I have been trying to implement PayU LatAM WebCheckout in a console app and I was facing similar issue. I got some inspiration from the answer given here: How to get Location header with WebClient after POST request
Based on the answer, I wrote a sample code:
public class NoRedirectWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var temp = base.GetWebRequest(address) as HttpWebRequest;
temp.AllowAutoRedirect = false;
return temp;
}
}
After creating the above class, I wrote the following code in my Main method:
var request = MakeRequestLocation(new NoRedirectWebClient());
var psi = new ProcessStartInfo("chrome.exe");
psi.Arguments = request.ResponseHeaders["Location"];
Process.Start(psi);
I am now calling the function MakeRequestLocation inside the same class.
private static WebClient MakeRequestLocation(WebClient webClient)
{
var loginUrl = #"https://sandbox.checkout.payulatam.com/ppp-web-gateway-payu/";
NameValueCollection formData = new NameValueCollection
{
{"ApiKey", "4Vj8eK4rloUd272L48hsrarnUA" },
{"merchantId", "508029" },
{"accountId", "512321" },
{"description", "Test PAYU" },
{"referenceCode", "SomeRandomReferenceCode" },
{"amount", "2" },
{"tax", "0" },
{"taxReturnBase", "0" },
{"currency", "USD" },
{"signature", "Signature generated via MD5 sum" },
{"buyerFullName", "test" },
{"buyerEmail", "test#test.com" },
{"responseUrl", #"http://www.test.com/response" },
{"confirmationUrl", #"http://www.test.com/confirmation" }
};
webClient.UploadValues(loginUrl, "POST", formData);
return webClient;
}
The object that is returned by the above function contains a header called location. The value of the location is your required URL for webcheckout.

How do I Convert this Ajax Post request to C#

I'm making a project in c# to get a facebook ID from any facebook URL. I an API that can helps but the code is using this Ajax POST code:
// get facebook id
$('#get-facebook-id').submit(function(event) {
$('#answer').html("<b>Working for you...</b>");
$.ajax({
type: 'POST',
url: 'https://codeofaninja.com/tools/get-facebook-id-answer.php',
data: $(this).serialize()
})
.done(function(data){
$('#answer').html(data);
$('#page_url_tb').val('')
})
.fail(function() {
alert( "Posting failed. Please try again." );
});
return false;
});
I'm trying to make my own code but is giving me an error. My code and my error down bellow.
private string getFbAccountID(string facebookurl)
{
var request = (HttpWebRequest)WebRequest.Create("https://codeofaninja.com/tools/get-facebook-id-answer.php");
var postData = "page_url="+facebookurl;
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return responseString;
}
Error:
<br />
<b>Notice</b>: Undefined index: page_url in <b>/home/100661.cloudwaysapps.com/rpxdhcedbx/public_html/tools/get-facebook-id-answer.php</b> on line <b>3</b><br />
<br />
<b>Notice</b>: Undefined offset: 1 in <b>/home/100661.cloudwaysapps.com/rpxdhcedbx/public_html/tools/get-facebook-id-answer.php</b> on line <b>19</b><br />
<p>There was an error. Please try a different input.</p>
This is always giving me this error. I hope someone can helps me
I take it you're working on this exercise. :)
But to answer your question, you're not URL encoding facebookurl.
If you use one of the example Facebook URLs on their page, and watch the network traffic using the developer tools in the browser (F12), you will see this as the form data being sent: page_url=https%3A%2F%2Fwww.facebook.com%2Fpages%2FAndrew-Garfield%2F166865773328160
jQuery's serialize() function does that for you.
In C#, you can use WebUtility.UrlEncode:
var postData = "page_url=" + WebUtility.UrlEncode(facebookurl);
Here you have an alternative using System.Net.WebClient, it will make your code leaner:
private string getFbAccountID(string facebookurl)
{
using (var webClient = new System.Net.WebClient())
{
var formValues = new System.Collections.Specialized.NameValueCollection
{
{ "page_url", facebookurl }
};
var responseBytes = webClient.UploadValues(
"https://codeofaninja.com/tools/get-facebook-id-answer.php",
formValues
);
return System.Text.Encoding.UTF8.GetString(responseBytes);
}
}

How to correctly send json with httpWebRequest?

I have a httpWebRequest object.
It is initialised like this:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://myURL.com"); // This is actually my company URL I can't show
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
Then I want to send to this URL json datas. After tries, I figured I do it wrong, but I don't get what it is... Here is where I send it datas:
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
List<string> datas = new List<string>();
datas.Add("1");
string json = Newtonsoft.Json.JsonConvert.SerializeObject(datas);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
It doesn't seem to be working. Is there a way to catch the URL I'm sending? I tried Fiddler, but I don't see my request.
Also this code works with a chrome console:
jQuery.ajax({
'url': 'http://myURL.com',
'type': 'POST',
'data': {data:[7]},
'success': function (data) {
console.log(data);
}
});
From the code you use at Chrome it is denoted your data structure is not correct.
First, you need a class to store the data, lets call it DataHolder:
public class DataHolder
{
public int[] data { get; set; }
}
So now you need to fill it:
var newData = new DataHolder{ data = new int[] { 1 } };
And now you can serialize it and it should work:
string json = Newtonsoft.Json.JsonConvert.SerializeObject(newData);
EDIT: as a note, in a previous question you posted you tried to send "{ data: [1] }" which is incorrect, it should be "{ \"data\": [1] }" but better stick to a class with the correct structure and let the serializer deal with those implementation details.

How to handle C# .NET POST and GET commands

The current project I am working on requires a 2 way communication from the bot to my website.
Supposing the example URL is www.example.com/foobar.php or something, can you explain me how to POST and GET data from there?
Thanks a lot.
P.S. - Using webclient right?
I'd suggest using RestSharp. It's a lot easier than using WebClient, and gives you a lot more options:
var client = new RestClient("http://www.example.com/");
//to POST data:
var postRequest = new RestRequest("foo.php", Method.POST);
postRequest.AddParameter("name", "value");
var postResponse = client.Execute(postRequest);
//postResponse.Content will contain the raw response from the server
//To GET data
var getRequest = new RestRequest("foo.php", Method.GET);
getRequest.AddParameter("name", "value");
var getResponse = client.Execute(getRequest);
Yes, you can use WebClient:
using (WebClient client = new WebClient())
{
NameValueCollection nvc = new NameValueCollection()
{
{ "foo", "bar"}
};
byte[] responseBytes = client.UploadValues("http://www.example.com/foobar.php", nvc);
string response = System.Text.Encoding.ASCII.GetString(responseBytes);
}
You can use WebClient
Look up method UploadString and DownloadString

Categories

Resources