title: Using Custom WCF Body Deserialization without changing URI Template Deserialization
body: <p>From <a href="http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx" rel="noreferrer">this blog post</a>, I was able to create a custom WCF <code>IDispatchMessageFormatter</code> that uses JSON.NET serialization. It works great with one caveat: using it with <code>UriTemplate</code> doesn't necessarily work as expected.</p>
  
  <p>Here's the implementation provided by the blog post:</p>
  
  <pre><code>class NewtonsoftJsonDispatchFormatter : IDispatchMessageFormatter
  {
      private readonly OperationDescription od;
      private readonly ServiceEndpoint ep;
      private readonly Dictionary&lt;string, int&gt; parameterNames = new Dictionary&lt;string, int&gt;();
  
      public NewtonsoftJsonDispatchFormatter(OperationDescription od, ServiceEndpoint ep, bool isRequest)
      {
          this.od = od;
          this.ep = ep;
          if (isRequest)
          {
              int operationParameterCount = od.Messages[0].Body.Parts.Count;
              if (operationParameterCount &gt; 1)
              {
                  this.parameterNames = new Dictionary&lt;string, int&gt;();
                  for (int i = 0; i &lt; operationParameterCount; i++)
                  {
                      this.parameterNames.Add(od.Messages[0].Body.Parts[i].Name, i);
                  }
              }
          }
      }
      public void DeserializeRequest(Message message, object[] parameters)
      {
          if (message.IsEmpty) 
              return;
  
          object bodyFormatProperty;
  
          if (!message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out bodyFormatProperty) ||
              (bodyFormatProperty as WebBodyFormatMessageProperty).Format != WebContentFormat.Raw)
          {
              throw new InvalidOperationException("Incoming messages must have a body format of Raw. Is a ContentTypeMapper set on the WebHttpBinding?");
          }
  
          XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
          bodyReader.ReadStartElement("Binary");
          byte[] rawBody = bodyReader.ReadContentAsBase64();
  
          using (MemoryStream ms = new MemoryStream(rawBody))
          using (StreamReader sr = new StreamReader(ms))
          {
              if (parameters.Length == 1)
                  parameters[0] = Helper.serializer.Deserialize(sr, od.Messages[0].Body.Parts[0].Type);
              else
              {
                  // multiple parameter, needs to be wrapped
                  using (Newtonsoft.Json.JsonReader reader = new Newtonsoft.Json.JsonTextReader(sr))
                  {
                      reader.Read();
                      if (reader.TokenType != Newtonsoft.Json.JsonToken.StartObject)
                          throw new InvalidOperationException("Input needs to be wrapped in an object");
                      reader.Read();
                      while (reader.TokenType == Newtonsoft.Json.JsonToken.PropertyName)
                      {
                          string parameterName = reader.Value as string;
                          reader.Read();
                          if (this.parameterNames.ContainsKey(parameterName))
                          {
                              int parameterIndex = this.parameterNames[parameterName];
                              parameters[parameterIndex] = Helper.serializer.Deserialize(reader, this.od.Messages[0].Body.Parts[parameterIndex].Type);
                          }
                          else
                              reader.Skip();
                          reader.Read();
                      }
                  }
              }
          }
      }
  
       public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) { ... }
  }
  </code></pre>
  
  <p>Basically, the <code>object[] parameters</code> in the <code>DeserializeMethod</code> signature are <code>out</code> parameters that this method needs to instantiate.</p>
  
  <p>So, this does a great job to handle a REST endpoint like this:</p>
  
  <pre><code>[WebInvoke(Method="POST", UriTemplate="foo/")]
  public Foo MakeFoo(Foo foo) { ... }
  </code></pre>
  
  <p>or like this:</p>
  
  <pre><code>[WebInvoke(Method="POST", UriTemplate="FooBar/")]
  public FooBar FooBar(Foo foo, Bar bar) { .. }
  </code></pre>
  
  <p>but it currently doesn't map the URI template parameters to the method parameters, e.g. something like this:</p>
  
  <pre><code>[WebGet(UriTemplate="Foo/{id}")]
  public Foo GetFoo(string id) { ... }
  </code></pre>
  
  <p>Microsoft writes on the overriden <a href="https://msdn.microsoft.com/en-us/library/system.servicemodel.description.webhttpbehavior.getrequestdispatchformatter(v=vs.110).aspx" rel="noreferrer"><code>GetRequestDispatchFormatter</code></a>:</p>
  
  <blockquote>
    <p>This is an extensibility point that derived behaviors can use to supply their own implementation of IDispatchMessageFormatter that is called to deserialize the input parameters of the service operation from the request message. Parameters specified in the UriTemplate of the service operation must be deserialized from the To URI of the request message and other parameters must be deserialized from the body of the request message.</p>
  </blockquote>
  
  <p>So, great. I updated the deserialization of the parameters from the body of a message. But I don't want to override deserializing the parameters in the <code>UriTemplate</code>. Is there any way to use existing code to map the incoming URI request to the parameters with the default way <code>UriTemplate</code> is handled?</p>
  
  <p>It seems I need to use something like the <a href="http://referencesource.microsoft.com/#System.ServiceModel.Web/System/ServiceModel/Dispatcher/UriTemplateDispatchFormatter.cs" rel="noreferrer"><code>UriTemplateDispatchFormatter</code></a> but I'm not sure how to implement this, and it's non-public.</p>