MSMQ, сообщение помещается в очередь и исчезает, но никогда не принимается договором на обслуживание

У меня есть локальная частная очередь. У меня также есть WCF-сервис внутри MVC-приложения, которое прослушивает очередь, используя msmqIntegrationBinding. Проблема в том, что сервисный контракт никогда не вызывается, когда сообщение ставится в очередь, но сообщение исчезает через мгновение. Сообщение не находится в очереди ядов. Вот часть config, где я объявляю привязку к очереди:

<services>
  <service name="SkruvInfo.Web.Service.QueueMessageReceiver">
    <endpoint address="msmq.formatname:DIRECT=OS:LEIA\private$\screwinfo_autotests_messagequeue"
                      binding="msmqIntegrationBinding"
                      bindingConfiguration="MsmqBinding"
                      contract="SkruvInfo.Web.Service.IQueueMessageReceiver" />
  </service>
</services>

А вот и контракт:

[ServiceContract(Namespace = "http://localhost/SkruvWeb/Service")]
public interface IQueueMessageReceiver
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void PutScrewInfoMessage(MsmqMessage<string> msg);
}

А вот метод в сервисе:

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void PutScrewInfoMessage(System.ServiceModel.MsmqIntegration.MsmqMessage<string> msg)
    {
        log4net.Config.XmlConfigurator.Configure();
        var log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        try
        {
            log.Debug("Message from queue: " + msg.Body.ToString(CultureInfo.InvariantCulture));
            var xDoc = new XmlDocument();
            xDoc.LoadXml(msg.Body);
            CacheScrewInfoModelFromScrewInfoXmlDoc(xDoc);
        }
        catch (Exception e)
        {
            log.Error("Error parsing message from queue",e);
            EventLog.WriteEntry("Application","Message error for screws");
        }
    }

Любые предложения, почему сообщение исчезает, но не вызывает службу?

2 ответа

Попробуйте изменить свой сервисный контракт с атрибутом ServiceKnownType:

[ServiceContract(Namespace = "http://localhost/SkruvWeb/Service")]
[ServiceKnownType(typeof(String))]
public interface IQueueMessageReceiver
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void PutScrewInfoMessage(MsmqMessage<string> msg);
}

ОБНОВИТЬ

Если вы используете MsmqIntegrationBinding, я предполагаю, что ваш клиент очереди является устаревшим приложением, таким как клиент VB6? Если это так, вам нужно будет указать формат сериализации в конфигурации привязки вашего сервиса. Например:

  <msmqIntegrationBinding>
    <binding name="MsmqBinding" serializationFormat="ActiveX">
      <security mode="None" />
    </binding>
  </msmqIntegrationBinding>

Допустимые значения задокументированы здесь.

По моему опыту, такое поведение вызвано ошибкой сериализации или слишком большим сообщением (максимальный размер сообщений по умолчанию - 64 КБ). Это приводит к сбою WCF (да, я тоже не понимаю этот выбор дизайна), но все равно удаляю сообщение из очереди.

Просто включите трассировку, и вы быстро увидите исключение в WCF, которое вызывает это.

Добавьте это в ваш web.config (он у меня чуть ниже ) для грубой настройки трассировки. Убедитесь, что у пользователя AppPool есть доступ на запись в папку журналов.

<system.diagnostics>
    <trace autoflush="true" indentsize="4" />
    <sources>
      <source name="System.ServiceModel" switchValue="Warning">
        <listeners>
          <add name="textLogger" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="textLogger"
           type="System.Diagnostics.TextWriterTraceListener"
           initializeData="C:\logs\webbackend_wcf_log.txt" />
</system.diagnostics>
Другие вопросы по тегам