Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP 400 Bad Request when calling WCF Service Operation?

When I call http://localhost/TestService.svc/GetColors, I get a Http (400) Bad Request. When I run this in fiddler, I also get Bad Request. When I invoke the service through the wcf test client, it works fine though. What could cause this?

Service contract:

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string GetColors();
}

Implementation of ITestService:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class TestService : ITestService
{
    public List<Color> GetColors()
    {
        List<Color> colors= new List<Color>();

        colors.Add(new Color { Name = "Red", Code = "123" });
        colors.Add(new Color { Name = "Blue", Code = "323" });
        colors.Add(new Color { Name = "Green", Code = "3394" });

       return colors;
    }
}

Here is my web.config:

<?xml version="1.0"?>
<configuration>
   <system.web>
       <compilation debug="true" targetFramework="4.0"/>
   </system.web>
   <system.serviceModel>
      <bindings>
         <wsHttpBinding>
            <binding name="CustomAuthentication">
               <security mode="Message">
                  <message clientCredentialType="UserName"/>
               </security>
            </binding>
         </wsHttpBinding>
      </bindings>
      <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
      <services>
          <service name="TestService.TestService"
                behaviorConfiguration="CustomValidator" >
             <endpoint 
                 address="" 
                 binding="wsHttpBinding" 
                 bindingConfiguration="CustomAuthentication"
                 contract="TestService.ITestService">
                 <identity>
                    <dns value="localhost" />
                 </identity>
             </endpoint>
             <endpoint 
                 address="mex" 
                 binding="mexHttpBinding" 
                 contract="IMetadataExchange" />
             <host>
                 <baseAddresses>
                     <add baseAddress="http://localhost/TestService/" />
                 </baseAddresses>
             </host>
          </service>
      </services>
      <behaviors>
          <serviceBehaviors>
             <behavior name="CustomValidator">
                <serviceCredentials>
                   <userNameAuthentication userNamePasswordValidationMode="Custom"
                                customUserNamePasswordValidatorType="TestService.CustomUserNameValidator, TestService"/>
                   <serviceCertificate findValue="Test" storeLocation="LocalMachine" 
                         storeName="My" x509FindType="FindBySubjectName"/>
                </serviceCredentials>
                <serviceMetadata httpGetEnabled="True"/>
             </behavior>
             <behavior>
                <serviceMetadata httpGetEnabled="True"/>
                <serviceDebug includeExceptionDetailInFaults="False"/>
             </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
   <system.webServer>
       <modules runAllManagedModulesForAllRequests="true"/>
   </system.webServer>
</configuration>

When I call it, I just open up a any browser and put the url http://localhost/TestService.svc/GetColors. If I do it through the dev environment, I see the Http 400 bad request. If I do it through IIS, I just see a blank page.

Here is the InnerException:

<ExceptionString>System.Xml.XmlException: The body of the message cannot be read  
because it is empty.</ExceptionString>

Another question regarding my CustomUserNameValidation:

I am implementing Custom Validation through the Validate Method of UserNamePasswordValidator, but when I call something like GetColors through the wcf client, it does not invoke the Validate method. The only way I can get it to Invoke validate is if I call Validate(user,pass) directly in GetColors. I thought it woulld be called automatically for every service call if you have it setup correctly in web.config.

like image 693
Xaisoft Avatar asked May 13 '11 17:05

Xaisoft


1 Answers

Your service contract and service implementation don't seem to match....

The service contract defines a single string to be returned from GetColors():

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string GetColors();
}

But the implementation returns a List<Color> instead:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class TestService : ITestService
{
    public List<Color> GetColors()
    {

Is there any chance you changed your service implementation, and forgot to update the service contract??

Also: since this is a SOAP service with a wsHttpBinding, you cannot just call the method from a browser by browsing to its address - you need to use the WCF Test Client (which works, as you say). Nor can you just call it from Fiddler, either - you would have to manually create the entire SOAP envelope with header and body and all - not an easy task at all.

What you can try is to go to http://localhost/TestService.svc?wsdl to check whether you'll get back the proper WSDL for the service.

like image 135
marc_s Avatar answered Nov 01 '22 16:11

marc_s