Web service issue over GPRS

Hi,

I'm developing my first Pocket PC application in C# in VS 2003. It's a cut down version of a desktop application I've been developing in VB6 for a few years now. It makes a call to a web service which is out on the internet. It's all gone really well until now.

I'm running/testing the application on a HP IPAQ hx2400. If I access the internet over broadband via my office wireless network the application works perfectly. However if I access the internet over GPRS via the bluetooth modem and my mobile phone on Orange the following happens:

1. The first call to the web service, which returns a DataSet, works fine.
2. The next and all subsequent calls to the web service returns the following error:

"Server found request context type to be 'text/html', but expected 'text/xml'."

3. At this point if I call:



httpWebRequest = (HttpWebRequest)WebRequest.Create(targetAddress); httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse);
httpWebRequest.Abort();

I get the following error:

"The remote server returned an error: (400) Bad Request."

4. At this point, if I repeat step 3 it succeeds and I can make one more successful web service call as in step 1. Then I go through step 2 and at step 3 and with all subsequent calls to the web service I get the following error:

"The operation has timed-out."

If I jump back to step 1 after step 3 I get the following error:

"The operation has timed-out."

It's as if my application "falls off" the internet, even though at all times I can still browse the internet from Pocket Internet Explorer, including the .asmx file for my web service, just fine.

If I restart the application the same pattern repeats. Needless to say I need some help.

Best Regards,

Craig Harrison

[2019 byte] By [CraigHarrison] at [2008-1-31]
# 1
Hi,
I don't know why this is happening but you can try manually setting the content type of the web request before you call GetResponse.
httpWebRequest.ContentType = "text/xml";
This forces the content type everytime a web service call is made.
I'll have to try to reproduce this issue on my on hardware.
Travis
TravisFeirtag at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 2
Hi,

I'm calling the web service in the following way:



wsAthenaOimWsInfo = new AthenaOIMWS.Information();
wsAthenaOimWsInfo.Url = Globals.Values.WebServiceAddress;
wsAthenaOimWsInfo.Credentials =
new NetworkCredential(Globals.Values.WebServiceLoginUserName, Globals.Values.WebServiceLoginPassWord);
dsDb = wsAthenaOimWsInfo.GetData(sqlDataSourceName, sqlWhere, sqlOrderBy);


I'm only using 'httpWebRequest' as a means of hitting the internet in another way from my application to get a bit more information about the state of the connection, etc.

I've discovered that if I pause at step 2 for an hour or so, after calling the web service and then calling again and getting the error, I can make another successful call to the web service but then the error returns again on the next call.

I've spoken to the data people at my mobile network provider and they suggested it could be a 'caching' issue? Whether that happens on the device or the web server I don't know.

Please let me know if you have any other ideas.

Best Regards,

Craig Harrison

CraigHarrison at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 3

Hi Craig,

Can you get a network trace of the web service calls? As for the connectivity issues after the Abort/Timeout, it is a known issue that NETCF are not releasing the connection properly in cases of an abort/timeout. We have fixed this in V2. Can you try NETCF V2 Beta 2 to see if that resolves your issue? For V1, you can try setting ServicePointManager.DefaultConnectionLimit to a large value, although connection might still be lost when the limit has been reached.

Cheers,
Anthony

AnthonyWong at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 4
Hi Anthony,

I've looked into getting a network trace but I haven't been successful yet.

I have ordered VS 2005 Beta 2 so that I can try it out.

Can 'ServicePointManager' be used when calling a web service using the method shown in my last post?

Best Regards,

Craig Harrison

CraigHarrison at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 5
You can use SoapExtension to trace the SOAP calls. MSDN has an excellent trace extension example with source code. Just look for SoapExtension class. It's very powerful and allows you to get access to incoming and outgoing messages.
You will need to get to the reference.cs source code that was automatically generated for the webreference. Once it is generated, you can modify the code to your needs. Such as adding a SoapExtension or getting access to the HttpWebRequest.
To get access to the reference.cs in the IDE, go to the Solution Explorer, click on the Web References folder and select Show All Files icon at the top of Solution Explorer. Under reference.map you will find the reference.cs file. You can modify the web proxy, recompile and your changes will be used.
To add the TraceExtension class from MSDN to your web proxy, just add the attribute [TraceExtension] to the method you want to use the SoapExtension.
To get access to the underlying HttpWebRequest object in the reference.cs. You can use the example code below. Just override the GetWebRequest method from the SoapHttpClientProtocol class.
protected override System.Net.WebRequest GetWebRequest(System.Uri uri) { System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest) base.GetWebRequest(uri); webRequest.ContentType = "text/xml"; return webRequest; }

Let me know if you want source code example and I can send you a CS project that uses the TraceExtension.
Travis

TravisFeirtag at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 6
Hi Craig,

ServicePointManager.DefaultConnectionLimit is a static property so you can call it anywhere in your program. Just remember to set it before you make a web service call.

Cheers,
Anthony

AnthonyWong at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 7
Hi Travis,

I would like to implement your suggestion regarding 'GetWebRequest' but I've discovered that I have NETCF Version 1.0.2268.0 installed in 'D:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE' on my development machine and I need SP 1 or later (Version 1.0.3111.0) to be able to override 'GetWebRequest'. The problem I have is I just can't work out how to install it (duh!). I have installed SP3 on my device but I don't know how to update my development machine. Can you help?

Regarding TraceExtension, I would like to see a code sample if you can send it to me.

Best Regards,

Craig Harrison

CraigHarrison at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 8
Hi Anthony,

I've tried setting 'ServicePointManager.DefaultConnectionLimit' to a high value (99999) before calling the web service but the problem persists.

Thanks,

Craig Harrison

CraigHarrison at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 9
Hi Craig,
No problem. VS uses reflection against the cf.NET assemblies in the '
\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE' directory to build your solution.
The hard way to get them is to pull the assemblies out of the .CAB files. Unfortunately they are named funky and not easy to determine the required names.
The easy way is to install the latest cf.NET CAB onto your device and then use ActiveSync to browse to the Windows directory on the device. You'll see the needed DLL files (12 files). They will all start with the name "GAC_" (the poor mans assembly cache :) Copy these files to your hard drive somewhere. Rename the files by removing the "GAC_", the version info, and the "cneutral" in the names. Just name them to their correct namespace. These files can then be dropped in the VS directory from above. Once VS is started up, it will use these new files when you build a Smart Device project.
One thing to remember, make sure Windows Explorer is set to show hidden files and show file extensions. These are system files and are not displayed by default.
If you want VS to deploy the correct cf.NET CAB file to the device you're using, put the new CAB file under the "C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce400" directory using the correct processor folder for your device. i.e. \armv4 will deploy to my HP4705
Let me know where you want me to email the example project with the trace extension. Send me an email at info@travisfeirtag.com and I'll reply.
Hope this helps...
Travis

TravisFeirtag at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 10
Hi Travis,

I followed your instructions and got the latest NETCF files on to my development machine. I managed to override 'GetWebRequest' and set 'ContextType = "text/xml"' as per your code above, however the problem persists.

When you send me the trace extension project I'll see what the trace turns up.

Best Regards,

Craig Harrison

CraigHarrison at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 11
Hi Craig,
I've spent fighting with gprs data sending issues more than one year, and found that you can be never sure in the result because of the gprs network.

As you want to send some data to the server and want to be sure it's there by waiting for the response that simply diappears somewhere on the way back, you simpliy need to send it again and again till you got the answer back.

As you use sql server on the server side that writes your data into a table, just let it write there more times, and simply extend your table with two fields:
- one filed a status bit that let's you sign the given row as 'expired'
- another field to store a unique id for the transaction, that can be generated on the pocketpc by using its id and the timestamp of your first trial.

A simple insert trigger can set the status flags of previously sent datarows, or can delete those that have been sent more times.

So:
Your pocketPC can be notified a later time by one of the trials you made and had luck.
On the other hand you surely have your data on server side and only once, so you can work with it safely.

A sending problem can be solved with this 'server side caching' - as you can implememt all important data sending communcation steps in one web service call's dataset.

Hope this helps you.
br
Attila

Gasys at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...
# 12
Hi,

I had almost exactly the same problem. 'ServicePointManager.DefaultConnectionLimit' seems to be set to 2 by default. I set it to 100 and my app works now.

Huwwuh at 2007-9-8 > top of Msdn Tech,Smart Device Development,.NET Compact Framework...