Использование пользовательской десериализации тела WCF без изменения десериализации шаблона URI

Отэтот блогЯ смог создать собственный WCFIDispatchMessageFormatter который использует сериализацию JSON.NET. Он прекрасно работает с одной оговоркой: используя его сUriTemplate не обязательно работает, как ожидалось.

Вот реализация, обеспеченная сообщением в блоге:

class NewtonsoftJsonDispatchFormatter : IDispatchMessageFormatter
{
    private readonly OperationDescription od;
    private readonly ServiceEndpoint ep;
    private readonly Dictionary<string, int> parameterNames = new Dictionary<string, int>();

    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 > 1)
            {
                this.parameterNames = new Dictionary<string, int>();
                for (int i = 0; i < 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) { ... }
}

В основном,object[] parameters вDeserializeMethod подписьout параметры, которые этот метод должен создать.

Таким образом, это отлично справляется с обработкой конечной точки REST:

[WebInvoke(Method="POST", UriTemplate="foo/")]
public Foo MakeFoo(Foo foo) { ... }

или вот так:

[WebInvoke(Method="POST", UriTemplate="FooBar/")]
public FooBar FooBar(Foo foo, Bar bar) { .. }

но в настоящее время он не отображает параметры шаблона URI на параметры метода, например, что-то вроде этого:

[WebGet(UriTemplate="Foo/{id}")]
public Foo GetFoo(string id) { ... }

Microsoft пишет о переопределенииGetRequestDispatchFormatter:

Это точка расширения, которую производные поведения могут использовать для предоставления своей собственной реализации IDispatchMessageFormatter, которая вызывается для десериализации входных параметров операции службы из сообщения запроса. Параметры, указанные в UriTemplate операции службы, должны быть десериализованы из URI To сообщения-запроса, а другие параметры должны быть десериализованы из тела сообщения-запроса.

Так здорово. Я обновил десериализацию параметров из тела сообщения. Но я не хочу отменять десериализацию параметров вUriTemplate, Есть ли способ использовать существующий код для сопоставления входящего запроса URI с параметрами по умолчаниюUriTemplate обрабатывается?

Кажется, мне нужно использовать что-то вродеUriTemplateDispatchFormatter но я не уверен, как это реализовать, и это не публично.

Ответы на вопрос(1)

Ваш ответ на вопрос