2015-12-08 2 views
0

У меня есть этот сервис:OperationContext равно нулю в методах асинхронными

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)] 
    public class CalculadoraService : ICalculadoraService 
    { 
     public int Add(int num1, int num2) 
     { 
      if(OperationContext.Current == null) 
      { 
       return -2; 
      } 
      else if(OperationContext.Current.SessionId == null) 
      { 
       return -1; 
      } 

      return num1 + num2; 
     } 



     public async Task<int> AddAsync(int num1, int num2) 
     { 
      return await Task<int>.Run(() => 
      { 
       if (OperationContext.Current == null) 
       { 
        return -2; 
       } 
       else if (OperationContext.Current.SessionId == null) 
       { 
        return -1; 
       } 

       return num1 + num2; 
      }); 
     } 
    } 

И это файл приложения конфигурации:

<system.serviceModel> 
    <services> 
     <service name="WCFCalculadoraService.CalculadoraService"> 
     <!--El endpoint correspondiente al contrato de la calculadora. ¿Se puede tener más para otros contratos y aplicaciones?--> 
     <!--<endpoint address="" binding="basicHttpBinding" contract="WCFCalculadoraService.ICalculadoraService">--> 
     <endpoint address="" binding="netHttpBinding" contract="WCFCalculadoraService.ICalculadoraService"> 
      <identity> 
      <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <!--Esto sirve para poder intercambiar información--> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8733/Design_Time_Addresses/WCFCalculadoraService/Service1/" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 


    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <!-- To avoid disclosing metadata information, 
      set the values below to false before deployment --> 
      <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, 
      set the value below to true. Set to false before deployment 
      to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 

Это мой прокси-сервер, чтобы потреблять услугу от моего клиента:

public class WCFCalculadoraServiceProxy : ClientBase<ICalculadoraService> 
    { 
     public int Add(int num1, int num2) 
     { 
      //Lo que hace es llamar al método del servicio. 
      return base.Channel.Add(num1, num2); 
     } 

     public async Task<int> AddAsync(int num1, int num2) 
     { 
      //Lo que hace es llamar al método del servicio. 
      return await base.Channel.AddAsync(num1, num2); 
     } 
    } 

Когда я вызываю метод Add, я получаю -1 как результат, потому что OperationContext.SessionID имеет значение NULL. если я звоню в AddAsync, тогда я получаю -2, потому что OperationContext имеет значение null.

Я хотел бы знать, как я могу получить SessionID в обоих случаях, методы синхронизации и асинхронизации, потому что я хотел бы сохранить SessionID в статической переменной.

Большое спасибо.

+2

ли SessionMode установить либо разрешено или требуется? Когда вы делаете вывод из ClientBase , вы получаете также T, чтобы вы правильно определили методы. – Maximus

ответ

0

Во-первых, нет необходимости писать асинхронные эквиваленты, поскольку VS может это сделать. Все, что вам нужно сделать, это Add Service ссылка -> Дополнительно -> Разрешить генерацию асинхронных операций

Во-вторых, если OperationContext.Current.SessionId равен нулю, что указывает на то, что ни одна сессия не поддерживается. У вас может не быть установлен параметр SessionMode равным либо разрешенным, либо обязательным.

Последнее, но не менее важное: если у вас нет прокси-класса клиента, сгенерированного автоматически, то выведите его из базы данных ClientBase или DuplexClientBase, а затем выведите из T так, чтобы у вас были правильно определены методы.

0

Для того чтобы OperationContext.Current.SessionOd не был пустым, вы должны настроить свой служебный интерфейс, чтобы потребовать сеанс, используя атрибут [ServiceContract(SessionMode=SessionMode.Required)] в определении интерфейса.

OperationContext.Current - это локальный поток, что означает, что он связан с потоком, созданным WCF. Он не будет доступен для потока ниток, используемого Task.Run. Но это довольно легко хранить идентификатор сессии для переменной перед вызовом Task.Run:

public async Task<int> AddAsync(int num1, int num2) 
{ 
    var context = OperationContext.Current 
    var sessionId = OperationContext.Current.SessionId; 
    return await Task<int>.Run(() => 
    { 
     if (context == null) 
     { 
      return -2; 
     } 
     else if (sessionId == null) 
     { 
      return -1; 
     } 

     return num1 + num2; 
    }); 
} 
Смежные вопросы