简体   繁体   中英

HTTP Bad Request (400) Error with a WCF Service with Multiple Endpoints

I have written a WCF service with the following configuration:

<system.serviceModel>
  <services>
     <service name="SyncService" behaviorConfiguration="SyncServiceBehavior">
        <endpoint name="DataBinding" address="/DataBinding" binding="wsHttpBinding" contract="ISyncService">
              <identity>
                <dns value="localhost"/>
              </identity>
        </endpoint>
        <endpoint name="FileBinding" address="/FileBinding" binding="basicHttpBinding" bindingConfiguration="httpLargeMessageStream" contract="ISyncService">
              <identity>
                <dns value="localhost"/>
              </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <bindings>
          <basicHttpBinding>
            <binding name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" transferMode="Streamed" messageEncoding="Mtom" />
          </basicHttpBinding>
        </bindings>
        <behaviors>
          <serviceBehaviors>
            <behavior name="SyncServiceBehavior">
              <serviceMetadata httpGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="true"/>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>

On the client, I am building the proxy to consume the service dynamically:

private static RemoteFileProviderProxy CreateDynamicFileProxy(string endPointAddress)
        {
            //endPointAddress = http://localhost/SyncService.svc/FileBinding
            BasicHttpBinding binding = new BasicHttpBinding();

            binding.Name = "httpLargeMessageStream";
            binding.TransferMode = TransferMode.Streamed;
            binding.MessageEncoding = WSMessageEncoding.Mtom;
            binding.MaxReceivedMessageSize = int.MaxValue;

            ServiceEndpoint endPoint = new ServiceEndpoint(ContractDescription.GetContract (typeof(ISyncService)), binding, new EndpointAddress(endPointAddress));

            endPoint.Name = "FileBinding";

            ChannelFactory<ISyncService> channelFactory = new ChannelFactory<ISyncService>(endPoint);

            return new RemoteFileProviderProxy((ISyncService)channelFactory.CreateChannel());
        }

Initially, I had only the DataBinding endpoint, residing at the default address (not the DataBinding address it currently does) and I used the same client side code to consume that service endpoint and everything worked correctly. When I added the FileBinding endpoint and moved the DataBinding endpoint to its new location http://localhost/SyncService.svc/DataBinding I was no longer able to connect to either endpoint and instead received a "Bad Request (400)" the first time it was used.

Looking at the Service Trace Viewer, I see the following additional information about the System.Xml.XmlException being thrown:

There is a problem with the XML that was received from the network. See inner exception for more details.

Inner Exception:

The body of the message cannot be read because it is empty.

Stack Trace:

at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

When I view SyncService.svc in a browser, I get the "You have created a service" page and everything looks correct. The wsdl also looks appropriate. When I go to http://localhost/SyncService.svc/FileBinding a blank page is loaded (in contrast to an error page when I go to something like http://localhost/SyncService.svc/XXX ).

I have waded through a number of similar issues, to no avail, including:

HTTP Bad Request error when requesting a WCF service contract

Large WCF web service request failing with (400) HTTP Bad Request

Anyone have any thoughts or suggestions on how to resolve this?

As it turns out, this issue was caused not by the contract object but by an object it REFERENCED not being found. In my case, I had forgot to install all of the required Microsoft Sync Framework pieces on the server.

I guess the moral of the story is that this error is pretty misleading and applies to all child objects as well!

Can you try to inspect the request being sent to the server using tools like Fiddler. There must be something in the soap envelop that is causing the issue.

Also try to send small data initially to make sure your service is accessible and then try to larger data so that you can narrow down on where the problem is.

Have you implemented the async pattern or is your web service marked as Async=True.

Would be helpful if you can post your service as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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