【问题标题】:WCF not processing MSMQ message with binary formatWCF 不处理二进制格式的 MSMQ 消息
【发布时间】:2014-06-30 02:29:29
【问题描述】:

我有一个检索 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);
}

数组参数可以是客户端可以传递的任何动态序列化类型。我认为问题出在这个参数上。如果我删除此参数和可序列化属性以及客户端中的 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();
        }
    }
}

【问题讨论】:

标签: wcf binary-serialization msmqintegrationbinding


【解决方案1】:

这里有一些事情要检查:

  1. 检查临时出站队列客户端中没有消息。如果此队列中有消息,则表明该消息无法通过网络传输。因为您的队列是事务性的,这可能意味着 MSDTC configuration(链接也支持 2012)。

  2. 在服务端的事务死信队列中检查没有消息。如果有,这表明将消息传递到服务队列时出现问题。可能的权限问题。服务帐户需要 Receive MessagePeek Message 在其队列中,客户端帐户需要 Send MessageGet Permissions获取目标队列上的属性

  3. Enable msmq logging in windows event log。这会记录盒子上所有与 MSMQ 相关的活动。服务端成功传输您应该在日志中看到 2 个事件:消息来自网络带有 ID 的消息被放入队列

    李>

【讨论】:

  • 我得到的错误是“无法找到程序集 'WCFClientApp'” 通过将 Transaction 类移动到定义 MyOrder 的库来解决问题(暂时)。但这并没有解决我的问题,因为参数(上面的字段)中的对象是从客户端(WCFClientApp 程序集)传递的。
  • 是的。但是您能否就上述问题(关于动态类型)提供一些想法
  • 你为什么要传递一个无类型对象数组?这是非常不寻常的。
  • 客户端希望将它未能保存的任何事务数据保存到磁盘(它将调用 Web 服务进行保存)。另一个应用程序将接收到此失败消息,尝试再次保存数据。现在这一次第二个应用程序将创建动态代理并通过反射调用该方法。所以挑战是如何保存这些参数(要发送),因为它可以是任何对象,以及如何检索这些参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2013-10-15
  • 2010-09-27
  • 1970-01-01
相关资源
最近更新 更多