首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SerializationException不去IErrorHandler

SerializationException不去IErrorHandler
EN

Stack Overflow用户
提问于 2013-12-31 21:44:02
回答 2查看 380关注 0票数 2

当试图反序列化一个相对较大的对象图~10000行时,我看到了一些奇怪的行为,其中有6列。我确信问题是,当试图将这个数组从服务反序列化回客户机时会出现序列化异常。对于少于9000个对象的数据集,它工作得很好,控制台窗口显示了第一次机会SerializationException和一个CommunicationException。我是自我托管这个服务在一个控制台应用程序,因为我使用它与第三方api集成。我的第一个问题是,有没有人知道是什么原因导致了这种异常?

我在客户端和服务器上以下面的方式配置绑定,我认为我已经将它转换为可能的最大值。

代码语言:javascript
复制
public static NetTcpBinding CreateStandardNetTcpBinding()
    {
        NetTcpBinding b = new NetTcpBinding(SecurityMode.None);
        b.OpenTimeout = new TimeSpan(0, 5, 0);
        b.ReceiveTimeout = new TimeSpan(0, 5, 0);
        b.SendTimeout = new TimeSpan(0, 5, 0);

        b.MaxReceivedMessageSize = Int32.MaxValue;
        b.MaxBufferSize =(int) b.MaxReceivedMessageSize;
        b.MaxBufferPoolSize = (int) b.MaxReceivedMessageSize;
        b.TransferMode= TransferMode.Buffered;



        b.ReaderQuotas.MaxNameTableCharCount = Int32.MaxValue;
        b.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
        b.ReaderQuotas.MaxBytesPerRead = 4096;
        b.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
        b.ReaderQuotas.MaxDepth = 32;
        return b;
    }

我的第二个问题是,为什么这个例外不引发ProvideFault接口上的IErrorHandler方法。当我在ServiceOperation中引发异常时,ProvideFault方法确实会被引发。WCF框架异常不是也被IErrorHandler捕获了吗?但是对于这个特定的问题,WCF似乎在捕获序列化异常后突然/立即关闭通道(因此超时是不可能的)。

'System.Runtime.Serialization.SerializationException‘型的一次偶然异常发生在System.Runtime.Serialization.dll中--System.ServiceModel.CommunicationException型的第一次偶然异常发生在System.ServiceModel.dll中 套接字连接被中止。这可能是由于处理邮件时出错、远程主机超过接收超时或基础网络资源问题造成的。本地套接字超时时间是'00:04:59.8939894‘。

我的第三个问题是,有人知道如何以编程方式添加WCF跟踪侦听器吗?我在一个插件环境中工作,在这个环境中,应用程序没有专用的app.config文件。

谢谢!

编辑

是的,这就是问题所在。缺省值大约是64K,这是我碰到的。一个解决办法是

在servicebehavior属性ServiceBehavior(IncludeExceptionDetailInFaults = true,MaxItemsInObjectGraph =int.MaxValue中设置MaxItemsInObjectGraph值)

把客户端的尺寸设置成这样.

代码语言:javascript
复制
var behaviors = Endpoint.Contract.Operations
                                .Select(o => o.Behaviors.Find<DataContractSerializerOperationBehavior>())
                                .Where(behavior => behavior != null);
        foreach (var serializationBehavior in behaviors)
        {
            serializationBehavior.MaxItemsInObjectGraph = int.MaxValue;
        }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-01 06:13:03

不是百分之百肯定,但我会在这里尝试一些答案。

您可能会遇到DataContractSerializerDataContractSerializer属性。但是,根据MSDN,缺省值是Int32.MaxValue (2,147,483,647),所以如果您没有触及该值,我不认为是这样的。

另一种选择可能是增加MaxDepth配额,但在此之前,我的钱将放在MaxItemsInObjectGraph上。

如何将创建的绑定分配给服务和客户端?MSDN建议为服务端提供以下代码:

代码语言:javascript
复制
OperationDescription operation = host.Description.Endpoints[0].Contract.Operations.Find("MyOperationName");
operation.Behaviors.Find<DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = 3;

不确定它将如何应用于客户端(而不深入了解更多)。

对于第二个问题,MSDN有点不清楚,但是序列化错误似乎不能由IErrorHandler来处理:

Exceptions can occur after all ProvideFault implementations are called and a response message is handed to the channel. If a channel exception occurs (for example, difficulty serializing the message) IErrorHandler objects are notified. In this case, you should still make sure that your development environment catches and displays such exceptions to you or makes use of tracing to discover the problem. For more information about tracing, see Using Tracing to Troubleshoot Your Application.

对于最后一个问题,似乎可以编程地启用WCF跟踪,但有点费解:如何在不使用配置文件(以编程方式)的情况下启用wcf跟踪?

不确定这些是否能解决你的问题,但希望它能给你一些可供探索的选择。

票数 1
EN

Stack Overflow用户

发布于 2017-06-21 14:14:44

至于问题标题中描述的问题,可以使用SerializationException来捕获IDispatchMessageInspector

代码语言:javascript
复制
public class DispatcherExceptionHandler : IDispatchMessageInspector
{

    public object AfterReceiveRequest(
        ref Message request, 
        IClientChannel channel, 
        InstanceContext instanceContext) => null;

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        try
        {
            reply.ToString();
        }
        catch (Exception e)
        {
            var faultCode = FaultCode.CreateSenderFaultCode(null);
            var faultReason = new FaultReason(e.GetBaseException().Message);

            reply = Message.CreateMessage(
                reply.Version,
                MessageFault.CreateFault(faultCode, faultReason),
                null);
        }
    }
}

若要设置检查器,请使用服务行为

代码语言:javascript
复制
public class HandleDispatcherExceptionsServiceBehavior : IServiceBehavior
{
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (var dispatchRuntime in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(ch => ch.Endpoints).Select(epd => epd.DispatchRuntime))
            dispatchRuntime.MessageInspectors.Add(new DispatcherExceptionHandler());
    }

    // (...)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20863496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档