Unable to cast MSMQ body to an object

  • Thread starter Thread starter Bill Wright
  • Start date Start date
B

Bill Wright

Hi,

I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is called
from the get_Body() method on the System.Messaging.Message object.

In the development environment on the remote computer in the Immediate
window of the debugger I can do the following:

(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"

(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"

so why doesn't this work:

System.Type.GetType("Tendril.NodeBuildCommand")

This last line returns null and this is the source of my problem with
the casting. Any ideas on how to proceed?

Thanks,
Bill
 
You need to beomce famaliar with the formatter argument


System.Messaging.IMessageFormatter




Here is smoe sample code:

public class MyMSMQListener
{

MessageQueue _queue = null;


public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}



private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{

Console.WriteLine("MyMSMQListenerwas constructed");

this._queue = new MessageQueue(queuePath);

this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;

}

}
 
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)



new BinaryMessageFormatter() ' good for using DotNet objects



Which formatter are you using?



....



And when you handle/receive the message, are you casting it?





Dim e As Employee = CType(msg.Body, Employee)



Or



Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.

If(null!=e)

{

Console.WriteLine ("We got the employee from the message body");

}





Something like that.







If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter

Then you have to cast the msg.Body



Make sense?





PS

I really like Manoj's helper

http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx



I added some code (to enhance his) in the comments section, basically to
overload the formatter.





Question #2.






--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object



Sloan,



Thanks for the email response. I appreciate it.



I'm using the Formatter. I think that is essential to send a message without
an error, though I'm not sure.



Anyway, when I initialize the Formatter I give it an array of two strings:



{ "System.string", "Tendril. NodeBuildCommand" }



So, I don't think that is the problem. Isn't it curious that can create an
object like this:



New Tendril. NodeBuildCommand()



but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")



?



I've seen stuff about explicitly loading the assembly, but it seems like the
program knows about the assembly - it can create objects from it explicitly,
but it can't seem to discover the type via the System.GetType() method...?



Any other ideas?



Bill
 
That shouldn't be ASP code as much as it is COM/ActiveX
component/unmanaged code.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sloan said:
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)



new BinaryMessageFormatter() ' good for using DotNet objects



Which formatter are you using?



...



And when you handle/receive the message, are you casting it?





Dim e As Employee = CType(msg.Body, Employee)



Or



Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.

If(null!=e)

{

Console.WriteLine ("We got the employee from the message
body");

}





Something like that.







If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter

Then you have to cast the msg.Body



Make sense?





PS

I really like Manoj's helper

http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx



I added some code (to enhance his) in the comments section, basically to
overload the formatter.





Question #2.






--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object



Sloan,



Thanks for the email response. I appreciate it.



I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.



Anyway, when I initialize the Formatter I give it an array of two strings:



{ "System.string", "Tendril. NodeBuildCommand" }



So, I don't think that is the problem. Isn't it curious that can create an
object like this:



New Tendril. NodeBuildCommand()



but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")



?



I've seen stuff about explicitly loading the assembly, but it seems like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?



Any other ideas?



Bill









sloan said:
You need to beomce famaliar with the formatter argument


System.Messaging.IMessageFormatter




Here is smoe sample code:

public class MyMSMQListener
{

MessageQueue _queue = null;


public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}



private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{

Console.WriteLine("MyMSMQListenerwas constructed");

this._queue = new MessageQueue(queuePath);

this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;

}

}
 
Good catch Nicholas.


ActiveXMessageFormatter = COM/ActiveX





Nicholas Paldino said:
That shouldn't be ASP code as much as it is COM/ActiveX
component/unmanaged code.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sloan said:
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)



new BinaryMessageFormatter() ' good for using DotNet objects



Which formatter are you using?



...



And when you handle/receive the message, are you casting it?





Dim e As Employee = CType(msg.Body, Employee)



Or



Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.

If(null!=e)

{

Console.WriteLine ("We got the employee from the message
body");

}





Something like that.







If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter

Then you have to cast the msg.Body



Make sense?





PS

I really like Manoj's helper

http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx



I added some code (to enhance his) in the comments section, basically to
overload the formatter.





Question #2.






--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object



Sloan,



Thanks for the email response. I appreciate it.



I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.



Anyway, when I initialize the Formatter I give it an array of two
strings:



{ "System.string", "Tendril. NodeBuildCommand" }



So, I don't think that is the problem. Isn't it curious that can create
an object like this:



New Tendril. NodeBuildCommand()



but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")



?



I've seen stuff about explicitly loading the assembly, but it seems like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?



Any other ideas?



Bill









sloan said:
You need to beomce famaliar with the formatter argument


System.Messaging.IMessageFormatter




Here is smoe sample code:

public class MyMSMQListener
{

MessageQueue _queue = null;


public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}



private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{

Console.WriteLine("MyMSMQListenerwas constructed");

this._queue = new MessageQueue(queuePath);

this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;

}

}






Hi,

I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is called
from the get_Body() method on the System.Messaging.Message object.

In the development environment on the remote computer in the Immediate
window of the debugger I can do the following:

(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"

(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"

so why doesn't this work:

System.Type.GetType("Tendril.NodeBuildCommand")

This last line returns null and this is the source of my problem with
the casting. Any ideas on how to proceed?

Thanks,
Bill
 
Initially, I was using an XmlFormatter to initialize the queue (from
both the sender's init code and the receiver's init code, like this:

string[] types = { "System.String",
"Tendril.NodeBuildCommand" };
BUILD_QUEUE.Formatter = new XmlMessageFormatter(types);

And that's when I got the original error message. I'm still baffled
why System.GetType() doesn't work and I think this problem needs to be
fundamentally understood to solve this problem. That said, I want to
get this to work and am willing to try a different formatter if it
will help matters. So, in the second go I did the following for queue
initialization:

BUILD_QUEUE.Formatter = new BinaryMessageFormatter();

This formatter doesn't appear to take any arguments?

Then each time I construct the message like this:

NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);
System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd);

Then in the receiving application, which uses the same DLL Assembly
that contains the code for the NodeBuildCommand class, I do the
following, in the callback method that I have setup for the queue:

private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)

The error I get the with the BinaryMessageFormatter method is "Cannot
deserialize the message passed as an argument". I would think this is
message I'd get when using the XmlFormatter, but I guess some form of
serialization is done either way. Each time the exception is thrown
from the System.Messaging.Message.get_Body() method.

Both of these problems are confounding to me.

Thanks for any advice,
Bill

Good catch Nicholas.

ActiveXMessageFormatter = COM/ActiveX

Nicholas Paldino said:
component/unmanaged code.
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)
new BinaryMessageFormatter() ' good for using DotNet objects
Which formatter are you using?
...
And when you handle/receive the message, are you casting it?
Dim e As Employee = CType(msg.Body, Employee)
Or
Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.
If(null!=e)
{
Console.WriteLine ("We got the employee from the message
body");
}
Something like that.
If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter
Then you have to cast the msg.Body
Make sense?
PS
I really like Manoj's helper
http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx
I added some code (to enhance his) in the comments section, basically to
overload the formatter.
Question #2.
--------------------------------------------------------------------------------
From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object
Sloan,
Thanks for the email response. I appreciate it.
I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.
Anyway, when I initialize the Formatter I give it an array of two
strings:
{ "System.string", "Tendril. NodeBuildCommand" }
So, I don't think that is the problem. Isn't it curious that can create
an object like this:
New Tendril. NodeBuildCommand()
but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")
?
I've seen stuff about explicitly loading the assembly, but it seems like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?
Any other ideas?
Bill

You need to beomce famaliar with the formatter argument
System.Messaging.IMessageFormatter
Here is smoe sample code:
public class MyMSMQListener
{
MessageQueue _queue = null;
public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}
private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{
Console.WriteLine("MyMSMQListenerwas constructed");
this._queue = new MessageQueue(queuePath);
this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;
}
}
Hi,
I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is called
from the get_Body() method on the System.Messaging.Message object.
In the development environment on the remote computer in the Immediate
window of the debugger I can do the following:
(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"
(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"
so why doesn't this work:
System.Type.GetType("Tendril.NodeBuildCommand")
This last line returns null and this is the source of my problem with
the casting. Any ideas on how to proceed?
Thanks,
Bill
 
You're saying the target code (the code receiving/peeking the msmq message)
has access to the concrete type.
Aka, the NodeBuildCommand.

Here is one method to debug. Make absolute sure you have the same
assembly/class.

Put this (kind of code) in both the sender and the receiving code.

Assembly SampleAssembly;
// Instantiate a target object.
Int32 Integer1 = new Int32();
Type Type1;
// Set the Type instance to the target class type.
Type1 = Integer1.GetType();
// Instantiate an Assembly class to the assembly housing the Integer type.
SampleAssembly = Assembly.GetAssembly(Integer1.GetType());
// Write the display name of assembly including base name and version.
Console.WriteLine("FullName=" + SampleAssembly.FullName);

Basically, you want to look at the FULLNAME to make sure you got apples to
apples. Just because the name is the same doesn't guarantee it.

................

Also , look at the documentation from MSDN.

Message () Initializes a new instance of the Message class with an
empty body.
Supported by the .NET Compact Framework.

Message (Object) Initializes a new instance of the Message class,
using the XmlMessageFormatter to serialize the specified object into the
body of the message.
Supported by the .NET Compact Framework.

Message (Object, IMessageFormatter) Initializes a new instance of the
Message class using the specified formatter to serialize the specified
object into the body of the message.
Supported by the .NET Compact Framework.




Notice the second constructor will by default use the XmlMessageFormatter.

You probably want to use the third constructor.


NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);

Does this class have a default constructor? XmlSerialization likes default
constructors.
I'm not sure about BinaryFormatter, as in, it must have a default
constructor or not.



What is the definition of NodeBuildCommand?

Did you mark it as
[Serializable]

See
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!114.entry
for a decent XmlSerialization example.


Then the slight modification of the code:
private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)

private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message;

if(null!=newMsg)
{
NodeBuildCommand nbc = newMsg.Body as NodeBuildCommand;

if(null!=nbc)
{
Console.WriteLine( nbc.ToString());
}
}

}


----------------------

While I would pick the BinaryFormatter over the XmlMessageFormatter, you
should look at the this constructor of the XmlMessageFormatter
XmlMessageFormatter.XmlMessageFormatter(Type[]) Constructor
http://msdn2.microsoft.com/en-us/library/6tb06chb.aspx

as you'll get strong typing vs depending on strings.

...............

From the ground up, here would be my instructions:

::Send
Create a Queue object. Set the formatter.
Create a Message. Get the body to be the object of your choice. Use the
third overload constructor to set the formatter of the Message.
Send the message.

::Receive
Peek/Receive the Queue
With the message, cast the msg.Body as your object.
Make super/double sure you have the same object (Assembly.FullName) as the
sender logic.



My explanation about formatters is this:

ActiveXFormatter. I'm using old COM/ActiveX code to create the message.
But DotNet needs to get at it.
(this is rare)

BinaryFormatter....going from a DotNet to DotNet world. No overloads,
because Microsoft is able to figure out which object it is.

XmlMessageFormatter.. with types. The reason you provide types is because
there are so very very many things which can be serialzied thru Xml. So
basically, you're providing the hint which says "I've got an object of X
type, via my Xml". So its a hint thing. And helps with performance. And
helps because ... .the Xml used to serialize an object can be created from a
variety of sources.


Ok...I hope that helps.

I think you're close, but go from the ground up again.





Bill Wright said:
Initially, I was using an XmlFormatter to initialize the queue (from
both the sender's init code and the receiver's init code, like this:

string[] types = { "System.String",
"Tendril.NodeBuildCommand" };
BUILD_QUEUE.Formatter = new XmlMessageFormatter(types);

And that's when I got the original error message. I'm still baffled
why System.GetType() doesn't work and I think this problem needs to be
fundamentally understood to solve this problem. That said, I want to
get this to work and am willing to try a different formatter if it
will help matters. So, in the second go I did the following for queue
initialization:

BUILD_QUEUE.Formatter = new BinaryMessageFormatter();

This formatter doesn't appear to take any arguments?

Then each time I construct the message like this:

NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);
System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd);

Then in the receiving application, which uses the same DLL Assembly
that contains the code for the NodeBuildCommand class, I do the
following, in the callback method that I have setup for the queue:

private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)

The error I get the with the BinaryMessageFormatter method is "Cannot
deserialize the message passed as an argument". I would think this is
message I'd get when using the XmlFormatter, but I guess some form of
serialization is done either way. Each time the exception is thrown
from the System.Messaging.Message.get_Body() method.

Both of these problems are confounding to me.

Thanks for any advice,
Bill

Good catch Nicholas.

ActiveXMessageFormatter = COM/ActiveX

in
message That shouldn't
be ASP code as much as it is COM/ActiveX
component/unmanaged code.
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)
new BinaryMessageFormatter() ' good for using DotNet objects
Which formatter are you using?

And when you handle/receive the message, are you casting it?
Dim e As Employee = CType(msg.Body, Employee)

Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.


Console.WriteLine ("We got the employee from the message
body");

Something like that.
If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter
Then you have to cast the msg.Body
Make sense?

I really like Manoj's helper

I added some code (to enhance his) in the comments section, basically
to
overload the formatter.
Question #2.
--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object

Thanks for the email response. I appreciate it.
I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.
Anyway, when I initialize the Formatter I give it an array of two
strings:
{ "System.string", "Tendril. NodeBuildCommand" }
So, I don't think that is the problem. Isn't it curious that can
create
an object like this:
New Tendril. NodeBuildCommand()
but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")

I've seen stuff about explicitly loading the assembly, but it seems
like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?
Any other ideas?

news:[email protected]...
You need to beomce famaliar with the formatter argument

Here is smoe sample code:
public class MyMSMQListener
{
MessageQueue _queue = null;
public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}
private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{
Console.WriteLine("MyMSMQListenerwas constructed");
this._queue = new MessageQueue(queuePath);
this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;


Hi,
I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is
called
from the get_Body() method on the System.Messaging.Message object.
In the development environment on the remote computer in the
Immediate
window of the debugger I can do the following:
(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"
(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"
so why doesn't this work:

This last line returns null and this is the source of my problem
with
the casting. Any ideas on how to proceed?
Thanks,
Bill
 
My hankering is that the issue is ... the third constructor of the Message
object.
http://msdn2.microsoft.com/en-us/library/system.messaging.message.message.aspx


And the fact you don't have a default constructor on your NodeBuildCommand
class.


But my previous post should give you the tools to figure it out.

If you're still stuck, post more code !






Bill Wright said:
Initially, I was using an XmlFormatter to initialize the queue (from
both the sender's init code and the receiver's init code, like this:

string[] types = { "System.String",
"Tendril.NodeBuildCommand" };
BUILD_QUEUE.Formatter = new XmlMessageFormatter(types);

And that's when I got the original error message. I'm still baffled
why System.GetType() doesn't work and I think this problem needs to be
fundamentally understood to solve this problem. That said, I want to
get this to work and am willing to try a different formatter if it
will help matters. So, in the second go I did the following for queue
initialization:

BUILD_QUEUE.Formatter = new BinaryMessageFormatter();

This formatter doesn't appear to take any arguments?

Then each time I construct the message like this:

NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);
System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd);

Then in the receiving application, which uses the same DLL Assembly
that contains the code for the NodeBuildCommand class, I do the
following, in the callback method that I have setup for the queue:

private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)

The error I get the with the BinaryMessageFormatter method is "Cannot
deserialize the message passed as an argument". I would think this is
message I'd get when using the XmlFormatter, but I guess some form of
serialization is done either way. Each time the exception is thrown
from the System.Messaging.Message.get_Body() method.

Both of these problems are confounding to me.

Thanks for any advice,
Bill

Good catch Nicholas.

ActiveXMessageFormatter = COM/ActiveX

in
message That shouldn't
be ASP code as much as it is COM/ActiveX
component/unmanaged code.
New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)
new BinaryMessageFormatter() ' good for using DotNet objects
Which formatter are you using?

And when you handle/receive the message, are you casting it?
Dim e As Employee = CType(msg.Body, Employee)

Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.


Console.WriteLine ("We got the employee from the message
body");

Something like that.
If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter
Then you have to cast the msg.Body
Make sense?

I really like Manoj's helper

I added some code (to enhance his) in the comments section, basically
to
overload the formatter.
Question #2.
--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object

Thanks for the email response. I appreciate it.
I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.
Anyway, when I initialize the Formatter I give it an array of two
strings:
{ "System.string", "Tendril. NodeBuildCommand" }
So, I don't think that is the problem. Isn't it curious that can
create
an object like this:
New Tendril. NodeBuildCommand()
but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")

I've seen stuff about explicitly loading the assembly, but it seems
like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?
Any other ideas?

news:[email protected]...
You need to beomce famaliar with the formatter argument

Here is smoe sample code:
public class MyMSMQListener
{
MessageQueue _queue = null;
public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}
private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{
Console.WriteLine("MyMSMQListenerwas constructed");
this._queue = new MessageQueue(queuePath);
this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;


Hi,
I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is
called
from the get_Body() method on the System.Messaging.Message object.
In the development environment on the remote computer in the
Immediate
window of the debugger I can do the following:
(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"
(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"
so why doesn't this work:

This last line returns null and this is the source of my problem
with
the casting. Any ideas on how to proceed?
Thanks,
Bill
 
Sloan,

Great suggestions and I have met with success! Thanks so much. There
are still things I do not understand, though.

First, what worked. Using the third constructor of the Message,
passing in a Binary formatter:

System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd, new BinaryMessageFormatter());

I do wonder why I need to do this if I set the formatter on the queue:

BUILD_QUEUE.Formatter = new BinaryMessageFormatter();

Why do I need to do this as well? Maybe I don't. Something is
redundant here. Anywhere when I made this change I got a clear
serialization error. Then I added

[Serializable]

to the class definition and it worked!

I had already had a default constructor for the class, as that
requirement came up earlier. I'm happy that this works and I'm moving
on, but here are some things I'm still confused about:

1. Why does the queue and the message have formatters associated with
them. One would be sufficient. If it wasn't specified in the message
constructor, why wouldn't it use the one on the queue? Yes, this would
have to be delayed until the message is sent, but so what? It doesn't
need to be formatted until then. Why assign formatters to the queue at
all? Maybe this is strictly for receiving messages. Probably, now that
I think of it.

2. I still don't understand why System.GetType() doesn't work here.
Yes, I have confirmed the assemblies are the same. In fact, I build
the receiving program by pointing it at the build directory on the
transmitting machine. I do not copy the assembly over there
explicitly.

3. What is the point of a BinaryFormatter? It seems like it is just
converting it to XML anyway. Maybe not. I guess serialization doesn't
imply XML necessarily. I think this should work for an XML formatter
as well, but I haven't gone back to try it with the [Serializable]
attribute.

Thanks again for all the great help,
Bill

My hankering is that the issue is ... the third constructor of the Message
object.http://msdn2.microsoft.com/en-us/library/system.messaging.message.mes...

And the fact you don't have a default constructor on your NodeBuildCommand
class.

But my previous post should give you the tools to figure it out.

If you're still stuck, post more code !


Initially, I was using an XmlFormatter to initialize the queue (from
both the sender's init code and the receiver's init code, like this:
string[] types = { "System.String",
"Tendril.NodeBuildCommand" };
BUILD_QUEUE.Formatter = new XmlMessageFormatter(types);
And that's when I got the original error message. I'm still baffled
why System.GetType() doesn't work and I think this problem needs to be
fundamentally understood to solve this problem. That said, I want to
get this to work and am willing to try a different formatter if it
will help matters. So, in the second go I did the following for queue
initialization:
BUILD_QUEUE.Formatter = new BinaryMessageFormatter();
This formatter doesn't appear to take any arguments?
Then each time I construct the message like this:
NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);
System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd);
Then in the receiving application, which uses the same DLL Assembly
that contains the code for the NodeBuildCommand class, I do the
following, in the callback method that I have setup for the queue:
private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)
The error I get the with the BinaryMessageFormatter method is "Cannot
deserialize the message passed as an argument". I would think this is
message I'd get when using the XmlFormatter, but I guess some form of
serialization is done either way. Each time the exception is thrown
from the System.Messaging.Message.get_Body() method.
Both of these problems are confounding to me.
Thanks for any advice,
Bill
Good catch Nicholas.
ActiveXMessageFormatter = COM/ActiveX
in
message That shouldn't
be ASP code as much as it is COM/ActiveX
component/unmanaged code.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

New ActiveXMessageFormatter ' good for using Asp code (That's ASP, not
Asp.Net)
new BinaryMessageFormatter() ' good for using DotNet objects
Which formatter are you using?
...
And when you handle/receive the message, are you casting it?
Dim e As Employee = CType(msg.Body, Employee)
Or
Employee e = msg.Body as Employee; //<< Can you do this, aka, is your
assembly referenced in the project.
If(null!=e)
{
Console.WriteLine ("We got the employee from the message
body");
}
Something like that.
If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter
Then you have to cast the msg.Body
Make sense?
PS
I really like Manoj's helper
http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx
I added some code (to enhance his) in the comments section, basically
to
overload the formatter.
Question #2.
--------------------------------------------------------------------------------
From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object
Sloan,
Thanks for the email response. I appreciate it.
I'm using the Formatter. I think that is essential to send a message
without an error, though I'm not sure.
Anyway, when I initialize the Formatter I give it an array of two
strings:
{ "System.string", "Tendril. NodeBuildCommand" }
So, I don't think that is the problem. Isn't it curious that can
create
an object like this:
New Tendril. NodeBuildCommand()
but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")
?
I've seen stuff about explicitly loading the assembly, but it seems
like
the program knows about the assembly - it can create objects from it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?
Any other ideas?
Bill

You need to beomce famaliar with the formatter argument
System.Messaging.IMessageFormatter
Here is smoe sample code:
public class MyMSMQListener
{
MessageQueue _queue = null;
public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter type
}
private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{
Console.WriteLine("MyMSMQListenerwas constructed");
this._queue = new MessageQueue(queuePath);
this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;
}
}
Hi,
I built an assembly with a class, NodeBuildCommand, in the namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a System.Messaging.Message.
This works without error. On the receiving computer I use the same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is
called
from the get_Body() method on the System.Messaging.Message object.
In the development environment on the remote computer in the
Immediate
window of the debugger I can do the following:
(new Tendril.NodeBuildCommand()).GetType().Name = "NodeBuildCommand"
(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"
so why doesn't this work:
System.Type.GetType("Tendril.NodeBuildCommand")
This last line returns null and this is the source of my problem
with
the casting. Any ideas on how to proceed?
Thanks,
Bill
 
//Quote
1. Why does the queue and the message have formatters associated with
them. One would be sufficient. If it wasn't specified in the message
constructor, why wouldn't it use the one on the queue? Yes, this would
have to be delayed until the message is sent, but so what? It doesn't
need to be formatted until then. Why assign formatters to the queue at
all? Maybe this is strictly for receiving messages. Probably, now that
I think of it.
//End Quote

#1 No idea. Its just the way it is. I would think that the message would
be more important to set as the BinaryFormatter, not the Queue.
But I don't know.

//Quote
2. I still don't understand why System.GetType() doesn't work here.
Yes, I have confirmed the assemblies are the same. In fact, I build
the receiving program by pointing it at the build directory on the
transmitting machine. I do not copy the assembly over there
explicitly.
//End Quote


I'm not "in your code" enough to see this.


//Quote
3. What is the point of a BinaryFormatter? It seems like it is just
converting it to XML anyway. Maybe not. I guess serialization doesn't
imply XML necessarily. I think this should work for an XML formatter
as well, but I haven't gone back to try it with the [Serializable]
attribute.
//End Quote

You have to remember that Xml is just a big fancy (and usually long) string
at the end of the day.
Xml is great for non propietary stuff. But it is in fact not the great
performer.
BinaryFormatter is more efficient, and if you're workign in a DotNot to
DotNet world, use it.

You can find a decent xml serialization demo here:
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!114.entry

//I guess serialization doesn't imply XML necessarily.//
Yes, exactly.

Your code should work if you have xml to xml (serialization), but again, you
shouldn't pick that one necessarily.

.......

If you had a situation where you needed to put messages in a queue.... and
you didn't have DotNet doing it, (ex: asp application), you can put xml in
the queue.
Remember, anybody can generation xml. And almost anybody can put a message
INTO the queue. As long as the xml is the right kind of xml, it'll work.



Anything to do with Remoting, MSMQ, WCF, or (in asp.net) Session variables
(stored in Sql Server) needs to be serializable.








Bill Wright said:
Sloan,

Great suggestions and I have met with success! Thanks so much. There
are still things I do not understand, though.

First, what worked. Using the third constructor of the Message,
passing in a Binary formatter:

System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd, new BinaryMessageFormatter());

I do wonder why I need to do this if I set the formatter on the queue:

BUILD_QUEUE.Formatter = new BinaryMessageFormatter();

Why do I need to do this as well? Maybe I don't. Something is
redundant here. Anywhere when I made this change I got a clear
serialization error. Then I added

[Serializable]

to the class definition and it worked!

I had already had a default constructor for the class, as that
requirement came up earlier. I'm happy that this works and I'm moving
on, but here are some things I'm still confused about:

1. Why does the queue and the message have formatters associated with
them. One would be sufficient. If it wasn't specified in the message
constructor, why wouldn't it use the one on the queue? Yes, this would
have to be delayed until the message is sent, but so what? It doesn't
need to be formatted until then. Why assign formatters to the queue at
all? Maybe this is strictly for receiving messages. Probably, now that
I think of it.

2. I still don't understand why System.GetType() doesn't work here.
Yes, I have confirmed the assemblies are the same. In fact, I build
the receiving program by pointing it at the build directory on the
transmitting machine. I do not copy the assembly over there
explicitly.

3. What is the point of a BinaryFormatter? It seems like it is just
converting it to XML anyway. Maybe not. I guess serialization doesn't
imply XML necessarily. I think this should work for an XML formatter
as well, but I haven't gone back to try it with the [Serializable]
attribute.

Thanks again for all the great help,
Bill

My hankering is that the issue is ... the third constructor of the
Message
object.http://msdn2.microsoft.com/en-us/library/system.messaging.message.mes...

And the fact you don't have a default constructor on your
NodeBuildCommand
class.

But my previous post should give you the tools to figure it out.

If you're still stuck, post more code !


Initially, I was using an XmlFormatter to initialize the queue (from
both the sender's init code and the receiver's init code, like this:
string[] types = { "System.String",
"Tendril.NodeBuildCommand" };
BUILD_QUEUE.Formatter = new XmlMessageFormatter(types);
And that's when I got the original error message. I'm still baffled
why System.GetType() doesn't work and I think this problem needs to be
fundamentally understood to solve this problem. That said, I want to
get this to work and am willing to try a different formatter if it
will help matters. So, in the second go I did the following for queue
initialization:
BUILD_QUEUE.Formatter = new BinaryMessageFormatter();
This formatter doesn't appear to take any arguments?
Then each time I construct the message like this:
NodeBuildCommand buildCmd = new NodeBuildCommand(11,
0x1111);
System.Messaging.Message buildMsg = new
System.Messaging.Message(buildCmd);
Then in the receiving application, which uses the same DLL Assembly
that contains the code for the NodeBuildCommand class, I do the
following, in the callback method that I have setup for the queue:
private void buildQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
System.Messaging.Message newMsg = e.Message);
(NodeBuildCommand)(newMsg.Body)
The error I get the with the BinaryMessageFormatter method is "Cannot
deserialize the message passed as an argument". I would think this is
message I'd get when using the XmlFormatter, but I guess some form of
serialization is done either way. Each time the exception is thrown
from the System.Messaging.Message.get_Body() method.
Both of these problems are confounding to me.
Thanks for any advice,
Bill
Good catch Nicholas.
ActiveXMessageFormatter = COM/ActiveX
"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote
in
message That
shouldn't
be ASP code as much as it is COM/ActiveX
component/unmanaged code.
New ActiveXMessageFormatter ' good for using Asp code (That's ASP,
not
Asp.Net)
new BinaryMessageFormatter() ' good for using DotNet objects
Which formatter are you using?

And when you handle/receive the message, are you casting it?
Dim e As Employee = CType(msg.Body, Employee)

Employee e = msg.Body as Employee; //<< Can you do this, aka, is
your
assembly referenced in the project.


Console.WriteLine ("We got the employee from the message
body");

Something like that.
If a DotNet to DotNet world, you want to usually use the
BinaryMessageFormatter
Then you have to cast the msg.Body
Make sense?

I really like Manoj's helper

I added some code (to enhance his) in the comments section,
basically
to
overload the formatter.
Question #2.
--------------------------------------------------------------------------------

From: Bill Wright [mailto:[email protected]]
Sent: Monday, October 01, 2007 5:28 PM
To: Sloan Holliday
Subject: Re: Unable to cast MSMQ body to an object

Thanks for the email response. I appreciate it.
I'm using the Formatter. I think that is essential to send a
message
without an error, though I'm not sure.
Anyway, when I initialize the Formatter I give it an array of two
strings:
{ "System.string", "Tendril. NodeBuildCommand" }
So, I don't think that is the problem. Isn't it curious that can
create
an object like this:
New Tendril. NodeBuildCommand()
but that I cannot get the type using System.GetType("Tendril.
NodeBuildCommand")

I've seen stuff about explicitly loading the assembly, but it seems
like
the program knows about the assembly - it can create objects from
it
explicitly, but it can't seem to discover the type via the
System.GetType() method...?
Any other ideas?

news:[email protected]...
You need to beomce famaliar with the formatter argument

Here is smoe sample code:
public class MyMSMQListener
{
MessageQueue _queue = null;
public MyMSMQListener(string queuePath ,
System.Messaging.IMessageFormatter formatter, int
receiveOrPeekMilliSeconds)
{
this.ConstructorCommon(queuePath , receiveOrPeekMilliSeconds);
this._queue.Formatter = formatter; // Customize the formatter
type
}
private void ConstructorCommon(string queuePath , int
receiveOrPeekMilliSeconds)
{
Console.WriteLine("MyMSMQListenerwas constructed");
this._queue = new MessageQueue(queuePath);
this.m_receiveOrPeekMilliSeconds = receiveOrPeekMilliSeconds;


Hi,
I built an assembly with a class, NodeBuildCommand, in the
namespace
"Tendril". I use that assembly on one computer to send a
NodeBuildCommand object in the body of a
System.Messaging.Message.
This works without error. On the receiving computer I use the
same
assembly and then try to cast the body to that object. When this
happens I get a "Type not found error" from GetType(), which is
called
from the get_Body() method on the System.Messaging.Message
object.
In the development environment on the remote computer in the
Immediate
window of the debugger I can do the following:
(new Tendril.NodeBuildCommand()).GetType().Name =
"NodeBuildCommand"
(new Tendril.NodeBuildCommand()).GetType().Namespace = "Tendril"
so why doesn't this work:

This last line returns null and this is the source of my problem
with
the casting. Any ideas on how to proceed?
Thanks,
Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top