Error using WCF and DataContractSerializer - wcf

I have a fairly complex object model that I'm trying to serialize using WCF. I'm running into a problem where I can create a new instance on the server and return it to the client, then trying to pass that same object back or even serialize it using the DataContractSerializer throws an exception.
Test method Server.Service.Test.SerializationTest.TestFilingSerialization threw exception: System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type MyNameSpace.MyObject. No set method for property '' in type ''
It's not giving me any info on a setter I'm supposedly missing, even though I've tried looking through the inheritance hierarchy for missing setters, I can't seem to get passed this. MyObject is a type of property on the object I'm trying to serialize, here's the funny part. In the setter for that property, I have code that looks like this:
set
{
_backingField = value;
_backingField.IsDirtyManager.SetIsDirty();
NotifyPropertyChanged("MyProperty");
if (!ContainsType(_backingField.GetType()))
{
Aggregates.Add(_backingField);
}
}
If I comment out the Aggregates.Add it goes onto the next property and throws the same exception there, the kicker is, it get's through other properties with the same code, before it hits this one and dies, so I don't know what the problem could be.
Anyone have experience where the real error is, because the Property name and Type are not filled out in the exception so it seems like the error has to be something else. If I just create a new instance on the client I can deserialize and serialize no problems, so there's gotta be something I'm missing here. Any ideas on what to look for?
EDIT
I am literally doing only this:
Create instance
Serialize
De-serialize
Re-serialize
Die here

I am assuming that the "Aggregates" is a list in your class.
If your class constructor does not create an Aggregates list, then it is null when you try to add items to it.
This does not match the error you are getting, but worth checking.
EDIT
In Visual Studio go into "Tools" -> "Options" -> "Debugging" -> "General" uncheck the option "Enable Just My Code". Then run it again, you may get a better error message.

Ok, figured it out. The last developer had set the Order property on the DataMember attribute. It was the property with the order before the property in the error message that was causing the problems. There were a couple read-only properties that I missed in that class.

You might see this if your setter is protected or private. If it's not marked public the serializer will not be able to set it. How do you have your Aggregates collection exposed?

Related

Exception CX_SY_REF_IS_INITAL

I'm setting up a Method call from a class
DATA: r_info TYPE REF TO zcl_sv_job_offline_ctrl.
CALL METHOD r_info->create
EXPORTING
is_data = lr_test_record.
And receiving the following errors:
CX_SY_REF_IS_INITAL
You are trying to access a component with a 'ZERO' object reference (points to nothing). Variable: "R_INFO".
Am I missing something?
You missed to create the object.
so you need to to:
create object r_info.
or
r_info = new zcl_sv_job_offline_ctrl( ).
or if there is a "factory method" ( what your 'create' method indicates )
r_info = zcl_sv_job_offline_ctrl=>create( is_data = lr_test_record ).
Your Exception tells you that the reference ( r_info ) is not connected with an object on the heap. So you need to do one of the above steps and then it should work. ( depending on your class )
Sorry, I don't have the rep to comment just yet...
I notice that your class is a Z so I'm wondering if you are trying to create a singleton class. In which case. Your 'Create' should be static. Your Constructor private and your Instance in a private attribute.
From the other comments, I agree, your question is missing some key details to provide an accurate answer.
If IO_DISPATCHER is part of the constructor and you are unable to pass a value, you need to dig a little deeper into the purpose of the class. See if you can give it what it wants. Try a 'where used' and check out the other usages of the class. You might find you are looking at the wrong class, or at least approaching from the wrong direction.
If create is some method on the class and it is not static then you will never get it to work until you create an instance of the class.
Another thought that comes to mind is that you might be in the right place and just doing the wrong thing. Check your globals to see if there is already an instance of the class and you are trying to access something via declaration as data rather than using the global instance??
All guess work without more details.
Thanks all.
The solution was simply to instantiate the parent classes (properly), enabled me to instantiate the class in question.

Late Binding in VB

From what I have read so far, late binding is defining a variable as Object and then assigning it to the actual object later which is actually done at run time. I don't understand the point to that. Maybe this is the Java in me, but doesn't that limit the functionality to what is just in Object? It is like saying, "I want the potential of the extra stuff, but I don't want to have access to it." Is there an actual purpose for late binding in VB, or Java for that matter, that I'm overlooking?
You have it backwards. By using early binding you are limiting yourself to just the members of the type of the variable. With Option Strict On, a variable declared as type Object will only allow you access to members of type Object, regardless of the type of the actually object it refers to. With Option Strict Off, you can access a member of any name on a variable of type Object and the compiler won't complain. It's only at run time that any type checking is done so, as long as the actual object assigned to the variable has a member with that name, the code will run.
Probably the most common use for late binding is Office Automation. There are other options now but, in the past, if you referenced an Office library and used the specific types it contained, facilitating early binding, then you were limited to that specific version of Office. In order to support multiple versions, you had to forgo the reference, declare all your variables as type Object and use late binding. As long as the version of Office present at run time included the specified members on the objects used, the code would run without issue.
By the way, late binding doesn't require using type Object, although it is probably the most common. It just means that the reference is a less derived type than the object and you use a member of the object's type that the reference's type doesn't have, e.g. you use type Control and then use a member specific to type Button.
What I seen - some early .NET adapters-developers were doing is - they were using late binding instead on interfaces. They would declare two or more types
Public Class Handler1
Public Sub Execute()
' do something
End Sub
End Class
Public Class Handler2
Public Sub Execute()
' do something else
End Sub
End Class
And they would stick this thing into session object
If someting = 1 Then
Session("Handler") = New Handler1()
Else
Session("Handler") = New Handler2()
End If
And then, to process something they would do
Session("Handler").Execute()
There we go. This is not pretty or smart. But that was instead of proper programming like this (Imagine handlers implement IHandler interface with method Execute)
Dim h As IHandler = TryCast(Session("Handler"), IHandler)
If h IsNot Nothing Then
h.Execute()
End If
Here is where downfall of late binding starts: In the case of late binding, someone, somewhere, can rename a method Execute and compile code nicely. Release. And only then, at runtime, get a problem.
Late binding was good when we used to deal with interop and COM. Other than this, it is detrimental.

ABAP Objects - access message class of a class?

In the header information of an ABAP Objects class, I can enter a message class to use with the MESSAGE statement. This works like the MESSAGE-ID statement of a report or a function pool. Since I can't find the message class I entered in the header data anywhere in the generated sections, I assume that it's generated into the top-level CLASS-POOL statement somewhere.
For some libraries (for examples, the BAL application logging), it's necessary to specify the message class using a variable or a method parameter. Up to now, I've defined a constant that specified the message class and used that constant. I'm wondering if it's possible to access the message class specified in the header data in some other way so that I can get rid of that redundant variable.
Has anyone found a way to do so?
EDIT: The new way should be easier than the old one - I'm not crazy enough to add a CLASS-CONSTRUCTOR and perform some database access or SEO_* function calls just to get rid of that constant.
I think you need a CLASS-CONSTRUCTOR to set a class attribute with the message class.
The MESSAGE statement with INTO clause has the side effect of setting the SY- system variables. So you could put into your CLASS-CONSTRUCTOR something like:
DATA: lf_dummy TYPE string.
MESSAGE s999 INTO lf_dummy.
af_msgid = sy-msgid.
You could use the class builder API:
data the_class type ref to cl_oo_class.
create object the_class
exporting
clsname = `ZCL_SOMECLASS`.
data message_class type arbgb.
message_class = the_class->class-msg_id.
I haven't come across any syntax to do what you ask. For the reasons I outline below, I could believe that SAP never saw a need to include such functionality.
In my experience, the message class is an attribute of the message, not of the object that raises it, so it should be kept together with the type, number, and variables of the message. For example if my object is returning the number of an error, it should be returning the id (class) as well.
In this light I cannot see a reason why you would ever need to know the message-class assigned to an ABAP-OO class, you would only ever need to know the message-class of the messages returned by the ABAP-OO class.
The way I usually manage this is to raise my messages into a dummy field, and then use a subroutine to populate the contents of the sy-msg* fields into a BAPIRETURN structure. Then I return this BAPIRETURN structure to the caller. This way the type, id, number, and variables of the message are all kept together.

How to transfer objects through the header in WCF

I'm trying to transfer some user information in the header of the message through message inspectors.
I have created a behavior which adds the inspector to the service (both client and server).
But when I try to communicate with the service I get the following error:
XmlException:
Name cannot begin with the '<' character, hexadecimal value 0x3C.
I have also get exception telling me that DataContracts where unexpected.
Type
'System.DelegateSerializationHolder+DelegateEntry'
with data contract name
'DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System'
is not expected. Consider using a
DataContractResolver or add any types
not known statically to the list of
known types - for example, by using
the KnownTypeAttribute attribute or by
adding them to the list of known types
passed to DataContractSerializer.
The thing is that my object contains other objects which are marked as DataContract and I'm not interested adding the KnownType attribute for those types.
Another problem might be that my object to serialize is very restricted in form of internal class and internal properties etc.
Can anyone guide me in the right direction. What I'm I doing wrong?
Some code:
public virtual object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var header = MessageHeader.CreateHeader("<name>", "<namespace>", object);
request.Headers.Add(header);
return Guid.NewGuid();
}
Don't put the angle brackets into the actual strings. Remember, the serialization format may not even be text based, all you're doing is specifying the name of the element and the namespace. So your code should look more like this:
var header = MessageHeader.CreateHeader("name", "urn:myNamespace", object);
request.Headers.Add(header);
To close this question, I never solved the exception. Instead I implementated ISerializable which worked great for me.

VB.NET problem converting DataTable to JSON

Ok so I'm trying to use the JavaScriptSerializer to work with this code. However it crashes when it reaches the last line;
Dim json As New String(sr.Serialize(dt))
I get this error message;
A circular reference was detected
while serializing an object of type
'System.Reflection.Module'.
I would really appreciate any insights that could help solve this problem.
Circular reference means that serialising the object would result in an infinite loop.
For example if you would try to serialize object "A" having a 1 to 1 reference to object "B".
Declare a class containg the data you want to serialize with JSON to solve this issue.
As hkda150 has already said, you could use a class specifically tailored for being serialized.
This will furthermore enable you to have foreign key values serialized instead of having related full objects serialized. Thus, if you are serializing object a which has a property a.SomeB of type B, then you will often want the ID of a.someB to be present in your webpage. Obviously I don't know enough to be able to say if this is relevant in your specific use case.
BTW, If you find yourself doing a lot of mapping between "business objects" and "objects meant for serialization" you may want to consider using AutoMapper.