C# call an API through proxy using HttpWebRequest - c#

I want to make an API call (outside my organization domain) in my existing application, the network team has told me to set up a proxy config - only then it'd have the ability to go to the internet.
Dev has the ability to go to the internet without referencing the proxy setup.
In my dev environment, it is working fine since the ports are open, how to configure a proxy for UAT environment so that it can hit the new target on the internet?
proxy IP is given by the network team for Non-prod: 12.XXX.XXX.0 Port 80
and also how to check:
if the above proxy is alive?
once it is configured how to check if the request is going through the
proxy because I just have dev server access where all ports are open,
how would I check if it is configured correctly so that once deployed
on UAT it works fine?

The HttpWebRequest has a proxy property:
var myWebRequest = (HttpWebRequest)WebRequest.Create("url");
myWebRequest.Proxy = new WebProxy("host", 80);
try
{
var response = myWebRequest.GetResponse();
//...
}
catch (WebException e)
{
// handling issues
}
If a request fails, an exception will be thrown that you can handle in catch block.

Related

Route traffic thru NTLM proxy when using Appium driver

In my application, I am scheduling Mobile Application tests for clients app. using Browserstack.
Unfortunately, when client is running the test on his local computer, he is unable to establish connection with Browserstack. It occurred that all "non-internal" traffic is going thru NTLM proxy so my app can`t create direct connection to BS.
I was trying to change config files settings to use default proxy, but it didnt helped - I get 407 authorization error.
Currently I`m trying to make it working in the code directly, but with no luck. Moreover i read that AppiumDriver is not using any proxy related settings.
var proxy = new Proxy();
proxy.Kind = ProxyKind.AutoDetect;
proxy.IsAutoDetect = true;
AppiumOptions caps = new AppiumOptions();
caps.AddAdditionalCapability("browserstack.user", "user");
caps.AddAdditionalCapability("browserstack.key", "key");
caps.AddAdditionalCapability("device", "Samsung Galaxy S8");
caps.AddAdditionalCapability("os_version", "7.0");
caps.AddAdditionalCapability("name", string.Format("Requested
time: {0}", DateTime.Now));
caps.AddAdditionalCapability("realMobile", true);
caps.AddAdditionalCapability("browserstack.idleTimeout", 300);
caps.AddAdditionalCapability("app", "MobileAppName");
caps.AddAdditionalCapability("ACCEPT_SSL_CERTS", true);
caps.Proxy = proxy;
try
{
return new
AndroidDriver<OpenQA.Selenium.Appium.Android.AndroidElement>(
new Uri("https://hub-cloud.browserstack.com/wd/hub"), caps);
}
catch (Exception e)
{
throw new Exception($"Couldn't create browserstack
instance. {e.Message + e.StackTrace}");
}
}
What I want to achieve is to force Appium Driver to use proxy and credentials defined on client`s computer to make connection with Browserstack hub.
Any suggestions are welcome as I`m struggling with the issue far too long now.
It seems Appium itself does not support passing proxy details programmatically. Relevant links for the same - #1, #2, #3
You may try to whitelist the BrowserStack Hub address in your client machine to connect to BrowserStack hub.

SendAsync is not working from an External server (Web API2)

We are running into a situation where sendAsync post call from a server is not working. Here's my scenario
We have a Web API hosted on a server outside our internal network (DMZ) which has a simple GET implemented to it as
Public HttpResponseMessage Get(strind id){ (API 1)
//do some work
using(HttpClient client = new HttpClient()){
//We Invoke another web API which is hosted inside our network and do a post // as
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);
message.Content = new StringContent(someStr);
message.Content.Header.ContentType = new MediaTypeHeaderValue("application/json");
try{
var response = client.SendAsync(message).Result (API 2)
}
catch(Exception e){
//Something
}
}
The post SendAsync().Results fails with the following exception
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) and the message says as One or More errors Occurred.
The innerexception is also not telling anything good. It just InnerException.StackTrace is coming blank and the InnerException.Message is An error occurred while sending request.
In order to test the communication, we ran a GET request from the external sever for API 2 and it worked fine but the POST's are not working.
Everything works fine when both the API's (the one for get and the other one that does the post) are hosted on our internal servers.
Any Suggestions why this might not be working when executed from the external server?
Short answer: Regardless of what I'm betting on, you have to inspect those inner exceptions and find out the exact message.
Longer answer:
The fact that when you host the application in your internal network, the code works (the POST call is successful) and when moved to DMZ it fails strongly indicates the server making the call has no access to the remote endpoint.
I'd bet on the lack of network connectivity between your App Server and the API 2.

Acessing a WebService (HTTPS) that requires a certificate via WCF in C#

I'm the client machine, and the server I'm trying to access is a program which I'll be providing support to (I'm a new 3rd party program) and I need to send then some data.
They use HTTPS but I couldn't connect with this:
public void StartProcess()
{
BasicHttpsBinding binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
// - They said they don't require credentials
EndpointAddress address = new EndpointAddress("https://www.outsideservice.com/services/C001");
OutsideServiceClient client = new OutsideServiceClient(binding, address);
DataToSend data = new DataToSend();
// - Filling up whatever data I need to send, omitted
try
{
client.StartProcess(data);
}
catch (Exception ex)
{
// ex = Could not establish trust relationship for SSL/TLS secure channel
}
}
They already have other 3rd party programs accessing their servers.
I don't have a very good knowledge on how certificates work (other than the basic reading on MSDN).
After questioning how I can access their servers, I got the reply:
" already access our servers via https, just access the machine, download the certificate and use on your client machine."
After googling around how I do this, I tried to access https://theirURL.com/certsrv from here, but I get Resource Not Found error.
From what I could understand from how certificates work, I must obtain a certificate from them, double click it, install on my machine (or the machine running the code to connect to them) to be able to connect right?
Or is there something that I have to do on my end to be able to connect?
"I must obtain a certificate from them, double click it, install on my machine (or the machine running the code to connect to them) to be able to connect right?"
This is the correct way to do things, however to get things up and running you can use this bit of code:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
I usually like to wrap this in code that doesn't apply this on a release build so that production actually has to have the certificate installed properly as follows:
#if (!Release)
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
#endif
I believe you should be able to put this anywhere you like, such as the Global.asax.cs or right before the call is made.

How to access web service on ServiceStack from android device?

I have an android application that's supposed to send a request to a simple HelloWorld C# webservice I made on ServiceStack but I am not able to connect. My application crashes when I try to connect. Here is my code on Eclipse, trying to access the ServiceStack service:
String base = "http://192.168.1.7:62938/json/reply/Hello?Name=";
String str = editTextField.getText().toString();
StringBuilder url = new StringBuilder(base + str);
String result = "";
HttpClient hc = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url.toString());
HttpResponse r = hc.execute(httpget);
int status = r.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity e = r.getEntity();
String data = EntityUtils.toString(e);
JSONObject o = new JSONObject(data);
result= o.getString("result");
}
My C# service code for ServiceStack:
//Request DTO
public class Hello
{
public string Name { get; set; }
}
//Response DTO
public class HelloResponse
{
public string Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
//Can be called via any endpoint or format, see: //http://mono.servicestack.net/ServiceStack.Hello/
public class HelloService : Service
{
public object Any(Hello request)
{
return new HelloResponse { Result = "Helloooo, " + request.Name };
}
}
My service works fine on my laptop when I go to localhost:62938/json/reply/Hello?Name="arbitraryName"
but it does not work when I try to replace localhost with my laptop's ip address and access the service from an android device. It also does not work if I replace localhost with my IP address and try it on my browser on my laptop. Note: I want to make it work from a real android device, not an emulator.
Is there something different with ServiceStack services where I cannot access it normally from another device? I have already tried opening port 62938 and it did not work.
I appreciate any guidance. Thank you.
It also does not work if I replace localhost with my IP address and try it on my browser on my laptop.
If you have tried accessing the ServiceStack service through the local IP address of 192.168.1.7 in your computer's web browser and it is also unreachable, then the issue isn't isolated to Android.
This is issue is likely the result of one or more of these problems:
Check you are listening on the correct IPs:
Your ServiceStack service isn't configured to listen for requests on any other interfaces other than localhost. Select your relevant hosting option:
Self Hosting:
This can happen if you are self hosting and you have configure the app host to start with appHost.Start("http://localhost:62938/");. You would need to replace localhost with a + symbol to have it listen on all local addresses.
IIS Express:
By default IIS Express is used by Visual Studio during development, unless manually configured to use IIS, and is restricted to localhost requests only. You should see this answer as to how to configure IIS Express to allow non-local access as well.
This tutorial by Scott Hanselman is also very good, and provides great step-by-step instructions for configuring IIS Express.
IIS:
You can confirm the IP addresses that you server is configure to listen on by following these instructions. They provide instructions for both IIS6 and IIS7+.
Firewall:
Your computer may have a firewall preventing you accessing that port, or accepting outside traffic. Note your firewall may be built into antivirus software you run. You should add an exception rule for http traffic on port 62938.
Correct IP:
You are trying to access on 192.168.1.7. You should confirm that IP address is in fact correct. Most home networks are configured to provide a dynamic IP address by the network router. The IP address may have changed since you last checked it. You should try running a ping to the IP from your development machine.
Until you can successfully access the service through your web browser on your development machine, at the local network IP starting 192.168.1.X then I wouldn't attempt to access from Android. It's not an Android issue if other systems can't access your service also.
I hope that helps. If you provide more information about your specific environment, I may be able to provide more specific instructions. If I had to guess, I would say IIS Express issue.
Edit:
Now that you can access the service in the web browser of your android device but not in the application, we know the service is remotely accessible. This means your connectivity issue is isolated now to your application. The first thing I would check, is that your application has permission to make network requests. In your AndroidManifest.xml you need to ensure that android.permission.INTERNET is included
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
If you have that permission then you should be able to make the request successfully. If it continues to fail, then the reason need to be diagnosed from the exception that is causing the application to crash. In which case you should wrap the data request in a try { ... } catch(Exception exception) { } and log the exception.
As the Android emulator is considered to be running on a different device, to refer to the loopback IP (127.0.0.1) on our local development machine we need to use the special 10.0.2.2 alias.
Other special device IP's can be found in Andorid's documentation.

System.Net.WebRequest not respecting hosts file

Is there a way to get a System.Net.WebRequest or System.Net.WebClient to respect the hosts or lmhosts file?
For example: in my hosts file I have:
10.0.0.1 www.bing.com
When I try to load Bing in a browser (both IE and FF) it fails to load as expected.
Dns.GetHostAddresses("www.bing.com")[0]; // 10.0.0.1
WebRequest.Create("http://10.0.0.1").GetResponse(); // throws exception (expected)
WebRequest.Create("http://www.bing.com/").GetResponse(); // unexpectedly succeeds
Similarly:
WebClient wc = new WebClient();
wc.DownloadString("http://www.bing.com"); //succeeds
Why would System.Net.Dns respect the hosts file but System.Net.WebRequest ignore it? What do I need to change to make the WebRequest respect the hosts file?
Additional Info:
If I disable IPv6 and set my IPv4 DNS Server to 127.0.0.1, the above code works (fails) as expected. However if I add my normal DNS servers back as alternates, the unexpected behavior resumes.
I've reproduced this on 3 Win7 and 2 Vista boxes. The only constant is my company's network.
I'm using .NET 3.5 SP1 and VS2008
Edit
Per #Richard Beier's suggestion, I tried out System.Net tracing. With tracing ON the WebRequest fails as it should. However as soon as I turn tracing OFF the behavior reverts to the unexpected success. I have reproduced this on the same machines as before in both debug and release mode.
Edit 2
This turned out to be the company proxy giving us issues. Our solution was a custom proxy config script for our test machines that had "bing.com" point to DIRECT instead of the default proxy.
I think that #Hans Passant has spotted the issue here. It looks like you have a proxy setup in IE.
Dns.GetHostAddresses("www.bing.com")[0]; // 10.0.0.1
This works because you are asking the OS to get the IP addresses for www.bing.com
WebRequest.Create("http://www.bing.com/").GetResponse(); // unexpectedly succeeds
This works because you are asking the framework to fetch a path from a server name. The framework uses the same engine and settings that IE frontend uses and hence if your company has specified by a GPO that you use a company proxy server, it is that proxy server that resolves the IP address for www.bing.com rather than you.
WebRequest.Create("http://10.0.0.1").GetResponse(); // throws exception (expected)
This works/fails because you have asked the framework to fetch you a webpage from a specific server (by IP). Even if you do have a proxy set, this proxy will still not be able to connect to this IP address.
I hope that this helps.
Jonathan
I'm using VS 2010 on Windows 7, and I can't reproduce this. I made the same hosts-file change and ran the following code:
Console.WriteLine(Dns.GetHostAddresses("www.bing.com")[0]); // 10.0.0.1
var response = WebRequest.Create("http://www.bing.com/").GetResponse(); // * * *
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
I got an exception on the line marked "* * *". Here's the exception detail:
System.Net.WebException was unhandled
Message=Unable to connect to the remote server
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at ConsoleApplication2.Program.Main(String[] args) in c:\Data\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 17
InnerException: System.Net.Sockets.SocketException
Message=A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.0.0.1:80
Source=System
ErrorCode=10060
Maybe it's an issue with an earlier .NET version, that's now fixed in .NET 4 / VS 2010? Which version of .NET are you using?
I also found this thread from 2007, where someone else ran into the same problem. There are some good suggestions there, including the following:
Turn on system.net tracing
Work around the problem by using Dns.GetHostAddresses() to resolve it to an IP. Then put the IP in the URL - e.g. "http://10.0.0.1/". That may not be an option for you though.
In the above thread, mariyaatanasova_msft also says: "HttpWebRequest uses Dns.GetHostEntry to resolve the host, so you may get a different result from Dns.GetHostAddresses".
You should overwrite the default proxy.
HttpWebRequest & WebRequest will set a default proxy if present in Internet Explorer and your file hosts will be bypassed.
request.Proxy = new WebProxy();
The following is just an example of code:
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("www.bing.com");
request.Proxy = new WebProxy();
request.Method = "POST";
request.AllowAutoRedirect = false;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
//some code here
}
}
catch (exception e)
{
//Some other code here
}

Categories

Resources