我有一个MVC应用程序,其控制器的动作应该是从队列中的最新消息(msmq)中公开数据。我在本地计算机上添加了一个专用队列。我希望应用程序在添加一个消息时自动从队列中接收消息。为此,我在已添加到应用程序的WCF服务上使用msmqIntegrationBinding。接收合同中消息的方法然后应该将消息保存在应用程序缓存中,以便在客户端请求最新数据时访问它。
我现在面临的挑战是,当我向队列添加消息时,它不被WCF服务接收。我需要指导我可能做错了什么或反馈我的方法。请帮忙。
以下是WCF服务的endpoint-config:
<bindings>
<msmqIntegrationBinding>
<binding name="MsmqBinding">
<security mode="None" />
</binding>
</msmqIntegrationBinding>
</bindings>
<services>
<service name="TestApp.Web.Service.QueueMessageReceiver">
<endpoint address="msmq.formatname:DIRECT=OS:.\private$\testsmessagequeue"
binding="msmqIntegrationBinding"
bindingConfiguration="MsmqBinding"
contract="TestApp.Web.Service.IQueueMessageReceiver" />
</service>
</services>
以下代码来自QueueMessageReceiver.cs WCF-service:
public class QueueMessageReceiver : IQueueMessageReceiver
{
private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(ScrewInfoModel));
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void PutScrewInfoMessage(System.ServiceModel.MsmqIntegration.MsmqMessage<System.Xml.XmlDocument> msg)
{
CacheScrewInfoModelFromScrewInfoXmlDoc(msg.Body);
}
private static void CacheScrewInfoModelFromScrewInfoXmlDoc(XmlNode screwInfoXmlDoc)
{
var reader = new StringReader(screwInfoXmlDoc.InnerXml);
var screwInfoModel = (ScrewInfoModel)Serializer.Deserialize(reader);
Common.Utils.CacheScrewInfo(screwInfoModel);
}
}
这是WCF的接口:
[ServiceContract]
public interface IQueueMessageReceiver
{
[OperationContract(IsOneWay = true, Action = "*")]
void PutScrewInfoMessage(MsmqMessage<XmlDocument> msg);
}
答案 0 :(得分:0)
尝试将操作合同更改为
void PutScrewInfoMessage(MsmqMessage<string> msg);
WCF堆栈可能难以反序列化为XmlDocument
。
<强>更新强>
要尝试的事情:
让你的队列“testsmessagequeue”具有正确的权限集。在这种情况下,运行托管控制器的应用程序池的服务帐户需要设置“接收消息”权限。
启用MSMQ日志记录(如果您使用的是Windows 2008服务器或Windows 7及更高版本),可以在事件查看器中找到:应用程序和服务日志 - &gt;微软 - &gt; Windows - &gt; MSMQ - &gt;端到端。这将捕获MSMQ中发生的所有事情,包括任何错误。
尝试使队列具有事务性(如果尚未)。这将确保消息未送达时存在错误情况。
在服务端点上启用WCF跟踪,以查看消息出列时发生的任何特定WCF错误。
更新2
我认为问题是队列权限。您的应用程序池在用户 ApplicationPoolIdentity 下运行(如果它在.net 4.0应用程序池下运行)。与此标识对应的用户称为 DefaultAppPool 。您需要为此用户提供队列上的消息权限。要选择此用户,请在“选择用户”对话框中搜索名为 IIS AppPool \ DefaultAppPool 的本地帐户。
更新3
让我感到震惊的是,IIS不是队列侦听器的适当托管容器。原因是应用程序池在一段时间不活动后卸载。这由IIS控制,不可配置。 (见here)
我认为您应该在Windows服务中创建一个新的托管容器(您可以使用控制台主机来加密它)来托管队列端点。 Windows服务将在实际的服务帐户下运行,因此授予权限将不那么复杂。
此服务可以直接写入缓存,或者如果不可能,则应写入网站控制器可以刷新缓存的数据库。
这有意义吗?
更新4
毒药消息表示由于某些问题,该消息无法出列。检查名为Transactional Dead Letter Queue的系统队列,看看你的消息是否在那里。