I'm coming to .net web api from a JavaScript background, and I'm trying to make a proxy to help with a cross domain JSON request. I'm GETing from a server I don't control the source code for, so I can't configure CORS directly. Likewise, it doesn't speak JSONP.
So two questions as I try to get my head around Web API:
1) Is Httpclient the right tool for this job? (if not, what is?)
2) If httpclient IS the right tool, what is an absolute bare bones httpclient config so I can test this out? Not worried about throwing exceptions or anything else other than just GETing API data and feeding it to a jQuery client.
I guess one other piece of information that would be nice would be building username / password authentication into the http request.
Any help is much appreciated, as are links to any good blogs / tutorials / etc that might help as an introduction to this sort of thing. I've watched several today alone, and I'm still not able to get a basic http request going on the server side without resorting to cutting / pasting other people's code.
Thanks in advance!
** EDIT - To make this question a bit more clear, what I'm trying to test is 1) Can the proxy connect to the third party server, which involves authentication via a username and password 2) Can the proxy then respond to the jQuery client request with the JSON data it received from the third party server.
Thanks to all who have taken the time to respond.
HttpClient seems to be ok in this job.
About the minimal config- it depends on what the third party expects. In most cases would work out-of-the-box, but there always may be some minor tweaks like headers and/or auth code.
I have just found some blog entry where some author shows how to test such a proxy and shows the proxy code too. Please see: http://www.davidbreyer.com/programming/2014/10/11/create-fake-responses-to-rest-service-calls-in-c/
You can find info about sending credentials here: How to use credentials in HttpClient in c#?
HTH
EDIT:
this sample code should work (copied from blog above and modified):
public class Proxy
{
public async Task<ExampleDto> GetExample(int id)
{
var client=new HttpClient();
//set some auth here
//set other headers
var response = client.GetAsync(
string.Format("/api/restserviceexample/{0}", id))
.Result.Content.ReadAsAsync<ExampleDto>();
return await response;
}
}
It's so simple that you can just run it and see if the other server responds. If not, you can play with headers - since all the session info and user auth info are sent using ookies and/or headers, all you have to do is to see how it's made with regular browser and then fake it on the server. Probably best tool for this job will be Fiddler.
However - there is one thing to consider. If the other service has special method for authorization (other than passing credentials with each request) the whole thing becomes tricky, since your proxy should perform authorization using their service, then store their auth cookie on the server or propagate them to the browser and attach them with all next requests.
First, you don't need ASP.NET with C# if you really want minimal.
.NET has great http handling without ASP. Check out classes like HttpListener, HttpListenerContext, HttpListenerRequest, etc... Yes, you'll have to write some boilerplate as your application, but these classes are pretty good.
See among others:
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=599978
Second, if you want user & password, I'd checkout using oauth authentication so you don't have to deal with them directly. Google Plus, Windows Live, Facebook, etc... all have similar OAuth 2.0 APIs for that. See among others:
http://msdn.microsoft.com/en-us/library/dn659750.aspx
https://developers.google.com/+/web/signin/server-side-flow
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2
Related
I am trying to add a custom header to google bigquery client in below way, some reasons it is not working. Can someone suggest me how I can add custom header to google bigquery client.
Below is my sample code:
var gClient = BigQueryClient.Create(projectId, credential);
gClient.Service.HttpClient.DefaultRequestHeaders.TryAddWithoutValidation("test", "this is default header");
var results = gClient.ExecuteQuery(query, null);
With above code, I can see that the custom header 'test' is added to the httpclient, but when gClient executes the query, I don't see this custom header.
I am using the fiddler to monitor the traffic from my machine. In fiddler, the I can see that there are two calls are made.
i. oauth authentication
ii. bigquery execution
In both of the messages I dont see the default http header 'test'.
I also tried, gClient.Service.HttpClientInitializer.Initialize() to initialize the httpclient, but didnt work.
var gClient = BigQueryClient.Create(projectId, credential);
ConfigurableHttpClient httpClient = new ConfigurableHttpClient(new ConfigurableMessageHandler(new CustomMessageHandler()), true);
httpClient.DefaultRequestHeaders.Add("xxxxx", "yyyyyyy");
gClient.Service.HttpClientInitializer.Initialize(httpClient);
In this case also, it is same problem... the default header is not part of the httprequest.
Can someone help me to solve this issue...?
FYI... we are intercepting all outbound calls using a proxy and based on this custom http header we need to take decision whether to allow outbound call or not. So, we would like to inject it at the service side and verify this custom header in the proxy.
As explained above, I have tried adding the DefaultRequestHeaders to the httpclient, but it is not working.
Also, I have tried httpclient.MessageHandler.AddExecuteInterceptor(). but still didnt work.
My question... can we inject a default httpclient for all outbound calls in c#? especially for google big queries.
I have a web application which is a mesh of a few different servers and 1 server is the front-end server which handles all request external incoming requests.
So some of these request will have to be passed along to different servers and ideally the only thing I want to change is the host and Uri fields of these request. Is there a way to map an entire incoming request to a new outgoing request and just change a few fields?
I tried something like this:
// some controller
public HttpResponseMessage get()
{
return this.Request.Rewrite("192.168.10.13/api/action");
}
//extension method Rewrite
public static HttpResponseMessage Rewrite(this HttpRequestMessage requestIn, string Uri) {
HttpClient httpClient = new HttpClient(new HttpClientHandler());
HttpRequestMessage requestOut = new HttpRequestMessage(requestIn.Method, Uri);
requestOut.Content = requestIn.Content;
var headerCollection = requestIn.Headers.ToDictionary(x => x.Key, y => y.Value);
foreach (var i in headerCollection)
{
requestOut.Headers.Add(i.Key, i.Value);
}
return httpClient.SendAsync(requestOut).Result;
}
The issue I am having is that this has a whole slew of issues. If the request is a get Content shouldn't be set. THe headers are incorrect since it also copies things like host which shouldn't be touched afterwards etc.
Is there an easier way to do something like this?
I had to do this in C# code for a Silverlight solution once. It was not pretty.
What you're wanting is called reverse proxying and application request routing.
First, reverse proxy solutions... they're relatively simple.
Here's Scott Forsyth and Carlos Aguilar Mares guides for creating a reverse proxy using web.config under IIS.
Here's a module some dude named Paul Johnston wrote if you don't like the normal solution. All of these focus on IIS.
Non-IIS reverse proxies are more common for load balancing. Typically they're Apache based or proprietary hardware. They vary from free to expensive as balls. Forgive the slang.
To maintain consistency for the client's perspective you may need more than just a reverse proxy configuration. So before you go down the pure reverse proxy route... there's some considerations.
The servers likely need to share Machine Keys to synchronize view state and other stuff, and share the Session Store too.
If that's not consistent enough, you may want to implement session stickiness through Application Request Routing (look for Server Affinity), such that a given session cookie (or IP address, or maybe have it generate a token cookie) maps the user to the same server on every request.
I also wrote a simple but powerful reverse proxy for asp.net / web api. It does exactly what you need.
You can find it here:
https://github.com/SharpTools/SharpReverseProxy
Just add to your project via nuget and you're good to go. You can even modify on the fly the request, the response, or deny a forwarding due to authentication failure.
Take a look at the source code, it's really easy to implement :)
I'm trying to get to grips with OneDrive, using this tutorial:
https://msdn.microsoft.com/en-us/library/hh826529.aspx
When I run in code, it gets as far as the makeAccessTokenRequest function, sending the following requestURL:
"https: //login.live.com/oauth20_token.srf?client_id=[myclientID] &client_secret=[myclientsecret]&redirect_uri=https:// login.live.com/oauth20_desktop.srf&grant_type=authorization_code&code=[authcode]"
(please ignore the spaces after "https:", I had to add them here to allow the question)
[myclientid], [myclientsecret], and [authcode] all appear to be populated correctly. It seems to get a response, as it runs the function "accessToken_DownloadStringCompleted", but throws a "TargetInvocationException" error, The inner message of the error is ""The remote server returned an error: (400) Bad Request.".
Could anyone throw any light on this? I'm completely new to this, so apologies if my question makes no sense, or is irritatingly vague..
Requests to the oauth20_token.srf end point need to be a POST with the parameters in the body of the post, instead of the query string. Since you didn't mention what code you're using to build the HTTP request it's hard to provide an example, but take a look at RedeemAuthorizationCodeAsync in my sample OAuth 2 project for an idea.
The outgoing request should look like this:
POST https://login.live.com/oauth20_token.srf
Content-Type: application/x-www-form-urlencoded
client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}&code={code}&grant_type=authorization_code
You may also find this tutorial easier to follow than the one you linked with: https://dev.onedrive.com/auth/msa_oauth.htm.
If you are doing something with OneDrive (you tagged the post OneDrive) then you may want to consider using the OneDrive SDK instead. It includes authentication for several types of .NET projects so you don't need to figure out how to do auth yourself.
I've searched some time, looking for easy way to connect with some other sites WebAPI. There are some solutions, but they are made in very complicated way.
What I want to do:
Connect with server using URL adress
Provide login and password to get some data
Get data as JSON/XML
Save this data in an "easy-to-read" way. I mean: save it to C# variable which could be easy to modify.
Currently, API that I want to work with is Bing Search, but I'm looking for some universal way. I found an example, but it doesn't work for me and in my app I can't use this class: "DataServiceQuery" because it doesn't exsist.
How do you usually do it? Do you have your favourite solutions? Are there some universal ways or it depends on type of API that you work with?
I'm currently working on .NET MVC app (in case it could make any difference)
From server side
You can use that like below.
// Create an HttpClient instance
HttpClient client = new HttpClient();
// Send a request asynchronously continue when complete
client.GetAsync(_address).ContinueWith(
(requestTask) =>
{
// Get HTTP response from completed task.
HttpResponseMessage response = requestTask.Result;
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
// Read response asynchronously as JsonValue
response.Content.ReadAsAsync<JsonArray>().ContinueWith(
(readTask) =>
{
var result = readTask.Result
//Do something with the result
});
});
You can see example on following link.
https://code.msdn.microsoft.com/Introduction-to-HttpClient-4a2d9cee
For JavaScirpt:
You could use jQuery and WebAPI both together to do your stuff.
There are few steps to it.
Call web api with Ajax jquery call.
Get reponse in JSON
Write javascript code to manipulate that response and do your stuff.
This is the easiest way.
See following link for reference:
http://www.codeproject.com/Articles/424461/Implementing-Consuming-ASP-NET-WEB-API-from-JQuery
It entirely depends on the type of API you want to use. From a .Net point of view, there could be .Net 2 Web Services, WCF Services and Web API Services.
Web APIs today are following the REST standard and RMM. Some APIs need API Keys provided as url parameters, others require you to put in request's header. Even some more robust APIs, use authentication schemes such as OAuth 2. And some companies have devised their own standards and conventions.
So, the short answer is that there is no universal way. The long answer comes from documentation of each API and differs from one to another.
I'm just trying to make an yahoo boot that send to registered user of my application an instant message. I've spent some hours searching the web on how to do it but yahoo developer documentation sucks.First of all I don't know what servers I should use for authorization, log in, and messaging. I have a consumer key and I've tried to follow this steps but nothing works.
Any advice/suggestion is welcome.
The documentation looks to be very good, I think the issue here is that your knowledge of how REST API's work in general is a bit lacking.
Let's talk about diagram #2: Get a request token using: get_request_token.
get_request_token is part of an HTTP endpoint, and in their diagram they want you to pass in a handful of parameters to validate your request.
oauth_consumer_key
oauth_nonce
oauth_signature_method
etc
(If you need more clarification of any step you can find it in the tree view on the left hand side of the page)
The request URL:
https://api.login.yahoo.com/oauth/v2/get_request_token.
Now at this point you can either use the HTTP GET or POST verb. If you decide to use GET you will need to include those above parameters as a query string.
?oath_consumer_key=myConsumerKey&oauth_nonce=oathNonce etc
I will leave it to you to write the associated C# code. You'll want to start off with the HttpWebRequest.Create() method