Serializing encapsulated lists in a Web Service - c#

I have a class MyClass containing a private List<MySecondClass> myList. The list is exposed through a getter as follows:
public IEnumerable<MySecondClass> MyList
{
get { return myList.Select(a => a); }
}
The list is modified through public AddItem(MySecondClass itemToAdd) and ClearItems() methods. I believe that this is a properly encapsulated list.
The problem lies in that I need to pass an object of type MyClass (containing myList) via SOAP to a web service, which fills myList (using the AddItem() method), and then returns the object.
However, when the webmethod returns the class, after serialization myList is empty. I am suspecting this is because I do not have a setter for myList, which is causing the list not to be set during serialization.
Is this a good assumption, or am I way off? If the problem is what I think it is, is there a way to allow for the list to be successfully passed from the webmethod without breaking encapsulation (I do not want to expose a generic list)?

Without trying this directly myself, I believe that you could definitely be correct.
serialization in .NET makes utilizing read only properties a fun circus.because the .net default serialization process requires a setter property in order to "deserialize" the object. Without a setter property the serialization piece will still work allowing you to serialize to a drive or across the network. But, it is the deserialization process that will fail which could definitely be why your collection is empty. Im just amazed it doesn't error out to be honest.
Have you tried to add a simple setter just to verify that this is in fact the issue just so that we know with 100% certainty that this is the problem before working to solve it.

While I never really solved the initial problem, what I did do to get it working was simplify the data that was being passed to the web method. Instead of passing an entire object to the web method, I instead passed a unique identifier. The webmethod then returns the list I need, and I handle actually adding the items in this list to the object client-side.

The XML Serializer used by ASMX services only serializes public read/write properties.

Related

WCF Event Order

I need to hook into an event in a slightly unusual manner in WCF.
I'm passing a model from the client to the server, and I need access to that model:
After the model has been created but
Before the incoming data has actually been deserialized to that model
The reason is I actually have deserialization events that are conditional, and ideally I want that condition itself to be a property on the object; thus, I'd have the pattern:
create object->set property->deserialize the rest of the object based
on that property
Is there an event in WCF that I can hook into for this? I've got an attribute set up that hooks into the "IOperationBehavior" and "IParameterInspector" set up, but those don't (as far as I can tell) have an action that hooks in between the creation and deserialization events.
Alternatively, I'd be fine with a way of modifying the data coming in off the wire and explicitly adding that property into the incoming data, provided I could guarantee that it would be the first property deserialized.
Any ideas?
[Edit]
Minor note, I'm using JSON as the data transport here, not that that should really have an impact on the final solution.
You could theoretically implement a nested envelope, whereby the actual data passed to your WCF service consists of a class (the envelope) which has the data needed to determine how to deserialize and a byte array which consists of the real data in a serialized format. Then you could manage the deserialization of the byte array manually.
Seems there is probably a better way, but I've done similar things and they work.
EDIT: Perhaps an IDispatchMessageInspector is the right place to hook?

How do I serialize a dynamic object?

I want to make a Configuration Data Manager. This would allow multiple services to store and access configuration data that is common to all of them.
For the purposes of the Manager, I've decided to create a configuration class object - basically what every configuration data entry would look like:
Name, type, and value.
In the object these would all be strings that discribe the configuration data object itself. Once it has gotten this data from its database as strings, it would put it into this configuration object.
Then, I want it to send it through WCF to its destination. BUT, I don't want to send a serialized version of the configuration object, but rather a serialized version of the object discribed by the configuration object.
The reason I'd like to do this is so that
The Data Manager does not need to know anything about the configuration data.
So I can add configuration objects easily without changing the service. Of course, I should be able to do all of the CRUD operations, not just read.
Summary:
Input: string of name, type and value
Output: Serialized output of the object; the object itself is "type name = value"
Questions:
Is this a good method for storing and accessing the data?
How can I/can I serialize in this manner?
What would the function prototype of a getConfigurationData method look like?
I have decided to go in a different direction, thanks for the help.
Is this a good method for storing and accessing the data?
That is difficult to answer, the best I can give you is both a "yes" and a "No". Yes, It's not a bad idea to isolate the serialization/rehydration of this data.... and No, I don't really care much for the way you describe doing it. I'm not sure I would want it stored in text unless I plan on editing it by hand, and if I'm editing it by hand, I'm not sure I'd want it in a database. It could be done; just not sure you're really on the right track yet.
How can I/can I serialize in this manner?
Don't build your own, never that. Use a well-known format that already exists. Either XML or JSON will serve for hand-editable, or there are several binary formats (BSON, protobuffers) if you do not need to be able to edit it.
What would the function prototype of a getConfigurationData method look like?
I would first break-down the 'general' aka common configuration into a seperate call from the service specific configuration. This enables getConfigurationData to simply return a rich type for common information. Then either add a extra param and property for service specific data, or add another method. As an example:
[DataContract]
public class ConfigurationInfo
{
[DataMember]
public string Foo;
...
// This string is a json/xml blob specific to the 'svcType' parameter
[DataMember]
public string ServiceConfig;
}
[DataContract]
public interface IServiceHost
{
ConfigurationInfo GetConfigurationData(string svcType);
}
Obviously you place a little burden on the caller to parse the 'ServiceConfig'; however, your server can treat it as an opaque string value. It's only job is to associate it with the appropriate svcType and store/fetch the correct value.

When do I need a datacontract in WCF and would it be better to use a simple type?

I am having some trouble designing my WCF service. Bassically I need the service to recieve an XML document. The xml maps to a class that was generated from xsd.exe. I was originally just had this:
public void AddDocument(string xmlString)
Then I would deserialize the xml into the generated class. I was told this is a bad idea because I am doing extra work since wcf will do the serialization for me if I just use the document class as a parameter like this:
public void AddDocument(MyGeneratedClass document)
I'm new to WCF but if I do it this way I thought I would have to create a datacontract for MyGeneratedClass. The generated class is 20,000+ lines so this would take forever.
Do I need a DataContract? Anyway I think I am missing something so I hope this makes sense and if anyone can point me in the right direction I would greatly appreciate it. Thanks!
I would use simple types if your method only requires one or two parameters, and will return only a single simple type value.
As a general rule:
If you need to pass in more than just a few (less than 5) simple types - use some kind of a Request object, otherwise your call gets unwieldy.
If you need to return more than one single simple type value, use a Response object to bundle up those values.
I would try to avoid sending and receiving XML and parse it - try to send back and forth real well structured (data) objects - much easier to deal with and type-safe and all !

Generically creating objects in C#

What I am trying to do is load in objects from an XML save file. The problem is those objects are configurable by the user at runtime, meaning i had to use reflection to get the names and attributes of those objects stored in an XML file.
I am in the middle of a recursive loop through the XML and up to the part where I need to create an object then thought ..... ah - no idea how to do that :(
I have an array stuffed with empty objects (m_MenuDataTypes), one of each possible type. My recursive loading function looks like this
private void LoadMenuData(XmlNode menuDataNode)
{
foreach (object menuDataObject in m_MenuDataTypes)
{
Type menuDataObjectType = menuDataObject.GetType();
if (menuDataObjectType.Name == menuDataNode.Name)
{
//create object
}
}
}
I need to put some code where my comment is but I can't have a big switch statement or anything. The objects in my array can change depending on how the user has configured the app.
You want to use Activator.CreateInstance(Type)
object instance = Activator.CreateInstance(menuDataObjectType);
for this to work efficiently, you may need to restrict the dynamically created instances to implement an interface
ICommonInterface i = (ICommonInterface)Activator.CreateInstance(menuDataObjectType)
That way, the dynamically created object becomes usable - you can call interface methods on it.
If you're instantiating a graph of objects, would the XmlSerializer or DataContractSerializer be more appropriate?
Activator.CreateInstance

How to use application settings in .NET 3.5 Windows Forms

I am trying to store a type of System.Collection.Queue. The queue will only contain strings. The issue is that when I attempt to use it, it is always Null.
Settings.Default.CorrectionsDescription.Enqueue(textString);
I get the following error.
Object reference not set to an instance of an object.
I have gotten StringCollection to work fine, but I need a FIFO queue.
How do you initialize the queue, in the Settings or through code? When I tried, it gave the error that it is read only.
Settings usually only store data in very simple objects or collections (xml-serializable, even Dictionary<TKey, TValue> already causes problem!).
Queue has special semantics and is not very suitable for data storage.
I suggest to use List<string> or StringCollection to store settings and create Queue on start of your application based on that collection.
Saving is the same but in reverse order - create List from your Queue, put it into Settings class and save.
Update:
Standard settings mechanism uses XML serialization for object persistence.
Object implementing IEnumerable<T> must also have method Add(T value) to be xml-serializable. Queue<T> doesn't have such method so can't be successfully deserialized.
MSDN:
XmlSerializer can process classes that implement IEnumerable or ICollection differently if they meet certain requirements. A class that implements IEnumerable must implement a public Add method that takes a single parameter
I have always just used:
if (Settings.Default.CorrectionsDescription == null)
{
Settings.Default.CorrectionsDescription = new Queue();
}
at the program startup, but I would like to know of a better way as well.

Categories

Resources