2009-07-05 2 views
0

Я пытаюсь реализовать очень базовую надежную систему обработки сообщений, чтобы обеспечить повышенную надежность в моей связи Silverlight с WCF-сервером.Проблема Реализация собственного дизайна надежной службы WCF для SilverLight (basicHttpBinding)

Я взял путь введения пользовательского заголовка сообщения в запрос SOAP, который содержит инкрементирующее целое число как идентификатор сообщения. Идея состоит в том, что когда я получаю запрос на сервере WCF, я хочу проверить идентификатор сообщения. Если идентификатором является> последний идентификатор, я просто выполняю запрос и ПОСЛЕ запроса, я кэширую копию результата вместе с новым идентификатором.

Если идентификатор == lastID, я предполагаю, что клиент никогда не получал мое сообщение, и я хочу просто вернуть объект ответа cache'd вместо повторной обработки запроса. Я написал объект MessageInspector Behavior, который я вставляю в поведение конечной точки WCF. Этот объект реализует IDispatchMessageInspector, который имеет 2 метода:

object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext) 
{ 
    // Get the incoming message headers and get the messageId 
    var idx = request.Headers.FindHeader("ClientRequestId", ""); 
    if (idx >= 0) 
    { 
     var requestHeader = request.Headers[idx]; 
     int requestId = 0; 
     if (Int32.TryParse(requestHeader.ToString(), out requestId)) 
     { 
      int lastRequest = myCache.GetLastId(); 
      if (requestId <= lastRequest) 
      { 
       // @TODO - Send back the saved message 
       var reply = myCache.GetLastResponse(); 
       if (reply != null) 
       { 
        /// ERK -- > Woops, how do I override the service 
        /// and make the reply here? 
       } 
      } 
      myCache.SetLastId(requestId); 
     } 
    } 
    return null; 
} 

void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) 
{ 
    var requestId = myCache.GetLastId(); 
    if (requestId > 0) 
    { 
     myCache.SetLastResponse(reply); 
    } 
} 

Ну, проблема, которую я столкнулся должно быть очевидно ... The AfterReceiveRequest возвращаемое значение (объект) значение передается BeforeSendReply как "correlatedState". НЕ, как я и предполагал, новое возвращаемое значение для запроса. Вопрос в том, могу ли я остановить обработку сообщения в службе в этом месте и вернуть ответ «кэшированный»?

На самом деле лучшая версия этого вопроса: это подходящее место для «инъекции» для обработки отслеживания кеширования и отклика? Если нет, где будет «утвержденный ms» или лучший способ выполнить отслеживание и восстановление этого запроса?

спасибо.

-Джефф

ответ

0

После долгих испытаний и несчастий я нашел решение своей проблемы, которая, если не элегантная, функциональна.

Чтобы обойти вызов конечной точки службы при обнаружении дублирующего запроса на обслуживание, я просто бросаю FaultException. Затем в методе BeforeSendReply я проверяю, есть ли replay.IsFault, а затем, если неисправность является конкретным кодом ошибки, я бросил AfterReceiveRequest. Если это так, я возвращаю кэшированную копию ответа на сообщение. Механизм FaultException - это то, что мне нужно использовать для обхода служебного вызова.

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

-Jeff

0

я думаю, что вы пытаетесь заново изобретать колесо немного здесь. WCF имеет Reliable Messaging, который предназначен для обеспечения доставки сообщений. Я бы попробовал это, если только вы не хотите использовать его по определенной причине?

+0

Да, но, насколько мне известно, надежный обмен сообщениями WCF НЕ доступен в silverlight. Silverlight реализует только basicHttpBinding, который из того, что я читал, не поддерживает надежную передачу сообщений. – Jeff