返回接口类型时服务中断 - 序列化问题?

Posted

技术标签:

【中文标题】返回接口类型时服务中断 - 序列化问题?【英文标题】:Service breaking when returning an Interface type - Serialization issue? 【发布时间】:2019-09-25 23:06:21 【问题描述】:

我的系统由以下部分组成:

通过代理与服务通信的客户端脚本 实现服务合同的服务 此服务通过使用/引用 Session.dll 和 SessionContracts.dll(均从不同的命名空间编译)来创建会话

服务代码运行,但代理在返回时中断 (System.ServiceModel.CommunicationObjectFaultedException)。请参阅下面的代码(可能与返回接口类型有关?):

请注意,在这种情况下通道会中断,但如果我返回 null 而不是会话,它不会再中断。

namespace SessionContracts  
  
    public interface ISessionBase
    
        void Connect();
    


namespace SessionNameSpace  
  
    [DataContract]  
    //    [KnownType(typeof(SessionBase))]     // Needed???
    [KnownType(typeof(ISessionBase))]  
    public class SessionBase : ISessionBase  
      
        public SessionBase() 
          
             
        public void Connect()  
          
          
      
  

namespace Device.ServiceContract

    [ServiceContract(Namespace = "http://Device.Service", CallbackContract = typeof(IDeviceServiceCallback))]
    public interface IDeviceService
    
        [OperationContract]
        ISessionBase CreateSession(Uin16 id);
    


// This code works, but break within the Proxy on return
namespace Device.Service

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                     ConcurrencyMode = ConcurrencyMode.Multiple)]

    public class DeviceService : IDeviceService
    
        public DeviceService()  

        ISessionBase CreateSession(Uin16 id) // Id not used for now
        
            return new SessionBase();
        
    


// Proxy breaking on return
namespace Device.Proxy

    public class DeviceProxy : IDeviceService
    
        public readonly IDeviceService _channel = null;

        private DeviceProxy()
        
            // Channel factory stuffs here…
        
    

    private static DeviceProxy _instance = null;
    public static DeviceProxy Instance() => _instance ?? (_instance = new DeviceProxy());

    public ISessionBase CreateSession(UInt16 id)
    
        ISessionBase a = _channel?.CreateSession(id);   // This line breaks
        return a;
    
    

编辑,添加异常详情:

服务器没有提供有意义的回复;这可能是由于合同不匹配、会话过早关闭或内部服务器错误造成的。

Server stack trace:  
   at System.ServiceModel.Channels.CommunicationObject.ThrowIfFaulted()  
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)  
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)  
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:   
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)  
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)  
   at Device.ServiceContract.IDeviceService.CreateSession()  
   at Device.Proxy.DeviceProxy.CreateSession() in E:\...\Device.Proxy\DeviceProxy.cs:line 71  
   at Client1.Program.Main(String[] args) in E:\...\Client1\Program.cs:line 97  

【问题讨论】:

请阅读How to Ask 并定义“中断”。实际发生了什么,您尝试过什么? 我添加了代码中断时返回的错误 这是一个异常类型。显示异常消息,并检查是否存在任何 InnerExceptions。该消息或内部异常将告诉您究竟出了什么问题。同样,请阅读How to Ask 并帮助我们帮助您。我们无法从这段代码和那个异常类型名称中猜测出什么问题。 谢谢,我已经更新了我的问题(添加了有关错误的更多详细信息) 这是堆栈跟踪,仍然不是消息或内部异常。 【参考方案1】:

我认为服务合同中的 CreateSession 需要更多地了解所支持的会话类型(必须使用 ServiceKnownType)。如果不这样做,服务就无法知道如何序列化此类数据。

以下是缺少的内容:

namespace Device.ServiceContract

    [ServiceContract(Namespace = "http://Device.Service", CallbackContract = typeof(IDeviceServiceCallback))]
    public interface IDeviceService
    
        [OperationContract]
        [ServiceKnownType(typeof(SessionBase))]
        ISessionBase CreateSession(Uin16 id);
    

【讨论】:

以上是关于返回接口类型时服务中断 - 序列化问题?的主要内容,如果未能解决你的问题,请参考以下文章

25 服务接口的结构

Linux内核中断之中断申请接口

2021-01-06控制层请求入参包含枚举类型时序列化的一点问题

PHP 7 接口,返回类型提示和自我

PHP 7接口,返回类型提示和自我

complex类 序列化时 IsRequired = true 问题