2

I've got a simple WCF service which takes json as input/output parameters. It works correctly as a SOAP based service and I get the expected results.

I have added RESTFul endpoints to the service. I'm using "Google-based" PostMan to test the service.

I can successfully call "Get" methods on the service and return JSON results:

 [OperationContract(IsOneWay = false)]
    [WebGet(UriTemplate = "/Test/{calcID}", 
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    CalcResults GetTestResults(string calcID);

When I attempt to access my "Put" based methods I get a status of: 405 Method Not Allowed

The signature for the "Put" method:

 [OperationContract(IsOneWay = false)]
    [WebInvoke(Method = "Post",
        UriTemplate = "/GetCalculation", 
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    CalcResults GetCalculation(CalcInput inputValues);

This is the output that I see in the PostMan output window:

<body>
   <div id="content">
      <p class="heading1">Service</p>
      <p>Method not allowed.</p>
   </div>
</body>

This is what my configuration settings look like for the endpoints for the RESTFul interface:

<system.serviceModel>
    <services>
      <service name="CalcServiceLibrary.CalcService">

        <endpoint address="regular" binding="wsHttpBinding" name="wsHTTPEndPoints"
          contract="CalcServiceLibrary.ICalcService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>

        <endpoint address="json" binding="webHttpBinding" name="wsWebHTTPEndPoint"
                  contract="CalcServiceLibrary.ICalcServiceRESTful"
                  behaviorConfiguration="RESTfulBehavior" bindingConfiguration="crossDomain">
            <identity>
              <dns value="localhost" />
            </identity>          
        </endpoint>
      </service>
    </services>

    <bindings>
      <webHttpBinding>
        <binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="RESTfulBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>      
    </behaviors>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

I'm sure that there is something that is not quite correct in my configuration definitions. I've researched several posts, but have not been able to come up with the solution.

NEW NOTE:: I've added the following simple endpoint to my service:

[OperationContract]
[WebInvoke(
    Method = "POST",
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json)]
public string TestPost(string name)
{
    return "Hello " + name + "!";
}

I'm testing using Postman. Here is a screen shot of my Postman screen: Postman Input Screenshot

This is what I see in the output: Postman Output Screenshot

This feels like it has to be some sort of configuration issue. Can someone point me in the right direction as to what I'm doing wrong?

JohnB
  • 3,921
  • 8
  • 49
  • 99

2 Answers2

1

Looks like you're specifying post instead of put as the method in the declaration, perhaps change to:

[OperationContract(IsOneWay = false)]
   [WebInvoke(Method = "PUT",
       UriTemplate = "/GetCalculation", 
       RequestFormat = WebMessageFormat.Json,
       ResponseFormat = WebMessageFormat.Json,
       BodyStyle = WebMessageBodyStyle.Bare)]
   CalcResults GetCalculation(CalcInput inputValues);
Isaac Raway
  • 302
  • 3
  • 11
  • IR: Thanks for the quick feedback. I tried changing it to "Put" and I get the same results in Postman. Thoughts? – JohnB Jan 12 '16 at 22:54
  • Been awhile since I use WCF, I typically just did POST instead of messing with PUT. Would indeed help to see the code that is sending the request as @Ian suggests. – Isaac Raway Jan 12 '16 at 23:06
  • IR: I don't have access to the code sending the request. I was using "PostMan" to test with. As I mentioned above, when I used Method="*", it started to work. Not sure why and not sure if this is the correct approach. – JohnB Jan 13 '16 at 19:09
  • 1
    I wonder if it's case sensitive. I hadn't really thought about it prior, but I bet that is why Method="*" is working for you but Method="Put" does not. I'll correct the code in my answer as I had just used the same style without thinking. Checking old code and the docs it is always in uppercase. – Isaac Raway Jan 14 '16 at 21:05
  • IR: That is exactly it. It is CASE sensitive. In all the doc, etc. I looked, nowhere did it say it needed to be all CAPITOL letters. THX! – JohnB Jan 14 '16 at 21:45
  • @JohnB Happy to help! – Isaac Raway Jan 14 '16 at 23:29
0

When troubleshooting the first thing I try to do is start with the bare essentials. I'd recommend dropping the UriTemplate = "/GetCalculation" and BodyStyle = WebMessageBodyStyle.Bare) attribute parameters. This is what I have which is working:

[OperationContract]
[WebInvoke(
    Method = "POST",
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json)]
public string TestPost(string name)
{
    return "Hello " + name + "!";
}

Edit: I thought I'd have a look at Postman, since I'm doing a lot of similar work anyway. Can you post a screenshot of your Postman configuration? In order to get Postman to work I had to set the following:

Postman headers and POST setting

Type is set to POST (obviously). But I also had to set the header Content-Type to application/json.

In order to send data, you can't use URL parameters (the 'Params' button next to the URL field). This only inserts in the style ?name=bob, which works for GET but not POST. Also I couldn't specify the data as JSON, so I had to enter raw data in JSON format:

Postman body text and valid response

Then I get a valid response, Hello bob!.

Ian
  • 1,475
  • 2
  • 15
  • 31
  • Ian: Thanks for the feedback. I will go back and play with the bare essentials. Note:: When I substituted Method="*", I was able to get it to work. Not sure why.... – JohnB Jan 13 '16 at 19:07
  • - "Method not allowed". I was testing using Postman. Here is my test code: http://localhost:61047/CalculatorService.svc/json/TestPost. The only other thing I can think of which is worth mentioning is that I've got my service set up as the following pattern: CalculatorServiceLibrary -- CalculatorService. Thoughts? – JohnB Jan 14 '16 at 17:17