krystan honour
krystan honour

Reputation: 6833

jQuery post to WCF service returns 405 error

I was recently brushing up on my jQuery and I came accross a problem when going over post, I was unable to get a response from a wcf service I constantly get 405 - Method not allowed. My request looks good to me and I wondered if I've missed something crucial yet obvious as to why this would happen.

here is the post code being used:

 $.ajax({
     type: "POST",
     url: "http://localhost:59929/CustomerService/GetCustomers",
     data: null,
     ContentType: "application/json",
     dataType: "json",
     success: function (msg) {
         alert("Called and got: " + msg);
     },
     error: function (result) {
         alert('Service call failed: ' + result.status + '' + result.statusText);
     }
 });

wcf code is as follows:

[ServiceContract]
public interface ICustomerService
{   

    [OperationContract]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
    List<Customer> GetCustomers();

    [OperationContract]
    OperationStatus InsertCustomer(Customer cust);
}

with the config being as follows:

<?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="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

Fiddler shows the raw post as:

POST http://localhost:59929/CustomerService/GetCustomers HTTP/1.1
Host: localhost:59929
Connection: keep-alive
Content-Length: 0
Origin: http://localhost:59513
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.60 Safari/537.1
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:59513/LearnJQuery2/ajax/ajax_post.htm
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

and fiddler also confirms the 405 response.

Upvotes: 2

Views: 2507

Answers (3)

krystan honour
krystan honour

Reputation: 6833

Well I looked at this for quite sometime and then realised there isn't one thing wrong with this but a pleathora :) so heres the issue solved.

Fist of all they must indeed be from the same domain with the same port and protocol, this was not the case. I moved my service into my application and configured the bindings appropriately. The next part is to adorn your WCF service correctly so here is the code to configure the service correctly.

ICustomerService.cs

[ServiceContract]
public interface ICustomerService
{
    [OperationContract]
    [WebInvoke(
        Method = "POST" ,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        ResponseFormat = WebMessageFormat.Json)]
    List<JSONCustomer> GetCustomers();
}

CustomerService.cs

[AspNetCompatibilityRequirements(RequirementsMode
    = AspNetCompatibilityRequirementsMode.Allowed)]
public class CustomerService : ICustomerService
{
    public List<JSONCustomer> GetCustomers()
    {
        return new List<JSONCustomer> 
        { 
            new JSONCustomer {id = 1, FirstName = "john", LastName = "Doe"},
            new JSONCustomer {id = 2, FirstName = "jane", LastName = "Doe"},        
        };
    }
}

Web.config

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServiceBehavior" 
               name="CustomerService">
        <endpoint address="" 
                  binding="webHttpBinding"
                  contract="ICustomerService" 
                  behaviorConfiguration="EndpBehavior"/>
      </service>
    </services>

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

</configuration>

Next here is the ajax code being used (entire webpage):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Ajax Post</title>
        <script type="text/javascript" src="../scripts/jquery-1.7.2.js"></script>
        <script type="text/javascript">
            $(document).ready(function () {
                $('#HelpButton').click(function () {
                    $.post('../CustomerService.svc/GetCustomers', null,
                        function (data) {
                            var custs = data["GetCustomersResult"];
                            var text = '';

                            $(custs).each(function () {
                                text += '<span>' + this.FirstName + ' ' + this.LastName + '</span><br/>';
                            });

                            $('#OutputDiv').html(text);
                        }
                    , 'json');
                });
            });
        </script>
    </head>
    <body>
        <input id="HelpButton" type="button" value="Press me"/>
        <div id="OutputDiv" />
    </body>
</html>

JSONCustomer.cs

[DataContract]
public class JSONCustomer
{
    [DataMember]
    public int id { get; set; }

    [DataMember]
    public string FirstName { get; set; }

    [DataMember]
    public string LastName { get; set; }
}

I truely hope those that are now having issues will find help with this, it is important that you pay attention to all the things, bindings, adornments and ajax code in jquery one little slip and it just won't work.

Upvotes: 1

JTMon
JTMon

Reputation: 3199

This looks like a server configuration issue where the caller can not see the method as part of the wcf service. This link has some helpful tips on how to fix the most common reasons for a 405 error. I Hope it helps: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/31d3f1aa-28b6-4bd7-b031-73b7e7588e6d/

Upvotes: 0

Fermin
Fermin

Reputation: 36111

What domain are you making the call from? It could be caused by Same origin policy. If this is the case try using JSONP rather than JSON.

Also, have you tried a tool like Fiddler to see exactly what the request/response is? This could shed some light as to what is happening.

Upvotes: 1

Related Questions