Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF service returns HTTP 400, but only when Content-Type is set to "text/xml" or "text/json"

Tags:

c#

iis

wcf

I'm truly stumped. I've tried every tool imaginable, checked every resource I can, and still can't make sense of this.

I have a WCF service designed to handle plain old XML requests in a proprietary XML format (this is an old ASMX conversion). I've setup the service using the WCF 3.5 to accept plain HTTP POST requests, and it works beautifully as long as the Content-Type in the request header is not set to "text/xml" (or any other XML or JSON type, such as "text/json" or "application/json").

In other words, if I set the content type of the request to "text" or "text/plain" or even "whatever", the service works as expected. However, when I set the content type to "text/xml", the service fails with an HTTP 400 Bad Request.

And I've failed to find a way to debug the failure to get some more information. The actual service method is never called, and implementing IErrorHandler didn't catch an error either. I'm suspecting something is wrong with my WCF config or with my IIS 7 setup, but I'm absolutely clueless as to what is going on.

Here's my service contract:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;

namespace App.api.v_1_1
{
    [ServiceContract]
    public interface IPlainXmlWebServiceViaHttpPost
 {
        [WebInvoke(UriTemplate = "", BodyStyle = WebMessageBodyStyle.Bare, Method = "POST", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
        [OperationContract]
  Stream Process(Stream xml);
 }
}

And here's my service implementation:

using System.IO;
using System.ServiceModel.Activation;
using App.api.v_1_0;
using System.ServiceModel;

namespace App.api.v_1_1
{
    [ServiceBehavior(Namespace = Constants.WebServiceNamespace)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class PlainXmlWebServiceViaHttpPost : IPlainXmlWebServiceViaHttpPost
 {
        public Stream Process(Stream request)
        {
            return request.ProcessTextStreamWith(PoxProcessor.Process);
        }
 }
}

Basically it's just turning the incoming Stream into a string, doing something with that string, and returning a string response converted back into a Stream. The idea is to be able to pass arbitrary XML to the service and return arbitrary XML.

And, finally, here's the relevant portion of the web.config:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <bindings>
        <webHttpBinding>
            <binding name="poxBinding" maxReceivedMessageSize="655360">
                <readerQuotas maxArrayLength="655360" />
                <security mode="None">
                    <transport clientCredentialType="None" />
                </security>
            </binding>
        </webHttpBinding>
    </bindings>
    <behaviors>
        <endpointBehaviors>
            <behavior name="REST">
                <webHttp />
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior name="poxBehavior">
                <serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service behaviorConfiguration="poxBehavior" name="App.api.v_1_1.PlainXmlWebServiceViaHttpPost">
            <endpoint address="" behaviorConfiguration="REST" binding="webHttpBinding"
                bindingConfiguration="poxBinding" contract="App.api.v_1_1.IPlainXmlWebServiceViaHttpPost" />
        </service>
    </services>
</system.serviceModel>

I've been trying all sorts of workarounds to get WCF/IIS to cooperate with me, and all have failed. Does anyone know what would cause requesting the expected content types to return HTTP 400, but all other content types to be processed as expected?

like image 828
adamjcooper Avatar asked Jan 22 '23 23:01

adamjcooper


1 Answers

Did you use WebServiceHostFactory in your .svc file:

<%@ ServiceHost 
    Factory="System.ServiceModel.Activation.WebServiceHostFactory"   
    Service="App.api.v_1_1.PlainXmlWebServiceViaHttpPost" 
%>
like image 198
Darin Dimitrov Avatar answered Jan 25 '23 11:01

Darin Dimitrov