Web API不会使用ISerializable实现

时间:2017-03-08 16:22:36

标签: serialization asp.net-web-api json.net swagger swashbuckle

我以为我已经跳过了必要的箍,让我的JsonMediaTypeFormatter使用自定义ISerializable实现,完成了单元测试。但是当我通过Swagger UI传递值时,我无法让它工作。

我的主要问题是:

  1. 我的单元测试有什么问题导致它序列化/反序列化与Web API正在做什么不同?
  2. 我需要更改什么才能使用Web API的序列化/反序列化和Swagger / Swashbuckle?
  3. 正在序列化的类(请注意,序列化然后反序列化会删除时间组件并仅保留日期组件。有助于测试/观察目的。)

    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输出为:
    2.   

      {“Dob”:“1/20/2017 12:00:00 AM”}

      这正是我想要/期望的。

      1. 我的Swagger UI使用Nuget的默认Swashbuckle设置。请注意,日期的值是默认构造函数中设置的值,表示我的ISerializable实现被忽略。
      2. Basic Deserialization Results

        注意: 我已经更改了从图片中删除所有泛型的问题。这个问题基本上是关于ISerializable实现的,而不是关于泛型。

1 个答案:

答案 0 :(得分:0)

WebAPI api不知道如何反序列化此通用对象。我在SO中看到了类似的问题,但没有亲自尝试/测试它。希望它有所帮助: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)
    {
        ...
    }
}