MSMQ 天生支援單向 (One-way) 訊息交換模式。客戶端送出訂單後立即返回,無法得知服務端是否成功處理、或發生何種錯誤。這在訂單處理、金融扣款等關鍵業務中完全無法接受。

核心思想:客戶端同時啟動一個本地 MSMQ 服務 (Response Service),專門接收處理端的回執訊息。客戶端提交訂單時,透過 SOAP Header 將本地回呼佇列地址 (OrderResponseContext) 夾帶傳遞。服務端處理完成後,主動連線至該地址發送 Acknowledge 訊息。

不修改 IOrderProcessor.Submit(Order) 簽名,改用 OperationContext 操作 Header:
// 客戶端:寫入 Header
OrderResponseContext context = new OrderResponseContext { ResponseAddress = localQueueAddress };
MessageHeader<OrderResponseContext> header = new MessageHeader<OrderResponseContext>(context);
OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader("OrderResponseContext", "ns"));
// 服務端:讀取 Header
OrderResponseContext ctx = OperationContext.Current.IncomingMessageHeaders.GetHeader<OrderResponseContext>("OrderResponseContext", "ns");
[DataContract]
public class OrderResponseContext
{
[DataMember] public Uri ResponseAddress { get; set; }
public static OrderResponseContext Current
{
get => OperationContext.Current?.IncomingMessageHeaders.GetHeader<OrderResponseContext>("OrderResponseContext", "ns");
set
{
var header = new MessageHeader<OrderResponseContext>(value);
OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader("OrderResponseContext", "ns"));
}
}
}
public void Submit(Order order)
{
// ... 業務處理邏輯 ...
FaultException fault = null;
if (order.IsExpired) fault = new FaultException(...);
var responseCtx = OrderResponseContext.Current;
var factory = new ChannelFactory<IOrderResponse>(new NetMsmqBinding(), new EndpointAddress(responseCtx.ResponseAddress));
var channel = factory.CreateChannel();
using (new OperationContextScope((IContextChannel)channel))
{
channel.SubmitOrderResponse(order.OrderNo, fault);
}
}
IOrderProcessor、IOrderResponse、Order、OrderResponseContextOrderProcessorService.\private$\orderprocessorOrderResponseService.\private$\orderresponseOrderResponseContext、送出訂單、等待回執客戶端送出兩筆訂單 (一筆正常、一筆過期):

服務端處理記錄:

回呼端接收結果:

此模式完美解決 MSMQ One-way 無法感知結果的問題,且不侵入業務 Contract,符合 SOA 解耦原則。適用於需異步可靠回執的分散式系統 (如訂單、付款、報表生成)。