I was given a wsdl by a third party.
This wsdl is defined using MessageContract (which I'm sorry to say, after much Googling I still don't understand what the differences are when using MessageContract vs ServiceContract from a client perspective)
After instantiating an new complex object of Type BaseComplex, which consists of arrays of ComplexA[] and ComplexB[] , where ComplexA has Decimal and Decimal? properties defined, I then call the service method passing in the BaseComplex type. (I unfortunately cannot debug the service request locally because of firewall, however, I have verified that the BaseComplex.ComplexA.Decimal field HAS A VALUE just before making the call to the service.)
Once the code is placed on the server, my team has used WireShark to see exactly what's in the packets going across the wire. When we look at this, ComplexA.Decimal field has been omitted... Not even empty tags.
The only step I can think of that happens between the client.SendRequest(BaseComplex) call and what the WireShark output shows, is the .Net framework's Xml serialization. I've Google'd the crap out of this issue but have not come across anything to point me in the right direction.
Why is my client failing to make the request xml properly?
A couple of notes:
I have pulled the wsdl given to me into SoapUI and when running this on the server, we see successful results. ( I use the same values in my testing when running through code)
I am only the consumer/client of this wsdl and have no control over the wsdl/service definitions.
I have no real understanding of why the service was done using a MessageContract and not a ServiceContract... (I've never had this problem before with ServiceContract)
One of the most interesting aspects to the problem is that the ComplexBase has a Decimal field defined, and this field is serialized properly. That is to say that Request.DecimalProperty serializes but Request.ComplexA.DecimalProperty does not.
Some other notes is that this is only a problem with Decimal and nullable Decimal fields in the ComplexA type. ComplexA.DecimalProperty and ComplexA.NullableDecimalProperty are failing to serialize.
Any and all help is very appreciated. Please request if a sample is necessary, (I didn't include on this post because it will need to be masked for security reasons)
So, I've figured this out.
The wsdl defined objects have the decimal and nullable decimals along with a bool of each that is defined as DecimalFieldIsSpecified. For some ungodly reason it's necessary to MANUALLY set these to true in order for the xmlserializer to pick up the fields....
Related
have a json stringresponse, that I need to deserialize in C#.
The problem is, that one of the json properties is called "contentHash" and can have a value that looks like this: "contentHash": "HY$RF>L#O-;G,2-&F7$TD#EH4\S)M[0L'DOHS\"`H'9<"
This is a problem, since the contentHas value has a " character, which looks like the end of the valuestring, but it is not. I don't need to use the contentHash property, so is there a way to exclude the contentHash property from the deserialization or ignore the " character inside the value of the property?
I imagine you are calling an API in order to get that json payload. I don't know whether you are in control of that API, but what follows holds true in any case.
When you call an API you are basically communicating with a remote resource with which you have agreed some conventions. The fact that the API declares to send you a json response having a certain shape is part of the agreement between you (the API consumer) and the API author. This means that, if the API author has documented that he is able to send you a json payload having a certain shape, then you need to trust him and assume that he will send you that kind of response whenever you call the API.
When you write the code to consume the API remember to send an Accept request header having the value application/json (this is useful when the API is able to serve responses in different formats, for instance json and xml, and supports what is called content negotiation).
When you get a response inspect the Content-Type response header and check whether the response media type actually is application/json. If it isn't, you need to find out a way to handle such an unexpected situation. You can decide to throw an exception for instance, because you are facing an unexpected situation and, probably, there is not a business rule in your application domain to handle it (you were expecting json and you get, for instance, xml. What can you possibly do ? nothing better than throwing an exception probably, because the scenario you are facing is totally unexpected).
Let's suppose you get an application/json response content. Then, you can deserialize it in order to consume it in your application. Don't do that manually. There are several libraries meant to do that; in the .NET space one widely adopted is newtonsoft json. Let the library to deserialize the json you get from the API. In case the string you get is not a valid json, the library will probably throw an exception: that's the right thing to do, again the reasoning is the same illustrated above for the response content type.
If the API returns you an invalid json string, it's not a concern of your own code to fix it, in order to make it valid json. That means that the API author is trying to cheat you, he is not being compliant with the agreement cited above at the beginning of my response. You should let him know that he has a bug, because he is not sending valid json and he should fix it. That's probably a sign that he is not using a proper library to serialize its objects to json.
If you need to validate a string in order to check whether it is valid json, use an online service like json lint.
Long story short: fixing the response content so that it becomes valid json is not a concern of the code meant to consume the API. It's a concern of the API author.
We facing a serious issue, but before saying that it's a bug in .net, I'd like to know if someone understand what's happening and why.
That's our configuration :
1 project DAL
1 project proxy
many others project that use DAL with WCF services as well.
They communicate with wcf services.
We have added some properties in one object in the DAL
We havn't updated service references in the proxy project.
(1)In the proxy with a breakpoint, we can see everything is retrieved properly except of course the new properties (service reference not updated => nothing abnormal)
The proxy is returning a JSON with WebMessageFormat.JSON ( we using the default provided serialization)
The response of the method called in proxy that call the (1) one in DAL is empty.
So it's definitely a problem in the JSON serialization ? no ?
Worst, we decided to changed from WebMessageFormat.JSON to WebMessageFormat.XML to see if the same happened, ==> It didn't
Last thing, no problem with other projects that hadn't been updated (they not using JSON ser)
Does someone have faced the same issue, or know why this is happening ?
Any help would be really nice :)
Thanks in advance to everyone and sorry for my english.
(This is not a definite answer, but a suspicion. However, this was too much to include as a comment.)
Note: I am assuming the following from your question (please correct/clarify if wrong).
The proxy project calls DAL through WCF and not the other way around. This would explain (1), and properties not updated through each layer.
A client calls the proxy project, which exposes itself through WCF too (this would explain the proxy project returning a WebMessageFormat.JSON response)
The issue here may be, as you say, with the serialization of the proxy response itself. While it's always advisable that you update your project references, in such a case it is possible that the generated classes are not mapping exactly to the response that they describe.
My take so far is that the changes in the classes had changed the internal responses in such a way that the references can no longer be mapped correctly to the response type, which is likely the ones from the mapped classes. The XML serializer is likely a separate implementation of the serializer, so it is likely that the JSON serializer has the problem failing on this specific case. You could check if this is the case by checking if there are any first chance exception in your internal output, or by adding debugging outside of your own code. This would likely confirm that the JSON serialization is facing an issue.
It may be actually be a bug, or an unsupported scenario when properties to map are not present.
I would advise that you use the DataContractSerializer with JSON if you are going to be consuming serialized JSON data from WCF (Set up your data contracts of course). I've ran into a few problems with JSON serializer, and realized it's a bit iffy with .NET
Another solution is to use this JSON serializer with .NET:
http://james.newtonking.com/json
Do you have object of type date or any other non primitive data type in the response data, I have faced problem when i try to include date object in the response data, for a quick work around I changed the
data type to string, it worked for me.
If I want to serialize an object I have to use [Serializable] attribute and all member variables will be written to the file. What I don't know how to do versioning e.g. if I add a new member variable (rename a variable or just remove a variable) and then I open (deserialize) the file how can I determine the object/file version so I can correctly set the new member or take some kind of migration? How can I determine that the variable was initialized during the load or not (ignored by deserializer).
I know that there are version tolerant approaches and I can mark variables with [OptionalField(VersionAdded = 1)] attribute. If I open an old file the framework will ignore this optional (new variable) and it will be just zero/null. But again how can I determine if the variable is initialized by load or it was ignored.
I can write the class/object version number to the stream. Use the ISerializable approach and in the constructor(SerializationInfo oInfo, StreamingContext context) method read this version number. This will exactly tell me what is the class version in the stream.
However I expected that such kind of versioning is already implemented by the streaming framework in C#. I tried to obtain the Assembly version from the SerializationInfo but it is always set to current version not to the version which was used when the object was saved.
What is the preferred approach? I found a lot of articles on the net, but I could not find a good solution for this which addresses versioning...
Any help is appreciated
Thanks,
Abyss
Forgive me if some of what I write is too obvious,
First of all, please! you must stop thinking that you are serializing an object...
That is simply incorrect as the methods which are part of your object are not being persisted.
You are persisting information - and so.. DATA only.
.NET serialization also serializing the type name of your object which contain the assembly name and its version, so when you deserialize - it compares the persisted assembly information with the type that will be manifested with the information - if they are not the same it will return an exception.
Beside the versioning problem - not everything can be serialized so easily.. try to serialize a System.Drawing.Color type and you will begin to understand the problems with the over simplistic mechanism of .NET serialization.
Unless you plan to serialize something really simple which has no plans to evolve I wouldn't use the serialization mechanism provided by .NET.
Getting the focus back to your question, you can read here about the versioning ignorance ability:
http://msdn.microsoft.com/en-us/library/ms229752(v=vs.80).aspx which is provided for BinaryFormatter.
You should also check XML Serialization which has some nice abilities, but the biggest benefit is that you getting an XML which is Human readable so your data will never be lost even if you had complication with the versioning of your types.
But finally, I recommend you either use Database with Entity Framework to persist your data or write your own flat file manager.. while EF is very good for most solutions, sometime you might want something lighter to persist something very simple.
(my imply is that I can no longer see a solution where .NET serialization can be relevant.)
I hope this helps, Good luck.
I have two "identical" webservices (Soap) on two different servers. Don't ask why :-)
WebService-1 decides if it handels the request itself or if it passes the request to WebService-2. If so, the response of WebService-2 should directly be returned from WebService-1.
The response datatype is complex and self defined. With simple datatypes like 'int or 'string' there would be no problem.
The response of WebService-2 is a serialized object (I think it is called "stubs") and theredore it is not possibel to pass this object through as the response of WebService-1 because the type of the objects doesn't match.
Is there a simple way to convert the serialised datatype into its original type without buiding a complex converter?
Yes - how to achieve this differs depending on whether you are using WCF or old-style Web Services.
Essentially, you want the web reference tools (svcutil.exe or wsdl.exe, respectively) to identify that the result of the webservice is actually a "well-known" object type - much as it does for many of the core framework objects.
Within WCF, this is normally achieved by ensuring that your contracts are held in a referenced assembly, and are decorated with namespace attributes. If you do this, when you add a reference to your webservice it should use your class natively instead of generating a similar proxy class.
If you are using old-style web-services, you will have to look into using a SchemaImporter project - this will allow the wsdl.exe tool to recognise your types and correctly utilise them. It should be mentioned that this is only required at design-time - no such measures are required during deployment.
I serialize some configuration objects and store the result bytes within a database.
new BinaryFormatter().Serialize(memoryStream, instance);
Convert.ToBase64String(memoryStream.ToArray());
These objects will be deserialized later.
new BinaryFormatter().Deserialize(memoryStream);
It's possible, that the Application has some new assembly versions at the time of deserialization. In general it works well, but sometimes I get a file load exception:
"The located assembly's manifest definition does not match the assembly reference.". The assemblies work all with strong naming, can that be the problem and how could I avoid this problem?
Thanks for help
Absolutely, using BinaryFormatter with database (i.e. long-term) storage is a bad idea; BinaryFormatter has two three big faults (by default):
it includes type metadata (shucks if you move/rename your types... this can mean strong name/versioning too)
it includes field names (fields are private details!)
it is .NET specific (which is a pain if you ever want to use anything else)
My blog post here raises two specific issues with this - obfuscation and automatically implemented properties... I won't repeat the text here, but you may find it interesting.
I recommend the use of a contract based serialization. XmlSerializer or DataContractSerializer would suffice normally. If you want small efficient binary, then protobuf-net might be of interest. Unlike BinaryFormatter, the binary from this is portable between implementations, extensible (for new fields), etc. And it is quicker and smaller, too.
I think WCF might be your best bet. It can handle passing unknown fields through to it's consumer even if it doesn't know how to deserialize them.
Example:
Service A: Knows about version 2 of the Widget class which has a Description field
Service B: Knows about version 1 of the Widget class which doesn't have a Description field
Service C: Knows about version 2 of the Widget class which has a Description field
If service A calls service B passing a Widget object and then service B calls service C passing on the same Widget object then service C will get the Description field as it was passed from service A. Service B won't have any Description field but when it deserializes it and re-serializes it it will just pass the Description field through without knowing what it is.
So, you could use WCF services with in-proc communication.
See this link for more on versioning wcf contracts.