diff --git a/Samples/Manufacturing/InteropPartner/InteropPartner.csproj b/Samples/Manufacturing/InteropPartner/InteropPartner.csproj new file mode 100644 index 00000000000..98b64f46ba2 --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/InteropPartner.csproj @@ -0,0 +1,65 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {AF9929C8-85B8-4A36-9EC8-E46C17FE3B65} + Exe + Properties + InteropPartner + InteropPartner + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Manufacturing/InteropPartner/Program.cs b/Samples/Manufacturing/InteropPartner/Program.cs new file mode 100644 index 00000000000..34ccd5fc5c1 --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/Program.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Messaging; +using System.Xml.Serialization; + +namespace InteropPartner +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Using straight xml serialization and msmq to test interop."); + Console.WriteLine("To exit, enter 'q'. Press 'Enter' to send a message."); + + string queueName = string.Format("FormatName:DIRECT=OS:{0}\\private$\\messagebus", Environment.MachineName); + + MessageQueue q = new MessageQueue(queueName); + + XmlSerializer serializer = new XmlSerializer(typeof(OrderMessage), new Type[] { typeof(OrderLine) }); + + string line = null; + while ((line = Console.ReadLine().ToLower()) != "q") + { + OrderMessage m1 = new OrderMessage(); + m1.PurchaseOrderNumber = Guid.NewGuid().ToString(); + m1.ProvideBy = DateTime.Now; + m1.PartnerId = Guid.NewGuid(); + m1.OrderLines = new OrderLine[] { new OrderLine { ProductId = Guid.NewGuid(), Quantity = 10F } }; + m1.Done = true; + + Message toSend = new Message(); + serializer.Serialize(toSend.BodyStream, m1); + + q.Send(toSend, MessageQueueTransactionType.Single); + Console.WriteLine("Sent order {0}", m1.PurchaseOrderNumber); + } + } + } +} diff --git a/Samples/Manufacturing/InteropPartner/Properties/AssemblyInfo.cs b/Samples/Manufacturing/InteropPartner/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..0c76a1b928a --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("InteropPartner")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("InteropPartner")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6e1c25c9-5c7e-4f9c-beee-576f1558a5f8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Samples/Manufacturing/InteropPartner/schema0.xsd b/Samples/Manufacturing/InteropPartner/schema0.xsd new file mode 100644 index 00000000000..a8da45d5c2e --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/schema0.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/Manufacturing/InteropPartner/schema1.xsd b/Samples/Manufacturing/InteropPartner/schema1.xsd new file mode 100644 index 00000000000..0b53564abff --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/schema1.xsd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Samples/Manufacturing/InteropPartner/schema1_schema0.cs b/Samples/Manufacturing/InteropPartner/schema1_schema0.cs new file mode 100644 index 00000000000..1f76db6c3db --- /dev/null +++ b/Samples/Manufacturing/InteropPartner/schema1_schema0.cs @@ -0,0 +1,260 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System.Xml.Serialization; + +// +// This source code was auto-generated by xsd, Version=2.0.50727.3038. +// + + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Diagnostics.DebuggerStepThroughAttribute()] +[System.ComponentModel.DesignerCategoryAttribute("code")] +[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.net/OrderService.Messages", IsNullable=true)] +public partial class OrderStatusChangedMessage { + + private string purchaseOrderNumberField; + + private System.Guid partnerIdField; + + private OrderStatusEnum statusField; + + private object[] orderLinesField; + + /// + public string PurchaseOrderNumber { + get { + return this.purchaseOrderNumberField; + } + set { + this.purchaseOrderNumberField = value; + } + } + + /// + public System.Guid PartnerId { + get { + return this.partnerIdField; + } + set { + this.partnerIdField = value; + } + } + + /// + public OrderStatusEnum Status { + get { + return this.statusField; + } + set { + this.statusField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("OrderLine")] + public object[] OrderLines { + get { + return this.orderLinesField; + } + set { + this.orderLinesField = value; + } + } +} + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.net/OrderService.Messages", IsNullable=false)] +public enum OrderStatusEnum { + + /// + Tentative, + + /// + Recieved, + + /// + Authorized, + + /// + Rejected, + + /// + Accepted, +} + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Diagnostics.DebuggerStepThroughAttribute()] +[System.ComponentModel.DesignerCategoryAttribute("code")] +[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.net/OrderService.Messages", IsNullable=true)] +public partial class OrderMessage { + + private bool doneField; + + private System.DateTime provideByField; + + private object[] orderLinesField; + + private string purchaseOrderNumberField; + + private System.Guid partnerIdField; + + /// + public bool Done { + get { + return this.doneField; + } + set { + this.doneField = value; + } + } + + /// + public System.DateTime ProvideBy { + get { + return this.provideByField; + } + set { + this.provideByField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("OrderLine")] + public object[] OrderLines { + get { + return this.orderLinesField; + } + set { + this.orderLinesField = value; + } + } + + /// + public string PurchaseOrderNumber { + get { + return this.purchaseOrderNumberField; + } + set { + this.purchaseOrderNumberField = value; + } + } + + /// + public System.Guid PartnerId { + get { + return this.partnerIdField; + } + set { + this.partnerIdField = value; + } + } +} + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Diagnostics.DebuggerStepThroughAttribute()] +[System.ComponentModel.DesignerCategoryAttribute("code")] +[System.Xml.Serialization.XmlTypeAttribute(TypeName="ArrayOfOrderLine", Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute("ArrayOfOrderLine", Namespace="http://tempuri.net/OrderService.Messages", IsNullable=true)] +public partial class ArrayOfOrderLine1 { + + private object[] orderLineField; + + /// + [System.Xml.Serialization.XmlElementAttribute("OrderLine", IsNullable=true)] + public object[] OrderLine { + get { + return this.orderLineField; + } + set { + this.orderLineField = value; + } + } +} + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Diagnostics.DebuggerStepThroughAttribute()] +[System.ComponentModel.DesignerCategoryAttribute("code")] +[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.net/OrderService.Messages", IsNullable=true)] +public partial class OrderLine { + + private System.Guid productIdField; + + private float quantityField; + + /// + public System.Guid ProductId { + get { + return this.productIdField; + } + set { + this.productIdField = value; + } + } + + /// + public float Quantity { + get { + return this.quantityField; + } + set { + this.quantityField = value; + } + } +} + +/// +[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] +[System.SerializableAttribute()] +[System.Diagnostics.DebuggerStepThroughAttribute()] +[System.ComponentModel.DesignerCategoryAttribute("code")] +[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.net/OrderService.Messages")] +[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.net/OrderService.Messages", IsNullable=true)] +public partial class CancelOrderMessage { + + private string purchaseOrderNumberField; + + private System.Guid partnerIdField; + + /// + public string PurchaseOrderNumber { + get { + return this.purchaseOrderNumberField; + } + set { + this.purchaseOrderNumberField = value; + } + } + + /// + public System.Guid PartnerId { + get { + return this.partnerIdField; + } + set { + this.partnerIdField = value; + } + } +} diff --git a/Samples/Manufacturing/Manufacturing.sln b/Samples/Manufacturing/Manufacturing.sln index ba7f0fca627..3e60f4ee090 100644 --- a/Samples/Manufacturing/Manufacturing.sln +++ b/Samples/Manufacturing/Manufacturing.sln @@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Partner", "Partner\Partner. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderService.Persistence", "OrderService.Persistence\OrderService.Persistence.csproj", "{C34B917B-14A4-4FFB-A744-F32E9AFBAECD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteropPartner", "InteropPartner\InteropPartner.csproj", "{AF9929C8-85B8-4A36-9EC8-E46C17FE3B65}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +67,10 @@ Global {C34B917B-14A4-4FFB-A744-F32E9AFBAECD}.Debug|Any CPU.Build.0 = Debug|Any CPU {C34B917B-14A4-4FFB-A744-F32E9AFBAECD}.Release|Any CPU.ActiveCfg = Release|Any CPU {C34B917B-14A4-4FFB-A744-F32E9AFBAECD}.Release|Any CPU.Build.0 = Release|Any CPU + {AF9929C8-85B8-4A36-9EC8-E46C17FE3B65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF9929C8-85B8-4A36-9EC8-E46C17FE3B65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF9929C8-85B8-4A36-9EC8-E46C17FE3B65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF9929C8-85B8-4A36-9EC8-E46C17FE3B65}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/Manufacturing/Manufacturing.suo b/Samples/Manufacturing/Manufacturing.suo index 9041f884744..d45ac9a8d01 100644 Binary files a/Samples/Manufacturing/Manufacturing.suo and b/Samples/Manufacturing/Manufacturing.suo differ diff --git a/Samples/Manufacturing/OrderService.Persistence/TableDefinitions.sql b/Samples/Manufacturing/OrderService.Persistence/TableDefinitions.sql index 704df57a6cb..6fae6851b34 100644 --- a/Samples/Manufacturing/OrderService.Persistence/TableDefinitions.sql +++ b/Samples/Manufacturing/OrderService.Persistence/TableDefinitions.sql @@ -6,7 +6,7 @@ SET ANSI_PADDING ON GO CREATE TABLE [dbo].[OrderSagaData]( [Id] [uniqueidentifier] NOT NULL, - [Originator] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL, + [Originator] [varchar](50) COLLATE Latin1_General_CI_AS, [PurchaseOrderNumber] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL, [PartnerId] [uniqueidentifier] NOT NULL, [ProvideBy] [datetime] NOT NULL, diff --git a/src/impl/Serializers/NServiceBus.Serializers.XML/MessageSerializer.cs b/src/impl/Serializers/NServiceBus.Serializers.XML/MessageSerializer.cs index edb28ca2323..0850067b1e8 100644 --- a/src/impl/Serializers/NServiceBus.Serializers.XML/MessageSerializer.cs +++ b/src/impl/Serializers/NServiceBus.Serializers.XML/MessageSerializer.cs @@ -94,13 +94,23 @@ public IMessage[] Deserialize(Stream stream) } } - foreach (XmlNode node in doc.DocumentElement.ChildNodes) + if (doc.DocumentElement.Name.ToLower() != "messages") { object m = null; - Process(node, ref m); + Process(doc.DocumentElement, ref m); result.Add(m as IMessage); } + else + { + foreach (XmlNode node in doc.DocumentElement.ChildNodes) + { + object m = null; + Process(node, ref m); + + result.Add(m as IMessage); + } + } defaultNameSpace = null; @@ -232,7 +242,7 @@ public void Serialize(IMessage[] messages, Stream stream) for (int i = 0; i < namespaces.Count; i++) { - builder.AppendFormat(" xmlns{0}=\"{1}/{2}\"", (i == namespaces.Count - 1 ? ":q" + i : ""), nameSpace, namespaces[i]); + builder.AppendFormat(" xmlns{0}=\"{1}/{2}\"", (i != namespaces.Count - 1 ? ":q" + i : ""), nameSpace, namespaces[i]); namespacesToPrefix[namespaces[i]] = i; } @@ -263,7 +273,8 @@ public void Write(StringBuilder builder, Type t, object obj) public void WriteObject(string name, Type type, object value, StringBuilder builder) { string element = name; - int i = namespacesToPrefix[type.Namespace]; + int i; + namespacesToPrefix.TryGetValue(type.Namespace, out i); if (i > 0) element = "q" + i + ":" + name; diff --git a/src/unicast/NServiceBus.Unicast/UnicastBus.cs b/src/unicast/NServiceBus.Unicast/UnicastBus.cs index 3be3d9bd8b1..fcbeffa8feb 100644 --- a/src/unicast/NServiceBus.Unicast/UnicastBus.cs +++ b/src/unicast/NServiceBus.Unicast/UnicastBus.cs @@ -480,6 +480,12 @@ public ICallback Send(string destination, Action messageConstructor) where /// The list of messages to send. public ICallback Send(string destination, params IMessage[] messages) { + if (destination == null) + { + log.Info("No destination specified. Not sending messages."); + return null; + } + TransportMessage toSend = this.GetTransportMessageFor(destination, messages); this.transport.Send(toSend, destination); @@ -530,8 +536,6 @@ public virtual void Start() this.transport.MessageTypesToBeReceived = this.messageTypes; - this.transport.Start(); - this.InitializeSelf(); this.SendReadyMessage(true); @@ -567,6 +571,8 @@ public virtual void Start() } } + this.transport.Start(); + this.started = true; } } @@ -849,6 +855,9 @@ void transport_FinishedMessageProcessing(object sender, EventArgs e) /// A is used out of convenience as the initialization message. private bool IsInitializationMessage(TransportMessage msg) { + if (msg.ReturnAddress == null) + return false; + if (!msg.ReturnAddress.Contains(this.transport.Address)) return false;