I write here because I'm working to transform a PHP webservice client to C# (VS2010).
Project are in Framework4 but the web service was added in VS2010 like a web service compatible with Framework2 (Web Reference with WSDL).
Actually I'm working only on a classical webservice (a Helloworld test).
With the client C# I have no problem I send a text to the web service and the web service responds by returing the text. I have no error in the Apache Server.
If I activate the basic authentification in the .htaccess apache server (host the webservice server), so in the client C# I have this error :
Exception : WebException Bad Request with state HTTP 400 : Bad Request.
In Apache error log I see this line :
[Thu Feb 02 23:52:06 2012] [error] [client XX.XX.XX.XX] Invalid URI in request
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/helloworld/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/helloworld/webservices.php?wsdl/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour><prenom xsi:type="xsd:string">Toto</prenom></tns:bonjour>
</soap:Body>
</soap:Envelope>
POST /api/helloworld/webservices.php HTTP/1.1
.
I'm sure is the credentials who are not working because when I try with a false user and password I have always the 400 Bad Request.
The code of C# Client are : // We create the webservice WebService mywebservice = new WebService();
// We define BASIC Authentication
CredentialCache myCredentials = new CredentialCache();
NetworkCredential netCred = new NetworkCredential("User1", "Pass1");
myCredentials.Add(new Uri(mywebservice.Url), "Basic", netCred);
myCredentials.PreAuthenticate = true;
mywebservice.Credentials = myCredentials;
// We define the UserAgent
mywebservice.UserAgent = ".NET Framework";
// We call the function of webservice
string retour = mywebservice.bonjour("Tata");
// We show the return
MessageBox.Show(retour, "Retour de l'API", MessageBoxButtons.OK, MessageBoxIcon.Information);
.
The .htaccess : # Don't show directory listings for URLs which map to a directory. Options -Indexes
# Se logue avec un compte AD
AuthType Basic
AuthBasicProvider ldap
AuthName "Acces au webservice"
AuthLDAPURL ldap://127.0.0.1:389/ou=clients,dc=domaine,dc=com?mail
Require valid-user
.
If I delete the .htaccess file everything it's working ... but without authentication :(
I post also the request and response with .htaccess (not working) :
POST https://www.domaine.com/api/login_ovh_pnp/webservices.php HTTP/1.1
User-Agent: .NET Framework
VsDebuggerCausalityData: uIDPo9/Tb/xbJxtKvSNra7boyJsAAAAAQcQin1OhXXXXXXXXXXX/KqROJW0w1FhAcrrhI1sGQACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl#bonjour"
Authorization: Basic bHZlaXJtYW5AYXF1aWxhLWXXXXXXXXXXXbmcuZnI6ZHluYXRlcmE3OA==
Host: www.domaine.com
Content-Length: 623
Expect: 100-continue
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl
/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour>
<prenom xsi:type="xsd:string">Tata</prenom>
</tns:bonjour>
</soap:Body>
</soap:Envelope>
=====================================
=====================================
HTTP/1.1 400 Bad Request
Date: Mon, 06 Feb 2012 13:40:32 GMT
Server: Apache
Vary: Accept-Encoding
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
.
And for finish the request without .htaccess :
POST https://www.domaine.com/api/login_ovh_pnp/webservices.php HTTP/1.1
User-Agent: .NET Framework
VsDebuggerCausalityData:
uIDPo4r/MO3TgmdMkQiWHfkXoWwAAAAA1krYOM0NBkS9vLzFQe3Vmln8F3GXClFNrTWXL/L622YACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl#bonjour"
Host: www.domaine.com
Content-Length: 623
Expect: 100-continue
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl
/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour>
<prenom xsi:type="xsd:string">Tata</prenom>
</tns:bonjour>
</soap:Body></soap:Envelope>
=====================================
=====================================
HTTP/1.1 200 OK
Date: Mon, 06 Feb 2012 13:51:31 GMT
Server: Apache
X-SOAP-Server: NuSOAP/0.9.5 (1.123)
Content-Length: 575
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/xml; charset=ISO-8859-1
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:bonjourResponse xmlns:ns1="https://supervision.dynatera.net/api/login_ovh_pnp/webservices.php?wsdl">
<return xsi:type="xsd:string">Bonjour Tata</return></ns1:bonjourResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
.
Thank you very much for your help on this complex problem because I searched many times without found anything to fix this issue.
I've also had this problem... When you define NetworkCredentials it does not get sent in the HTTP header, and thus no 'Authorization' header...
What I did and it worked for me was:
I created a class that implements IClientMessageInspector and implement the BeforeSendRequest method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
namespace BasicAuth
{
public sealed class MessageHttpHeaderInspector : IClientMessageInspector
{
private string userName;
private string password;
#region Constructor
public MessageHttpHeaderInspector(string userName, string password)
{
this.userName = userName;
this.password = password;
}
#endregion
#region IClientMessageInspector Members
public void AfterReceiveReply(ref Message reply, object correlationState)
{
//throw new NotImplementedException();
}
public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequest;
if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
httpRequest = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
}
else
{
httpRequest = new HttpRequestMessageProperty();
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequest);
}
if (httpRequest != null)
{
string credentials = this.CreateBasicAuthenticationCredentials(this.userName, this.password);
httpRequest.Headers.Add(System.Net.HttpRequestHeader.Authorization, credentials);
}
return request;
}
#endregion
#region Private Worker Methods
private string CreateBasicAuthenticationCredentials(string userName, string password)
{
string returnValue = string.Empty;
string base64UsernamePassword = Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password)));
returnValue = String.Format("Basic {0}", base64UsernamePassword);
return returnValue;
}
#endregion
}
}
Then I created a class that implements IEndpointBehavior and implements the ApplyClientBehavior method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace BasicAuth
{
public sealed class CustomEndpointCallBehavior : IEndpointBehavior
{
private string userName;
private string password;
#region Constructor
public CustomEndpointCallBehavior(string userName, string password)
{
this.userName = userName;
this.password = password;
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
//throw new NotImplementedException();
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MessageHttpHeaderInspector(this.userName, this.password));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
//throw new NotImplementedException();
}
public void Validate(ServiceEndpoint endpoint)
{
//throw new NotImplementedException();
}
#endregion
}
}
Then you need to apply this behavior to the proxy:
mywebservice.Endpoint.Behaviors.Add(new CustomEndpointCallBehavior("User1", "Pass1"));
Have a look at the following:
This should do the trick... Hope it works for you!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With