this blog postから、私はJSON.NETシリアル化を使用するカスタムWCF IDispatchMessageFormatter
を作成できました。 1つの注意点でうまくいきます。UriTemplate
でそれを使用しても、必ずしも期待どおりに動作するわけではありません。ここでURIテンプレートの逆シリアル化を変更せずにカスタムWCFボディの逆シリアル化を使用する
は、ブログ記事によって提供された実装です:
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) { ... }
}
は基本的には、DeserializeMethod
署名でobject[] parameters
は、このメソッドはインスタンス化する必要がout
パラメータです。
[WebInvoke(Method="POST", UriTemplate="foo/")]
public Foo MakeFoo(Foo foo) { ... }
またはこのような:
だから、これはこのようなRESTエンドポイント処理するために素晴らしい仕事をしていません
[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で指定されたパラメータは、要求メッセージのTo URIから逆シリアル化されなければならず、他のパラメータは要求メッセージの本文から逆シリアル化されなければならない。
だから素晴らしい。メッセージの本文からパラメータの逆シリアル化を更新しました。しかし、私はUriTemplate
のパラメータをデシリアライズすることを無効にしたくありません。既存のコードを使用して着信URIリクエストをデフォルトの方法でパラメータにマップする方法はありますかUriTemplate
が処理されていますか?
UriTemplateDispatchFormatter
のようなものを使用する必要があるようですが、これを実装する方法がわかりません。非公開です。
非常に実用的なアプローチを作品! @ carlosfigueiraのNewtonsoftJsonDispatchFormatter実装では、最初のボディーパートがペイロードボディーであると想定しています。本体部分が最初の引数ではないようにメソッドが構造化されている場合、 'JsonReaderException'が返されます。 – Tedford
こんにちは、私は同じ問題を抱えていた、それはまだ最高のソリューションをご利用いただけますか?私はそれを試していますが、私は自分のソリューションでフレームワークからコードをコピーするファンではありませんが、ああ、よく... – Vinhent
@Vinhentよりよい解決策は、RESTful WebサービスのためにWCF以外のものを使用することですあなたはWCFに固執する必要がありますはいです –