WebServices fail because (400) Bad Request because of special character - c#

Using Visual Studio 2008, I setup a client that uses Web Services.
It has nothing to do with buffer sizes (as that is a typical response, all appropriate sizes were increased).
I was using a List as the parameter of the Method.
After much experimentation, I used the System.Net.WebClient to manually create a Soap 1.1 and a Soap 1.2 request to test test the result.
using (var webCtx = new System.Net.WebClient())
{
webCtx.Headers.Add(System.Net.HttpRequestHeader.ContentType, "text/xml");
webCtx.Headers.Add("SOAPAction", "http://tempuri.org/HelloWorld");
var uri = new Uri("http://localhost:12345/MyProject/WebService.asmx");
MessageBox.Show(webCtx.UploadString(uri, xml));
}
Where the xml is a string variable of the xml with actual data.
The problem is when one of the fields has a special character. Here is the example of the message body of the xml.
<PocoClass>
<UnicodeString>123</UnicodeString>
</PocoClass>
If the value of UnicodeString was something simple (i.e. 123), but once the special character appeared, I got 400 Bad Request.
Now, I have found a Microsoft Knowledge Base Article describing the bug kb911276, which basically states, install a hot fix. That really isn't something that can be a solution to the problem, so I was wondering if there are any ideas of how to solve this problem?
Are the only solutions to write some sort of custom encoding/decoding or custom bindings to be implemented by the server and client? Are there any easier ideas?
Thanks
Edited:
The use of a List is not an issue as it is handled by VS. Here is a more complete (but still partial) contents of the soap message.
<HelloWorld xmlns="http://tempuri.org/">
<pocoList>
<PocoClass>
<UnicodeString>123</UnicodeString>
</PocoClass>
</pocoList>
</HelloWorld>

I had a similar problem with a webservice we had that users of our app run online account searches. I found a VS Feedback item about this, but it appears MS considers this behaviour by-design.
What we ended up doing was writing a method that replaced all characters that are not allowed when serializing to XML with question marks.
The allowed list was: 0x09, 0x0a, 0x0d, 0x20-0xd7ff, and 0xe000-0xfffd. Everything else, we turned to "?".
I guess if you can't do that, the data should be base64-encoded in transit to avoid this issue. Seems a bit odd to me, as it breaks the ability to losslessly route a call through a web service.

My concern is where you state that you are using a List as the parameter to a method. Web services don't directly support lists. You need to use an array as the parameter. Then internally you can convert it to a list using .ToList(). This may not be your issue directly!

That KB article was referring to unicode character sets within a request URL, not actual data being posted to the server.
That being said; i'd verify that your headers are well formed.
Also, if VS generated the client proxy for you; right click on the service reference and then on "Update Service Reference"
Just noticed one more thing; you said that you are passing in a list as a parameter; from the snippet of xml shown, that doesn't look like something that would be serialized from a list (by any of the .NET xml serializers); if you want to debug using the webclient approach; try verifying that the format of the xml is valid.

Where are you seeing ? In the raw XML or the serialized data? XML is defined to contain only human-readable characters and  is the XML entity for the unreadable ASCII Shift-Out character. If you're looking at the raw XML and it contains the XML entity code, that's allowed, but if you are looking at serialized data and your XML document contains raw control characters it is invalid and will be rejected.

Related

How to figure out exactly where the error is in the deserialization of WCF SOAP XML response?

Apologies if this has been asked before but it seems I cannot find the answer.
I am trying to consume a SOAP Web Service using WCF. I've used Visual Studio 2015's Add Service Reference to add the service reference and generate all code.
The service call fails with the following CommunicationException error:
System.ServiceModel.CommunicationException : Error in deserializing body of reply message for operation 'XYZ'.
---- System.InvalidOperationException : There is an error in XML document (2, 979).
-------- System.FormatException : Input string was not in a correct format.
I understand the error; I understand that something (an element value, probably) in the XML response document cannot be deserialized according to what the svcutil's generated code dictates.
I am logging the XML response document. Also, I am comparing it with the SoapUI response and they both look identical.
SO how can I figure out exactly where the problem is in the XML document? Is there any method, technique or trick to step through the deserialization process and pinpoint the faulty bit? It is a rather long XML document ...
IMHO, at this point the WCF behaves like a black box that I cannot look inside it.
TIA,
Turn on WCF Trace:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/configuring-tracing
Use the following application to view the results:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/service-trace-viewer-tool-svctraceviewer-exe
Well, it seems one cannot really find exactly where such a deserialization error lies. Things get even worse if the service developer is not the same person as the service client developer.
In my case, the error was due to a mismatch of a data type between the service and the generated client code. The origin of the problem was the erroneous XSD. In order to find the error, I had to contact the service developer who managed to locate it.
Generally speaking, this is one of those things that make you feel you are losing control over your code; much like that point in a project when you want to look the source code of a library but you just can't because you don't own it. This is something all developers who decide to work on web services consuming project should be aware of.
For debugging, you can use Fiddler2 easily to capture any web traffic, including the full xml of a SOAP request/response (and it even handles SSL easily, unlike Wireshark)
For logging... I wish I knew. Sorry.
Also, dupe of In C#, How to look at the actual SOAP request/response in C#

passing xml as a string to webservice causes complete failure

I am hosting a .net webservice written in c#. In one of my web methods, I'm expecting a few inbound parameters, all of which are strings. The final string is actually a string of xml (I started out doing a dataset for this, but read this was a big no-no, so went this route instead).
The xml (as a string) is incredibly simple.
<FriendsArray><Friend><FriendSocialID>123456789</FriendSocialID><FriendName>Test Test</FriendName><AvatarImage>https://www.imagelocation.com</AvatarImage><FriendGender></FriendGender></Friend></FriendsArray>
With the <FriendsArray> being the bounder, and the <Friend> node being repeated n times. On the webservice side, I take this string, serialize it into xml and deal with the data.
When the webservice is run locally on the server in Visual Studio, it works perfectly, no issues. When the webservice is run locally and attached to a test calling program that simply emulates passing these parameters, including the FriendArray to the webservice, again, right as rain, no issues, works perfectly.
Real world scenario of calling the webservice foreign (either via emulation, like SoapUI or XMLSpy, or directly from the app that is meant to call it) it bombs the service. No error is returned, or empty response object, it completely fails, and returns nothing.
The second I remove this FriendArray (its optional on the codebehind), it works perfectly.
Is there some inherent issue to doing this the way I am trying to? If so, is there an easy alternate way that requires not a huge amount of recoding? Thanks!
Apparently "<" and ">" are reserved in XML. Wasn't aware of that. All I had to do was escape them with < and > in the string, and it works perfectly now.

Sending information between JavaScript and Web Services using AJAX

Alright so I'm using Microsoft's Web Services and AJAX to get information from a SQL database for use with java script on the client side. And I'm wondering what the best method is. Before I started working on the project, the web services were setup to return a C# List filled with some objects. Those objects variables (ints, strings, etc.) contain the data I want to use. Of course, java script can't do much with this, to the best of my knowledge.
I then modified the web service to return a 2D Array, but java script got confused, and to the best of my knowledge can't handle 2D array's returned from C#. I then tried to use a regular array, but then a found the length property of an array in JS doesn't carry over, so I couldn't preform a for loop through all the items, because there wasn't anyway of knowing how many elements there were.
The only other thing I can thing of is returning a string with special char's to separate the data, but this seems way too convoluted. Any suggestions? Thanks in advance!
EDIT
First, I'm assuming your using a SOAP based Webservice. By SOAP, more or less I'm talking about a webservice (in this case C#) that generates XML messages to accept requests for data and send back results from those requests. You can read more about SOAP here: http://en.wikipedia.org/wiki/SOAP
Going from a C# webservice to a C# client application is fairly simple since Visual Studio will automatically generate a consumer class for your client application. Example of this here: http://my.execpc.com/~gopalan/dotnet/webservices/webservice_csharp_client.html (though I think Visual Studio has better integration than this example shows).
More or less, your JavaScript will need to generate the appropriate SOAP request (XML) for your WebService to understand which method you want to invoke. After it has been invoked, you'll need to use JavaScript to parse the response (also XML) for the data you want (jQuery is great for this).
Here is a library that will help you make the request and get a response from your webserver. http://www.ibm.com/developerworks/webservices/library/ws-wsajax/
Here's a similar question on the same topic with a pretty good example : Simplest SOAP example
Let me know if this is what you're looking for. Hope it helps!
ORIGINAL
Your Data (2D Array, List, etc.) is being serialized to XML.
So you'll need your Javascript to parse the XML and not treat it like literal C# objects.
OR like keatch said, return JSON
Try to return a JSON array. JSON is a standard notation for passing javascript objects.
See this link for reference: http://www.codeproject.com/KB/aspnet/CSJSON.aspx
Try this in your service:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<SomeObject> name()
{
....
}

Prefix in Webservice with SOAP

i was cheaching this link:
http://es.w3support.net/index.php?db=so&id=665327
i this is part of what i need, i use the same kind of code with SoapDocumentMethodAttribute and the Invoke Method, and this is my question.
in the link they show how to get the response with the prefix, and works, but what abut the request?, i need to send to the client the xml strucuture with the prefix.
i try add
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("mes-root", "CAP");
before the invoke method, but does not work
i hope some one can help me i'm really frustrated
First of all, unless you're stuck using .NET 2.0, you shouldn't be doing any new development using ASMX web services or clients. You should use "Add Service Reference", not "Add Web Reference".
Secondly, the article you linked to is a translated version of XML Serialization - Missing Namespace Prefix at client end.
Third, note that the person who asked that question was running .NET 1.1, posted incorrect XML, and never actually reported what the real problem was.
Finally, if your client requires a specific prefix, then they have a fatal, critical bug in their code: that would mean that they're not actually communicating using XML. In XML, the prefix is only an alias for the actual namespace. It shouldn't matter whether there is a prefix, much less what the actual prefix is. The following are all identical:
<root xmlns="somenamespace"/>
<a:root xmlns:a="somenamespace"/>
<b:root xmlns:b="somenamespace"/>
Note that the actual problem that the OP was having was that she was running .NET 1.1, which had several bugs in its handling of XML. The problem had nothing at all to do with prefixes!

Providing better WSDL from C# SOAP

I'm pulling together some services in C# that have to match specific data format; e.g. string lengths, various enumerations and formatting. I have the back-up approach to validate post the SOAP call and respond with friendly messages and pre-defined error codes, but I would like to place additional information into the WDSL (so it is clear that field x can only be 15 alpha characters only with no numbers or punctuation for example).
Is this possible, if so are there any examples and or tutorials?
Take a SOAP message, generate a XSD out of it, and then edit the XSD until all your validation things are in there. Provide the XSD along with the WSDL to your customer.
When you both validate the messages using the same XSD the problem should be gone.
First of all, you should be aware that .NET does not validate SOAP messages against the schema in a WSDL. For instance, if part of your input message shows a maxLength of 50, there will be no error or exception when you are sent 51 instead.
Second, it is not possible to adjust your classes in such a way that you can control the exact schema. For instance, you cannot cause a maxLength attribute into the WSDL.
Third, if you must completely control the WSDL, then you need to write it by hand. You will never have complete control over the WSDL that .NET generates.
Finally, you seen to be talking about ASMX web services here. You should not be using ASMX web services for new development - they have been replaced with WCF.

Categories

Resources