2017-03-08 25 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

相关问题