WCF POST 方法返回“方法不允许”

Posted

技术标签:

【中文标题】WCF POST 方法返回“方法不允许”【英文标题】:WCF POST Method returning "Method not allowed" 【发布时间】:2018-07-21 17:55:51 【问题描述】:

我有以下 WCF 网络服务:

我在IService1中定义

    [OperationContract]
    [WebInvoke(Method = "POST")]
    string testSer();

在 Service1.svc 中

public string testSer()

return "test";

我正在从 C# winForm 应用程序调用 Web 服务,如下所示:

var client = new RestClient("http://localhost/webservices/Service1.svc/");


            var request = new RestRequest("testSer", Method.POST);
            IRestResponse response = client.Execute(request);
            var content = response.Content; // raw content as string
            MessageBox.Show(content);

返回的响应是“方法不允许”。如果我将方法类型更改为“GET”,它就可以工作。

如果我尝试从浏览器调用“POST”方法,返回的响应是“方法不允许”

我的配置文件:

    <?xml version="1.0"?>
<configuration>
    <connectionStrings>
      <remove name="LocalSqlServer" />
      <add name="LocalSqlServer" connectionString="Data Source=myserver;Initial Catalog=db;User ID=sa;Password=111;" />
    </connectionStrings>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5"/>
    <httpRuntime targetFramework="4.5"/>
    <httpModules>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/>
    </httpModules>
  </system.web>
  <system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
    <services>

      <service name="WcfService3.Service1">
        <endpoint address="mex" binding="mexHttpBinding"  contract="IMetadataExchange" />  
        <endpoint address="" behaviorConfiguration="restfulBehavior" binding="webHttpBinding"
        bindingConfiguration="jsonp" name="jsonService" contract="WcfService3.IService1" />
        <endpoint address="soap" binding="basicHttpBinding" name="soapService" contract="WcfService3.IService1" />

      </service>
    </services> 
  <bindings>
      <basicHttpBinding>
        <binding name="soapService" />
      </basicHttpBinding>
      <webHttpBinding>
        <binding name="jsonp" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>

    <behaviors>
      <endpointBehaviors>
        <behavior name="restfulBehavior">
          <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
          <!--<enableWebScript />-->
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"  policyVersion="Policy15" />/>
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

 <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping> 

  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="ApplicationInsightsWebTracking"/>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"
        preCondition="managedHandler"/>
    </modules>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
    <validation validateIntegratedModeConfiguration="false"/>

    <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>
  </system.webServer>

</configuration>

编辑 当我尝试使用 WCF 测试客户端(Microsoft Visual Studio 附带)测试服务时,我收到以下错误:

错误:无法从https://www.example.net/cms/Service1.svc/TestSer 获取元数据如果这是您有权访问的 Windows (R) Communication Foundation 服务,请检查您是否已在指定地址启用元数据发布。有关启用元数据发布的帮助,请参阅位于 http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange 错误 URI:https://www.example.net/cms/Service1.svc/TestSer 元数据包含无法解析的引用的 MSDN 文档:“https://www.example.net/cms/Service1.svc/TestSer”。内容类型application/json;响应消息的 charset=utf-8 与绑定的内容类型不匹配(application/soap+xml;charset=utf-8)。如果使用自定义编码器,请确保正确实现 IsContentTypeSupported 方法。响应的前 34 个字节是:'"testSerResult":"test-1 service"'。HTTP GET 错误 URI:https://www.example.net/cms/Service1.svc/TestSer 下载 'https://www.example.net/cms/Service1.svc/TestSer' 时出错。请求失败,HTTP 状态为 405: Method Not Allowed。

【问题讨论】:

由于您只是返回一个带有当前 OperationContract 的字符串,因此您宁愿发出 GET 请求而不是 POST 请求。 是的,但是,如果我需要发送一个 JSON 字符串(大约 500 个字符或更多)并返回一个 JSON 字符串,GET 是否适用? 这实际上取决于您如何处理正在发送的数据。如果数据被处理或/和持久化(保存到数据库中),您应该使用 POST。如果数据仅用于查询和获取数据,那么您可以使用 GET。 如果我将操作合同更改为 [OperationContract] [WebInvoke(Method = "*")] 需要保存在数据库中,它可以工作,但是 * 是什么意思? 表示具体操作是允许所有HTTP请求方法(GET、POST、DELETE;OPTIONS ....) 【参考方案1】:

像下面的代码一样更改webconfig

<system.webServer>
<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<modules>
<remove name="WebDAVModule" />
</modules>
 <security>
    <requestFiltering>
        <verbs allowUnlisted="false">
            <add verb="GET" allowed="true" />
            <add verb="POST" allowed="true" />
            <add verb="DELETE" allowed="true" />
            <add verb="PUT" allowed="true" />
        </verbs>
    </requestFiltering>
  </security>
</system.webServer>

【讨论】:

服务器现在返回:已检测到不适用于集成托管管道模式的 ASP.NET 设置。请注意,我正在从 winForm App 调用 Web 服务【参考方案2】:

装饰您的运营合同
[OperationContract]
[WebInvoke(Method = "POST")]

在你的 Web Config 中应该是这样的:

   <system.serviceModel>
    <client />
    <behaviors>
      <endpointBehaviors>
        <behavior name="restfulBehavior">
          <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
          <!--<enableWebScript />-->
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="soapService" />
      </basicHttpBinding>
      <webHttpBinding>
        <binding name="jsonp" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="WcfService3.Service1">
        <endpoint address="" behaviorConfiguration="restfulBehavior" binding="webHttpBinding" bindingConfiguration="jsonp" name="jsonService" contract="WcfService3.IService1" />
        <endpoint address="mex" binding="mexHttpBinding" name="metadata" contract="IMetadataExchange" />
      </service>
    </services> 
  </system.serviceModel>

这是您从 post 端点返回的数据:

【讨论】:

@HassanShouman 没用?您确定您使用 webinvoke 装饰了操作合同并检查了配置吗?我复制了相同的环境、相同的服务及其工作。 你好没有没有工作!是的,我装饰了操作合同。我在问题中发布了我的配置文件 @HassanShouman 我在您的代码中找不到任何问题。我认为您正在尝试从浏览器访问 POST 方法。无法从浏览器访问 POST 方法端点,因为 POST 方法有一个 GET 方法不需要也没有的主体。 @HassanShouman 你看到我上次更新你的代码了吗? 让我们continue this discussion in chat.【参考方案3】:

首先感谢大家,尤其感谢@jalison-evora 的帮助。

错误是由于 nginx 配置造成的。

请检查此链接

WCF Service Method Not Allowed When Using WebsiteName

【讨论】:

以上是关于WCF POST 方法返回“方法不允许”的主要内容,如果未能解决你的问题,请参考以下文章

WCF REST 服务返回 405:jQuery AJAX GET 不允许的方法

Wcf 中的 WebInvoke POST“方法不允许”

wcf REST 服务和 JQuery Ajax Post:方法不允许

自托管 WCF REST 服务 JSON POST 方法不允许

WebApi Post 方法总是返回“请求的资源不支持 http 方法 'GET'。”状态:405 方法不允许

WCF RESTful 应用程序 PUT、POST、DELETE 收到相同的错误:“该方法不允许。”