从服务契约的RealProxy中抛出WCF故障异常

时间:2017-02-07 14:54:13

标签: c# wcf uwp faultexception realproxy

我有一个带有WCF后端和UWP前端的C#应用​​程序。我有一项服务实施我的服务合同。如果我捕获服务上的异常并将它们重新抛出为Fault Exceptions,那么一切都按预期工作。

现在,我正在尝试通过使用RealProxy实例包装服务调用并从代理中抛出故障异常来清理我的服务代码。不幸的是,现在当服务上抛出异常时,我的客户端收到一个异常,其中包含以下消息:

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

我有以下服务合同:

[ServiceContract(Namespace = @"blah/blah/blah", SessionModel = SessionMode.Required)
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(Exception))]
    bool DoSomething(Setting setting);
}

通过以下实施:

[Export(typeof(IService1)]
[ServiceBehavior(InstanceContextMode = IntanceContextMode.Single,
    ConcurrencyMode = ConcurrencyModel.Single]
public class Service1 : IService1
{
    bool DoSomthing(Setting setting)
    {
        try
        {
            throw new ArgumentException("setting");
        }
        catch (Exception ex)
        {
            throw WrapException(ex);
        }
    } 

    private FaultException<Exception> WrapException(Exception ex)
    {
        string message = exception.GetBaseException().Message;
        Console.WriteLine(string.Format("Exception: {0}", message));
        return new FaultException<Exception>(exception, new FaultReason(message));
    }
}

我的WCF服务主机具有以下配置,并在客户端具有相应的配置。

<system.serviceModel>
    <services>
      <service name="Host.Services.Service1">
        <endpoint address="net.tcp://localhost:8082/Service1" 
            binding="netTcpBinding" 
            contract="Host.Domain.IService1"/>
      </service>
    </services>
    <bindings>
      <netTcpBinding>
        <binding maxReceivedMessageSize="1000000">
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

现在,我已经创建了一个代理:

public class ServiceProxy<T> : RealProxy
    {
        private readonly T _instance;

        private ServiceProxy(T instance)
        : base(typeof(T))
        {
            _instance = instance;
        }

        public static T Create(T instance)
        {
            return (T) new ServiceProxy<T>(instance).GetTransparentProxy();
        }

        public override IMessage Invoke(IMessage msg)
        {
            var methodCall = (IMethodCallMessage) msg;
            var method = (MethodInfo) methodCall.MethodBase;

            try
            {
                var result = method.Invoke(_instance, methodCall.InArgs);
                return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
            }
            catch (Exception ex)
            {
                string message = ex.GetBaseException().Message;
                Console.WriteLine(string.Format("Exception: {0}", message));
                var wrapped = new FaultException<Exception>(ex, new FaultReason(message));

                return new ReturnMessage(wrapped, msg as IMethodCallMessage);
            }
        }
    }

(感谢@bradmo的想法。)

Dynamically creating a proxy class

我正在使用代理作为我的服务:

static void Main(string[] args)
{
    try
    {
        var service = new Bootstrapper().Run().GetExport<IService1>().Value;
        IService1 proxy = ServiceProxy<IService1>.Create(service);

          using (var host = new ServiceHost(proxy))
          {
                host.Open();
                Console.WriteLine("Running...");
                Console.ReadLine();
          }
     }
     catch (Exception ex)
     {
          Console.WriteLine(string.Format("Exception: {0}", ex.GetBaseException().Message));
          Console.ReadLine();
     }
  }
}

在没有代理的情况下抛出错误异常并且当没有异常时代理工作正常但是当我使用代理来包装异常时,我在客户端遇到以下错误:

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

1 个答案:

答案 0 :(得分:0)

问题似乎与你的FaultContract的定义方式有关。

尝试沿着这些方向做一些事情,看看它是否有帮助:

public interface IService
{
    [OperationContract]
    [FaultContract(typeof(WrappedExceptionFault))]
    bool DoSomething(string setting);
}

[DataContract]
public class WrappedExceptionFault
{
    [DataMember]
    public string Message { get; set; }
}

public class Service : IService
{
    public bool DoSomething(string setting)
    {
        try
        {
            throw new ArgumentException(setting);
        }
        catch (Exception ex)
        {
            throw WrapException(ex);
        }
    }

    private FaultException<WrappedExceptionFault> WrapException(Exception ex)
    {
        string message = ex.GetBaseException().Message;
        Console.WriteLine(string.Format("Exception: {0}", message));
        WrappedExceptionFault fault = new WrappedExceptionFault()
        {
            Message = message,
        };

        return new FaultException<WrappedExceptionFault>(fault, new FaultReason(message));
    }
}

另外:你不应该将你的serviceHost包裹在&#39;使用&#39;条款......你只是在寻找重大麻烦。考虑做这样的事情:

        ServiceHost host = new ServiceHost(proxy);
        host.Open();
        Console.WriteLine("Running...");
        Console.ReadLine();

        try
        {
            host.Close();
        }
        catch
        {
            host.Abort();
        }