ProtocolException is thrown when content-type header is missing

Posted on November 10, 2010 by

0


Symptom –

WCF can not handle requests and responses which don’t include the content-type header and it throws exception which contains the following message –

An HTTP Content-Type header is required for SOAP messaging and none was found

According to RFC 2616 (see http://www.ietf.org/rfc/rfc2616.txt section 7.2.1 ) this is a legal scenario:

Any HTTP/1.1 message containing an entity-body SHOULD include a Content-Type header field defining the media type of that body. If and only if the media type is not given by a Content-Type field, the recipient MAY attempt to guess the media type via inspection of its content and/or the name extension(s) of the URI used to identify the resource. If the media type remains unknown, the recipient SHOULD treat it as type “application/octet-stream”.

Solution

We should divide this case into two scenarios:

1. When the server receives a request without the content-type header

2. When the client receives a response without the content type header

Missing content-type header in request (server side)

This bug was fixed in .Net 4.0 and also has a work around for .Net 3.5.

It requires adding ContentTypeMapper to the  WebMessageEncodingBindingElement, in the following way:

public class SampleContentTypeMapper : WebContentTypeMapper
{
     public override WebContentFormat GetMessageFormatForContentType(string contentType)
     {
          return WebContentFormat.Xml;
     }
 }
static void Main(string[] args)
{
     try
     {
          CustomBinding binding = new CustomBinding();
          WebHttpBinding webHttpBinding = new WebHttpBinding(WebHttpSecurityMode.None);
          WebMessageEncodingBindingElement webMessageEncoding = new WebMessageEncodingBindingElement();
          webMessageEncoding.ContentTypeMapper = new SampleContentTypeMapper();
          foreach (BindingElement element in webHttpBinding.CreateBindingElements())
          {
              if (element is WebMessageEncodingBindingElement)
              {
                   binding.Elements.Add(webMessageEncoding);
              }
              else
              {
                   binding.Elements.Add(element);
              }
           }
           ServiceHost host = new ServiceHost(typeof(SampleService), new Uri("http://localhost:8000"));
           ServiceEndpoint ep = host.AddServiceEndpoint(typeof(ISampleService), binding, "http://localhost:8000");
           ep.Behaviors.Add(new WebHttpBehavior());
           host.Open();
     }
     catch (Exception e)
     {
           Console.WriteLine("Received exception: {0}", e);
     }
     Console.WriteLine("Press any key to quit...");
     Console.ReadKey();
}

Missing Content-Type header in response (Client side)

Unfortunately, this case has no easy solution. The error occurs very early in the WCF chain, at the transport layer.

The only possible workarounds are creating a custom http transport element (which is not trivial solution) or using System.Net.WebClient instead of WCF.

Another option is inserting another element in the middle, which will add this header to all responses, such as F5 for example, but this is dependent on the architecture of your environment.

Advertisements
Posted in: Pitfalls