How do I remove a specific character from a JSON property? - c#

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.

Related

xml serialization causes missing fields

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....

Are you allowed to pass extra data in a WCF service as part of the post data?

I'm trying to send objects which are serialised as JSON to my WCF service. The thing is, though, some of the data from my android isn't needed on the service side, so I didn't add the attributes. I was wondering how I'd be able to have it so it can lack the attributes but still receive it?
So, in my android, I have JSON like this {"buiildings":{"id":1, "name":"boob", "otherThing":"Ya"}} and my Building object in WCF only has the id and name as attributes, so it only expects them. Can I have it so it just ignores the other attribute?
Yes, You can pass as many as extra attribute in JSON object. it will not give any error at WCF side. but you are not able to use these extra attribute as it is not define in Building object in WCF.
But i suggest do not to pass extra attribute because it will increase request size, and cause effect on performance.

calling a webservice and deserializing soap without a wsdl

I have a vendor who doesn't seem to have a wsdl or is unwilling or doesn't know how to provide it. They have a number of web services (technically they are JSPs that return soap messages) and I need to use about 10-15 of these to get my stuff done.
Since there isn't a WSDL, I can't use the 'add web reference' functionality to generate proxy classes and such. I've gotten around this by using WebClient to make the calls and return the response as a string, but now I need to deserialize the response into client classes.
I've already made c# classes to match the xml that's returned, but I'm not sure how to deserialize from SOAP since there's so much xml noise. I could strip the SOAP envelope tags and then use the XML serializer to deserialize to a List<SomeType>, but that seems really dirty. Is there a nicer way?
i published an article detailing on how to deserialize a complex xml.
here is the link : http://blog.impact-works.com/2011/06/30/how-to-serializedeserialize-complex-xml-in-asp-net-c/
hope it helps
Have you tried using SoapFormatter.Deserialize() for deserializing the response. If so, this would be helpful.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.soap.soapformatter.deserialize(v=vs.71).aspx

WCF Between .NET 2010 and Any Type Of Client

I'm a complete neub to working with WCF but have been put on a project that needs it. Although not given as a requirement I want this service to seemlessly work with any client regardless of the technology it is written in (e.g. Java).
Basically, the client will send me a block of XML which I will validate and process. If all is well, I am going to return an XML document with 2 fields in it (an exit code and a message).
If I use DataContracts (with 1 write only and 2 read only properties) will that do the trick or is there more to this than I am seeing.
Thanks much!
Clay
DataContracts are not "the solution"; the DC is one possible approach for message serialization. whether you want to use DC depends on what the XML must look like, or can look like, and also how you want or need to map from objects in program memory to messages (xml documents or fragments).
In particular, if you want or need xml attributes in the messages, then DataContracts is probably not the way to go.
DC can support this kind of input message:
<request>
<flavor>7</flavor>
<param>eiueuie</param>
</request>
notice all data is stored as xml elements. DataContract will not work for this kind of message:
<request flavor='7'>
<param>eiueuie</param>
</request>
...in which any of the message data is stored in xml attributes. If you want to use XML Attributes, then you probably want to use the XML Serializer. If you don't care one way or the other then DC will probably be fine.
BUT, the Xml Serializer cannot map private fields or properties into XML elements, while DC Can. So, if your object model requires that, then you cannot use XML Serializer and you should use DC.
To find out more on the tradeoff between DC and XMLS, read this.
Having said all that, the decision on whether to use DC or not is just one part of your design. You will also need to decide whether you want full SOAP Envelope support (which allows for things like message signatures and so on) or whether you want the simpler "REST" message format, which is probably better called "plain old XML" .
And then there are things like instancing, hosting and activation (use IIS or self-host?), logging/auditing, security (authentication and authorization), and so on.
So, WCF can work for you, for any type of client, but the choice to use DataContracts or not is just one piece of the puzzle.
Data contract is just definition of transferred data - it is not domain object so making decision about what will be read only doesn't make sense. Client will deserialize the response and you will have no control over its processing of the data = client can change response anyway. Response can be also changed by any processing component in WCF pipeline.
Just start with DataContract and basic SOAP service (basicHttpBinding) or basic REST service (webHttpBinding + webHttpBehavior) and you will be fine.

How to pass additional data to a Web Service

From .NET(C#) code, we are invoking a Java Web Service.
Its a SAOP request. The Java WebServices are developed using Axis 1.4.
Following is the sample code that makes the java web service request:
private string GetUserInfo(string strEID)
{
string strEmpData = string.Empty;
GetEmpInfo.EmpProxyService objEmp;
try
{
objEmp = new GetEmpInfo.EmpProxyService();
strEmpData = objEmp.searchByEID(strEID);
}
catch (WebException ex)
{
}
objEmp.Dispose();
return strEmpData;
}
Now, we have a change request which requires passing some additional information - a name_value pair to the java webservice.
How can we achieve this ?
Can I pass the information in HTTP/SOAP headers?
Changing the method signature and adding the additional info to pass the info is not at all the good idea I guess.
EDIT: Its basically we want to add the logging inforamtion of who are all consuming the web services. Once the java webservice request is processed successfully, we will log the usage information along with the source of the request (from webappln/windows appln/flex client).
We want the clients to send its unique id to identify it. Since this has nothing to do with the business logic, can we add it meta-data info...say in headers.
If you have control over the service signature, I would actually suggest that you change the signature of this web service, or add another method that takes the additional arguments. When you're using a high-level language like C# or Java, the tendency is for the web service framework to abstract the entire SOAP stack away from you, and leaves you dealing with just the plain objects that eventually get serialized to make the method call. With only the argument objects exposed, it can be tricky to try to inject additional stuff into the SOAP message, if it's not part of the actual method signature.
There are usually ways to manipulate the SOAP message by hand, but I would probably shy away from that if possible, as editing the SOAP message by hand goes against the point of using a serialization-driven framework. That said, if you have no control over the service method, and the group in control of it needs you to pass additional data outside of the soap objects, you might be stuck messing with the SOAP message by hand.
If you want to add some future proofing to your services, I would suggest passing a full-fledged object rather than a single string or primitive value. In your object, you could include a key-value data store like a HashMap or Dictionary so that additional data can be passed without changing the signature or schema of the web service. With key-value data, documentation becomes important because it's no longer clearly specified data types or parameters.
You can use SOAP headers but I would rather not go that route since the headers have no business meaning. Rather change the signature and use request and response objects.
SearchByEIDResponse GetEmpInfo.EmpProxyService.searchByEID(SearchByEIDRequest)
Ths makes any changes less painfull and prevents huge parameter lists.
How you pass information to a web service is dependent on the methods that web service exposes. What language that service is written in is inconsequential to you as the consumer. IF the Java web service requires a name value pair to retrieve some data than a method signature will expose that.
objEmp.searchByEID(strEID, strVal1, strVal2);
That said you as Eben indicates you are better off using request and response objects to keep your parameter lists short. When to use these more complex types comes with experience i.e. don't use a request object from the get go if you need to only pass a single string value, but use a request object if you need to pass 50 string values.
If you have multiple webservices and don't want to change all methods (which is reasonable), a SoapExtension is the way to go http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx
You write your soap extension class on the client, declare it in the web.config and you're done.

Categories