C# 4.0 WCF REST JSON - HTTP GET CODE 400 Bad Request

19,364

Solution 1

For REST WCF You have to do binding and endpoint setting in web.config

Replace your whole web.config by following and it will work

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <protocolMapping>
      <add scheme="http" binding="webHttpBinding"/>
    </protocolMapping>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>

        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior>
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
 </configuration>

You were remaining with following 2 things

Use webHttpBinding (change default http port mapping to webHttpBinding)

<system.serviceModel>
    <protocolMapping>
        <add scheme="http" binding="webHttpBinding"/>
    </protocolMapping>
    <behaviors>

<system.serviceModel>

Specify webHttp End Point Behaviors

<system.serviceModel>
    -----
    </protocolMapping>
    <behaviors>
        <endpointBehaviors>
            <behavior>
                <webHttp />
            </behavior >
        </endpointBehaviors>
    <behaviors>
    ------
<system.serviceModel> 

Solution 2

You didn't specify any endpoint... By default on WCF 4, an endpoint using basicHttpBinding will be used. It'll not work here because it is a SOAP-based binding. What you want to use is webHttpBinding which is REST-based...

Here is how to override default binding with WCF 4 :

<system.serviceModel>
  <protocolMapping>
    <add scheme="http" binding="webHttpBinding"/>
  </protocolMapping>
</system.serviceModel>

You also have to enable webHttp by adding this endpoint behavior in your config :

<behaviors>
    <endpointBehaviors>
        <behavior>
            <webHttp />
        </behavior >
    </endpointBehaviors>
<behaviors>

http://msdn.microsoft.com/en-us/library/bb924425.aspx

Solution 3

I'm not entirely sure why, but when I added the 'Factory' attribute to my .SVC file (you need to explicitly drag it to Visual Studio), everything just works - without any changes to default settings in Web.config!

I added Factory="System.ServiceModel.Activation.WebServiceHostFactory" so my .SVC file went from this:

<%@ ServiceHost Language="C#" Debug="true" Service="ServiceNameSpace.ServiceName" CodeBehind="ServiceName.svc.cs" %>

to this:

<%@ ServiceHost Language="C#" Debug="true" Service="ServiceNameSpace.ServiceName" CodeBehind="ServiceName.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

The only side effect seems to be that when you click on the .SVC file in the browser, you get an 'Endpoint not found' error, but the service works fine when you invoke it correctly anyway. As mentioned previously, I'm using a default Web.config with .NET 4.6 (Simplified WCF configuration), so I may yet need to add endpoint details for that to work again.

Note to moderator: my apologies for posting this answer on a couple of questions. Won't do it again. However, I don't think that deleting it from BOTH questions was very balanced. This is why I have re-posted this answer here only.

Share:
19,364
Admin
Author by

Admin

Updated on June 15, 2022

Comments

  • Admin
    Admin almost 2 years

    When trying to create a simple service to return a simple JSON string by following several tutorials. I get stuck on two different machines with a HTTP Statuscode 400 bad request. Example tutorials RESTful WCF Service with JSON pt.1 & pt.2 - http://www.youtube.com/watch?v=5BbDxB_5CZ8

    I have also Google and searched here (StackOverflow) for similar problem without success.

    The problem is I get the 400 bad request when trying to do a sanity check to browse to the WCF service and execute the method. By compiling the service and browse this address: http://localhost:49510/Service1.svc/GetPerson Just like the tutorial. I have tried finding a solution for like 3 days. Any help is appreciated.

    This is what I do.

    First i create a new project a simple WCF Service application. I delete the default Service1.svc and add a new WCF Service, that generate a new Service1.svc and a IService1.cs

    Here is the code for the interface (IService1.cs)

    namespace WcfService1
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            [WebInvoke(Method="GET", BodyStyle=WebMessageBodyStyle.Bare, ResponseFormat=WebMessageFormat.Json, RequestFormat=WebMessageFormat.Json, UriTemplate="GetPerson")]
            Person GetPerson();
        }
    
        [DataContract(Name="Person")]
        public class Person
        {
            [DataMember(Name="name")]
            public string Name { get; set; }
        }
    }
    

    Here is the code for the Service1.svc

    namespace WcfService1
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
        public class Service1 : IService1
        {
            public Person GetPerson()
            {
                return new Person() { Name = "Tobbe" };
            }
        }
    }
    

    And the Web.config is untouched and look likes this web.config

    <?xml version="1.0"?>
    <configuration>
    
      <system.web>
        <compilation debug="true" targetFramework="4.0" />
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
              <serviceMetadata httpGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
     <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    
    </configuration>
    
  • Admin
    Admin over 12 years
    I just copied and paste the file as you said! You saved my day! Excellent! Thanks a lot!