jQuery .ajax()POST请求在RESTful WCF上抛出405(方法不允许)

时间:2013-06-27 01:16:25

标签: jquery web-services rest post wcf-rest

我正在向RESTFUL WCF服务应用程序发送一个post请求。我能够通过Fiddler成功发送POST请求。

但是当我通过jQuery Ajax方法执行此操作时,该函数会将以下内容返回到Chrome Developer Console:

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

然后是日志后的第二个:

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

这告诉我的是,jQuery正在发送 OPTIONS 请求,该请求失败,然后发送返回预期数据的POST请求。

我的jQuery代码:

$.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             
});

我使用的是jQuery 2.0.2版。

任何有关此错误发生原因的帮助都会有很大帮助。

5 个答案:

答案 0 :(得分:58)

您的代码实际上是在尝试发出Cross-domain (CORS)请求,而不是普通的POST

即:现代浏览器只允许Ajax调用相同域中的服务作为HTML页面。

示例: http://www.example.com/myPage.html中的页面只能直接请求http://www.example.com中的服务,例如http://www.example.com/testservice/etc。如果该服务位于其他域中,则浏览器不会进行直接调用(如您所期望的那样)。相反,它会尝试发出CORS请求。

简而言之,要执行CORS请求,请使用浏览器:

  • 首先会向目标网址发送OPTION个请求
  • 然后仅当服务器对该OPTION的响应包含允许CORS请求的adequate headers (Access-Control-Allow-Origin is one of them)时,浏览才会执行调用(几乎完全按照它的方式执行如果HTML页面位于同一个域中)。
    • 如果没有预期的标题,浏览器就会放弃(就像它对你做的那样)。

如何解决?最简单的方法是在服务器上启用CORS(启用必要的标头)。

如果您没有服务器端访问权限,则可以从其他地方镜像Web服务,然后在那里启用CORS。

答案 1 :(得分:5)

您必须在 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();
            }
        }

答案 2 :(得分:4)

您也可以在过滤器中创建所需的标题。

@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);
    }
    ...
}

答案 3 :(得分:0)

由于相同的错误代码,我有完全不同的原因,我在这里分享帮助

我有如下所示的Web api操作

public IHttpActionResult GetBooks (int id)

我更改了接受两个参数类别和作者的方法,因此我按如下所示更改了参数,我还放置了[Httppost]属性

public IHttpActionResult GetBooks (int category, int author)

我还更改了如下所示的ajax选项,这时我开始收到错误405方法不允许

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

当我为Web api操作参数创建类时,如下错误消失了

public class BookParam
{
    public int Category { get; set; }
    public int Author { get; set; }
}
public IHttpActionResult GetBooks (BookParam param)

答案 4 :(得分:0)

这对我有用

Web.config 中添加以下脚本

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

也在RouteConfig.cs

改变

settings.AutoRedirectMode = RedirectMode.Permanent;

settings.AutoRedirectMode = RedirectMode.Off;

希望它对你或某人有帮助:)