I have an application made with c# which gets something from the user.
I need that piece of information to be submitted to me somehow by that application downloading a string,
for example, I have seen URL shortener APIs that would take a request, then shorten something, and that target URL would appear in my account.
I was thinking something along the lines of:
private void example_click(object sender, EventArgs e)`
{
WebClient wc1 = new WebClient();
string datatosend = "example"
string received = wc1.DownloadString("https://examplesite.com/api?=" + datatosend + "&format=json");
}
Or something along those lines, I used the main format of the shrinkearn API https://shrinkearn.com/, however, I think that there might be a site with their own API that works in this way.
Reference: DownloadString
Thanks in advance
Martin
Related
I am currently working on a OAuth2 implementation. However I am stuck on an Error 401. It seems like there is something wrong with my post request that is supposed to retrieve the access token from the Company the User logged in to. This is my code:
internal void RequestAccessToken(string code)
{
string requestBody = "grant_type="+ WebUtility.UrlEncode(GRANTTYPE)+ "&code=" + WebUtility.UrlEncode(code)+"&redirect_uri="+ WebUtility.UrlEncode(REDIRECT_URI);
WebClient client = new WebClient();
client.Headers.Add("Authorization",HeaderBase64Encode(CLIENT_ID, SECRETKEY));
var response = client.UploadString("https://thewebsiteiamcallingto.com/some/api", requestBody);
var responseString = client.OpenRead("https://thewebsiteiamcallingto.com/some/api");
}
My Questions are:
Is there anything wrong with the way I try to make the POST request ?
Is there a way to retrieve the whole string that is posted to the URI using UploadString?
P.S. I have seen this post regarding the POST creation. However I find the async part to be too complicated for my case.
Since we dont know the api documentation, I would suggest you to make a postman request and view the actual request sent and response received, and secondly make a request using your method and capture using a utility like wireshark and compare the difference.
I've created a .NET API, but when I try to use it I'm getting strange results.
If I go to the URL of an API call in Chrome I get the result I would expect, in XML format, but if I try it in IE it downloads a file and when I open it it just says {} or sometimes [{},{},{},{}] if I try a call that returns an array.
I've also tried using a webclient.
WebClient web = new WebClient();
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/APIMethod?parameter1=hiImAParameter");
This also returns empty {}.
I've tried searching online, but I don't see any mentions of this problem anywhere. I'm sure I must be missing something somewhere, but I've tried looking over how I set up my API, and it all looks fine to me.
Edit:
Here's the response I get in Chrome.
<ArrayOfRoute xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TimePointModel">
<Route>
<RouteId>11235</RouteId>
<RouteName>Fibonacci</RouteName>
<Status i:nil="true"/>
<Width>0</Width>
</Route>
</ArrayOfRoute>
It returns XML on Chrome because of Chrome's accept headers. It's supposed to return JSON on IE, but for some reason the JSON is empty.
This is in my api controller:
[AcceptVerbs("GET")]
public IEnumerable<Route> APIMethod(double parameter)
{
return new Manager(parameter).GetRoutes();
}
This is in my Global.asax.cs:
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "APIMethod",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "APIMethod", id = System.Web.Http.RouteParameter.Optional }
);
}
Edit:
This works great when I do an API call which doesn't require parameters.
WebClient web = new WebClient();
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/SimpleAPIMethod");
I've been doing research, and I tried adding parameters like this:
NameValueCollection myQueryStringCollection = new NameValueCollection();
string myParameter = "hiImAParameter";
myQueryStringCollection.Add("parameter1", myParameter);
web.QueryString = myQueryStringCollection;
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/APIMethod");
I've noticed that the number of empty {} in my array matches the number of items in the array if I put the full url with the querystring into chrome. It just empties them out for my webclient.
I also tried adding
web.Headers[HttpRequestHeader.ContentType] = "application/json";
before making the call, but there's still no change in the result.
And I tried to follow that tutorial, but it's written for a console application and they're using HttpClient. I can't do that because I can't do Asynchronous calls. This is to be used by a website. That's why I'm using WebClient. I also tried using StreamReader with HttpWebRequest and HttpWebResponse, but it had the same problem as I've been encountered with WebClient.
Without more information, it's a bit hard to diagnose your issue. However, I would say that it is likely your web API is interpreting the expected response type and providing an empty result as it does not support responses of that type, such as happens with ASP .NET Web API websites.
In that sense, the DownloadString is indicating it is expecting a text/html response. You should probably download the Microsoft ASP .NET Web API Client Libraries with NuGet. This library will give you HttpClient which has support for making the queries you want to make with responses such as application/json and application/xml.
You can view a tutorial on how to do the calls right here.
If you want it to work from your web browser, you need to ensure the Accept header field is correct, as you mentioned. Ensure it is being communicated with IE by using something like Fiddler.
I figured out what the problem was. I needed to add [DataMember] attributes to the attributes of the items in the list. I didn't realize it was left out of the return type of that call.
UPDATE:
Maybe it's just me not understanding how oAuth works? I tried running
the query manually on http://www.apikitchen.com and I get a 400 error
there too! Just to be sure, am I constructing the URL correctly here?
POST URL:
https://api.bufferapp.com/1/oauth2/token.json?client_id=[hidden]&client_secret=[hidden]&redirect_uri=http://apps.joel-murphy.com/buffer/code/success.php&code=[the
access code I get from buffer starting with
1/]&grant_type=authorization_code
Original post:
I'm building a Windows Phone application which requires the use of data from a website. The website uses oAuth to authenticate users.
I used the built in web browser control to make a GET request to authenticate users. The official documentation requires the URL structure to be like this:
GET https://bufferapp.com/oauth2/authorize?
client_id=...&
redirect_uri=...&
response_type=code
This part of my app works. Although when it comes to exchanging the Authorization token for an access token from the server, I am facing problems. The official documentation requires the URL structure to be like this:
POST https://api.bufferapp.com/1/oauth2/token.json?
client_id=...&
client_secret=...&
redirect_uri=...&
code=...&
grant_type=authorization_code
Correct me if I'm wrong, but from what I know there is no way to make a POST request from a browser, unless submitting a form. For this reason, I have decided to use the WebClient class to submit data to the server. However, no matter if I run my code on an actual device or on the Visual studio emulator I always receive the following error:
The remote server returned an error: NotFound
Does anyone have any idea what's wrong with the following code? I've spent over 5 hours across 2 days trying to solve this error, but nothing seems to be working.
The code I'm using:
WebClient wc = new WebClient();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wc_UploadStringCompleted);
wc.UploadStringAsync(new Uri(access_token_url), "POST", GetPostParameters());
void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
MessageBox.Show(e.Result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
string GetPostParameters()
{
string data = "";
data += "client_id="+client_id + "&";
data += "client_secret=" +client_secret + "&";
data += "redirect_uri=" + redirect_uri+ "&";
data += "code=" + App.AccessToken + "&";
data += "grant_type=authorization_code";
return data;
}
Does anyone have any idea what's wrong? this is driving me crazy and it's a real shame that oauth has to be so complicated when it's such a used technology nowadays.
Thanks in advance.
Can you try URL-encoding the redirect_uri variable?
We have a website that allow firmware downloads.
Somwhere along the way it uses a StreamReader. For some unknown reason, some customer (In Israel) get a 400 Bad Request error. Everyone else do not get this error.
Any1 out there experienced the same thing ? Anyone got a clue ?
protected void Page_Load(object sender, EventArgs e)
{
string strURL = Request.Url.Host;
System.Net.WebRequest reqPT = System.Net.WebRequest.Create("http://" + strURL + "/Products/ProductTree.asp");
System.IO.StreamReader srPT = new System.IO.StreamReader(reqPT.GetResponse().GetResponseStream());
dvPT.Controls.Add(new LiteralControl(srPT.ReadToEnd()));
}
It crashes, for them only, at the new StreamReader.
Thank you !
UPDATE : We noticed that the customer is actually loosing the "www" in the address (strURL), wich cause the error. Why would someone, (clicking on the same link as the rest of the planet is) would loose the www ?? I'm seeing 2 differents behavior for the exact same code :S
Well with the HTTP 400 error the requested URL is probably invalid, and since the literals in your System.Net.WebRequest look OK, my guess is your Israeli user is requesting the page using a different Request.Url.Host than everyone else. Can you debug and verify the value of strUrl?
I'm looking for a code fragment that will show me how to get an SID for Google Reader in C#. Anyone know of such a beast?
It's quite easy. First you should perform a GET request to https://www.google.com/accounts/ClientLogin page with your login and password (don't forget to url encode them). And then just parse response (there will be several parameters divided by a new line character \n) to get SID. Here is a simplest example (no error handling):
var url = string.Format("https://www.google.com/accounts/ClientLogin?service=reader&Email={0}&Passwd={1}",
HttpUtility.UrlEncode(email),
HttpUtility.UrlEncode(password)
);
var web = new WebClient();
web.DownloadStringCompleted += (sender, e) =>
{
var sid = e.Result.Split('\n')
.First(s => s.StartsWith("SID="))
.Substring(4);
};
web.DownloadStringAsync(new Uri(url));
But you could make this code more elegant by using AsyncCTP.
You will have to deal with manual HTTP manipulations and cookies for this. A pretty decent explanation is available on this page. If you worked with HTTP requests in C#, it shouldn't be a problem to pick up the methods described there.