2017-03-08 70 views
1

我以爲我已經跳過了必要的環節,讓我的JsonMediaTypeFormatter與定製ISerializable實現一起工作,並通過了單元測試。但是,當我通過Swagger UI傳入值時,我無法使其工作。Web API將不會使用ISerializable實現

我的關鍵問題是:

  1. 我在做什麼毛病我的單元測試使其序列化/反序列化從什麼是Web API是做不同?
  2. 爲了使Web API的序列化/反序列化和Swagger/Swashbuckle能夠正常工作,需要做些什麼?

類被序列:(請注意,序列化,然後反序列化脫落時間部分,只保留日期組件的測試/觀察的目的的幫助。)

public class Pet : ISerializable 
{ 
    public DateTime Dob { get; set; } 

    public Pet() 
    { 
     Dob = DateTime.Parse("1500-12-25 07:59:59"); 
    } 

    public Pet(SerializationInfo info, StreamingContext context) 
    { 
     Dob = DateTime.Parse(info.GetString("Dob")); 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("Dob", Dob.Date.ToString()); 
    } 
} 

的Web API方法:(始終返回null)

public class TestController : ApiController 
{ 
    [Route("~/api/Pet")] 
    public string Get([FromUri] Pet data) 
    { 
     return data.Dob.ToString(); 
    } 
} 

通過單元測試:(和序列化助手from MSDN文檔)

[TestFixture] 
public class SerializationTests 
{ 
    [Test] 
    public void PetTest() 
    { 
     var date = new DateTime(2017, 1, 20, 5, 0, 0); 
     var foo = new Pet { Dob = date }; 

     var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableInterface = false } } }; 
     var serialized = SerializationHelpers.Serialize(jsonFormatter, foo); 

     Console.WriteLine(serialized); 
     var deserialized = SerializationHelpers.Deserialize<Pet>(jsonFormatter, serialized); 

     Assert.That(foo.Dob, Is.Not.EqualTo(date.Date)); 
     Assert.That(deserialized.Dob, Is.EqualTo(date.Date)); 
    } 
} 

public static class SerializationHelpers 
{ 
    public static string Serialize<T>(MediaTypeFormatter formatter, T value) 
    { 
     // Create a dummy HTTP Content. 
     Stream stream = new MemoryStream(); 
     var content = new StreamContent(stream); 
     // Serialize the object. 
     formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait(); 
     // Read the serialized string. 
     stream.Position = 0; 
     return content.ReadAsStringAsync().Result; 
    } 

    public static T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class 
    { 
     // Write the serialized string to a memory stream. 
     Stream stream = new MemoryStream(); 
     StreamWriter writer = new StreamWriter(stream); 
     writer.Write(str); 
     writer.Flush(); 
     stream.Position = 0; 
     // Deserialize to an object of type T 
     return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T; 
    } 
} 

WebApiConfig.cs

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 
     config.Formatters.Clear(); 
     var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableInterface = false } } }; 
     config.Formatters.Add(jsonFormatter); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 
    } 
} 

一些其它註釋:

  1. 當運行通過單元測試中,Console.WriteLine輸出是:

{ 「多波」: 「2017年1月20日12:00:00 AM」}

這正是我想要的/期望。

  1. 我的Swagger UI看起來像這樣使用Nuget的默認Swashbuckle設置。請注意,日期的值是在默認構造函數中設置的值,表明我的ISerializable實現被忽略。

Basic Deserialization Results

注: 我已經改變了問題,從圖片中刪除所有的仿製藥。這個問題現在基本上是關於ISerializable的實現,而不是關於泛型。

+0

我覺得這裏的問題是與你的GET請求模型使用泛型 - '公共字符串獲取([FromUri] MyClass的數據)'。 MyClass模型不能是通用的。嘗試將該參數設置爲具體類型。 – alltej

+0

@alltej我可以肯定地得到簡單的POCO類來正確序列化。爲什麼泛型是一個問題?我曾嘗試使用自定義的'JsonMediaTypeFormatter'(它在單元測試中工作),但當Web API調用它時,完全相同的'JsonMediaTypeFormatter'失敗。爲什麼我不能使用自定義序列化?所有的博客和MSDN文檔都說我可以使用自定義序列化。 – Jaxidian

回答

0

WebAPI API不知道如何反序列化這個通用對象。我在這裏看到類似的問題,但沒有親自嘗試/測試它。希望它有幫助:Generic Web Api method

而不是有一個通用的方法,您可以創建一個通用控制器。所以你的代碼如下所示。

public abstract class MyClass{ } 

public class PersonDto: MyClass{} 


public class TestController<T> : ApiController where T: MyClass 
{ 
    public string Get([FromUri] T data) 
    { 
     ... 
    } 
} 
+0

根據您的意見,我發現我可以簡化問題。我已經編輯了這個問題,現在泛型現在已經成爲問題的一部分。這個問題完全是關於Web API和'ISerializable'的實現。這應該證實泛型不是這裏的根本問題。 – Jaxidian