WCF не обрабатывает сообщение MSMQ в двоичном формате

У меня есть служба Windows WCF, которая получает сообщения MSMQ. SubmitPurchaseOrderInMessage, кажется, не вызывается, и я не вижу никаких сообщений в очереди. Код показан ниже.

WCF класс:

public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    [ServiceKnownType(typeof(MyOrder))]
    public void SubmitPurchaseOrderInMessage(MsmqMessage<MyOrder> ordermsg)
    {
        MyOrder po = (MyOrder)ordermsg.Body;
        Console.WriteLine("Processing id:{0}, name:{1} ", po.ID, po.Name);
    }

    public static void Main()
    {
        //init queue
        if (!MessageQueue.Exists(Constants.QUEUE_PATH)) MessageQueue.Create(Constants.QUEUE_PATH, true);

        //init wcf host via code
        Uri baseUri = new Uri("http://localhost:7878/msmqsvc");
        using (ServiceHost host = new ServiceHost(typeof(OrderProcessorService),baseUri))
        {
            //add metadata behavior
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior(){ HttpGetEnabled=true};
            host.Description.Behaviors.Add(smb);

            //add service endpoint
            MsmqIntegrationBinding binding = new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None);
            binding.SerializationFormat = MsmqMessageSerializationFormat.Binary;
            host.AddServiceEndpoint(typeof(ClassLib.IOrderProcessor), binding, "msmq.formatname:DIRECT=OS:" + Constants.QUEUE_PATH);

            host.Open();

            // The service can now be accessed.
            Console.WriteLine("The service is ready.");
            Console.WriteLine("Press <ENTER> to terminate service.");
            Console.ReadLine();
            host.Close();
        }
    }
}

Контракт интерфейса:

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(MyOrder))]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void SubmitPurchaseOrderInMessage(MsmqMessage<MyOrder> msg);
}

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

Сериализуемый класс:

[DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[Serializable]
public class MyOrder
{
    [DataMember]
    public string ID;

    [DataMember]
    public string Name;

    [DataMember]
    public object[] Parameters;
}

[Serializable]
public class Transaction
{
    public int Amount { get; set; }
}

Клиент:

 class Program
 {
    static void Main(string[] args)
    {
        try
        {
            Run();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    static void Run()
    {
        MsmqIntegrationBinding binding = new MsmqIntegrationBinding();
        binding.Security.Mode = MsmqIntegrationSecurityMode.None;
        binding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;
        binding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;
        binding.SerializationFormat = MsmqMessageSerializationFormat.Binary;
        EndpointAddress address = new EndpointAddress("msmq.formatname:DIRECT=OS:" + Constants.QUEUE_PATH);

        ChannelFactory<ClassLib.IOrderProcessor> channelFactory = new ChannelFactory<ClassLib.IOrderProcessor>(binding, address);

        try
        {
            ClassLib.IOrderProcessor channel = channelFactory.CreateChannel();

            MyOrder order = new MyOrder();
            order.ID = DateTime.Now.Ticks.ToString();
            order.Name = "Order_" + order.ID;
            order.Parameters = new object[] { new Transaction { Amount = 108 }, new Transaction { Amount = 100 } };
            MsmqMessage<MyOrder> ordermsg = new MsmqMessage<MyOrder>(order);

            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
            {
                channel.SubmitPurchaseOrderInMessage(ordermsg);
                scope.Complete();
            }

            Console.WriteLine("Order has been submitted:{0}", ordermsg);
        }
        catch(Exception ex)
        {

        }
        finally
        {
            channelFactory.Close();
        }
    }
}

1 ответ

Вот несколько вещей для проверки:

  1. Проверьте отсутствие сообщений во временной исходящей очереди на стороне клиента. Если в этой очереди есть сообщения, это означает, что сообщение не может быть передано по сети. Поскольку ваши очереди являются транзакционными, это может означать настройку MSDTC (ссылка также поддерживает 2012).

  2. Проверьте отсутствие сообщений в транзакционной очереди недоставленных сообщений на стороне обслуживания. Если есть, это указывает на проблему доставки сообщения в очередь обслуживания. Вероятная проблема с разрешениями. Учетная запись службы требует получения сообщений и ожидающих сообщений в своей очереди, учетная запись клиента требует отправки сообщений, получения разрешений и получения свойств в целевой очереди.

  3. Включите ведение журнала msmq в журнале событий Windows. Это регистрирует все связанные с MSMQ действия на коробке. Служебная сторона для успешной передачи вы должны увидеть в журнале 2 события: Сообщение пришло по сети, а Сообщение с ID было помещено в очередь.

Другие вопросы по тегам