0
votes

I have the following WCF web service:

I defined in IService1

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

and In Service1.svc

public string testSer()
{
return "test";
}

I am calling the web service, from C# winForm application like this:

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

The response returned is "Method Not Allowed". If I change the method type to "GET" it works.

If I tried to call the "POST" method from the browser the response returned is "Method Not Allowed"

My config file:

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

EDIT When I tried to test the service using WCF Test Client (That comes with Microsoft visual studio) I recieve the following error :

Error: Cannot obtain Metadata from https://www.example.net/cms/Service1.svc/TestSer If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: https://www.example.net/cms/Service1.svc/TestSer Metadata contains a reference that cannot be resolved: 'https://www.example.net/cms/Service1.svc/TestSer'. The content type application/json; charset=utf-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 34 bytes of the response were: '{"testSerResult":"test-1 service"}'.HTTP GET Error URI: https://www.example.net/cms/Service1.svc/TestSer There was an error downloading 'https://www.example.net/cms/Service1.svc/TestSer'. The request failed with HTTP status 405: Method Not Allowed.

3
Since you are just returning a string with the current OperationContract, you'd rather make a GET request than a POST request.S.Dav
Yes, however, what if I need to send a JSON string(about 500 chars or more) and return also a JSON string, will GET be applicable?Hassan Shouman
It actually depends on what you do with the data that is being sent. If the data is processed or/and persisted (saved into database) you should use POST. If the data is only used for query and fetching data, then you're good with GET.S.Dav
I need to save it in the database if I changed the operation contract to [OperationContract] [WebInvoke(Method = "*")] it works, but what does * means?Hassan Shouman
It means that specific operation is allowing all HTTP request methods (GET, POST, DELETE; OPTIONS ....)S.Dav

3 Answers

0
votes

change webconfig like the code below

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

Decorate your Operation contract with

[OperationContract]
[WebInvoke(Method = "POST")]

And in your Web Config should be like this:

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

This is your data returned from the post endpoint:

enter image description here

0
votes

First thanks you all and especially for @jalison-evora for his help.

The error was due to NGinX configuration.

Please check this link

WCF Service Method Not Allowed When Using WebsiteName