none
Remote server returns 405 error when calling a webHttp service from within another webHttp service RRS feed

  • Question

  • I've created two WCF 3.5 RESTful web services, service A and service B. Service A uses a WCF client for B to obtain a stream via its GetB method. Whenever the client GetB method is called, the request fails. If the same method is called from a console app, it succeeds. Each service is running from a VS2005 web server, under localhost, but with different port numbers.

     

    This is the interface of service A.

    Code Snippet

    [ServiceContract(Namespace = NS.Contract)]

    public interface IServiceA

    {

    [OperationContract]

    [WebGet(UriTemplate = "/serviceA/{id}")]

    Stream GetA(string id);

    ...

     

    This is the interface of service B.

    Code Snippet

    [ServiceContract(Namespace = NS.Contract)]

    public interface IServiceB

    {

    [OperationContract]

    [WebGet(UriTemplate = "{id1}/{id2}/{id3}")]

    Stream GetB(string id1, string id2, string id3);

     

     

    This is the web.config that is giving me grief.

    Code Snippet

    <?xml version="1.0"?>

    <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

    <system.web>

    <compilation debug="true"/>

    </system.web>

    <system.diagnostics>

    <sources>

    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">

    <listeners>

    <add name="Default" type="System.Diagnostics.DefaultTraceListener"/>

    <add name="Messages" initializeData="logs\Messages.xml" type="System.Diagnostics.XmlWriterTraceListener"/>

    </listeners>

    </source>

    <source name="System.ServiceModel" switchValue="Verbose,ActivityTracing" propagateActivity="true">

    <listeners>

    <add name="Default" type="System.Diagnostics.DefaultTraceListener"/>

    <add name="Activity" initializeData="logs\Activity.xml" type="System.Diagnostics.XmlWriterTraceListener"/>

    </listeners>

    </source>

    </sources>

    <trace autoflush="true" />

    </system.diagnostics>

    <system.serviceModel>

    <diagnostics>

    <messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" />

    </diagnostics>

    <client>

    <endpoint

    name="ClientB"

    binding="webHttpBinding"

    bindingConfiguration="ClientBBindingConfig"

    behaviorConfiguration="ClientBBehaviourConfig"

    contract="XX.Service.Interfaces.IServiceB">

    </endpoint>

    </client>

    <behaviors>

    <endpointBehaviors>

    <behavior name="ClientBBehaviourConfig">

    <webHttp />

    </behavior>

    <behavior name="ServiceAEndpointBehaviourConfig">

    <webHttp />

    </behavior>

    </endpointBehaviors>

    <serviceBehaviors>

    <behavior name="ServiceABehaviourConfig">

    <serviceDebug includeExceptionDetailInFaults="true" />

    <serviceMetadata httpGetEnabled="true" />

    </behavior>

    </serviceBehaviors>

    </behaviors>

    <bindings>

    <webHttpBinding>

    <binding name="ServiceABindingConfig" />

    <binding name="ClientBBindingConfig" maxBufferSize="1048576" maxReceivedMessageSize="1048576" />

    </webHttpBinding>

    </bindings>

    <services>

    <service name="XXX.Service.ServiceA"

    behaviorConfiguration="ServiceABehaviourConfig">

    <endpoint

    binding="webHttpBinding"

    behaviorConfiguration="ServiceAEndpointBehaviourConfig"

    bindingConfiguration="ServiceABindingConfig"

    contract="XXX.Service.Interfaces.IServiceA" />

    </service>

    </services>

    </system.serviceModel>

    </configuration>

     

     

    The stack trace I get is:

    Code Snippet

    The remote server returned an unexpected response: (405) Method Not Allowed.
    System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (405) Method Not Allowed. ---> System.Net.WebException: The remote server returned an error: (405) Method Not Allowed.
       at System.Net.HttpWebRequest.GetResponse()
       at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       --- End of inner exception stack trace ---

    Server stack trace:
       at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException)
       at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at XXX.GetB(String id1, String id2, String id3)

     

     

    Adding message and activity logging shows the error as a HttpChannelRequestAborted, with the description: "Failed to send request message over HTTP."

     

    Any ideas why this is happening?

    Tuesday, April 15, 2008 11:18 AM

Answers

All replies

  • You'll get the 405 error when you send a GET request to an endpoint / operation which expects POST requests (or vice-versa). What is the address that you're using for the request to the service B (in other words, how are you creating the client for service B in the code of service A)?

     

    Can you also enable tracing on the service B to see which message is arriving there? The request should be a HTTP GET request sent to <Service B base address>/<id1>/<id2>/<id3>.

    Tuesday, April 15, 2008 9:00 PM
  • Thanks for your response. I'll try enabling tracing in Service B, but I suspect that the request is not even leaving ClientB / ServiceA. My reason for thinking that is that when I run ClientB with the same configuration, but from a console app (no ServiceA config or instance), the Get method works. I'll confirm this via a trace though.

     

    The client is constructed with the name of the client endpoint config, i.e. ClientB and its root Uri, e.g. http://localhost:8000/Service.svc.

    Tuesday, April 15, 2008 9:31 PM
  • The client endpoint in config doesn't have the address attribute; what happens if you add it?

     

    Tuesday, April 15, 2008 9:46 PM
  • The point at which the client's address is set makes no difference (whether it be in the config file, or via the client's constructor).

     

    Adding WCF tracing to service B uncovered strange behaviour though:

     

    When client B runs from within Service A, the request arrives at Service B, but is not matched to the GetB method. Instead it is matched to operation ''. The message log trace shows the HttpRequest method to be a Post, instead of a Get. Two exceptions are then thrown:

    • "A property with the name 'UriMatched' already exists."
    • Followed by, "The HTTP method 'POST' of the incoming request (with URI 'http://localhost:8000/Service.svc/12/34/5678910') is not allowed."

    Yet when I execute the same client B code from within a console application (no Service A present), the request is correctly matched to operation 'GetB', is logged as a GET and is processed correctly!

     

    I'm currently working around this by using a simple HttpRequest to access Service B, but this is not the ideal!

    Friday, April 18, 2008 11:26 AM
  • I have experienced the same behavior. My workaround was to set the HTTP method explicitly:

     

     

    Code Snippet

     

    SomeMethodResponseClass response = null;

     

    MyServiceClient client = new MyServiceClient();

     

    try
    {

        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {
            WebOperationContext.Current.OutgoingRequest.Method = "GET";

            response = client.SomeMethod();
        }

        client.Close();

    }
    catch (CommunicationException)
    {
        client.Abort();
    }
    catch (TimeoutException)
    {
        client.Abort();
    }

     

    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:30 AM
    • Unmarked as answer by lyndsayp Wednesday, October 15, 2008 11:31 AM
    • Proposed as answer by abhishekfromindia Tuesday, April 20, 2010 12:22 PM
    Thursday, July 3, 2008 2:11 PM
  • I am having the same problem, but WebOperationContext.Current.OutgoingRequest.Method = "GET"; did not work to me.

    Any suggestions????
    Friday, August 1, 2008 10:24 PM
  • These symptoms also occur if the request URL has something that IIS interprets as a file extension, ahead of the service.svc. This causes IIS to try and find a handler for the first file extension, instead of the .svc one.
    Thursday, October 16, 2008 6:54 AM
  • Thanks GVAS!  Explicitly setting the method as GET work perfectly for me.  I would still like to know why this behavior exists, but I will save that for another day.
    Friday, February 6, 2009 7:49 PM
  • Sorry how do you explicitly set method as GET? Do you mean on service's web.config? Or in AJAX clientside call?

    I tried on browser: http://localhost/xxxxxWeb/xxxxxService.svc/xxxxxMethodName

    Getting "Method not allowed".

    I see no place in web.config/WCF Config Editor where you can specify a method as GET method. Thanks
    Friday, May 22, 2009 12:52 AM
    • Marked as answer by lyndsayp Wednesday, June 3, 2009 1:46 PM
    Wednesday, June 3, 2009 1:46 PM
  • I'am facing the same issue in a service calling service scenario.

    When I try to hit a Rest service end point from console client it works properly, but when I try to hit rest endpoint from my wcf service it throws the same exception.

    I'm using same configuration in both the cases and if I use the configuration on wcf service in console application then also it works, that means there is no problem with configuration.

    Can anyone help me with this.

    I didn't usderstand much in this post  http://tdoks.blogspot.com/2009/06/calling-one-wcf-service-from-another.html.

    ~Abhishek Singh

    Tuesday, April 20, 2010 6:18 AM
  • I'am facing the same issue in a service calling service scenario.

    When I try to hit a Rest service end point from console client it works properly, but when I try to hit rest endpoint from my wcf service it throws the same exception.

    I'm using same configuration in both the cases and if I use the configuration on wcf service in console application then also it works, that means there is no problem with configuration.

    Can anyone help me with this.

    I didn't usderstand much in this post  http://tdoks.blogspot.com/2009/06/calling-one-wcf-service-from-another.html.

    ~Abhishek Singh

    Tuesday, April 20, 2010 6:18 AM
  • I have experienced the same behavior. My workaround was to set the HTTP method explicitly:

     

     

    Code Snippet

     

    SomeMethodResponseClass response = null;

     

    MyServiceClient client = new MyServiceClient();

     

    try
    {

        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {
            WebOperationContext.Current.OutgoingRequest.Method = "GET";

            response = client.SomeMethod();
        }

        client.Close();

    }
    catch (CommunicationException)
    {
        client.Abort();
    }
    catch (TimeoutException)
    {
        client.Abort();
    }

     

     

     


    Works wonders for me. Thanks Man. :)
    Tuesday, April 20, 2010 12:22 PM
  • Dont just use WebOperationContext.Current.OutgoingRequest.Method = "GET"; try the full solution

      using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {
            WebOperationContext.Current.OutgoingRequest.Method = "GET";

            response = client.SomeMethod();
        }

    Pass your channel object to 'OperationContextScope' cast it appropriately.

    Should work.

     

    ~Abhishek Singh    

    Tuesday, April 20, 2010 12:24 PM