简体   繁体   English

WCF 错误:不允许使用 405 方法

[英]WCF error : 405 Method Not Allowed

Going nuts with this issue.为这个问题发疯。 I have a solution with 2 projects, one of them is a plain old html with jquery ajax call while the other is a WCF service.我有一个包含 2 个项目的解决方案,其中一个是带有 jquery ajax 调用的普通旧 html,而另一个是 WCF 服务。 The html page will issue a ajax call to the WCF service to get a json string and use it for display purpose. html 页面将向 WCF 服务发出 ajax 调用以获取 json 字符串并将其用于显示目的。

Now the issue is whenever i run in debug mode, both the html page and the WCF will be started with different port.现在的问题是,每当我在调试模式下运行时,html 页面和 WCF 都将以不同的端口启动。 And this has created a cross-origin issue for me when i perform testing (ie getting a 405 Method Not Allowed error with the calling type = OPTIONS in Firefox).这在我执行测试时为我创建了一个跨域问题(即在 Firefox 中调用 type = OPTIONS 时出现 405 Method Not Allowed 错误)。 I'd triple check the call method on my ajax script and the WCF service is the same (GET).我会三次检查我的 ajax 脚本上的调用方法,并且 WCF 服务是相同的 (GET)。

I'd search google but found that either i have to install a extension or perform some configuration on IIS, which i found cumbersome since what i'm doing is something simple.我会搜索谷歌,但发现我必须安装扩展或在 IIS 上执行一些配置,我发现这很麻烦,因为我正在做的事情很简单。 Following one example, I'd add in the following configuration in my web.config but it didn't work:按照一个示例,我将在我的 web.config 中添加以下配置,但它不起作用:

    <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="MobileService.webHttpBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="MyServiceBehavior">
          <serviceMetadata httpGetEnabled="true"  />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="MobileService.SimpleMemberInfo" behaviorConfiguration="MyServiceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="MobileService.IMemberInfo" bindingConfiguration="crossDomain" behaviorConfiguration="MobileService.webHttpBehavior">
        </endpoint>
      </service>
    </services>
  </system.serviceModel>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
    </system.webServer>

Any one has any idea to get rid of this annoying issue?任何人有任何想法摆脱这个恼人的问题?

EDIT: Just to add, I'm running the debug with IIS Express that comes together with the VS Studio 2012编辑:补充一下,我正在使用 VS Studio 2012 附带的 IIS Express 运行调试

Add in WCF Code and Updated web.config添加 WCF 代码并更新 web.config

[ServiceContract]
public interface IMemberInfo
{
    [WebInvoke(Method = "GET",
           BodyStyle = WebMessageBodyStyle.Wrapped,
           ResponseFormat = WebMessageFormat.Json
    )]
    [OperationContract]
    string GetMemberInfoById();
    // TODO: Add your service operations here
}

My Script:我的脚本:

$(document).ready(function () {
    $.ajax("http://localhost:32972/SimpleMemberInfo.svc/GetMemberInfoById", {
        cache: false,
        beforeSend: function (xhr) {
            $.mobile.showPageLoadingMsg();
        },
        complete: function () {
            $.mobile.hidePageLoadingMsg();
        },
        contentType: 'application/json',
        dataType: 'json',
        type: 'GET',
        error: function () {
            alert('Something awful happened');
        },
        success: function (data) {
            var s = "";

            s += "<li>" + data + "</li>";
            $("#myList").html(s);

        }
    });
});

You need to use JSONP for a cross-domain call to get round the browser restrictions, and to update your web.config with crossDomainScriptAccessEnabled set to true to get round server ones.您需要使用 JSONP 进行跨域调用以绕过浏览器限制,并更新您的 web.config 并将crossDomainScriptAccessEnabled设置为 true 以绕过服务器限制。 There's a good example in the answer here: how to avoid cross domain policy in jquery ajax for consuming wcf service?这里的答案中有一个很好的例子: how to avoid cross domain policy in jquery ajax for consuming wcf service?

You may also have a problem with GET requests. GET 请求也可能有问题。 Try the fixes outlined here: Making a WCF Web Service work with GET requests尝试此处列出的修复: Making a WCF Web Service work with GET requests

Altogether, you want a web.config that looks something like this:总之,您需要一个如下所示的 web.config:

<bindings>
  <webHttpBinding>
    <binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
  </webHttpBinding>
</bindings>
<behaviors>
  <endpointBehavior>
    <behavior name="restBehavior">
      <webHttp />
    </behavior>
  </endpointBehavior>
  <serviceBehavior>         
     <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true"  />
        <serviceDebug includeExceptionDetailInFaults="true"/>
     </behavior>
  </serviceBehavior>
</behaviors>
<services>
  <service name="..." behaviorConfiguration="MyServiceBehavior">
    <endpoint address="" binding="webHttpBinding" bindingConfiguration="crossDomain" 
              contract="..." behaviorConfigurations="restBehavior" /> 
  </service>
</services>

(Note that both the service and the endpoint have behaviours attached, allowing webHttp calls and httpGet calls respectively, and that the binding has crossDomain access explicitly enabled). (请注意,服务和端点都附加了行为,分别允许 webHttp 调用和 httpGet 调用,并且绑定明确启用了跨域访问)。

... a service method decorated like this: ...这样装饰的服务方法:

[ServiceContract]
public interface IMyService
{
    [WebGet] // Required Attribute to allow GET
    [OperationContract]
    string MyMethod(string MyParam);
}

... and a client call using JSONP: ...和使用 JSONP 的客户端调用:

<script type="text/javascript">
$(document).ready(function() {
    var url =  "...";
    $.getJSON(url + "?callback=?", null, function(result) { // Note crucial ?callback=?
       // Process result
    });
});
</script>

However its an old thread, but I would like add my comment about the problems I faced and the solution I got for working of CORS.然而,它是一个旧线程,但我想添加我对我遇到的问题以及我为 CORS 工作获得的解决方案的评论。 I am developing a web service in the following environment:我正在以下环境中开发 Web 服务:

  1. WCF web service. WCF 网络服务。
  2. .NET 3.5 framework. .NET 3.5 框架。
  3. Added wcf web service into existing asp.net website.将 wcf web 服务添加到现有的 asp.net 网站中。
  4. Visual Studio 2008视觉工作室 2008

Most of the people mentioned about adding the crossDomainScriptAccessEnabled attribute in tag under <webHttpBinding> in web.config.大多数人提到在 web.config 中<webHttpBinding>下的标记中添加crossDomainScriptAccessEnabled属性。 I am not sure this works or not but its not available in 3.5 version, so I had no choice.我不确定这是否有效,但它在 3.5 版本中不可用,所以我别无选择。 I also found that adding the following tags in web.config will work...我还发现在 web.config 中添加以下标签会起作用...

<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET" /> <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" /> </customHeaders> </httpProtocol>

but no luck...kept getting 405 method not allowed errors但没有运气......不断得到 405 方法不允许的错误

After struggling a lot with these options I found another solution to add these headers in global.asax file dynamically as per the given below...在与这些选项苦苦挣扎之后,我找到了另一种解决方案,按照下面给出的动态将这些标头添加到 global.asax 文件中......

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, Authorization");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

And remove the from web.config.并从 web.config 中删除。 Publish the website and continue to client side jquery/ajax...and you will get the data from api calls.发布网站并继续客户端 jquery/ajax...您将从 api 调用中获取数据。 Good Luck!祝你好运!

What worked for me was enabling WCF related features of IIS:对我有用的是启用 IIS 的 WCF 相关功能: 在此处输入图像描述

Just wanted to append some issues with the CORS rework at the bottom - The problem with it is that if your input does not support the GET and POST method, the OPTIONS request is not actually returning the correct allowed headers.只是想在底部附加一些与 CORS 返工有关的问题 - 它的问题是,如果您的输入不支持 GET 和 POST 方法,则 OPTIONS 请求实际上不会返回正确的允许标头。 It really isn't looking at which methods are actually allowed on the WCF endpoint - its just artificially saying "GET, POST" are allowed for every single endpoint in the application when a client performs an OPTIONS request (which is really the client asking what is supported).它实际上并没有查看 WCF 端点上实际允许哪些方法——它只是人为地说当客户端执行 OPTIONS 请求时应用程序中的每个端点都允许“GET、POST”(这实际上是客户端询问什么支持)。

This is probably OK, if you aren't really relying on the information in the OPTIONS method to return you a valid list of methods (as is the case with some CORS requests) - but if you are, you will need to do something like the solution on this question: How to handle Ajax JQUERY POST request with WCF self-host这可能没问题,如果你不是真的依赖 OPTIONS 方法中的信息来返回你一个有效的方法列表(就像一些 CORS 请求的情况一样) - 但如果你是,你将需要做一些事情这个问题的解决方案: How to handle Ajax JQUERY POST request with WCF self-host

Basically, each endpoint should implement:基本上,每个端点都应该实现:

Webinvoke(Method="OPTIONS", UriTemplate="")

and call an appropriate method which loads the proper headers to the response (including the proper "Access-Control-Allow-Method" list for that endpoint) to the caller.并调用适当的方法,将适当的标头加载到调用方的响应(包括该端点的适当的“Access-Control-Allow-Method”列表)。 It kind of sucks that hosted WCF endpoints don't do this for us automatically, but this is a workaround that allows finer control over the endpoint.托管 WCF 端点不会自动为我们执行此操作有点糟糕,但这是一种允许更好地控制端点的解决方法。 In that solution the proper response headers are loaded at the endpoint implementation:在该解决方案中,正确的响应标头在端点实现中加载:

public void GetOptions()
    {
        // The data loaded in these headers should match whatever it is you support on the endpoint
        // for your application. 
        // For Origin: The "*" should really be a list of valid cross site domains for better security
        // For Methods: The list should be the list of support methods for the endpoint
        // For Allowed Headers: The list should be the supported header for your application

        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
    }

try to use.尝试使用。 WebInvoke(Method = "POST") instead of WebInvoke(Method = "GET") WebInvoke(Method = "POST")而不是WebInvoke(Method = "GET")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM