2012-05-16 41 views
3

我有一個具有CommandMessage類型參數的Web API控制器操作。該類型具有基本類型CommandBase的列表。我的問題是,我不能讓它們成爲派生類型,在這個例子中是MyCommand。將具有基本類型的列表序列化爲派生類型json

我正在使用Web API contrib項目中的JsonNetFormatter。它使用Json.Net作爲序列化程序。

的Web API控制器:

public class CommandController : ApiController 
{ 
    public HttpResponseMessage Post(CommandMessage command) 
    { 
     //command.Commands[0].GetType().Name is always "CommandBase" instead of "MyCommand" 
     var message = new HttpResponseMessage(HttpStatusCode.OK) 
          { 
           Content = new StringContent(string.Format("Type of command 1 is '{0}'", command.Commands[0].GetType().FullName)) 
          }; 
     return message; 
    } 
} 

這我我的要求:

private void When() 
    { 
     using (client) 
     { 
      command = new MyCommand 
          { 
           CommandId = Guid.NewGuid(), 
           Id = Guid.NewGuid(), 
           Name = "Martin" 
          }; 

      var message = new CommandMessage(Guid.NewGuid(),new List<CommandBase> {command}); 

      var requestMessage = GetHttpRequestMessage(message); 
      var task = client.PostAsync("http://localhost.:16218/api/command", requestMessage.Content); 
      task.Wait(); 
      responseMessage = task.Result; 
     } 
    } 

private static HttpRequestMessage GetHttpRequestMessage<T>(T data) 
    { 
     var mediaType = new MediaTypeHeaderValue("application/json"); 
     var jsonFormatter = new JsonNetFormatter(DefaultJsonSettings.Settings()); 

     var requestMessage = new HttpRequestMessage<T>(data, mediaType, new[] {jsonFormatter}); 

     return requestMessage; 
    } 

而作爲JSON:

{ 
    "$type": "PostToBaseClassList.Models.CommandMessage, PostToBaseClassList", 
    "Commands": [ 
    { 
     "$type": "PostToBaseClassList.Models.MyCommand, PostToBaseClassList", 
     "Id": "45923a41-0c15-46e3-907d-64dd06840539", 
     "Name": "Martin" 
    } 
    ], 
    "MessageId": "c873970a-8621-4223-806e-b809039438ab" 
} 

從API控制器動作返回消息是:

類型命令1是 'PostToBaseClassList.Models.CommandBase'

Command類:

[DataContract] 
[XmlRoot] 
public class MyCommand : CommandBase 
{ 
    private readonly string name; 

    public MyCommand() 
    { 
    } 

    public MyCommand(Guid id, string name) 
    { 
     this.name = name; 
     Id = id; 
    } 

    [DataMember(Order = 1)] 
    [XmlElement] 
    public Guid Id { get; set; } 

    [DataMember(Order = 2)] 
    [XmlElement] 
    public string Name { get; set; } 
} 

[DataContract] 
[KnownType("GetKnownTypes")] 
public class CommandBase 
{ 
    public Guid CommandId { get; set; } 

    public static Type[] GetKnownTypes() 
    { 
     var query = 
      from type in typeof (CommandBase).Assembly.GetTypes() 
      where typeof (CommandBase).IsAssignableFrom(type) 
      select type; 

     var types = query.ToArray(); 
     return types; 
    } 
} 

[DataContract] 
[Serializable] 
[XmlRoot] 
public class CommandMessage 
{ 
    public CommandMessage() 
    { 
    } 

    public CommandMessage(Guid messageId, IEnumerable<CommandBase> commands) 
    { 
     MessageId = messageId; 
     Commands = new List<CommandBase>(commands); 
    } 

    [DataMember] 
    [XmlElement] 
    public List<CommandBase> Commands { get; set; } 

    [DataMember] 
    [XmlElement] 
    public Guid MessageId { get; set; } 
} 

Json.Net設置:

//DefaultJsonSettings.Settings() 
var settings = new JsonSerializerSettings 
          { 
           NullValueHandling = NullValueHandling.Ignore, 
           TypeNameHandling = TypeNameHandling.Objects, 
           Converters = new List<JsonConverter> 
               { 
                new IsoDateTimeConverter 
                 () 
               } 
          }; 

private static void RegisterFormatters(HttpConfiguration config) 
    { 
     var jsonNetFormatter = new JsonNetFormatter(DefaultJsonSettings.Settings()); 
     config.Formatters.Insert(0, jsonNetFormatter); 
    } 

任何想法?

+0

我只是將System.Net.Http.Formatting更新到4.0.20710.0,現在我在JsonNetFormatter類中得到了很多錯誤。任何線索?謝謝 – VAAA

+0

不,但您應該創建一個新的SO問題並更詳細地描述您的問題。例如,你會得到什麼錯誤? –

回答

0

它的工作後,我加入這行RegisterFormatters()

config.Formatters.Remove(config.Formatters.JsonFormatter); 

這是不夠的

config.Formatters.Insert(0, jsonNetFormatter); 

完整版

private void RegisterFormatters() 
{ 
    config.Formatters.Remove(config.Formatters.JsonFormatter); 
    var jsonNetFormatter = new JsonNetFormatter(DefaultJsonSettings.Settings()); 
    config.Formatters.Insert(0, jsonNetFormatter); 
} 
2

Json.NET不尊重KnownTypes屬性,你必須提供你自己的轉換器。

這個問題提供瞭解決這個問題的幾個不同的解決方案: Using Json.NET converters to deserialize properties

+0

但是不應該TypeNameHandling設置句柄嗎? var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }; \t \t \t \t \t 還發現[此](http://json.codeplex.com/discussions/210326) –

+0

TypeNameHandling在JSON消息' 「$類型」 創建這樣的: 「PostToBaseClassList.Models.MyCommand,PostToBaseClassList」 ' –

相關問題