6

モデルがあるとします。

public class Menu
{
    public string Name { get; set; }
    public IMenuCommand Next { get; set; }
}

IMenuCommand次のようなさまざまな実装が可能です。

public class NextStepCommand : IMenuCommand
{
    public int Step { get; set; }
}

public class VoiceCommand : IMenuCommand
{
    public string Message { get; set; }
}

また、さまざまなコマンドを含むメニューをASP.NETWebAPIサービスにPOSTしたいと思います。どうやってやるの?

以下のリクエストは、指定されたオブジェクトを作成しますNameが、Nextコマンドはnullになります。

POST http://localhost/api/menus: {"name":"bob","next":{"step":1}}
Returns 201: {"Name":"bob","Next":null}

デフォルトのWebAPIバインダーは、要求パラメーターを必要なC#タイプにマップできません。もちろん、これは注意が必要な部分です。インターフェイスベースのプロパティに「既知のタイプ」属性を使用できますか、それともこのケースを処理する他のアプローチ、おそらくカスタムモデルバインダーはありますか?

4

1 に答える 1

5

あなたが探しているのは、型名の処理に対する Json.NET のサポートだと思います。「$type」json タグを追加することで、デシリアライズするタイプを指定できます。このコードを試して、どのように機能するかを確認できます。

Console.WriteLine(JsonConvert.DeserializeObject<Menu>(
    @"{
         ""name"":""bob"",
         ""next"":
         {
           ""$type"" : ""ConsoleApplication.NextStepCommand,ConsoleApplication"",
           ""step"" : 1
         }
    }",
    new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }).Next);

名前空間とアセンブリ名を独自のものに置き換える必要がありますが、NextStepCommand が正しく逆シリアル化されていることがわかります。

WebAPI では、リクエストを微調整して「$type」タイプ情報を追加する必要があり、次のように TypeNameHandling を有効にする必要があります。

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
于 2012-12-19T03:23:34.640 に答える