JohnB
JohnB

Reputation: 4359

Why am I getting a "405 Method not allowed" error on "Put" operations through a WCF Resful service?

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?

Upvotes: 2

Views: 2223

Answers (2)

Isaac Raway
Isaac Raway

Reputation: 300

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);

Upvotes: 1

Ian
Ian

Reputation: 1504

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!.

Upvotes: 0

Related Questions