WCF Web HTTP formatting

The WCF Web HTTP programming model allows you to dynamically determine the best format for a service operation to return its response in. Two methods for determining an appropriate format are supported: automatic and explicit.

Automatic formatting

When enabled, automatic formatting chooses the best format in which to return the response. It determines the best format by checking the following, in order:

  1. The media types in the request message’s Accept header.

  2. The content-type of the request message.

  3. The default format setting in the operation.

  4. The default format setting in the WebHttpBehavior.

If the request message contains an Accept header the Windows Communication Foundation (WCF) infrastructure searches for a type that it supports. If the Accept header specifies priorities for its media types, they are honored. If no suitable format is found in the Accept header, the content-type of the request message is used. If no suitable content-type is specified, the default format setting for the operation is used. The default format is set with the ResponseFormat parameter of the WebGetAttribute and WebInvokeAttribute attributes. If no default format is specified on the operation, the value of the DefaultOutgoingResponseFormat property is used. Automatic formatting relies on the AutomaticFormatSelectionEnabled property. When this property is set to true, the WCF infrastructure determines the best format to use. Automatic format selection is disabled by default for backwards compatibility. Automatic format selection can be enabled programmatically or through configuration. The following example shows how to enable automatic format selection in code.

// This code assumes the service name is MyService and the service contract is IMyContract
Uri baseAddress = new Uri("http://localhost:8000");  
  
WebServiceHost host = new WebServiceHost(typeof(MyService), baseAddress)  
try  
{  
   ServiceEndpoint sep = host.AddServiceEndpoint(typeof(IMyContract), new WebHttpBinding(), "");  
   // Check it see if the WebHttpBehavior already exists  
   WebHttpBehavior whb = sep.Behaviors.Find<WebHttpBehavior>();  
  
   if (whb != null)  
   {  
      whb.AutomaticFormatSelectionEnabled = true;  
   }  
   else  
   {  
      WebHttpBehavior webBehavior = new WebHttpBehavior();  
      webBehavior.AutomaticFormatSelectionEnabled = true;  
      sep.Behaviors.Add(webBehavior);  
   }  
         // Open host to start listening for messages  
   host.Open();
  
  // ...  
}  
  catch(CommunicationException ex)  
  {  
     Console.WriteLine("An exception occurred: " + ex.Message());  
  }  

Automatic formatting can also be enabled through configuration. You can set the AutomaticFormatSelectionEnabled property directly on the WebHttpBehavior or using the WebHttpEndpoint. The following example shows how to enable the automatic format selection on the WebHttpBehavior.

<system.serviceModel>  
  <behaviors>  
    <endpointBehaviors>  
      <behavior>  
        <webHttp automaticFormatSelectionEnabled="true" />  
      </behavior>  
    </endpointBehaviors>  
  </behaviors>  
  <standardEndpoints>  
    <webHttpEndpoint>  
      <!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->  
      <standardEndpoint name="" helpEnabled="true" />  
    </webHttpEndpoint>  
  </standardEndpoints>  
</system.serviceModel>  

The following example shows how to enable automatic format selection using WebHttpEndpoint.

<system.serviceModel>  
    <standardEndpoints>  
      <webHttpEndpoint>  
        <!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->  
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"  />  
      </webHttpEndpoint>  
    </standardEndpoints>  
  </system.serviceModel>  

Explicit formatting

As the name implies, in explicit formatting the developer determines the best format to use within the operation code. If the best format is XML or JSON the developer sets Format to either Xml or Json. If the Format property is not explicitly set, then the operation’s default format is used.

The following example checks the format query string parameter for a format to use. If it has been specified, it sets the operation’s format using Format.

public class Service : IService  
{  
    [WebGet]  
     public string EchoWithGet(string s)  
    {  
        // if a format query string parameter has been specified, set the response format to that. If no such
        // query string parameter exists the Accept header will be used
        string formatQueryStringValue = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["format"];  
        if (!string.IsNullOrEmpty(formatQueryStringValue))  
        {  
            if (formatQueryStringValue.Equals("xml", System.StringComparison.OrdinalIgnoreCase))  
            {
                WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Xml;
            }
            else if (formatQueryStringValue.Equals("json", System.StringComparison.OrdinalIgnoreCase))  
            {  
                WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;  
            }  
            else  
            {  
                throw new WebFaultException<string>($"Unsupported format '{formatQueryStringValue}'",   HttpStatusCode.BadRequest);
            }  
        }  
        return "You said " + s;  
    }  

If you need to support formats other than XML or JSON, define your operation to have a return type of Message. Within the operation code, determine the appropriate format to use and then create a Message object using one of the following methods:

  • WebOperationContext.CreateAtom10Response

  • WebOperationContext.CreateJsonResponse

  • WebOperationContext.CreateStreamResponse

  • WebOperationContext.CreateTextResponse

  • WebOperationContext.CreateXmlResponse

Each of these methods takes content and creates a message with the appropriate format. The WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements method can be used to get a list of formats preferred by the client in order of decreasing preference. The following example shows how to use WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements to determine the format to use and then uses the appropriate create response method to create the response message.

public class Service : IService  
{  
    public Message EchoListWithGet(string list)  
    {  
        List<string> returnList = new List<string>(list.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));  
        IList<ContentType> acceptHeaderElements = WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements();  
        for (int x = 0; x < acceptHeaderElements.Count; x++)  
        {  
            string normalizedMediaType = acceptHeaderElements[x].MediaType.ToLowerInvariant();  
            switch (normalizedMediaType)  
            {  
                case "image/jpeg": return CreateJpegResponse(returnList);  
                case "application/xhtml+xml": return CreateXhtmlResponse(returnList);  
                case "application/atom+xml": return CreateAtom10Response(returnList);  
                case "application/xml": return CreateXmlResponse(returnList);  
                case "application/json": return CreateJsonResponse(returnList);  
          }  
    }  
  
    // Default response format is XML  
    return CreateXmlResponse(returnList);  
    }  
}  

See also