我有一个案例,我需要使用wsHttp使用WCF 传输大量的序列化对象图(通过NetDataContractSerializer).我正在使用邮件安全性,并希望继续这样做.使用这个设置我想传输序列化的对象图,有时可以接近300MB左右但是当我尝试这样做时,我开始看到System.InsufficientMemoryException类型的异常出现.
经过一些研究后,默认情况下,WCF中默认情况下,服务调用的结果默认包含在单个消息中,其中包含序列化数据,并且默认情况下在服务器上缓冲此数据,直到完整写入整个消息.因此,内存异常是由于服务器的内存资源不足而导致分配的,因为该缓冲区已满.我遇到的两个主要建议是使用流式传输或分块来解决这个问题,但是我不清楚这涉及到什么,以及我的当前设置是否可以使用任何解决方案(wsHttp/NetDataContractSerializer/Message Security).到目前为止,我理解使用流式消息安全性不起作用,因为消息加密和解密需要处理整个数据集而不是部分消息.然而,Chunking听起来似乎有可能,但是我不清楚如何使用我列出的其他约束来完成它.如果有人可以就可用的解决方案以及如何实施它提供一些指导,我将非常感激.
我应该补充一点,在我的情况下,我真的不担心与其他客户端的互操作性,因为我们拥有并控制通信的每一面,并使用共享接口模式传输到任何一方的数据.所以我愿意接受任何符合使用带有消息安全性的wsHttp以转移使用NetDataContractSerializer序列化的对象图的约束的想法,我更喜欢一个解决方案,我不需要大幅改变我现有的服务和周围的基础设施.
相关资源:
我也对可以对这些数据进行的任何类型的压缩感兴趣,但看起来我可能最好在传输级别执行此操作,一旦我可以转换到.NET 4.0,以便客户端将自动支持gzip标题如果我理解正确的话.
关于如何在结论中得出缓冲消息太大导致我的问题的一些历史.最初我在测试时看到了下面的CommunicationException.
底层连接已关闭:连接意外关闭.
最后,在运行此操作并进行更多日志记录后,我发现了导致指定消息出现问题的基础InsufficientMemoryException异常.
无法分配268435456字节的托管内存缓冲区.可用内存量可能很低.
其中源于以下方法.
System.ServiceModel.Diagnostics.Utility.AllocateByteArray(Int32 size)
所以在其他方面,失败来自分配阵列.当写入序列化到磁盘的相同数据时,它需要大约146MB,如果我将其减少一半,那么我就会停止获取错误但是我没有更多地挖掘破坏我的缓冲区的特定阈值以及它是否特定于我的系统或不.
我想在这一点上我正在为以下内容寻找一些澄清.我的理解是,默认情况下WCF wsHttp具有消息安全性,在响应被发送回客户端之前需要在服务器上缓冲整个消息(通常是我正在返回的整个数据集),从而导致我的问题.
可能的解决方案:
限制我可以返回的数据只能达到某一点,并且与Streaming选项一样,这些选项需要在WCF服务调用之外编写许多较低级别的工作.所以我想我需要知道的是,通过允许将一组数据分解为服务器上的单独消息然后在客户端上拼凑在一起,是否任何可能的分块通道实现都可以解决大型消息问题.这样一种方式,我不必改变现有服务合同的接口/形状,并且在仍然使用消息安全性和wsHttp的同时,几乎隐藏了每个服务实现的客户端和服务器部分的过程.如果分块通道要求我重新编写我的服务合同以暴露流,那么我不会 看看这与Streaming解决方案有什么不同.如果有人可以简单地为我回答这些问题,我会给予奖励,并将其标记为答案.
wcf large-data-volumes chunking wshttpbinding netdatacontractserializer
在WebAPI控制器中返回对象列表时,我一直在努力输出自定义的根xml元素.
我的控制器方法看起来像这样:
public List<Product> Get()
{
return repository.GetProducts();
}
Run Code Online (Sandbox Code Playgroud)
它呈现像这样的xml输出:
<ArrayOfProduct>
<Product>
<Name>Product1</Name>
</Product>
<Product>
<Name>Product2</Name>
</Product>
</ArrayOfProduct>
Run Code Online (Sandbox Code Playgroud)
我想改变<ArrayOfProduct>,<Products>但没有找到这样做的方法.
我尝试了不同的属性DataContract和DataMember属性无济于事.
有没有人知道是否有办法做我想做的事情,没有把我的List<Product>对象包装在一个新的类中而是返回它?
c# asp.net xml-serialization netdatacontractserializer asp.net-web-api
我有一个类,它包含所有现有实例的静态字典,这些实例是在编译时定义的.
基本上它看起来像这样:
[DataContract]
class Foo
{
private static Dictionary<long, Foo> instances = new Dictionary<long, Foo>();
[DataMember]
private long id;
public static readonly Foo A = Create(1);
public static readonly Foo B = Create(2);
public static readonly Foo C = Create(3);
private static Foo Create(long id)
{
Foo instance = new Foo();
instance.id = id;
instances.Add(instance);
return instance;
}
public static Foo Get(long id)
{
return instances[id];
}
}
Run Code Online (Sandbox Code Playgroud)
还有其他字段,派生类,但这对问题无关紧要.
只有id序列化.当反序列化此类型的实例时,我想获取已创建为静态字段(A,B或C)的Foo.Get(id)实例,而不是获取新实例. …
我们有一个应用程序,包含我们希望在数据库中序列化的对象.
目前我们正在使用NetDataContractSerializer,但最近发现,由于涉及的.Net类型信息,它创建了大量文件,这意味着应用程序缓慢,即使对于基本对象.
我们正在考虑DataContractSerializer改用,我一直在寻找两者的比较,但没找到.
List<X>,其中包含X多个其他对象,以便列表在运行时包含许多不同的类型?(我被告知DataContractSerializer可以赋予KnownTypes属性,但这意味着代码中存在更多依赖关系.有没有办法DataContractSerializer在我的解决方案中了解所有类型?) 谢谢.
我有一个现有的代码库,它将几个简单的类保存到磁盘上NetDataContractSerializer,但遗憾的是,这些类没有用[DataContract],而是用[Serializable].这工作正常,但现在我想为持久化类添加一些新属性,同时仍然能够读取旧版本生成的文件.
让我们说这是班级:
[Serializable]
public class Persisted
{
public int OldProperty {get;set;}
public int NewProperty {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我反序列化旧文件时,我得到一个异常,因为它们不包含NewProperty.这是有道理的.所以我想NewProperty忽略,但是虽然有一个[OptionalField]属性让序列化程序忽略缺少的字段,但它不能应用于属性 - 仅字段.
所以我想我会使用[DataContract]和[DataMember],它也有一个IsRequired属性,但这会改变序列化文件的布局,而且它无法读取旧的数据文件.此外,你不能混用[Serializable]和[DataMember]-如果串行看到[Serializable]属性,它忽略了[DataMember]指令.
因此,除非选择对旧文件进行一次性转换(可能,但不是我的第一选择),有没有办法让NetDataContractSerializer忽略现有XML序列化对象中的字段?
我有一个场景,我需要使用NetDataContractSerializer而不是DataContractSerializer.
到目前为止,我一直在使用这种方法 - http://www.pluralsight.com/community/blogs/aaron/archive/2006/04/21/22284.aspx - 看起来很简单但是根据这个http:// social.msdn.microsoft.com/forums/en-US/wcf/thread/cb0c56c0-3016-4cda-a3c7-8826f8cc5bb0/方法不正确.
环顾四周我找到了以下内容 - http://social.msdn.microsoft.com/forums/en-US/wcf/thread/f30ecd17-cac0-4cdc-8142-90b5f411936b/
基本上你需要运行以下内容:
所以这就是我在客户端所拥有的:
ChannelFactory<IPersonService> factory = new ChannelFactory<IPersonService>("WSHttpBinding_IPersonService");
foreach (OperationDescription desc in factory.Endpoint.Contract.Operations)
{
DataContractSerializerOperationBehavior dcsOperationBehavior = desc.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
int idx = desc.Behaviors.IndexOf(dcsOperationBehavior);
desc.Behaviors.Remove(dcsOperationBehavior);
desc.Behaviors.Insert(idx, new NetDataContractSerializerOperationBehavior(desc));
//return true;
}
}
IPersonService svc = factory.CreateChannel();
Run Code Online (Sandbox Code Playgroud)
在服务器端:
myServiceHost = new ServiceHost(typeof(PersonService), baseAddress);
foreach (ServiceEndpoint endPoint in myServiceHost.Description.Endpoints)
{
foreach (OperationDescription desc in endPoint.Contract.Operations)
{
DataContractSerializerOperationBehavior dcsOperationBehavior = desc.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
int idx = …Run Code Online (Sandbox Code Playgroud) 我有一种情况,我使用NetDataContractSerializer序列化一些.NET对象,并将XML存储在数据库中,以此来记住应用程序中这些对象的状态.最近我遇到了第一种情况,其中一些代码重构属性和类型名称导致无法反序列化此XML数据.
到目前为止,我已经提出了两种不同的攻击计划,用于处理版本兼容性中断,例如使用NetDataContractSerializer本身可用的工具来控制反序列化或直接转换XML.从我的实验和研究看来,可以使用自定义SerializationBinder将其反序列化为不同的类型,并且可以通过实现ISerializable或通过实现ISurrogateSelector和ISerializationSurrogate来编写序列化代理来解决属性名称/类型更改.不幸的是,这个首选机制还没有完成,除非我可以显示,否则看起来使用代理商在NetDataContractSerializer上无法在序列化数据的版本之间移动,这是由于微软的一些无法解释的设计决定.Microsoft提出的建议是在双方使用相同的序列化,这完全违背了使用代理的目的,以便在类型名称更改或移动到不同的命名空间或程序集中时提供帮助.
要修复它,请使用相同的NetDataContractSerializer实例或另一个也使用兼容的SurrogateSelector初始化的实例.
这个解释与MSDN文章冲突,该文章说明了如何使用自定义绑定器替换类型以及处理序列化结构中的其他更改.
在反序列化期间,格式化程序看到已设置了活页夹.当每个对象即将被反序列化时,格式化程序调用绑定器的BindToType方法,向其传递格式化程序要反序列化的程序集名称和类型.此时,BindToType决定实际构造的类型并返回此类型.
请注意,如果新类型通过Serializable自定义属性使用简单序列化,则原始类型和新类型必须具有相同的确切字段名称和类型.但是,该类型的新版本可以实现ISerializable接口,然后将调用其特殊构造函数,该类型可以检查SerializationInfo对象中的值并确定如何反序列化自身.
因此,要么我能够让NetDataContractSerializer将我的V1 XML反序列化为我的V2类型,要么我将不得不手动转换XML.如果有人能够证明NetDataContractSerializer的SerializationInfo确实在使用ISerializable或使用序列化代理时确实有效,或者至少提供比Microsoft给出的更好的解释,否则我可能会发布一个新问题来讨论最好的方法在.NET中直接转换旧的XML.
更新2011-08-16: 经过一些实验,似乎ISerializable和序列化代理技术都可以正常工作,如果序列化的原始类型实现ISerializable,否则如果类型只使用[Serializable]属性,它会出现在对象中的每个字段图形以额外属性的形式缺少一些有价值的类型信息.
使用[Serializable]属性的示例
<OldClass2 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="1" z:Type="NdcsSurrogateTest.OldClass2" z:Assembly="NdcsSurrogateTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/NdcsSurrogateTest">
<_stable z:Id="2">Remains the same</_stable>
<_x003C_OldProperty_x003E_k__BackingField>23</_x003C_OldProperty_x003E_k__BackingField>
</OldClass2>
Run Code Online (Sandbox Code Playgroud)
实现ISerialzable的示例:
<OldClass2 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" z:Id="1" z:Type="NdcsSurrogateTest.OldClass2" z:Assembly="NdcsSurrogateTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/NdcsSurrogateTest">
<_stable z:Id="2" z:Type="System.String" z:Assembly="0" xmlns="">Remains the same</_stable>
<_x003C_OldProperty_x003E_k__BackingField z:Id="3" z:Type="System.Int32" z:Assembly="0" xmlns="">23</_x003C_OldProperty_x003E_k__BackingField>
</OldClass2>
Run Code Online (Sandbox Code Playgroud)
当使用带有自定义绑定器的NetDataContractSerializer反序列化第一个示例以更改类型,然后在该类型上实现ISerializable或提供指定基本上满足ISerializalbe角色的序列化代理的代理选择器时,您将在ISerializationSurrogate中看到一个空的SerializationInfo .SetObjectData方法.在第二个示例中处理xml时,SerializationInfo似乎可以获得正确的信息,并且按预期工作.
我的结论是NetDataContractSerializer为仅支持通过SerializableAttribute进行序列化的类型生成的默认XML与使用ISerializable或序列化代理技术的反序列化不兼容,因为缺少类型信息.因此,为了使NetDataContractSerializable更具未来性,可以自定义序列化以确保XML中包含此类型信息,以便可以自定义以后的反序列化,而无需手动转换源XML.
我有一系列的类,我在.NET 4.0中使用.NET的DataContractSerializer转换为XML.序列化工作正常,我可以解析XML并在以后重新创建.NET对象而没有任何困难.
但是,大多数DataMember都不是必需的.[DataMember(IsRequired = false)].这非常适用于反序列化XML,然后您可以在文档中错过XML节点,但在将现有对象序列化为XML时,DataContractSerializer坚持将具有空值的属性写为具有属性的节点,例如
[DataContract(Name = "response", Namespace = "http://domain.com/name")]
public class MyResponseClass
{
[DataMember(Name = "count", IsRequired = true, Order = 0)]
public int Count { get; set; }
[DataMember(Name = "info", IsRequired = false, Order = 1)]
public InfoClass Info { get; set; }
[DataMember(Name = "metadata", IsRequired = false, Order = 2)]
public MetadataList Metadatas { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
可以序列化
<response xmlns="http://domain.com/name">
<count>4</count>
</response>
Run Code Online (Sandbox Code Playgroud)
但是,如果我序列化对象,它会创建:
<response xmlns="http://domain.com/name" xmlns:i="http://www.w3.org/2001/XmlSchema-instance">
<count>4</count>
<info i:nil="true" />
<metadata i:nil="true" /> …Run Code Online (Sandbox Code Playgroud) .net c# xml datacontractserializer netdatacontractserializer
dataElementsList : TypesAndData.DataElement list
Run Code Online (Sandbox Code Playgroud)
是一个包含50,000条记录的列表(实际上还有更多记录,但让我们从小开始).我正在尝试序列化为JSON文件:
let ser = Json.DataContractJsonSerializer(typeof<TypesAndData.DataElement list>)
use ofs = File.OpenWrite(fileName)
let result = ser.WriteObject(ofs, dataElementsList)
Run Code Online (Sandbox Code Playgroud)
并得到臭名昭着的StackOverflowException.准确地说:
FSharp.Core.dll中发生了未处理的"System.StackOverflowException"类型异常
任何建议?
stack-overflow f# datacontractserializer netdatacontractserializer
在.NET 3.5中,我想创建一个自定义属性(比如[NetDataMember]),它将序列化行为从切换DataContractSerializer到NetDataContractSerializer.
基本上,对于A如下图所示的类
[DataContract]
class A
{
[DataMember]
public int SimpleProperty { get; set; }
[Transcient]
public IBar ComplexProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想获得一个DataContractSerializer默认行为的序列化程序,但是NetDataContractSerializer对于标记为的属性,它将被覆盖[NetDataMember].
知道如何设计一个能够实现这种行为的串行器吗?
.net serialization datacontractserializer netdatacontractserializer
我有一个我能想到的最通用的序列化示例:一个包含两个变量和一个实例的类,我想序列化.但是我遇到的问题是下面的代码总是让我得到一个空字符串.我没想到为什么会这样......
public static async void SaveState()
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(new Deck().GetType());
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, new Deck());
using (var sr = new StreamReader(stream))
{
Debug.WriteLine(sr sr.ReadToEnd());
}
}
}
[DataContract]
class Deck
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Points { get; set; } = 1500;
public Deck()
{
this.Name = "Deck Name";
}
}
Run Code Online (Sandbox Code Playgroud) c# serialization json datacontractserializer netdatacontractserializer