【问题标题】:How do I resolve this WCF exception?如何解决此 WCF 异常?
【发布时间】:2009-09-07 12:01:11
【问题描述】:

我在使用 WCF 服务时遇到问题。返回类型是一个半复杂类型,它引用了各种基本类型和每个类型继承的基本接口。

在我的调试中,序列化消息的总字节大小远低于默认的 65535 字节阈值。尽管如此,我已将 maxReceivedMessageSize 属性增加到 1000000,但问题仍然存在。

WCF服务定义如下:

[ServiceContract]
public interface ILoggingService
{
    [OperationContract]
    NotesInfo ListNotes(NotesQueryOptions options);
}

NotesInfo 返回对象的定义如下:

[DataContract]
public class NotesInfo
{
    [DataMember] public List<TokenizedNote> Notes { get; set; }
    [DataMember] public Dictionary<long, User> Users { get; set; }
    [DataMember] public Dictionary<long, NoteCategory> NoteCategories { get; set; }
    [DataMember] public Dictionary<string, Dictionary<long, IIdentifiable<long>>> EntitiesByToken { get; set; }
}

当我尝试调用服务时,抛出以下异常:

服务器没有提供 有意义的回复;这可能是由于 由于合同不匹配,过早 会话关闭或内部服务器 错误。描述:一个未处理的 期间发生异常 执行当前的 Web 请求。 请查看堆栈跟踪以获取更多信息 有关错误和位置的信息 它起源于代码。

异常详情: System.ServiceModel.CommunicationException: 服务器没有提供 有意义的回复;这可能是由于 由于合同不匹配,过早 会话关闭或内部服务器 错误。

来源错误:

Line 242:
Line 243: public AxeFrog.Mobile.NotesInfo ListNotes(AxeFrog.Mobile.NotesQueryOptions options) {
Line 244:            return base.Channel.ListNotes(options);
Line 245:        }
Line 246:    }

源文件: C:\用户\内森\工作\内部 项目\AxeFrog System\Source\Trunk\AxeFrog.Mobile.WebInterface\Service 参考\LoggingServiceReference\Reference.cs 线路:244

以下是其他相关实体的代码:

public interface IIdentifiable<TID>
{
    TID ID { get; set; }
}

[DataContract]
public class Note : IIdentifiable<long>
{
    [DataMember] public long ID { get; set; }
    [DataMember] public DateTime DateStamp { get; set; }
    [DataMember] public long? UserID { get; set; }
    [DataMember] public long NoteCategoryID { get; set; }
    [DataMember] public NoteType NoteType { get; set; }
    [DataMember] public string Message { get; set; }
}

public enum NoteType
{
    Information = 0,
    Warning = 10,
    Failure = 20
}

[DataContract]
public class NoteCategory : IIdentifiable<long>
{
    [DataMember] public long ID { get; set; }
    [DataMember] public string Name { get; set; }
}

[DataContract]
public class NoteEntityType : IIdentifiable<long>
{
    [DataMember] public long ID { get; set; }
    [DataMember] public Type TypeName { get; set; }
}

[DataContract]
public class TokenizedNote
{
    [DataMember] public Note Note { get; set; }
    [DataMember] public List<NoteSegment> NoteSegments { get; set; }
}

public abstract class NoteSegment
{
    public abstract string Render(INoteRenderer renderer, Dictionary<string, Dictionary<long, IIdentifiable<long>>> entitiesByToken);
}

[DataContract]
public class NoteTextSegment : NoteSegment
{
    [DataMember]
    public string Text { get; set; }
}

[DataContract]
public class NoteEntitySegment : NoteSegment
{
    [DataMember] public long EntityID { get; set; }
    [DataMember] public string Token { get; set; }
}

请注意,为了便于阅读,我已从 NoteSegment 的抽象实现中删除了 Render() 覆盖。

以下是来自调试器的一些信息,以便您查看返回的内容:

对我在这里可能做错的任何见解将不胜感激。谷歌搜索很少能找到有用的答案。

【问题讨论】:

  • 这是在防火墙后面的公司 LAN 上吗?在这种情况下,我会推荐 NetTcp 绑定——比标准的、重量级的 wsHttpBinding 更快、更高效...
  • 但 netTcp 需要 IIS7(Win Server 2008 或更高版本或 Vista)或自托管
  • 不,现在都在本地主机上。

标签: c# wcf


【解决方案1】:

您在客户端显示异常;当您在服务器上附加调试器(或打开日志记录)时会发生什么,看看那里有什么有用的?

【讨论】:

  • 服务器端没有错误。成功构造并返回返回对象。
  • 嗯。任何机会服务器和客户端的合同不匹配(例如,服务器合同已更改,但客户端没有)?可能需要使用例如提琴手看看发生了什么。
  • 合约接口上的其他方法有用吗?如果你只返回一个'int'怎么办?我猜可能是下一个序列化,并尝试各种数据类型,看看你是否能想出它失败/成功的条件......
  • 我有另一个服务并排返回更简单的类型,它工作正常。
  • 听起来你有一个对问题进行二分搜索的秘诀。您有一个简单类型的服务可以工作。您有一个复杂类型的服务,但没有。开始把简单的变成复杂的,一步一步,直到失败,找到不同的失败轴,直到你理解问题。
【解决方案2】:

这可能是由于消息过长造成的。您应该尝试通过编辑 app.config 来更改限制,如下所示:

<binding name="WebBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
  <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
    maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

【讨论】:

  • 感谢您的回复。问题开头段落的第三句是:“在我的调试中,序列化消息的总字节大小远低于默认的 65535 字节阈值。”
  • @Nathan :消息长度不是唯一有意义的阈值。即检查 maxArrayLength 参数
【解决方案3】:

可能是您的服务器花费了一点时间来整理响应吗?客户端上的默认“sendTimeout”只有 60 秒 - 您可以尝试将其增加到更高的值:

<binding name="TweakedBinding" sendTimeout="120" />

您的客户端配置是什么样的?你用的是什么绑定?什么安全设置?

马克

更新:
您能否将服务调试行为添加到您的服务中,以便在出现问题时在客户端获得更多调试和错误信息??

<behaviors>
  <serviceBehavior>
    <behavior name="YourBehaviorName">
       <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehavior>
</behaviors>

【讨论】:

  • 不,响应非常快。我刚刚更新了问题以显示调试器信息的屏幕截图。
  • 绑定和安全配置都是Visual Studio生成的默认值。该服务通过 ASP.Net 并设置为通过 IIS 而不是内置的 Web 服务器运行。
【解决方案4】:

这个问题已经很老了,但我会把它扔在那里以防其他人发现它有用。我对这里发生的事情的猜测是从 NoteSegment 继承 - 您需要使用 KnownType 属性来告诉 TokenizedNote 对象它在反序列化时可以期待 NoteTextSegment 和 NoteEntitySegment(因为默认情况下它只会期待 NoteSegment 的实例)。

[DataContract]
[KnownType(typeof(NoteEntitySegment)]
[KnownType(typeof(NoteTextSegment)]
public class TokenizedNote
{
    [DataMember] public Note Note { get; set; }
    [DataMember] public List<NoteSegment> NoteSegments { get; set; }
}

详情请参阅此资源:http://msdn.microsoft.com/en-us/library/ms730167(v=vs.110).aspx

【讨论】:

    【解决方案5】:

    我遇到了类似的问题。在花了 2 个小时思考这个问题并试图在网上找到答案之后,我决定遵循使用 System.Runtime.Serialization.DataContractSerializer 在服务器端序列化和反序列化返回值/对象的方法,最后发现我错过了在其中一个枚举上添加 EnumMember 属性。

    这是帮助我解决问题的代码 sn-p:

          var dataContractSerializer = new System.Runtime.Serialization.DataContractSerializer(typeof(MyObject));
          byte[] serializedBytes;
            using (System.IO.MemoryStream mem1 = new System.IO.MemoryStream())
            {
                dataContractSerializer.WriteObject(mem1, results);
                serializedBytes = mem1.ToArray();
            }
    
            MyObject deserializedResult;
            using (System.IO.MemoryStream mem2 = new System.IO.MemoryStream(serializedBytes))
            {
                deserializedResult = (MyObject)dataContractSerializer.ReadObject(mem2);
            }
    

    【讨论】:

      【解决方案6】:

      打开 IIS,选择站点,点击“基本设置”,然后点击“测试设置”。我忽略的是该站点需要有效的凭据及其应用程序池。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-03
        • 2021-08-04
        • 1970-01-01
        • 2015-10-01
        相关资源
        最近更新 更多