I am working on a project where I can only return 30 results at a time from a server. I am using a loop in my program to change a parameter of the connection and return the next set after each loop by using the GetWorkers() command below.
I need to use a token to get the JObject.Parse(serverResponse). I want to be able to save the Token upon each loop to reuse it since it times out after 1 hour.
I am not sure what the best way to save the token is upon every loop. Currently it takes 30 sec to 1 minute to execute this entire process, and I would like it to be shorter anywhere I can manage to avoid any timeouts.
private ADPAccessToken GetAccessToken()
{
//var session = HttpContext.Current.Session;
////var session = Request.Properties["System.Web.HttpContex"] as HttpContextWrapper;
ADPAccessToken token = null;
//if (session["Token"] != null)
//{
// token = session["Token"] as ADPAccessToken;
// if (DateTime.Compare(DateTime.Now, token.ExpiresOn.Value) > 0)
// token = null;
//}
if (token == null)
{
//string formData = string.Concat("grant_type=client_credentials&scope=", HttpUtility.UrlEncode(accessScope));
string formData = string.Concat("grant_type=client_credentials");
var usrpwd = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Concat(NetworkUserName, ":", NetworkUserPassword)));
byte[] data = Encoding.ASCII.GetBytes(formData);
var result = postToADPServer(ADPAuthenticationURL, data, "Basic " + usrpwd);
if (!string.IsNullOrEmpty(result))
{
token = JsonConvert.DeserializeObject<ADPAccessToken>(result);
//session["Token"] = token;
}
}
return token;
}
public JObject GetWorkers()
{
return GetData(getWorkerURL);
}
private JObject GetData(string url)
{
ADPAccessToken token = GetAccessToken();
HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
var usrpwd = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(token.TokenType + " " + token.AccessToken));
var serverResponse = postToADPServer(url, null, token.TokenType + " " + token.AccessToken, "application/json");
return JObject.Parse(serverResponse);
}
private string postToADPServer(string url, byte[] postData, string authorization, string contentType = null)
{
HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
X509Certificate2 certificate = new X509Certificate2(");
myHttpWebRequest.ClientCertificates.Add(certificate);
myHttpWebRequest.Headers.Add(HttpRequestHeader.Authorization, authorization);
if (postData != null)
{
if (!string.IsNullOrEmpty(contentType))
myHttpWebRequest.ContentType = contentType;
else
myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
myHttpWebRequest.Method = "POST";
myHttpWebRequest.ContentLength = postData.Length;
Stream requestStream = myHttpWebRequest.GetRequestStream();
requestStream.Write(postData, 0, postData.Length);
requestStream.Close();
}
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Stream responseStream = myHttpWebResponse.GetResponseStream();
StreamReader myStreamReader = new StreamReader(responseStream, Encoding.Default);
string pageContent = myStreamReader.ReadToEnd();
myStreamReader.Close();
responseStream.Close();
myHttpWebResponse.Close();
return pageContent;
}
Related
I am trying to use this C# to get oauth token from a website. But the below codes return '404 Bad Request' error. Is there anything wrong in my code? The website engineer says there should be a JSON file returned to show error details. How do I get that JSON file? What I can see is just 1 line error message in VS2012.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://xxxx.com/api/oauth/token");
webRequest.Method = "POST";
webRequest.AllowAutoRedirect = true;
//write the data to post request
String postData = "client_id=abc&client_secret=xxx&grant_type=client_credentials";
byte[] buffer = Encoding.Default.GetBytes(postData);
if (buffer != null)
{
webRequest.ContentLength = buffer.Length;
webRequest.GetRequestStream().Write(buffer, 0, buffer.Length);
}
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string strResponse = reader.ReadToEnd();
I used Postman to send a request and I can get the token in its response. How should I modify my C# codes to get the token?
Can you try like this
public (string, string, string, string) GetOAuth(string CliendId, string ClientSecret, string OAuthURl)
{
using (var httpClient = new HttpClient())
{
var creds = $"client_id={CliendId}&client_secret={ClientSecret}&grant_type=client_credentials";
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var content = new StringContent(creds, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = httpClient.PostAsync(OAuthURl, content).Result;
var jsonContent = response.Content.ReadAsStringAsync().Result;
var tokenObj = JsonConvert.DeserializeObject<dynamic>(jsonContent);
var access_token = tokenObj?.access_token;
var token_type = tokenObj?.token_type;
var expires_in = tokenObj?.expires_in;
var scope = tokenObj?.scope;
return (access_token, token_type, expires_in, scope);
}
}
private void HowTOUse()
{
string access_token, token_type, expires_in, scope;
(access_token, token_type, expires_in, scope) = GetOAuth("client_id", "client_secret", "oauthurl");
}
Try using like the below code hope this code will solve the problem
private void Button_Click_1(object sender, RoutedEventArgs e)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://xxxx.com/api/oauth/token");
webRequest.Method = "POST";
webRequest.AllowAutoRedirect = true;
//write the data to post request
String postData =
"client_id=abc&client_secret=xxx&grant_type=client_credentials";
//byte[] buffer = Encoding.Default.GetBytes(postData);
//add these lines
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(postData);
if (buffer != null)
{
webRequest.ContentLength = buffer.Length;
webRequest.GetRequestStream().Write(buffer, 0, buffer.Length);
}
try
{
using (HttpWebResponse response =
(HttpWebResponse)webRequest.GetResponse())
{
using (Stream dataStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
string strResponse = reader.ReadToEnd();
TokenModel dt = JsonConvert.DeserializeObject<TokenModel>
(strResponse);
token = dt.accessToken;
//Assign json Token values from strResponse to model tok_val
tok_val.accessToken = dt.accessToken;
tok_val.expires_in = dt.expires_in;
tok_val.RefreshToken = dt.RefreshToken;
tok_val.tokenType = dt.tokenType;
}
}
}
catch (WebException wex)
{
error = "Request Issue: " + wex.Message;
}
catch (Exception ex)
{
error = "Issue: " + ex.Message;
}
So I am using the Dailymotion API for uploading the video and use the code I get from the GitHub and it works perfectly but after 4 videos it gives the exception:
{"The remote server returned an error: (403) Forbidden."}
And I am getting an error in PublishVideo method
var response = request.GetResponse();
Main Code
var accessToken = GetAccessToken();
Authorize(accessToken);
Console.WriteLine("Access token is " + accessToken);
var fileToUpload = #"E:\Courses\[FreeCourseSite.com] Udemy - Entity Framework in Depth The Complete Guide\3. Building a Model using Database-First Workflow\11. Summary.mp4";
Console.WriteLine("File to upload is " + fileToUpload);
var uploadUrl = GetFileUploadUrl(accessToken);
Console.WriteLine("Posting to " + uploadUrl);
var response = GetFileUploadResponse(fileToUpload, accessToken, uploadUrl);
Console.WriteLine("Response:\n");
Console.WriteLine(response + "\n");
Console.WriteLine("Publishing video.\n");
var uploadedResponse = PublishVideo(response, accessToken);
Console.WriteLine(uploadedResponse);
Console.WriteLine("Done. Press enter to exit.");
Console.ReadLine();
}
private static UploadResponse GetFileUploadResponse(string fileToUpload, string accessToken, string uploadUrl)
{
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
var responseBytes = client.UploadFile(uploadUrl, fileToUpload);
var responseString = Encoding.UTF8.GetString(responseBytes);
var response = JsonConvert.DeserializeObject<UploadResponse>(responseString);
return response;
}
private static UploadedResponse PublishVideo(UploadResponse uploadResponse, string accessToken)
{
var request = WebRequest.Create("https://api.dailymotion.com/me/videos?url=" + HttpUtility.UrlEncode(uploadResponse.url));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("Authorization", "OAuth " + accessToken);
var requestString = String.Format("title={0}&tags={1}&channel={2}&private={3}&published={4}",
HttpUtility.UrlEncode("123123123"),
HttpUtility.UrlEncode("tag1"),
HttpUtility.UrlEncode("news"),
HttpUtility.UrlEncode("true"),
HttpUtility.UrlEncode("true"));
var requestBytes = Encoding.UTF8.GetBytes(requestString);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var uploadedResponse = JsonConvert.DeserializeObject<UploadedResponse>(responseString);
return uploadedResponse;
}
private static string GetAccessToken()
{
var request = WebRequest.Create("https://api.dailymotion.com/oauth/token");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestString = String.Format("grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}",
HttpUtility.UrlEncode(SettingsProvider.Key),
HttpUtility.UrlEncode(SettingsProvider.Secret),
HttpUtility.UrlEncode(SettingsProvider.Username),
HttpUtility.UrlEncode(SettingsProvider.Password));
var requestBytes = Encoding.UTF8.GetBytes(requestString);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var oauthResponse = JsonConvert.DeserializeObject<OAuthResponse>(responseString);
return oauthResponse.access_token;
}
private static void Authorize(string accessToken)
{
var authorizeUrl = String.Format("https://api.dailymotion.com/oauth/authorize?response_type=code&client_id={0}&scope=read+write+manage_videos+delete&redirect_uri={1}",
HttpUtility.UrlEncode(SettingsProvider.Key),
HttpUtility.UrlEncode(SettingsProvider.CallbackUrl));
Console.WriteLine("We need permissions to upload. Press enter to open web browser.");
Console.ReadLine();
Process.Start(authorizeUrl);
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
Console.WriteLine("Press enter once you have authenticated and been redirected to your callback URL");
Console.ReadLine();
}
private static string GetFileUploadUrl(string accessToken)
{
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
var urlResponse = client.DownloadString("https://api.dailymotion.com/file/upload");
var response = JsonConvert.DeserializeObject<UploadRequestResponse>(urlResponse).upload_url;
return response;
}
}
It could be related to many causes. I suggest you to catch the error and get the response stream from our API:
try{
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var uploadedResponse = JsonConvert.DeserializeObject<UploadedResponse>(responseString);
return uploadedResponse;
}
catch(WebException e){
var rs = e.Response.GetResponseStream();
string errorResponseString;
using (var reader = new StreamReader(rs))
{
errorResponseString = reader.ReadToEnd();
}
Console.WriteLine(errorResponseString);
return null;
}
You will get a message explaining you why your access is forbidden.
I also invite you to check our API rate limit rules which can be a cause of forbidden call: https://developer.dailymotion.com/api/#rate-limit
I want to obtain a string response of this:
public async Task<string> CheckConnection(){
//Declarations of Variables
string result = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContinueTimeout = 4000;
request.Credentials = CredentialCache.DefaultNetworkCredentials;
//Add headers to request
request.Headers["Type"] = "CHECK";
request.Headers["Device"] = "1";
request.Headers["Version"] = "0.000";
request.Headers["Os"] = "WindowsPhone";
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
//To obtain response body
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse, Encoding.UTF8);
result = streamRead.ReadToEnd();
streamRead.Dispose();
}
return result;
}
public async Task<string> SizeFit()
{
//Declarations of Variables
string result = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultNetworkCredentials;
//Add headers to request
request.Headers["Type"] = "SIZEFIT";
request.Headers["Device"] = "1";
request.Headers["Version"] = "0.000";
request.Headers["Os"] = "WindowsPhone";
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
if (response.StatusCode != null)
{
//To obtain response body
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse, Encoding.UTF8);
result = streamRead.ReadToEnd();
streamRead.Dispose();
}
return result;
}
When I use this general function for obtain 1 for true connect and Size, but always return 1 as syze when my zip have 4k of size...
public async Task<string> doSync()
{
//Declaration of variables
string response = await CheckConnection();
//When is 1, the checkConnection will connect then request Size of zip!
if (response == "1")
{
response = await SizeFit();
}
return response;
}
Any one can help me? Thanks in advance.
Solved! Just add:
request.Headers["Cache-Control"] = "no-cache";
request.Headers["Pragma"] = "no-cache";
This is for windows phone cache problems with httpwebrequest!
I working in project that connect to appannie.com API and get result and it is working fine in debug but when I publish it and try to test it I get this page :
and here is the code used for this page in C#:
protected void Button1_Click(object sender, EventArgs e)
{
string url = "https://api.appannie.com/v1/accounts?page_index=0";
string id="",temp="";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.UseDefaultCredentials = true;
request.Proxy = WebProxy.GetDefaultProxy();
request.Credentials = new NetworkCredential("username", "password");
request.ContentType = "Accept: application/xml";
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Referer = "http://stackoverflow.com";
request.Headers.Add("Authorization", "bearer **************");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
temp = readStream.ReadToEnd();
//TextArea1.InnerText = temp + "\n";
string[] id_arr = temp.Split(',');
int count = 0;
while (count != id_arr.Length)
{
if (id_arr[count].Contains("account_id"))
{
id = id_arr[count];
count = id_arr.Length;
break;
}
count++;
}
id = id.Substring(id.IndexOf("account_id") + 13);
//TextArea1.InnerText += id;
//Console.Write(readStream.ReadToEnd());
//response.Close();
response = null;
//readStream.Close();
request = null;
string date = Calendar1.SelectedDate.ToString("yyyy-MM-dd");
string url2 = "https://api.appannie.com/v1/accounts/" + id + "/sales?break_down=application+date" +
"&start_date="+date+
"&end_date="+date+
"¤cy=USD" +
"&countries=" +
"&page_index=0";
TextArea1.InnerText = url2;
request = (HttpWebRequest)WebRequest.Create(url2);
request.Proxy = WebProxy.GetDefaultProxy();
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Referer = "http://stackoverflow.com";
request.Headers.Add("Authorization", "bearer **************");
response = (HttpWebResponse)request.GetResponse();
receiveStream = response.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
readStream = new StreamReader(receiveStream, Encoding.UTF8);
temp = "";
temp = readStream.ReadToEnd();
//TextArea1.InnerText = temp;
string[] id_arr2 = temp.Split(',');
int count2 = 0;
string down = "";
string update = "";
while (count2 != id_arr2.Length)
{
if (id_arr2[count2].Contains("downloads"))
{
down = id_arr2[count2];
count2 = id_arr2.Length;
break;
}
count2++;
}
count2 = 0;
while (count2 != id_arr2.Length)
{
if (id_arr2[count2].Contains("update"))
{
update = id_arr2[count2];
count2 = id_arr2.Length;
break;
}
count2++;
}
down = down.Substring(down.IndexOf("downloads") + 12);
update = update.Substring(update.IndexOf("update") + 9);
//TextArea1.InnerText = "downloads : "+down+ "----- update :" + update;
TextBox1.Text = down;
TextBox2.Text = update;
}
}
Once you publish it, one of the following is not taking effect:
Credentials
Proxy Settings.
Hence the remote api is giving back a 403. 2 ways to torubleshoot this further:
Run fiddler trace on the working request/response and compare it with the non-working request/response. Typically a good API has more details in the response body as to why it is a 403 error.. (token invalid, invalid credentials etc.)
You can also catch a WebException in code, and try to get the exception body if any. The same will also be visible in Fiddler.
<< code formatting refuses to work on my browser. please bear with unformatted code below >>
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
// breakpoint and see what this is.
string errorDetails = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
}
I have done POSTING and GETing from server using string post data, but now i have the next WebService:
submitFeedback(String token, String subject, String body, byte[] photo, byte[] video);
private void PostFeedbackData()
{
if (GS.online != true)
{
MessageBox.Show(GS.translations["ErrorMsg0"]);
}
else
{
HttpWebRequest request = HttpWebRequest.CreateHttp("https://****/feedback");
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
// End the stream request operation
Stream postStream = myRequest.EndGetRequestStream(callbackResult);
// Create the post data
string postData = "";
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
postData = "{\"jsonrpc\": \"2.0\", \"method\": \"getUserSchedule\", \"params\":[" + "\"" + (App.Current as App).UserToken + "\",\"" + FeedbackTitle.Text + "\",\"" + FeedbackContent.Text + "\",\"" + imageBytes + "\"], \"id\": 1}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), myRequest);
});
}
Look at post data - it is a string, i can't place there imageBytes array. How to do it?
Is there any reason for using HttpWebRequest ?
I am asking that because i think that the correct way of sending files to a service is by multipartform data. With HttpWebRequest you have to manually implement that.
Here is an example that is using Microsoft's HttpClient that might work for you:
public async Task<string> submitFeedback(String token, String subject, String body, byte[] photo, byte[] video) {
var client = new HttpClient();
var content = new MultipartFormDataContent();
// Some APIs do not support quotes in boundary field
foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
param.Value = param.Value.Replace("\"", String.Empty);
var tok = new StringContent(token);
content.Add(tok, "\"token\"");
var sub = new StringContent(subject);
content.Add(tok, "\"subject\"");
// Add the Photo
var photoContent = new StreamContent(new MemoryStream(photo));
photoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"photo\"",
FileName = "\"photoname.jpg\""
};
photoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(photoContent);
// Add the video
var videoContent = new StreamContent(new MemoryStream(video));
videoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"video\"",
FileName = "\"videoname.jpg\""
};
videoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("video/mp4");
content.Add(videoContent);
HttpResponseMessage resp;
try {
resp = await client.PostAsync("SERVER_URL_GOES_HERE", content);
}
catch (Exception e)
{
return "EXCEPTION ERROR";
}
if (resp.StatusCode != HttpStatusCode.OK)
{
return resp.StatusCode.ToString();
}
var reponse = await resp.Content.ReadAsStringAsync();
return reponse;
}
Change accordingly.
Note: HttpClient is also using HttpWebRequest under the hood.
Also I don't think its a good idea to have the UI thread making the request. That makes no sense since you are blocking the interface and making the async theory useless.