1

MSMQ メッセージを取得する WCF Windows サービスがあります。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);
}

配列 Parameters は、クライアントが渡すことができる任意の動的なシリアル化可能な型にすることができます。問題はこのパラメータにあると思います。このパラメーターとシリアライズ可能な属性、およびクライアントの 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();
        }
    }
}
4

1 に答える 1

0

確認すべき点は次のとおりです。

  1. クライアント側の一時送信キューにメッセージがないことを確認します。このキューにメッセージがある場合は、メッセージをネットワーク経由で送信できないことを示しています。キューはトランザクション対応であるため、これはMSDTC 構成を意味する可能性があります(リンクは 2012 もサポートしています)。

  2. サービス側のトランザクション デッド レター キューにメッセージがないことを確認します。存在する場合、サービス キューへのメッセージの配信に問題があることを示しています。権限の問題の可能性があります。サービス アカウントには、そのキューにReceive MessagePeek Messageが必要です。クライアント アカウントには、宛先キューにSend MessageGet Permissions、およびGet Propertiesが必要です。

  3. Windows イベント ログで msmq ログを有効にします。これにより、MSMQ に関連するすべてのアクティビティがボックスに記録されます。送信が成功した場合、サービス側では、ログに 2 つのイベントが表示されます。Message came over networkMessage with ID was put into queueです。

于 2014-06-30T08:24:28.050 に答える