I'm making the following call in jQuery, using jsonp as my data format, that I'd like to make directly in Silverlight:
$.getJSON('https://api.wordstream.com/authentication/login?callback=?',
{ 'username': un,
'password': pw
}, function (loginResults) {
API_SESSION_ID = loginResults['data']['session_id'];
$.getJSON('https://api.wordstream.com/keywordtool/get_keywords?callback=?',
{ 'session_id': API_SESSION_ID,
'seeds': keyword,
'max_results': 20
}, function (keywordResults) {
for (i = 0; i < +keywordResults['data'].length; i++) {
Keywords[i] = keywordResults['data'][i][0];
}
return(Keywords);
});
});
I tried something like this to handle the first $.getJSON (authenticating & returning my auth token):
WebClient downloader = new WebClient();
WebRequest.RegisterPrefix("https://", System.Net.Browser.WebRequestCreator.ClientHttp);
var client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.UseDefaultCredentials = false;
client.DownloadStringCompleted += new
DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(loginEndpoint);
When I try and run this I get the following error inside my downloadstringcompleted eventhandler:
{System.Security.SecurityException: Security error.
at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass4.<BeginOnUI>b__1(Object sendState)}
I've used WCF Ria Services in EF & SOAP services via .asmx files in the past, so I'm not a total stranger to the idea of web services. I am not sure if I need to be using the clientaccesspolicy or crossdomain files or not.
Any ideas on how to proceed?
Thanks,
Scott
What you trying to do in this series of questions has become clearer to me now.
Unless api.wordstream.com includes a ClientAccessPolicy xml (or the Flash equivalent) you will not be able to make requests to this api from Silverlight.
You have two options:
Call into Javascript to make these requests on behalf of the Silverlight app.
Create WCF service to on your server to make these requests on behalf od the Silverlight app.
I would recommend the first approach, however don't use getJSON. Instead use the standard ajax api in JQuery to fetch the JSON content asynchronously. When the final JSON content is available (still in string form) call into Silverlight from Javasript passing in the string.
What would be preferable is to create the appropriate set of .NET classes and collections that match the data from the api. You could then use DataContractJsonSerialializer to deserialize the received string into instances of your classes.
Sometimes creating a class structure can be a bit of a burden. Another approach is to use the set of objects in the System.Json namespace starting with JsonValue.Parse to load up the set of JsonObjects from the string. You can now navigate around the returned data using these `son objects and Linq where necessary.
Did a little digging and a test.
When you are calling an external domain, the cross-domain issue will occur and that's why you are seeing the Security error.
Remember that this is a Web application after all, it does run inside the browser!
To enable Silverlight to reach outside it's domain, give this article a try if you are doing a self hosted app.
http://blogs.msdn.com/b/carlosfigueira/archive/2008/03/07/enabling-cross-domain-calls-for-silverlight-apps-on-self-hosted-web-services.aspx
Related
I have a web api with controller methods that use rest http(post/get calls).
Clients consume this API with normal httpclient calls and I pass an http response back.
My use case is I have a legacy method that needs to make a call to another server. This method currently uses WCF and contract binding but I don't want to use WCF in this API project.
Is there a way that I can still call these methods using just WEB API or do I have to mix architectures (Web api with WCF)?
Here is the normal method call
First I initialize the proxy
var proxy = GetAccountProxy();
public static AcountClient GetAccountProxy()
{
var client = new AccountClient();
client.ClientCredentials.ClientCertificate.SetCertificate(...);
return client;
}
I connect to a method on the other server through the proxy
var accountInfo = proxy.GetAccountInfo(xmlAccount);
public string AccountInfo(string sXml){
AccountLookup val = new AccountLookup();
val.Body = new AccountLookupRequestBody();
val.Body.XML = sXML;
AccountLookupResponse retVal = ((AccountLookupResponse)(this)).AccountLookup(val);
return retVal;
}
In my webconfig the endpoints look like this
<endpoint address="https://www.mylookup.com/AccountLookupWS/AccountLookupWS.svc/wshttp" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IAccountLookupWS" contract="AccountLookupWS.IAccountLookupWS" name="WSHttpBinding_IAccountLookupWS1" />
So my question is can I just call this endpoint using a normal rest httpclient call and have the same result?
Uri baseUrl = new Uri("https://www.mylookup.com/AccountLookupWS/AccountLookupWS.svc/wshttp");
IRestClient client = new RestClient(baseUrl);
IRestRequest request = new RestRequest("GetAccountInfo", Method.GET)
request.AddParameter("XmlAccount", sXml);
IRestResponse<dynamic> response = client.Execute<dynamic>(request);
if (response.IsSuccessful)
{
response.Data.Write();
}
else
{
Console.WriteLine(response.ErrorMessage);
}
Console.WriteLine();
In general it is possible to access wcf with webrequest, but it depends on the wcf service implementation. Check out the WebGet and/or WebInvoke attributes https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.web.webgetattribute?view=netframework-4.8 and start from there.
It is work to be done on WCF side, after it is done properly, you can access your wcf as normal rest services.
It depends on your WCF server bindings. You see, HTTP/s protocol implementation is just possible module of WCF, a part, just like any other protocol out there - it is just called binding. Different bindings means same bindings should be on client side, otherwise they don't understand each other.
For example if server tells:
use gzip on my data which I send over wire
then I xor my data with 666 if first bit is set true
then use SSL to protect it
then send it over TCP
Then client should do the same thing in reverse. This is WCF and it's flexibility for you which opened hell gates for researchers and developers.
As I said, if your server supports HTTP bindings, without extra stuff - you are good. Use http client or billion other HTTP classes. If not - port your server protocol bindings to NET Core and use them.
I'm trying to execute a function using a Soap Port Client object (from an external WebService), and I need to set a proxy (address and credentials) for it. Because when I test the app (not on localhost), the WS functionality doesn't work.
Namespace.WebService.SoapPortClient foo = new Namespace.WebService.SoapPortClient();
short cod_error;
string des_error;
string url = "";
int fooNumber = 10;
url = foo.Execute(fooNumber, out cod_error, out des_error);
...code continues
In the above example, I need to set a proxy for 'foo'. I've tried with foo.Proxy but this property doesn't exists in the SoapPortClient.
Thank you all!
After reading your comments and problem I realized that you are talking about WCF.
Regards to your latest problem:
Now I'm getting the following error: The content type text/HTML of the response message does not match the content type of the binding (text/XML; charset=utf-8)
My first suggestion would be to check that the user you're running the WCF client under has access to the resource.
Can't say much since it's very hard to say something without seeing the config file or code in general.
Is there any way to hide/override real IP while using anonymous or transparent proxy?
I want to send empty in HTTP_X_FORWARDED_FOR. I am using C# Winform. Below is the code snippet.
WebClient wc = new WebClient();
//wc.Headers["HTTP_X_FORWARDED_FOR"] = "0.0.0.0"; --Not working
wc.Proxy = new WebProxy(ipproxy, port);
string t = wc.DownloadString("https://www.leaky.org/ip_tester.pl");
The goal is to send completely anonymous request. The proxies I am using is not brought from any website, they are collected from random sites. It would be great if someone also mention any good site of working proxies.
Thanks
Yes. You can use ProxySharp to generate/get proxy servers to use for your request.
https://github.com/m-henderson/ProxySharp
After you install the ProxySharp nuget package, you can get a random anonymous proxy to use with your request. Like this:
WebClient wc = new WebClient();
var proxyServer = Proxy.GetSingleProxy();
wc.Proxy = new WebProxy(proxyServer);
string t = wc.DownloadString("https://www.leaky.org/ip_tester.pl");
It also has different methods for getting, renewing, and popping proxies from the queue that it generates.
Yes. I built ProxySharp to do exactly what you are trying to do.
ProxySharp has a method that will get you a random anonymous proxy to use with your web request. Check out the repo for more info https://github.com/m-henderson/ProxySharp
The X-Forwarded-For header is generally added by the proxy server, not the client. If you put something there, the proxy server will overwrite or append to it.
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.
is it possible to send a web request from the user browser to another api and then process the result sent back??
im trying the following ajax code but its not working, i was wondering whether is it possible or not and if its a yes how can i implement it ...
$(document).ready(function() {
$.ajax({
type: "GET",
url: "http://api.ipinfodb.com/v2/ip_query.php?key=a9a2b0ec2c4724dd95286761777b09f1c8e82894de277a5b9d7175fa5275f2da&ip=&output=xml",
dataType: "xml",
success: function(xml) {
alert("sucess");
$(xml).find('Ip').each(function() {
var ip = $(this).find('Ip').text();
alert(ip);
});
}
});
});
Due to same origin policy restriction you are pretty limited to sending AJAX requests to your own domain only. JSONP is a common workaround but the remote site needs to support it. Another workaround consists in crating a server side script on your domain which will serve as a bridge between your domain and the remote domain and it will simply delegate the AJAX request sent to it from javascript.
Should be possible, I have done the same.
BUT you have to have the pages on the same server, you cannot send a request to another server, in that case you would have to use a proxy on your server to relay the call.
Just to add to what was already said: if you can't create your own JSONP proxy, you can use YQL service which creates that proxy for you. Note that YQL will wrap your data with it's own meta data (unless there is a way yo disable that...).
By the way, you should use JSON output instead of XML output from your API service. JSON is a more lightweight format and as such is more adapted for Web.
Below is a fully functional example with your API URL (outputting JSON this time) and YQL:
var apiRequestUrl = "http://api.ipinfodb.com/v2/ip_query.php?key=a9a2b0ec2c4724dd95286761777b09f1c8e82894de277a5b9d7175fa5275f2da&ip=&output=json";
var yqlRequestUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%20%3D%20%22";
yqlRequestUrl += encodeURIComponent(apiRequestUrl);
yqlRequestUrl += "%22&format=json&callback=?";
$.getJSON(yqlRequestUrl,
function(jsonData) {
alert(jsonData.query.results.json.Ip);
});
Finally, this article can come handy: http://www.wait-till-i.com/2010/01/10/loading-external-content-with-ajax-using-jquery-and-yql/