WCF private member reference in DataContract class becomes NULL - c#

I have a pecular problem in my WCF in the web services layer.
When I instantiate a private member (_Wagon) of my class (This instantiation is not null) in WCF, after few seconds, it's become null.
I've been trying to diagnose the problem, but no result so far.
So I'm turning to you people to help me solve this problem.
Thank you.
Hence there is my code :
[DataContract]
public class RemoteWagon
{
private readonly IWagon _Wagon;
public RemoteWagon(IWagon Wagon)
{
_Wagon = Wagon; //_Wagon isn't null here
}
~RemoteWagon()
{
Trace.WriteLine("Do nothing");
}
[DataMember]
public RemoteBreakpoint Breakpoint
{
set
{
if (value == null)
{
_Wagon.Breakpoint = null; //_Wagon member is NULL...
}
else
{
//... useless code in this context.
}
}
}
}

This would happen if your class had been serialized and deserialized by DataContractSerializer (for example when sending data between client and server)
Some reference: DataContractSerializer doesn't call my constructor?
If this is the case, then one possible solution, that worked for me: https://stackoverflow.com/a/9419943/724944
So a quick check&fix for this problem (I assume that you want to initialize the field yourself and not serialize it) would be to create method:
[OnDeserializing]
private void OnDeserializing(StreamingContext c)
{
_Wagon = initializeWagon();
}
however, as you probably noticed, you won't be able to pass Wagon during deserialization - you'll have to initialize it differently.
On the other hand, If you want _Wagon serialized, then expose it as public [DataMember] property

It seems that if you want _Wagon serialized you should mark it as a DataMember and ditch the "readonly" on it. If you don't want it serialized, show us your code to construct and fill this object.

Related

How to reset JsonProperties in a class with new JSON string

I've deserialized JSON into a c# object, but with an incomplete JSON such that some properties are missing. At the time of deserializing the object, I don't have access to the full JSON. I can get the full JSON by making another API call, but I don't want to make that call if I don't have to.
I would like my property getters to work such that they return the property if it's not null. If it is null, it should make the call to the API to get the full JSON and update all of the JsonProperties in the class, and then return the property I've asked for.
public class Car
{
private string _make;
private string _model;
[JsonProperty("make")]
public string Make
{
get
{
if (_make != null)
{
return _make;
}
else
{
UpdateProperties();
return _make;
}
}
}
[JsonProperty("model")]
public string Model
{
get
{
if (_model != null)
{
return _model;
}
else
{
UpdateProperties();
return _model;
}
}
}
[JsonProperty("self")]
public Uri Self { get; set; }
public void UpdateProperties()
{
}
}
In the UpdateProperties() method above, I can make it use the Self property to get and deserialize a new instance of a Car class, but I want it to refresh the properties of the current Car class instance instead. I can do this manually by setting each property individually again, but since I need to do this for many classes, I would appreciate a better way. Is this possible?
Or am I going about this all wrong?
EDIT:
Here is an example of the JSON the API would return. Lets say I make a call to get information about the vehicle fleet. It would return:
{
"details" : "something"
"car": {
"make": "Ford",
"self": "https://..."
}
"truck": {
"age": 30,
"self": "https://..."
}
}
where when you access the url provided by car.self, it would return the following JSON:
{
"make" : "Toyota",
"model" : "Camry",
"self" : "https://..."
}
So, let me offer a different perspective. The problem description seems straightforward enough- I have two API calls, one which returns a partial object, and one which returns a complete object. I don't want to make two calls if I don't have to. So, I'll just make the second call and "fill in the details" if I need to, right?
Wrong.
The proposed approach is not a good idea.
This goes off the rails from the beginning with the design of the API. The objects returned by the API should not be so complicated so as to require multiple calls to return the "full" object as described in the code. But, let's assume I have no control over the design of the API - what should I do?
Programmers are frequently faced with the task of confronting a badly-designed API. These create leaky abstractions like the one described in this problem, where there is a strong desire to "paper over" the bad API design. The problem is that not all bad designs can be papered over. This is one.
What is proposed here is to introduce a painful side-effect of a get accessor. This is arguably the worst way to solve the problem of a bad API design. A typical get method returns with a negligible amount of time - it's a simple memory access. This proposed get accessor could potentially take seconds to return, it could fail, it could throw an exception. Worse yet, there is no indication to the caller that this is, in fact, access to an external interface. At the end of the day, the state of your object is not deterministic, which is the arguably the worst thing you can have in a program.
If that wasn't bad enough, get accessors have no provision for asynchronous operations, which are common when dealing with remote APIs. User experience will suffer. By taking this approach, I will have actually taken one problem and made a new problem everywhere this class is used.
A better approach:
The API has two separate functions, so really, this implies two separate result types. I would create one type for the partial class and a second type for the full class. After all, I'm writing code - and unless the code is in the habit of re-writing itself, I should know at the time of writing whether I need the full or the partial representation of the object.
To get the full representation, I'll provide a separate access to the API, with appropriate methods to allow for asynchronous execution (e.g. observables). This will have the added benefit of allowing me to examine (via the "where used" function) where in the program these different API calls are used. This might build a case for me to return to the API designer and suggest a change to the design, based on how I'm using it.
The only way with your current setup to reset all of the properties manually.
You're right to want to have this be automatic, since that's a lot of boilerplate code. This is a common problem and the most common solution to it is to use the DTO or Data Transfer Object pattern.
You would introduce a new class called a CarDto and instead of Car exposing private fields, it would expose the properties on the CarDto.
See Below:
public class Car {
private CarDto _dto = null;
public Car(CarDto dto = null) {
//If we pass in a dto, use it, otherwise create a new one
_dto = dto ?? new CarDto();
}
[JsonProperty("make")]
public string Make {
get {
if (_dto.Make == null) {
UpdateProperties();
}
return _dto.Make;
}
}
[JsonProperty("model")]
public string Model {
get {
if (_dto.Model == null) {
UpdateProperties();
}
return _dto.Model;
}
}
[JsonProperty("self")]
public Uri Self { get; set; }
public void UpdateProperties() {
//The API would return a CarDto.
CarDto newDto = APICall(); //Mock code
_dto = newDto;
}
}
public class CarDto {
public string Make { get;set; }
public string Model { get;set; }
}
So now, if you ever have a null property, you will make a call to UpdateProperties. This will then return a new CarDto that you use as your private _dto field.
This is a SUPER useful and common pattern, and one that makes things a lot easier so it's great to implement and get practice using! Let me know if anything is unclear.

Dynamically ignore data members from getting serialized

We have an existing WCF service which uses several DataContracts. We want to modify the serialization based on the device, so that when accessed from mobile devices, the service should serialize only some important data members(not all)
We have 2 options here
Create separate operation and data contracts for different types of
devices
Mess with the actual xml serialization and suppress creating
unnecessary elements based on the device
We don't want to go with the first option since it introduces a lot of redundant code problems in the future
Small research showed that we need to use IXmlSerializable and override the readXML() and writeXML() methods. But at the same time, I have seen somewhere that DataContract and IXmlSerializable should not be used together
Any example to mess with actual serialization is greatly appreciated .
[DataContract]
public class TokenMessage
{
string tokenValue;
string extraValue;
[DataMember]
public string Token
{
get { return tokenValue; }
set { tokenValue = value; }
}
[DataMember]
public string Extra
{
get { return extraValue; }
set { extraValue = value; }
}
}
Now when i access the service which returns a typical TokenMessage data contract, from a mobile device, i don't want the "Extra" data member to be serialized i.e. When I supply a different argument to the operation contract, it should be able to serialize some/all the data members(depending on the action)
PS: For now please ignore the device detection part. Lets assume we have an argument in the operation contract, which helps us identify the device
I'm not convinced that some variant of #Pranav Singh's answer isn't a better design, but that's not your question...
As you mentioned in a comments attributes in .NET are static by design. This means dynamically adding/removing [DataMember] isn't a good option. It is possible. There are options like using Reflection.Emit to recreate the instance with the meta data changes (see all the answers to Can attributes be added dynamically in C#?) but all of those routes are complicated.
I see two reasonable options:
1) Implement an IParameterInspector for the service. In the AfterCall() method you could inspect and alter the parameters being returned to the client before they are serialized. There is some work to use reflection to dynamically determine the parameter types and set their values, but its not complicated. This is the better design that enables reuse of the behavior across many contracts or services. Carlos Figueira's blog is the best source for WCF extension examples.
2) Use the [OnSerializing] and [OnSerialized] events. In the [DataContract] you could temporarily alter what the properties are returning during serialization. The events are actually designed to enable initialization and as such this solution is a bit of a hack. This solution is also not thread safe. But it does keep the code contained to the DataContract class and solves the problem quickly (and I think you are looking for quick).
Solution #2 mights look something like:
[DataContract]
public class TokenMessage
{
string tokenValue;
string extraValue;
bool enableExtraValue = true;
[DataMember]
public string Extra
{
get {
if (enableExtraValue)
return extraValue;
return null;
}
set { extraValue = value; }
}
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context)
{
enableExtraValue = false;
}
[OnSerialized()]
internal void OnSerializedMethod(StreamingContext context)
{
enableExtraValue = true;
}
}
Solution #2 is a quick fix (which is what I think you are looking for).
Solution #1 is the better design.
Try using IgnoreDataMemberAttribute
There is a approach, but I think this will require extra DataContract to be generated but still no need for separate operation and data contracts for different types of devices.
It can classic implementation to run-time polymorphism. I am just giving idea:
Say you have a generic DataContract like :
[DataContract]
[KnownType(typeof(Extra))]
[KnownType(typeof(Extra2))]
public class TokenMessage
{
string tokenValue;
string extraValue;
[DataMember]
public string Token
{
get { return tokenValue; }
set { tokenValue = value; }
}
}
Other device specific contracts can inherit TokenMessage as base class like:
[DataContract]
public class Extra:TokenMessage
{
[DataMember]
public string Extra
{
get ;set;
}
}
[DataContract]
public class Extra2:TokenMessage
{
[DataMember]
public string Extra2
{
get ;set;
}
}
Now at run-time as you say you know an argument in the operation contract, which helps us identify the device. Say based on device type, you can instantiate base class with derived class like:
TokenMessage tm= new Extra();
OR
TokenMessage tm= new Extra2();
So at run-time you will decide which device contract will be part of genric response.
Note: Adding KnownType will generate the separate xsd within wsdl for all known types within base class, but saves serialization for data at run-time as this should depend on actual inheritance chosen.
In your model add a property 'ShouldSerializeYOUR_PROPERTY_NAME', set it to false when you do not want the property serialized.
See more here: http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.shouldserializeproperty(v=vs.110).aspx

How to XMLSerialize member Object inside a container object

I've been searching on google about this for an hour but I think I don't use the right word because I can't find a very simple example of what I'm trying to do. People always use complexe structure like List or derived object in the samples.
All I want to do is to XMLSerialize my main object called SuperFile to a file. This SuperFile class contains 2 members and these 2 members are not serialized so the resulting XML file is empty (containing only the header).
Here is my code, what am I doing wrong?
SuperFile
public class SuperFile
{
private NetworkInfo _networkInfo;
private Planification _planification;
public NetworkInfo NI
{
get
{
return _networkInfo;
}
}
public Planification Planif
{
get
{
return _planification;
}
}
}
NetworkInfo and Planification are very normal class with mostly double member and they serialize perfectly on their own if I want. But now, I want them to serialize inside the SuperFile object.
Finally, here is my code to do the serialization
public void Save(string strFilename)
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(ExoFile));
TextWriter WriteFileStream = new StreamWriter(strFilename);
x.Serialize(WriteFileStream, this);
WriteFileStream.Close();
}
If I put this inside SuperFile, it get serialized but the 2 other member gets skipped. I think it get serialize since it's not a complex type...
public int _nDummy;
Hope it's clear!
Thanks!
XMLSerializer has some limitations, one of which is to require a setter. (It also doesn't serialise private fields, indexers..). It's not an obvious gotcha, and has had me scratching my head in the past :)
here's an answer with some details - Why isn't my public property serialized by the XmlSerializer?

Find out whether property setter is called in DeSerialization process

Is there a way to find out whether an object property is called as part of the DeSerialization process (e.g. by the XmlSerializationReaderXXX).
Background: A typical scenario is to disable events and complex operations in that case, until the initialization is complete.
One approach I have found, is to "interpret" the stack and look up whether the call is triggered by XmlSerializationReaderXXX, which is not so elegant IMHO. Is there anything better?
public SomeClass SomeProperty
{
get { ..... }
set
{
this._somePropertyValue = value;
this.DoSomeMoreStuff(); // Do not do this during DeSerialization
}
}
-- Update --
As Salvatore has mentioned, somehow similar to How do you find out when you've been loaded via XML Serialization?
I have a possible solution.
public class xxx
{
private int myValue;
[XmlElement("MyProperty")]
public int MyPropertyForSerialization
{
get { return this.myValue; }
set
{
Console.WriteLine("DESERIALIZED");
this.myValue = value;
}
}
[XmlIgnore]
public int MyProperty
{
get { return this.myValue; }
set
{
Console.WriteLine("NORMAL");
this.myValue = value;
}
}
}
class Program
{
static void Main(string[] args)
{
xxx instance = new xxx();
instance.MyProperty = 100; // This should print "NORMAL"
// We serialize
var serializer = new XmlSerializer(typeof(xxx));
var memoryStream = new MemoryStream();
serializer.Serialize(memoryStream, instance);
// Let's print our XML so we understand what's going on.
memoryStream.Position = 0;
var reader = new StreamReader(memoryStream);
Console.WriteLine(reader.ReadToEnd());
// Now we deserialize
memoryStream.Position = 0;
var deserialized = serializer.Deserialize(memoryStream) as xxx; // This should print DESERIALIZED
Console.ReadLine();
}
}
The trick is using the XmlIgnore, it will force the xml serializer to ignore our property, then we use XmlElement to rename the property for serialization with the name of the property we want.
The problem with this technique is that you have to expose a public property for serialization, and is in some way bad because it can virtually be called by everyone.
It will not work if the member is private, unfortunally.
It works, is not totally clean, but is thread safe and don't rely on any flag.
Another possibility is to use something like the Memento pattern.
Using the same trick you can add a property called for example Memento that returns another object that contains properties suitable only for serialization, it can makes things a little cleaner.
Did you think instead of changing approach and using DataContractSerializer? It is much more powerful and produces pure XML. It supports the OnDeserializationCallback mechanism.
Since you got a pretty complex scenario you might want to consider creating a "data core" class which will be actually serialized/deserialized using simple direct way. Then your complex object is constructed from that object and you fire all events/operations as normal. It will make sequence of deserialize -> fire events/operations more explicit and easier to understand.
There's an OnDeserializingAttribute/OnDeserializedAttribute attributes pair. You can set isDeserializing flag while object is being deserialized. I don't know if they play well with XML serialization, though.
For XML Serialization solution could be implementing IXmlSerializable and embedding such logic into the ReadXml()/WriteXml() method
To have finer control of the deserialization process you could implement IXmlSerializable interface for SomeClass - in ReadXML you can then for example have some field set a flag that you are in deserialization... this flag can then be checked in the respective methods... and on completion it needs to be reset.
Another option (though not for XML IIRC) is to implement the above via OnDeserializingAttribute and OnDeserializedAttribute .
I misunderstood the question at first, but you want to ask from within setter if you are called during deserialization. To do that, use a static flag:
[serializable]
class SomeClass
{
public static IsSerializing = false;
SomeProperty
{
set
{
if(IsSerializing) DoYouStuff();
}
}
}
and then set the flag just before the serialization:
try
{
SomeClass.IsSerializing = true;
deserializedClass = (SomeClass)serializer.Deserialize(reader);
}
finaly
{
SomeClass.IsSerializing = false; //make absolutely sure you set it back to false
}
Note that same approach can work even if you deserialize a class that contains a member of your class...
Set a breakpoint on the property, and run in debug mode. It will break at the point of access for the getter/setter that you set the breakpoint on.

XML serialisation won't write out lazy-evaluated property

Following on from a previous question, I am having trouble combining the Lazy<T> generic that was suggested with my XML Serialization.
Here is the functionality I am using for Lazy<T>:
public struct Lazy<T> where T : class, new()
{
private T _Value;
public bool HasValue
{
get
{
return (_Value != null);
}
}
public T Value
{
get
{
if (!HasValue)
_Value = new T();
return _Value;
}
}
}
Now the MSDN Docs say that it's fine to have an [XmlElement("ElementName")] on a property and it does indeed seem to be able to deserialize just fine. The problem comes when I am serializing an object. I am running the following piece of code:
class SomeClass
{
[XmlElement("ExternalElementName")]
public ComplexElementType InternalElementName
{
get { return _InternalElementName.Value; }
}
protected Lazy<ComplexElementType> _InternalElementName;
}
Elsewhere:
SomeClass someClass = new SomeClass();
someClass.InternalElementName.ComplexElementTypeChild = "some string";
// serialize...
The strange thing is, this works fine in the debugger but no element is output in the XML. Non Lazy<T> elements work fine. Any ideas?
The problem is that the property has no setter. Even if it would be possible to get the value to serialise it, it can't be deserialised as there is no way to put the value back in the new object.
By design, XML Serialization will only serialize public read/write properties, and public fields.
Not sure what the problem is (I have always found the XML serializer behaviour to be shifty), but why not use the Nullable<T> class? Don't re-invent the wheel :)

Categories

Resources