6

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.

Xaisoft
  • 45,655
  • 87
  • 279
  • 432

2 Answers2

5

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.

Paul C
  • 4,687
  • 5
  • 39
  • 55
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Sorry marc_s, I just forgot to edit it on here. My actual code is List GetColors(); in my interface. – Xaisoft May 13 '11 at 18:40
  • marc_s, thanks for the help so far. I do get the proper wsdl. Do you have any idea about the username password validator issue? – Xaisoft May 13 '11 at 18:58
  • Use SoapUI for testing, it creates empty requests for you, then you fill in the parameters and send it – SparK Feb 11 '14 at 18:36
0

Many things could cause this. I suggest you first enable WCF Tracing, it's usually very helpful as it gives you the server side output of what's really going on. Here is a link that should help: How to enable WCF tracing

EDIT: One little thing to note with WCF: unlike auto generated ole' ASMX web service it does not allow you to browse to the base address with a standard browser. You can browse to the Metadata address (the mex one), but not to the root. This is just by design (the HTTP method is not supported I believe).

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • ok, I enabled tracing. How do I get something meaningful out of it now? – Xaisoft May 13 '11 at 17:43
  • You need to use the Service Trace Viewer Tool: http://msdn.microsoft.com/en-us/library/ms732023.aspx – Simon Mourier May 13 '11 at 17:56
  • I found that, but I can't seem to see any issues. I don't see any error icons. Is there anything I should look out for? – Xaisoft May 13 '11 at 18:04
  • @xaisoft - I have updated my answer. I think you're trying to browse the base address. You just can't do that. – Simon Mourier May 13 '11 at 18:30
  • Simon, you are correct. I am trying to browse to the base address\GetColors. So does this mean that everything is actually working the way it is supposed to work and that error is actually what is expected when I try to call an operation (GetColors) through the browser url. – Xaisoft May 13 '11 at 18:37
  • I do have another question that you might know since I posted my web.config. – Xaisoft May 13 '11 at 18:40