I am creating a configuration utility that can be used to change the web service configuration. I am doing this as my application has a lot of exes and contains a lot of configuration files.
This is also used to change the configuration for the web service as there are a lot of services and I need and easy way to change the server and the virtual directory in the connection string through a utility.
So what I am trying to do is use the service url and try connect to it to check if the connection can be established without needing to create a proxy.
So far this is what I am doing:
string url = "http://localhost/VirtualDirectory/Service.svc";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Credentials = new NetworkCredential("UserName", "Password");
using(HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{ MessageBox.Show("Connection successful!"); }
else
{ MessageBox.Show("Connection failed!!!"); }
}
But I am getting "The remote server returned an error: (401) Unauthorized." and the exception status is "System.Net.WebExceptionStatus.ProtocolError"
But when I am trying to connect to the web service using these credentials from the browser, I am able to connect and see the service xml.
I am not sure if it is something that I am doing wrong or if there is anything that is wrong from the IIS side(IIS 7.5). I see that for the service, anonymous authentication is enabled and rest is disabled in IIS.
I could not get the solution from another SO question. But it can be a possible duplicate. Please provide a link in such a case.
Thanks.
I figured out the problem and the solution as well for this. What I did not realize that the service was expecting an "Authorization" custom header which I was not providing, as I didn't notice it. My bad.
Below is the code that worked for me:
string url = #"http://" + ServerName + #"/" + VirtualDirectoryName
+ #"/Service.svc";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
NetworkCredential nc = new NetworkCredential("Username", "Password");
request.Credentials = nc;
string credentials = "Username:Password";
request.Headers.Add("Authorization", "Basic "
+ Convert.ToBase64String(Encoding.Default.GetBytes(credentials)));
CredentialCache cache = new CredentialCache();
cache.Add(new Uri(url), "Basic", nc);
request.Credentials = cache;
request.PreAuthenticate = true;
bool pingSuccess = false;
var ping = new Ping();
PingReply reply;
try
{
reply = ping.Send(ServerName);
if (reply.Status == IPStatus.Success)
pingSuccess = true;
}
catch
{
string msg = "Connection to the server failed.\nCheck server name.";
MessageBox.Show(msg, _error, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{
MessageBox.Show("Server connection successful!",
_info,
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
if (pingSuccess)
{
string msg = "Server is Available but connection failed."
+ "\nCheck virtual directory name.";
MessageBox.Show(msg,
_error,
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
Related
I'm trying to create an application using MS Visual Studio in either vb.net or C# to receive a token for a web api that has both basic authentication and application/x-www-form-urlencoded. When I send the request from Postman the requested works. Please see Postman screen shots below. When is use the below code I receive and message "Request failed with status code NotFound" back and the request fails. Can any point in the the right direction to resolve this.
Thank you
Postman
postman body
`private void button1_Click(object sender, EventArgs e)
{
Uri baseurl = new Uri("https://api address/token");
RestClient client = new RestClient(baseurl);
//client.Timeout = -1;
RestRequest request = new RestRequest("post", Method.Post);
request.AddHeader("Authorization", "Basic M2U4Y");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials",true);
request.AddParameter("scope", "https://?????????",true);
RestResponse response = client.Execute(request);
if (response.Content == "")
{
textBox1.Text = response.ErrorException.Message ;
}
else
{
textBox1.Text = response.Content;
}
}
`
I solved the problem. With the below code.
Uri baseurl = new Uri("https://api address/token");
RestClient client = new RestClient(baseurl);
RestRequest request = new RestRequest(baseurl, Method.Post);
request.AddHeader("Authorization", "Basic M2U4Y");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&scope=https://FED0C291",arameterType.RequestBody);RestResponse response = client.Execute(request);
if (response.Content == "")
{
textBox1.Text = response.ErrorException.Message ;
}
else
{
textBox1.Text = response.Content;
}
I am trying to call the third party webservice in WCF service.
i am able to call the the service by adding the service reference in(URL) through WCF service, but while doing that i heard from the people it is not the right way of doing this, when i googled this, found through channelfactory we can call the service .
But the problem is it is saying the contract dlls should get shared between client and server, this i am not getting.
can any body provide the sample to call the service with out adding service reference.
http://www.codeproject.com/Tips/558163/Difference-between-Proxy-and-Channel-Factory-in-WC
and what are the issues if we add service reference in the project and what are the pitfalls?
I am sure that i have to call SOAP service only
Thanks
You can use HttpWebRequest to create a web request and then pass the XML document describing whole SOAP request and get the response. Something like below code I used in one of my application. I have removed few bits from it that are specific to my application but you will get the idea.
public static string ProcessRequestSOAP()
{
string result = "";
try
{
XmlDocument soapEnvelop = new XmlDocument();
soapEnvelop.LoadXml(SOAPXML_Request); // This is the SOAP xml document that is generated when calling web service. You have to manually create this.
string url = webServiceURL; // External Web Service URL
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.Credentials = new NetworkCredential(userName,password); // Username/password to call web service if required
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelop.Save(stream);
}
//get response from server
WebResponse response = webRequest.GetResponse();
//read response stream
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
if (reader != null)
{
result = System.Xml.Linq.XDocument.Load(reader).ToString();
}
else
{
result = null;
}
}
}
catch (SoapException ex)
{
result = new ExceptionXElement(ex, false).ToString();
}
catch (Exception ex)
{
result = new ExceptionXElement(ex, false).ToString();
}
return result;
}
I am trying to connect a target host, which requires a username and password for primitive authentication from a proxy server that also have its own host, username and password.
Updated
The use case is something like this
My System connects with internet using proxy assume proxy.mydomain.com
And my proxy uses authentication to connect and authenticatuion is done using username and password
Username : MyDomain\myusername
Password : Password
Ok now the API or service which I want to connect is using Preemptive authentication I have some code snippet form API Docs :
final HttpState state = client.getState();
final HttpClientParams params = client.getParams();
myCreds = new UsernamePasswordCredentials(userName, userPassword);
System.out.println("Created credentials for " + myCreds.getUserName());
// Apply the credentials to the httpclient for preemptive authentication.
params.setAuthenticationPreemptive(true);
state.setCredentials(AuthScope.ANY, myCreds);
I tried with all apche clients from 4.1 to 4.3 but no solution at all.
I can set one credential but not getting how can both set together to a HttpClient ?
Below is my Code :
CloseableHttpResponse response;
HttpHost myHost=new HttpHost("172.17.8.192", 443, "https");
CredentialsProvider myServerCredsProvider;
if (userName.length() > 0 && userPassword.length() > 0)
{
myServerCredsProvider = new BasicCredentialsProvider();
myServerCredentials = new UsernamePasswordCredentials(userName, userPassword);
logger.info("Username : "+userName+" Password : "+userPassword);
myServerCredsProvider.setCredentials(
new AuthScope(myHost.getHostName(),myHost.getPort()),
myServerCredentials);
logger.info("After Creds Provider");
client = HttpClients.custom()
.setDefaultCredentialsProvider(myServerCredsProvider).build();
}
HttpHost proxy = new HttpHost("proxy.mycompany.com", 8080);
UsernamePasswordCredentials poxyAuthDetails=new UsernamePasswordCredentials("MyDomain//username", "password");
CredentialsProvider proxyProvider=new BasicCredentialsProvider();
proxyProvider.setCredentials(new AuthScope(proxy.getHostName(),proxy.getPort()), poxyAuthDetails);
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpGet getServerDetailsUrl=new HttpGet(BaseURI+DominoServerAddress+API_BASE_URI);
getServerDetailsUrl.setConfig(config);
try {
response=client.execute(getServerDetailsUrl);
try {
HttpEntity entity = response.getEntity();
logger.info("----------------------------------------");
logger.info(response.getStatusLine());
if (entity != null) {
logger.info("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} catch (IOException ex) {
isAuthenticate=false;
logger.info("Exception Occured "+ex.getMessage());
}
I am getting exception while trying to execute :
HTTP/1.1 407 Proxy Authorization Required
I have a JavaScriptHelper class with a custom WebPost method as follows:
public string WebPost(string url, string json)
{
#region
string responseData = "";
try
{
HttpWebRequest webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
StreamWriter requestWriter = null;
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(json);
}
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
responseData = responseReader.ReadToEnd();
}
webRequest = null;
}
catch (WebException ex)
{
LogBase.LogController.WriteError(ex);
}
catch (Exception ex)
{
LogBase.LogController.WriteError(ex);
}
return responseData;
#endregion
}
I use this to send a POST request to an ASP.NET WebAPI service as follows:
RegisterModel model = new RegisterModel();
model.email = "abc#gmail.com";
model.oAuthId = "11111111";
model.oAuthType = "Facebook";
string jsonStr = JsonConvert.SerializeObject(model);
string response = new JavaScriptHelper().WebPost("http://localhost:9091/api/Authentication/authenticateoauth", jsonStr);
The service receives this call. If the user exists, it returns the response, if it doesnt, it creates the user and returns the response.
The problem I am facing is that when the user exists, everything works fine. I get the response on the client (JSON). When it doesn't exists, it creates the user correctly on the server, but my client breaks off early and doesn't wait for a response. I get the following error:
System.Net.WebException was unhandled
HResult=-2146233079
Message=The remote server returned an error: (500) Internal Server Error.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
How can I force my request to wait for a response a little longer?
Thanks to this answer, I am now able to successfully call a JSON RESTful service using a WCF client. But that service uses HTTP status codes to notify the result. I am not sure how I can access those status codes since I just receive an exception on client side while calling the service. Even the exception doesn't have HTTP status code property. It is just buried in the exception message itself.
So the question is, how to check/access the HTTP status code of response when the service is called.
As a quick win, you can access the status code in the exception like this:
try
{
client.DoSomething(); // call the REST service
}
catch (Exception x)
{
if (x.InnerException is WebException)
{
WebException webException = x.InnerException as WebException;
HttpWebResponse response = webException.Response as HttpWebResponse;
Console.WriteLine("Status code: {0}", response.StatusCode);
}
}
Maybe there's a solution with a message inspector. But I haven't figured it out yet.
A solution without WCF would be to use the HttpRequest and DataContractJsonSerializer classes directly:
private T ExecuteRequest<T>(Uri uri, object data)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
// If we have data, we use a POST request; otherwise just a GET request.
if (data != null)
{
request.Method = "POST";
request.ContentType = "application/json";
DataContractJsonSerializer serializer = new DataContractJsonSerializer(data.GetType());
Stream requestStream = request.GetRequestStream();
serializer.WriteObject(requestStream, data);
requestStream.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
Stream responseStream = response.GetResponseStream();
T result = (T)deserializer.ReadObject(responseStream);
responseStream.Close();
response.Close();
return result;
}