简体   繁体   English

MsmqIntegrationBinding是否支持多个服务操作

[英]Does MsmqIntegrationBinding support multiple service operations

I'm learning about MsmqIntegrationBinding. 我正在学习MsmqIntegrationBinding。 All the samples and guidelines I've seen so far were covering scenario where, there is just one operation with one data contract. 到目前为止,我看到的所有样本和指南都涵盖了这样的情况:只有一个操作只有一个数据合同。 I tried to add another contract and the service started successfully. 我尝试添加另一个合同,服务已成功启动。 However I cannot figure out how to reach the second operation. 但是我无法弄清楚如何进行第二次操作。 Is such thing even possible with this binding? 这种绑定是否可以实现这一点?

[ServiceContract]
[ServiceKnownType(typeof(Data1))]
[ServiceKnownType(typeof(Data2))]
public interface ISampleService
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void Operation1(MsmqMessage<Data1> msg);

    [OperationContract(IsOneWay = true)]
    void Operation2(MsmqMessage<Data2> msg);
}

public class SampleService : ISampleService
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void Operation1(MsmqMessage<Data1> msg)
    {
        var data = msg.Body;
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void Operation2(MsmqMessage<Data2> msg)
    {
        var data = msg.Body;
    }
}

Calling code 调用代码

var queue = new MessageQueue(@".\private$\samplequeue");
var body = new Data1() { Data = "some data" };
var message = new Message(body);
message.Label = "some label";
queue.Send(body, MessageQueueTransactionType.Single);

This will fire the Operation1 which has Action set to "*". 这将触发Action1设置为“*”的Operation1。

Not sure this is an answer and I don't have the required 50 reputation to comment. 不确定这是一个答案,我没有评论所需的50个声誉。

Taking inspiration from this answer: https://stackoverflow.com/a/33154517/1095296 we're doing the following. 从这个答案中获取灵感: https//stackoverflow.com/a/33154517/1095296我们正在做以下事情。

[ServiceContract]
public interface IMSMQueueHandler
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void Handle(MsmqMessage<object> message);
}

Then we have a constructor on a class wrapping the service host 然后我们在包装服务主机的类上有一个构造函数

    public MSMQueueServiceHost(IMSMQConfig msmqConfig, IMSMQueueHandler handler)
    {
        _hostService = new ServiceHost(handler);

        AddHostServiceEndPoint(msmqConfig);

        _hostService.Open();
    }

    private void AddHostServiceEndPoint(IMSMQConfig msmqConfig)
    {
        ServiceMetadataBehavior smb = new ServiceMetadataBehavior { HttpGetEnabled = false };
        _hostService.Description.Behaviors.Add(smb);

        MsmqIntegrationBinding binding = new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None);
        binding.SerializationFormat = MsmqMessageSerializationFormat.Stream;
        binding.ReceiveErrorHandling = ReceiveErrorHandling.Move;

        ServiceEndpoint endpoint = _hostService.AddServiceEndpoint(
            typeof(IMSMQueueHandler),
            binding, 
            string.Format("msmq.formatname:DIRECT=OS:{0}", msmqConfig.MsmqPath));

        // enforce ServiceBehaviours and OperationBehaviours so we dont have to decorate all the handlers
        _hostService.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
        _hostService.Description.Behaviors.Find<ServiceBehaviorAttribute>().ConcurrencyMode = ConcurrencyMode.Single;

        AddKnownTypes(endpoint);
    }

    private static void AddKnownTypes(ServiceEndpoint endpoint)
    {
        foreach(OperationDescription operation in endpoint.Contract.Operations)
        {
            operation.KnownTypes.Add(typeof(XElement));
            operation.Behaviors.Find<OperationBehaviorAttribute>().TransactionScopeRequired = true;
            operation.Behaviors.Find<OperationBehaviorAttribute>().TransactionAutoComplete = true;
        }
    }

The key lines of code here to make it work are: 这里使代码的关键代码是:

[OperationContract(IsOneWay = true, Action = "*")]
void Handle(MsmqMessage<object> message);

binding.SerializationFormat = MsmqMessageSerializationFormat.Stream;

operation.KnownTypes.Add(typeof(XElement));

The reason for the Stream format is we were seeing the XML in the message body wrapped in braces (smells like JSON but we saw no reason why). Stream格式的原因是我们看到消息体中的XML包裹在大括号中(闻起来像JSON,但我们没有看到原因)。

Finally, and the reason I'm not sure this is an answer because it's not using a WCF DataContract and the built-in WCF serialization, we pass a handler containing the following method to the constructor: 最后,我不确定这是一个答案,因为它没有使用WCF DataContract和内置的WCF序列化,我们将包含以下方法的处理程序传递给构造函数:

    public void Handle(MsmqMessage<object> message)
    {
        object msmqType = Serializer.Deserialize(message.Body);

        _bus.Publish(msmqType);
    }

If it wasn't obvious, we're using XML serialization for the messages. 如果不是很明显,我们就会对消息使用XML序列化。

This is a very interesting question. 这是一个非常有趣的问题。

The Action OperationContractAttribute is normally used by the WCF stack to populate the WS-Addressing soap headers. Action OperationContractAttribute通常由WCF堆栈用于填充WS-Addressing soap标头。 It's use is obviously overridden in some way by the queued bindings. 它的使用显然被排队的绑定以某种方式覆盖。

It is possible that there is an undocumented feature of WCF which allows for some mapping of msmq message headers to the operation based on the Action attribute acting like a filter, but if there is I don't know what form it would take. WCF可能存在未记录的功能,它允许将msmq消息头部分映射到基于Action属性的操作,就像过滤器一样,但如果有,我不知道它将采用什么形式。

I think the simplest explanation is: no, it's not possible, and the reason for that is that the msmqIntegrationBinding is exactly what it says on the tin: it's about interop over functionality. 我认为最简单的解释是:不,这是不可能的,其原因是msmqIntegrationBinding正如它在锡上所说的那样:它是关于互操作功能的。

Because you are forced to call the operation with a MsmqMessage wrapper it kind of makes this binding semantically one-dimensional, and this lends to my theory that it is intended to wrap a single endpoint operation to support interop with legacy COM and ActiveX clients. 因为您被迫使用MsmqMessage包装器调用该操作,所以它使得这种绑定在语义上是一维的,这使我的理论认为它旨在包装单个端点操作以支持与传统COM和ActiveX客户端的互操作。

Anyhow, there's no law saying that a binding must support multiple operations, just like certain bindings don't support callbacks, and certain others only one-way operations. 无论如何,没有法律规定绑定必须支持多个操作,就像某些绑定不支持回调一样,而某些绑定只支持单向操作。

Appreciate this doesn't answer your question directly. 感谢这不直接回答你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM