2017-02-07 8 views
1

У меня есть приложение C# с внутренним интерфейсом WCF и интерфейсом UWP. У меня есть сервис, реализующий мой контракт на обслуживание. Все работает так, как ожидалось, если я поймаю исключения из сервисов и повторно выброшу их как исключения ошибок.Throwing Ошибка WCF Исключение из RealProxy договора на обслуживание

Теперь я пытаюсь очистить свой служебный код, завернув вызов службы с помощью экземпляра RealProxy и выбросив мои исключения Fault из прокси. К сожалению, теперь, когда на службу отправляется исключение, мой клиент получает исключение со следующим сообщением:

«Сервер не дал значимого ответа, это может быть вызвано несоответствием контракта, преждевременным отключением сеанса или внутренняя ошибка сервера. "

У меня есть следующий контракт на обслуживание:

[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> 

Теперь, я создал прокси-сервер: (. Спасибо к @bradmo за идею)

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); 
      } 
     } 
    } 

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(); 
    } 
    } 
} 

Ошибки сбрасывания Исключения без прокси-сервера прекрасно работают, и прокси работает нормально, когда нет исключений, но когда я использую прокси-сервер для обертывания исключения, я получаю следующую ошибку на стороне клиента:

«Сервер не предоставил значимый ответ; это может быть вызвано несоответствием контракта, преждевременной остановкой сеанса или ошибкой внутреннего сервера.»

ответ

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 вокруг «используя» п .. вы просто просите крупные неприятности Рассмотрят делать что-то вроде этого:.

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

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

Спасибо за ваш ответ. Почему это плохо, чтобы обернуть узел службы в 'use'? –

+0

В Интернете есть много документации по этому вопросу. Вот несколько статей, объясняющих почему: https://philmunro.wordpress.com/2011/03/07/wcf-using-gotcha/ && https://msdn.microsoft.com/en-us/library/aa355056 (v = vs.110) .aspx –

+0

Это уже трюк. Благодарю. –

 Смежные вопросы

  • Нет связанных вопросов^_^