Get Proxy configuration before accessing an external webservice (.NET 2.0) - proxy

When trying to invoke a method on an external webservice (over the Internet) it throws me
"The remote server returned an error: (407) Proxy Authentication Required."
To solve this, I used the following code to set the proxy we use in the office:
//Set the system proxy with valid server address or IP and port.
System.Net.WebProxy pry = new System.Net.WebProxy("MyHost", 8080);
//The DefaultCredentials automically get username and password.
pry.Credentials = System.Net.CredentialCache.DefaultCredentials;
System.Net.WebRequest.DefaultWebProxy = pry;
That works fine, but now... I need to do that "less harcoded" trying to get the information from my system instead of setting that manually.

This will use whatever the default proxy is for IE I believe (not deprecated):
Services.MyService service = new Services.MyService();
service.UseDefaultCredentials = true;
service.Proxy = new System.Net.WebProxy();
service.Proxy.Credentials = service.Credentials;

System.Net.WebProxy.GetDefaultProxy() although VS cautions its been deprecated.

Related

Using HttpClient to access Web API issue (certificate?)

I have been following this link to understand how to use HttpClient to call a Web API Method.
https://www.tutorialsteacher.com/webapi/consuming-web-api-in-dotnet-using-httpclient
The code of interest in the article is below with ‘client’ being the HttpClient object:
client.BaseAddress = new Uri("http://localhost:60464/api/"); //HTTP GET
var responseTask = client.GetAsync("student");
responseTask.Wait();
var result = responseTask.Result;
Error results as follows:
System.AggregateException: 'One or more errors occurred. (Failed to connect to localhost/127.0.0.1:443)'
Please understand my background in networking, IIS and the like is very limited.Most of my time is spent in code and SQL Sprocs. This is a personal project so I have to get this setup myself
If I replace localhost with my machines IP I get the following error:
One or more errors occurred. (java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)'
So two questions:
How do I install this needed certificate or settings or otherwise (again no idea about this configuration network stuff) but I do have IIS up and running with the Web API hosted and working
If using ‘localhost’ is not supposed to work, what might be the reason this article is using it?
This is only for a personal development machine, yes at some point I am going to want it to work in the real world but for now I just need to get some ‘hello world’ stuff going before the end of times.

calling a https api from another web api

I am attaching the below piece of code which works perfectly fine in localhost but throws web exception/socket when hosted in IIS on another server.
System.Net.Sockets.SocketException (0x80004005): 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 40.113.232.243:443
It was throwing the same error in local too, unless I added this line-
httpWebRequest.Proxy = WebRequest.GetSystemWebProxy();
yet it throws socketexception when hosted in iis server.
public async Task<string> Get()
{
try
{
string uri = "https://hp-reporting-*****.azurewebsites.net/********";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.Timeout = 600000;
httpWebRequest.Proxy = WebRequest.GetSystemWebProxy(); // adding this line resolved error in local but still same issue persists when hosted in iis in another server
httpWebRequest.Method = "GET";
HttpWebResponse httpResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var response = streamReader.ReadToEnd();
// this is your code here...
System.Xml.Linq.XNode node = JsonConvert.DeserializeXNode(response, "Root");
return node.ToString();
}
well, look at what that line does : https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest.getsystemwebproxy?view=netframework-4.7.2
On your local machine, you have a web proxy defined in Internet Explorer which you use when making the call. On the deployed IIS you clearly don't have it.
So, either you setup the server exactly how you setup your local machine or find another way to solve this issue locally, without using that local proxy. When you get it working, then you deploy again and it will work.

When self-hosting what exactly causes AddressAccessDeniedException : HTTP could not register URL

I am writing a bdd test for a component that will startup phantomjs and hit a specific route on my site and do processing on that. Because the component is fundamentally about automating a phantom instance there is no way to easily stub out the http requests.
So I want to stub out a self-hosted endpoint that will stub out the data I'm after. Because this is a unit test I think its really important for it to run in isolation so I do something like this:
async Task can_render_html_for_slide_async() {
var config = new HttpSelfHostConfiguration("http://localhost:54331");
config.Routes.MapHttpRoute("Controller", "{controller}", new {});
using (var server = new HttpSelfHostServer(config)) {
server.OpenAsync().Wait();
var client = new HttpClient();
var resp = await client.GetStringAsync(config.BaseAddress+"/Stub");
Console.WriteLine(resp);
}
}
public class StubController : ApiController
{
public string Get() {
return "Booyah";
}
}
Which gets me
AddressAccessDeniedException : HTTP could not register URL http://+:54331/
I understand that netsh or Admin mode is required for this but I don't understand why. Nodejs for example runs perfectly fine on windows but has no such requirement.
Also using OWIN directly needs no netsh-ing. So....what's going on?
I wrote an article about it on codeproject, it was done to make it possible for multiple application to share the same port.
You can have both, IIS and Apache (or OWIN in your case) listenening port 80. The routing to the right application is done thanks to the path of the url.
IIS and Apache both would use this driver (http.sys). But you need permission to "reserve" a path.
Administrators are always authorized. For other users, use netsh or my GUI tool HttpSysManager to set ACL.
Any method that requires giving permission via netsh uses a Windows kernel driver to provide http access.
If a library opens a socket itself and handles the http communication that way, no netsh use is needed.
So to answer your question, some methods are using the kernel driver and some are handling the protocol themselves.

RavenDB domain error

I have set up an instance of RavenDB on IIS. I can connect to it just fine using a network service application, however when I try and connect then initialize using an application running under local administrator I get an error "Unable to determine the identity of domain". The only thing I can think of is trying to impersonate "Network Service", but I am not sure if that is possible. The administrator has full rights to raven web folder.
Figured out this problem. I had to run my Raven document store connect and initialize in a different application domain. I ended up doing this.
string pathToDLL = installerFolder + "\\RavenSiteSetup.dll";
AppDomainSetup domainSetup = new AppDomainSetup {
ApplicationBase = installerFolder,
PrivateBinPath = pathToDLL
};
Evidence ev1 = new Evidence();
ev1.AddAssemblyEvidence(new ApplicationDirectory(
typeof(RavenSetup).Assembly.FullName)
);
ev1.AddHostEvidence(new Zone(SecurityZone.Internet));
AppDomain ad = AppDomain.CreateDomain("RavenSetup", ev1, domainSetup,
Assembly.GetExecutingAssembly().PermissionSet,null);
IIdentity identity = new GenericIdentity("RavenSetup");
IPrincipal principal = new GenericPrincipal(identity, null);
ad.SetThreadPrincipal(principal);
RavenSetup remoteWorker = (RavenSetup)ad.CreateInstanceFromAndUnwrap(
pathToDLL,
typeof(RavenSetup).FullName);
remoteWorker.Connect(sitePath);
Connecting locally, are you using http://localhost:[port]? I've had problems using the domain name locally.
Try running your application locally and connect to the RavenDB via locahost address.

Getting "Object is read only" error when setting ClientCredentials in WCF

I have a proxy object generated by Visual Studio (client side) named ServerClient. I am attempting to set ClientCredentials.UserName.UserName/Password before opening up a new connection using this code:
InstanceContext context = new InstanceContext(this);
m_client = new ServerClient(context);
m_client.ClientCredentials.UserName.UserName = "Sample";
As soon as the code hits the UserName line it fails with an "Object is read-only" error. I know this can happen if the connection is already open or faulted, but at this point I haven't called context.Open() yet.
I have configured the Bindings (which uses netTcpBinding) to use Message as it's security mode, and MessageClientCredentialType is set to UserName.
Any ideas?
I noticed that after creating an instance of the proxy class for the service, I can set the Username and Password once without errors and do a successful call to my webservice. When I then try to set the Username and Password again on the existing instance (unnecessary of course) I get the 'Object is Read-Only' error you mentioned. Setting the values once per instance lifetime worked for me.
It appears that you can only access these properties pretty early in the instanciation cycle. If I override the constructor in the proxy class (ServerClient), I'm able to set these properties:
base.ClientCredentials.UserName.UserName = "Sample";
I'm beginning to appreciate the people who suggest not using the automatically built proxies provided by VS.
here is the solution:
using SysSvcmod = System.ServiceModel.Description;
SysSvcmod.ClientCredentials clientCredentials = new SysSvcmod.ClientCredentials();
clientCredentials.UserName.UserName = "user_name";
clientCredentials.UserName.Password = "pass_word";
m_client.ChannelFactory.Endpoint.Behaviors.RemoveAt(1);
m_client.ChannelFactory.Endpoint.Behaviors.Add(clientCredentials);
I have similar code that's passing UserName fine:
FooServiceClient client = new FooServiceClient("BasicHttpBinding_IFooService");
client.ClientCredentials.UserName.UserName = "user";
client.ClientCredentials.UserName.Password = "password";
Try creating the proxy with binding name in app.config.
The correct syntax is:
// Remove the ClientCredentials behavior.
client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
// Add a custom client credentials instance to the behaviors collection.
client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());
http://msdn.microsoft.com/en-us/library/ms730868.aspx
It worked for me.
I was facing same problem, my code started working when I changed my code i.e. assigning values to Client credential immediately after initializing Client object.
here is the solution ,
ProductClient Manager = new ProductClient();
Manager.ClientCredentials.UserName.UserName = txtUserName.Text;
Manager.ClientCredentials.UserName.Password = txtPassword.Text;
This will not happen if the service reference is added through -> Add service reference ->Advanced->Add Web Reference-> Url/wsdl (local disk file).
I was facing this issue where I was trying to create a generic method to create a clients for different end points.
Here how I achieved this.
public static T CreateClient<T>(string url) where T : class
{
EndpointAddress endPoint = new EndpointAddress(url);
CustomBinding binding = CreateCustomBinding();
T client = (T)Activator.CreateInstance(typeof(T), new object[] { binding, endPoint });
SetClientCredentials(client);
return client;
}
public static void SetClientCredentials(dynamic obj)
{
obj.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
obj.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
obj.ClientCredentials.UserName.UserName = "UserId";
obj.ClientCredentials.UserName.Password = "Password";
}
I think your problem might be related to the use of the InstanceContext. I thought that was only needed for duplex communication channels from the server side.
I admit I'm not sure about this, but I think in this case you are telling the client to use an existing instance context so it thinks there is already a running service and will not allow changes.
What is driving the use of InstanceContext?
If using a duplex client, when you instantiate it the DuplexChannelFactory within the DuplexClientBase that your client is derived from is initialized with existing credentials so it can open the callback channel, which is why the credentials would be read only.
I second Mike's question and also ask why are you using NetTcpBinding if you are not going to use its inherent transport level security? Perhaps an HTTP based binding would be a better fit? That would allow you to use certificate based security which I believe can be modified after instantiation (http://msdn.microsoft.com/en-us/library/ms576164.aspx).
A shot in the dark but does netTcpBinding allow username and password validation? Try using application layer (SOAP) security using a http binding
or you could just simply check the Credentials
if (client.ClientCredentials.ClientCertificate.Certificate == null || string.IsNullOrEmpty(client.ClientCredentials.ClientCertificate.Certificate.Thumbprint))
{
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("CertificateThumbprint"));
}
In .NET 4.6 I couldn't remove the credentials using Fabienne's answer. Kept getting Compiler Error CS0308 in the Remove method. What worked for me was this:
Type endpointBehaviorType = serviceClient.ClientCredentials.GetType();
serviceClient.Endpoint.EndpointBehaviors.Remove(endpointBehaviorType);
ClientCredentials clientCredentials = new ClientCredentials();
clientCredentials.UserName.UserName = userName;
clientCredentials.UserName.Password = password;
serviceClient.Endpoint.EndpointBehaviors.Add(clientCredentials);

Resources