jQuery .ajax() POST Request throws 405 (Method Not Allowed) on RESTful WCF
Asked Answered
H

6

39

I am sending a post request to a RESTFUL WCF service application. I am able to successfully send a POST request through Fiddler.

However when I do this through the jQuery Ajax method the function returns the following to the Chrome Developer Console:

OPTIONS http://www.example.com/testservice/service1.svc/GetData 405 (Method Not Allowed) jquery.min.js:6

But then a second after logs:

Object {d: "You entered 10"} testpost.html:16

What this tells me is that jQuery is sending a OPTIONS request, which fails, and then sending a POST request which returns the expected data.

My jQuery Code:

$.ajax() {        
type: "POST", //GET or POST or PUT or DELETE verb 
    url: "http://www.example.com/testservice/service1.svc/GetData", // Location of the service      
    data: '{"value":"10"}', //Data sent to server
    contentType:"application/json",
    dataType: "json", //Expected data format from server    
    processdata: false,
    success: function (msg) {//On Successfull service call   
        console.log(msg);
    },
    error: function (xhr) { console.log(xhr.responseText); } // When Service call fails             
});

I am using jQuery version 2.0.2.

Any help on why this error is occurring would be a great help.

Homopterous answered 27/6, 2013 at 1:16 Comment(0)
W
71

Your code is actually attempting to make a Cross-domain (CORS) request, not an ordinary POST.

That is: Modern browsers will only allow Ajax calls to services in the same domain as the HTML page.

Example: A page in http://www.example.com/myPage.html can only directly request services that are in http://www.example.com, like http://www.example.com/testservice/etc. If the service is in other domain, the browser won't make the direct call (as you'd expect). Instead, it will try to make a CORS request.

To put it shortly, to perform a CORS request, your browser:

  • Will first send an OPTION request to the target URL
  • And then only if the server response to that OPTION contains the adequate headers (Access-Control-Allow-Origin is one of them) to allow the CORS request, the browse will perform the call (almost exactly the way it would if the HTML page was at the same domain).
    • If the expected headers don't come, the browser simply gives up (like it did to you).

How to solve it? The simplest way is to enable CORS (enable the necessary headers) on the server.

If you don't have server-side access to it, you can mirror the web service from somewhere else, and then enable CORS there.

Wheels answered 27/6, 2013 at 1:22 Comment(3)
Okay it makes sense now. Thank you very much.Homopterous
would't jsonp also do the job - as long as it's supported by the server?Laparotomy
@Sumit If all you do is GET, then JSONP could be an option. Still, JSONP is more of a workaround than a solution, since you can do very limited things with it. You cant do POSTs (or PUTs etc.) through JSONP.Wheels
P
6

You must add this code in global.aspx:

 protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }
Phoebe answered 23/3, 2015 at 14:50 Comment(0)
M
4

You can create the required headers in a filter too.

@WebFilter(urlPatterns="/rest/*")
public class AllowAccessFilter implements Filter {
    @Override
    public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain chain) throws IOException, ServletException {
        System.out.println("in AllowAccessFilter.doFilter");
        HttpServletRequest request = (HttpServletRequest)sRequest;
        HttpServletResponse response = (HttpServletResponse)sResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type"); 
        chain.doFilter(request, response);
    }
    ...
}
Moten answered 7/11, 2014 at 14:15 Comment(0)
K
1

This Worked for me

In Web.config add below script

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" >
    <remove name="WebDAVModule"/>
  </modules>
  <handlers accessPolicy="Read, Execute, Script">
    <remove name="WebDAV" />
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <remove name="TRACEVerbHandler" />

    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
         verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
         type="System.Web.Handlers.TransferRequestHandler"
         preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
 </system.webServer>

Also in RouteConfig.cs

Change

settings.AutoRedirectMode = RedirectMode.Permanent;

To

settings.AutoRedirectMode = RedirectMode.Off;

Hope it helps you or some one :)

Keelia answered 21/1, 2021 at 14:20 Comment(0)
Q
0

For same error code i had quite different reason, I'm sharing here to help

I had web api action like below

public IHttpActionResult GetBooks (int id)

I changed the method to accept two parameters category and author so i changed the parameters as below, i also put the attribute [Httppost]

public IHttpActionResult GetBooks (int category, int author)

I also changed ajax options like below and at this point i start getting error 405 method not allowed

var options = {
    url: '/api/books/GetBooks',
    type: 'POST',
    dataType: 'json',
    cache: false,
    traditional: true, 
    data: {
        category: 1,
        author: 15
    }
}

When i created class for web api action parameters like below error was gone

public class BookParam
{
    public int Category { get; set; }
    public int Author { get; set; }
}
public IHttpActionResult GetBooks (BookParam param)
Quito answered 27/2, 2020 at 19:54 Comment(0)
F
0

for VScode users - are you using the live-server through vs code? access normally :)

jQuery .ajax() does not work in -

http://127.0.0.1:5500/index.html

it works in!! -

http://192.168.29.10/index.php
Foe answered 9/1, 2023 at 3:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.