【问题标题】:Reading CollectionJson content in Web Api Project在 Web Api 项目中读取 CollectionJson 内容
【发布时间】:2014-08-27 16:52:50
【问题描述】:

我有一个与Conference API project 类似(几乎相同)的项目,它采用与上述项目类似的方法来返回 CollectionJson 内容。我很难设置 ReadDocument 的 Collection 属性(第 30 行),因为它没有任何设置器。我可以通过以下更改绕过这个问题

public CollectionJsonContent(Collection collection)
{
    var serializerSettings = new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            Formatting = Newtonsoft.Json.Formatting.Indented,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    collection.Version = "1.0";

    Headers.ContentType = new MediaTypeHeaderValue("application/vnd.collection+json");

    using (var writer = new JsonTextWriter(new StreamWriter(_memoryStream)){CloseOutput = false})
    {
        //var readDocument = new ReadDocument(); {IReadDocument.Collection = collection};
        var serializer = JsonSerializer.Create(serializerSettings);
        serializer.Serialize(writer,collection);
        writer.Flush();
    }
    _memoryStream.Position = 0;
}

虽然上面的代码可以编译并在一定程度上解决了问题,但我又会遇到另一个问题,即无法在我的控制器单元测试中使用 JsonCollection 内容。考虑以下单元测试代码 sn-p:

            using (var request = CreateRequest())
            {                
                var controller = new TestController(DataService) {Request = request};

                var temp = await controller.ListAsync(gridSearchData, sampleSearchData);

                if ((temp is NotFoundResult) && (sampleCollection.Any()))
                {
                    Assert.Fail("Controller did not return any result but query did");
                }

                var json = await temp.ExecuteAsync(cancellationTokenSource);



                var readDocument = json.Content.ReadAsAsync<ReadDocument>(new[] {new CollectionJsonFormatter()}, cancellationTokenSource).Result;

         }

由于我没有设置 ReadDocument 的集合属性,所以 readDocument 总是空的,我无法读取它的内容。 WEB API项目中如何在客户端异步读取JsonCollection的内容?

要获得该方法的清晰图片,请查看Conference Web Apiauthors blog

【问题讨论】:

    标签: c# json asp.net-web-api asp.net-web-api2 collection-json


    【解决方案1】:

    好的,这个问题已经解决了。现在可以再次设置 Collection 属性。

    我刚刚推送了release 0.7.0 进行此修复,这是一次重大的命名重构以及对序列化的一个很好的改进,不会写出空集合。

    请参阅release notes 了解更改(尤其是包名和命名空间已更改的命名)

    【讨论】:

    • 确实做得很好,更新也很棒。现在我可以设置 ReadDocument 集合属性。但有一个问题:为什么我会得到:“没有 MediaTypeFormatter 可用于从内容中读取 'ReadDocument' 类型的对象当我运行 json.Content.ReadAsAsync(new[] {new CollectionJsonFormatter()},cancellationTokenSource).Result 时出现媒体类型“application/vnd.collection+json”异常;如上述单元测试所述?在测试控制器时,您在单元测试中在哪里设置 MediaTypeFormetter?
    • @MHOOS 我回复了您的电子邮件,询问您是否可以向我发送一些示例代码。单元测试的要点也可以。
    【解决方案2】:

    据我从您的代码中看到,您没有序列化 ReadDocument 对象,而只是序列化它的一个属性 (Collection),然后您尝试将该值反序列化为新的 ReadDocument 对象。

    样本ReadDocument 应该像这样序列化

    "{"Collection": [1,2,3,4,5] }"
    

    但是你序列化集合,所以你得到

    "[1,2,3,4,5]"
    

    我推荐这样的序列化代理类

    class SerializableReadDocument
    {
       public Collection Collection { get; set; }
    }
    

    并像这样更新您的序列化代码

    using (var writer = new JsonTextWriter(new StreamWriter(_memoryStream)){CloseOutput = false})
    {
        var readDocument = new SerializableReadDocument() { Collection = collection };
        var serializer = JsonSerializer.Create(serializerSettings);
        serializer.Serialize(writer, readDocument);
        writer.Flush();
    }
    

    但是,当您尝试反序列化您的输出时,这不会解决您的问题,因为ReadDocument 没有可设置的Collection 属性,反序列化将失败,或者返回带有空CollectionReadDocument 对象.

    如果您愿意,可以在单元测试中使用SerializableReadDocument

    【讨论】:

    • 正如我在问题中所述,您还提到“反序列化本身并不是真正的问题,但我在使用 ReadDocument 反序列化时遇到问题。因为我无法设置 Collection 属性(这使用在旧版本的 CollectionJson 中设置 setter 但包所有者 Glen Block 在新版本中对其进行了修改>(new[] {new CollectionJsonFormatter()}, cancelTokenSource).Result
    • WebApiContrib.CollectionJson 的 0.6.2 版开始,您根本无法做到。即使您设法使用反射设置Collectionproperty,您也不能使用newtonsoft json 对其进行反序列化,因为它不会设置集合。可能的解决方法是; 1- 使用以前的版本,2- 将收藏内容复制到 ReadDocument.Collection,3- 使用 SerializableReadDocument。使用SerializableReadDocument,这是最简单的方法。
    • @edokan 如果您使用的是 JSON.NET 之类的东西,它应该可以很好地反序列化。只需将项目添加到集合中就没有问题。如果这不起作用,人们根本无法使用图书馆。
    • @GlennBlock 它在 javascript 中可以很好地反序列化,但在 .NET 中却不行,正如您在 github.com/WebApiContrib/… 中看到的那样。 OP 正在尝试反序列化单元测试
    【解决方案3】:

    我正在研究这个问题,并会在本周末提出一个有希望的解决方案,要么将其设为公共 setter,要么将 setter 设为内部并让公共 ctor 接受集合。

    抱歉给您带来了困难。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 2013-08-22
      • 2017-07-29
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多