2012-09-12 4 views
0

J'ai une application ASP.Net WebAPI qui utilise NServiceBus. Les commandes sont envoyées depuis l'application vers un serveur principal qui exécute l'hôte NSB. Le serveur est responsable de la communication avec la base de données.NServiceBus Reply Message d'avertissement

La plupart des commandes sont fire-and-forget. Un simple Bus.Send (...) et le client web sont libérés immédiatement afin que l'opération puisse se faire de manière asynchrone.

L'exception concerne les commandes qui créent de nouveaux enregistrements dans la base de données. La base de données est responsable de la génération de l'ID de l'entité nouvellement créée, et j'ai besoin de la renvoyer à l'appelant. C'est moins performant parce que l'appelant doit rester, mais c'est un coup acceptable dans ma situation. J'utilise avec succès la fonction Bus.Reply() pour cela, comme documenté dans les exemples Full Duplex. Je réponds avec un message qui a une seule propriété pour l'Id nouvellement généré. Sur le web, j'ai enregistré le rappel avec une continuation de tâche (en profitant de la capacité asynchrone de WebAPI), et en utilisant .Register après Bus.Send().

Tout cela fonctionne très bien. Il accomplit exactement ce que je veux, d'une manière très simple et directe. Le seul problème est que chaque fois qu'un message de réponse est reçu par le client, il enregistre un avertissement comme suit:

2012-09-11 16:46:44,745 [Worker.26] WARN NServiceBus.Unicast.Transport.Transactional.TransactionalTransport [(null)] - Failed raising 'transport message received' event for message with ID=1faee572-f904-4b09-b1d5-c0bd7c12738d\82936 
System.InvalidOperationException: No handlers could be found for message type: MyProject.Messages.MyEntityCreatedResponseMessage 
    at NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder childBuilder, TransportMessage msg) 
    at NServiceBus.Unicast.UnicastBus.TransportMessageReceived(Object sender, TransportMessageReceivedEventArgs e) 
    at System.EventHandler`1.Invoke(Object sender, TEventArgs e) 
    at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage msg) 

Comment puis-je me débarrasser de cet avertissement? Je n'ai pas besoin d'un gestionnaire de messages ici.

+0

En haut de la tête - je pense que vous devez implémenter un mannequin factice (vide). Sinon, vos événements MyEntityCreatedResponseMessage finiront dans la file d'erreurs –

+0

Un gestionnaire factice arrête l'avertissement, mais j'obtiens un avertissement différent indiquant que je suis en train de faire pub/sub sans événements ... Pourquoi pense-t-il que .Reply est à être traité comme si j'avais fait un .Publish ?? –

+0

J'ai trouvé que si j'utilise Bus.Return au lieu de Bus.Reply, que je peux accomplir ce que je voulais sans erreur ni avertissement. Cependant, cela ne fonctionne que parce que je traite le nouvel ID comme s'il s'agissait d'un ErrorCode et que mes ID sont des entiers. Si j'avais besoin de passer des ID d'un type différent, ou des informations supplémentaires (comme un code d'erreur réel), cela ne fonctionnerait pas. –

Répondre

2

Je suggère de créer l'ID sur le serveur ou même le client (navigateur). De cette façon, votre message peut toujours être ignoré et vous n'avez pas besoin de synchroniser quoi que ce soit.

Si vous souhaitez persister avec les ID gérés par la base de données, NServiceBus ajoute uniquement une surcharge. Mai aussi bien parler directement à la base de données à partir de votre code de site Web et ajouter des tentatives là-bas.

+0

Cela nécessiterait quelque chose comme les identifiants GUID. Je voudrais coller avec un simple entier auto-incrémentant si possible. Écrire directement sur la BD au lieu de passer par le bus serait une option, mais cela contournerait le reste de mon architecture, donc je ne suis pas sûr de vouloir suivre cette route. Vraiment, je veux juste que le message de réponse ne nécessite pas de gestionnaire. –

+1

Rien ne dit que le GUID doit être utilisé pour conserver l'entité dans la base de données. Tout ce que le GUID doit être pour identifier le message utilisé pour persister l'entité et corréler la réponse. Dans ce cas, le GUID serait créé par le client. – Rich

+1

@Matt, vous n'avez pas besoin d'utiliser la même architecture pour l'ensemble du projet (ou du système). Si l'architecture fait obstacle à une solution optimale, alors c'est la mauvaise architecture. Pensez à ce qui se passe pendant cet appel synchrone. La requête Web arrive, est convertie en message MSMQ, le message est traité, la réponse est convertie en message MSMQ, le message factice arrive et est traité, la réponse est ensuite renvoyée au client Web. Tous ces frais généraux, quel est l'avantage? –

Questions connexes