C# 读取Web Api项目中的CollectionJson内容

C# 读取Web Api项目中的CollectionJson内容,c#,json,asp.net-web-api,asp.net-web-api2,collection-json,C#,Json,Asp.net Web Api,Asp.net Web Api2,Collection Json,我有一个与之类似(几乎相同)的项目,该项目采用了与返回CollectionJson内容的著名项目类似的方法。我很难设置ReadDocument(第30行)的Collection属性,因为它没有任何setter。我可以通过做以下更改来绕过这个问题 public CollectionJsonContent(Collection collection) { var serializerSettings = new JsonSerializerSettings {

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

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内容。考虑下面的单元测试代码片段:

            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;

         }
使用(var request=CreateRequest())
{                
var controller=newtestcontroller(DataService){Request=Request};
var temp=await controller.ListAsync(gridSearchData,sampleSearchData);
if((temp为NotFoundResult)&&(sampleCollection.Any())
{
Assert.Fail(“控制器未返回任何结果,但查询返回了”);
}
var json=await temp.ExecuteAsync(cancellationTokenSource);
var readDocument=json.Content.ReadAsAsync(new[]{new CollectionJsonFormatter()},cancellationTokenSource);
}
由于我没有设置ReadDocument的collection属性,ReadDocument始终为空,我无法读取其内容。 在WEB API项目中,如何在客户端异步读取JsonCollection的内容

要清楚了解该方法,请查看

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

示例
ReadDocument
应该像这样序列化

"{"Collection": [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();
}
但您序列化了集合,所以

"[1,2,3,4,5]"
我建议像这样的序列化使用代理类

"{"Collection": [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();
}
并像这样更新序列化代码

"{"Collection": [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
属性,反序列化将失败,或者返回带有空
集合的
ReadDocument
对象


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

我正在研究这一点,并将在本周末提出一个解决方案,这将是使其成为公共setter,或者使setter成为内部的,并具有接受集合的公共ctor


很抱歉给您添麻烦。

好的,这已经解决了。集合属性现在可以再次设置

我刚刚推出了这个修复程序,这是一个主要的命名重构,也是对序列化的一个很好的改进,以避免写出空集合


有关更改(尤其是包名称和名称空间已更改时的命名),请参阅。

正如我在问题中所述,您也提到“反序列化本身不是实际的问题,但我在使用ReadDocument进行反序列化时遇到问题。因为我无法设置集合属性(以前在旧版本的CollectionJson中有setter,但Glen Block包所有者在新版本中对其进行了修改)我的ReadDocument集合属性为空,我的问题是:如何设置ReadDocument的集合属性,以便我可以拥有json.Content.ReadAsAsAsync(new[]{new CollectionJsonFormatter()},cancellationTokenSource).ResultAs是
WebApiContrib.CollectionJson
的0.6.2版,您根本不能。即使您设法使用反射设置
Collection
属性,也不能使用newtonsoft json对其进行反序列化,因为它不会设置集合。可能的解决方法是:1-使用以前的版本,2-将集合内容复制到
ReadDocument.Collection
,3-使用
SerializableReadDocument
。使用
SerializableReadDocument
,这是最简单的方法。@如果您使用类似JSON.NET的东西,它应该可以反序列化。只向集合中添加项目没有问题。如果这不起作用,人们根本无法使用该库。@GlennBlock it deserializes在javascript中很好,但在.NET中没有,正如您在中看到的那样。OP正在尝试为unit testsGreat作业和伟大的更新进行反序列化。现在我可以设置ReadDocument集合属性。但有一个问题:我为什么得到:当我运行json.content.ReadAsAsync(new[]{new CollectionJsonFormatter()},cancellationTokenSource)时,没有MediaTypeFormatter可用于从媒体类型为“application/vnd.collection+json”的内容中读取“ReadDocument”类型的对象.Result;如上述单元测试中所述?在测试控制器时,您在单元测试中将MediaTypeFormetter设置在哪里?@MHOOS我回复了您的电子邮件,询问您是否可以发送一些示例代码。单元测试的要点也可以。