Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wcf REST Services and JQuery Ajax Post: Method not allowed

Anyone knows what's wrong with this? I cant get the json response from my wcf rest service.

Jquery



$.ajax({
  type: 'POST',
  url: "http://localhost:8090/UserService/ValidateUser",
  data: {username: 'newuser', password: 'pwd'},
  contentType: "application/json; charset=utf-8",
  success: function(msg) {
   alert(msg);
  },

  error: function(xhr, ajaxOptions, thrownError) {
   alert('error');
  }

});


Service



  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class UserService: IUserService
    {
        private readonly IUserRepository _repository;

        public UserService()
        {
            _repository = new UserRepository();
        }

        public ServiceObject ValidateUser(string username, string password)
        {
           //implementation
        }
    }

    [ServiceContract]
    public interface IUserService
    {
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
        [OperationContract]
        ServiceObject ValidateUser(string username, string password);
    }


web config



 <system.serviceModel>

    <!--Behaviors here.-->
    <behaviors>
      <endpointBehaviors>
        <behavior name="defaultEndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--End of Behaviors-->

    <!--Services here-->   
   <services>
      <service name="MyWcf.Services.UserService">
        <endpoint address="UserService" behaviorConfiguration="defaultEndpointBehavior"
          binding="webHttpBinding" contract="MyWcf.Services.IUserService" />
      </service>
    </services>

    <!--End of Services-->

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name=""
                          helpEnabled="true"
                          automaticFormatSelectionEnabled="true"
                          defaultOutgoingResponseFormat ="Json"
                          crossDomainScriptAccessEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>


like image 632
h3n Avatar asked Dec 17 '22 12:12

h3n


2 Answers

I see multiple problems in your code:

405 means method not allowed - it can mean that you are posting data to wrong resource. Are you sure that your address is correct? How do you expose the service? Is it .svc file or ServiceRoute? If it is .svc file the address will be UserService.svc/UserService/ValidateUser

  • UserService.svc because this is entry point for your service (if you are using ServiceRoute you can redefine this
  • UserService because you are defining this relative address in endpoint configuration
  • ValidateUser because that is default entry point for your operation

Now your JSON request is completely bad and your method signature as well. Method signature in your service contract must expect single JSON object = it must be single data contract like:

[DataContract]
public class UserData
{
    [DataMember]
    public string UserName { get; set; }

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

and operation signature will be:

[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
ServiceObject ValidateUser(UserData userData);

There is no wrapper element in JSON request and because of that you must use Bare. Also it is not needed to set response format because you will set it on endpoint level (btw. you must also set request format if you don't).

Once you defined data contract for your request you must correctly define ajax request itself:

$.ajax({
  type: 'POST',
  url: "UserService.svc/UserService/ValidateUser",
  data: '{"UserName":"newuser","Password":"pwd"}',
  contentType: "application/json; charset=utf-8", 
  success: function (msg) {
    alert(msg);
  },

  error: function (xhr, ajaxOptions, thrownError) {
    alert('error');
  }

});

JSON object is as string! and all its members as well!

For last modify your configuration to:

<system.serviceModel>
  <services>
    <service name="UserService.UserService">
      <endpoint address="UserService" kind="webHttpEndpoint" contract="UserService.IUserService" />
    </service>
  </services>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  <standardEndpoints>
    <webHttpEndpoint>
      <standardEndpoint helpEnabled="true" automaticFormatSelectionEnabled="true" />
    </webHttpEndpoint>
  </standardEndpoints>
</system.serviceModel>

If you want to use standardEndpoint you must use kind in endpoint definition and you don't need to specify behavior (it is part of standard endpoint). Also you are not using cross domain calls so you don't need to enable them and you don't need default format because it is resolved automatically.

like image 165
Ladislav Mrnka Avatar answered Mar 05 '23 04:03

Ladislav Mrnka


I believe Ivan is on the right track here!

You are calling your service from javascript in a browser, right?

Does the html page with that javascript reside in the same domain as the wcf service?

If they are not in the same domain, then I would say that it is a cross-site-scripting issue. I believe GET is allowed cross-sites, but POST are not. http://en.wikipedia.org/wiki/JSONP would be a solution, if it's supported server-side (by WCF)

like image 30
Joakim Avatar answered Mar 05 '23 05:03

Joakim