locked
How to build an N-tier mobile application via Web Service OR WCF Service RRS feed

  • Question

  • Hello,

     

    I want to share my experience with everyone, because I spend DAYS trying to figure out what is going on and I guess I could spend another 20 minutes in order to save everyone else's time.

     

    I will try to explain how to build a mobile application, a desktop one, with SQL servers on both sides, and how to synchronize them via an ASP.NET Web Service OR a WCF Service.

     

    First of all - I used Visual Studio 2008 (with a Service Pack 1 beta, but I guess you could run without it), .NET Compact Framework 3.5 SP1 Beta, Windows Mobile 6 Professional SDK, SQL Server CE 3.5, SQL Server 2005 Express (you could use any), Windows Vista Ultimate x64.

     

    Ok, so to start. Create a mobile application and a Windows Forms desktop one. The first thing I will explain will be synchronization via a WCF Service, which will be hosted in the desktop application (it is practically the same if it is a project itself, but I think that way is better). Click on the desktop application to add a new item and add a Local Database Cache in the data category. It will open the wizard from which you should configure (in the advanced section) the server application which is, as it is, the WinForms one, and the client, which you should change to the Mobile. For server connection you should choose an SQL Server (any) connection that you have. For a client leave it as it is (it will create a SQL CE database in the mobile project). Then you can add the tables to the left that you want to sync. If you don't have an "Add" button, then your tables probably don't have a primary key, which is a mandatory. Click ok after you are finished and it will create a bunch of things for you - the SQL CE on the Mobile application, a DataSet, and some sync code. Here comes an interesting thing - I am not sure, but I think that Visual Studio 2008 WITHOUT a Service Pack doesn't create a <yourname>.SyncContract.cs in the desktop application, while the one with a SP does. If it doesn't, you should create a WCF Service Library project, move the server part to it, and then copy the code from there. Now, to continue. The first VERY, VERY important thing to do is to open this .SyncContract.cs file in the desktop application, find the OperationContract attributes for the 4 interface methods and add each of them a [XmlSerializerFormat] attribute. That will save you from a:

     

    "The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/yncSession. The InnerException message was 'Error in line 1 position 862. 'EndElement' 'syncSession' from namespace 'http://tempuri.org/' is not expected. Expecting element '_clientId'.'.  Please see InnerException for more details."

     

    Or something like that exception. Thanks goes to zac morris and his post in:

     

    http://forums.microsoft.com/sync/ShowPost.aspx?PostID=3444564&SiteID=75

     

    Next we need to create the service in the application itself. The easiest way to host a WCF Service in a managed application is to write some code in your main form constructor like this:

     

    // as a class field

    ServiceHost serviceHost;

     

    // in the constructor

    Uri baseAddress = new Uri("http://localhost:62291/");

    serviceHost = new ServiceHost(typeof(MyService), baseAddress);

    serviceHost.AddServiceEndpoint(typeof(IMyContract), new BasicHttpBinding(), "Service");

    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();

    smb.HttpGetEnabled = true;

    serviceHost.Description.Behaviors.Add(smb);

    serviceHost.Open();

     

    Points of interest - you can add whichever port you wish; rename MyService with your service (that is the implementation of the interface you added the xml attributes); rename IMyContract (that is the interface itself), new BasicHttpBinding() MUST be basic binding, because the Power-toy-utility which we will use in a minute doesn't support anything else; and you can rename "Service" to whichever you wish. Don't forget to Close() the serviceHost after you are finished.

     

    Now the time is to produce some code so we can consume our service from our mobile device. Run the desktop application and let it run, while you go to

    C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\bin

    via a command prompt, where you can write: "NetCFSvcUtil.exe http://localhost:62291/" without the quotes and it will produce 2 files. Move them to the mobile project's location and add them to the project. The second VERY, VERY important thing to do - for some STRANGE reason the code that this thing produces isn't going to work for us. Open the newly added file (not the CFClientBase.cs, as it is perfectly fine - the other one) and you should DELETE all the code, EXCEPT the interface (which happens to be almost the same as the one in the desktop application), the ContractClient (which implements the interface) and the 8 classes which have in their names Request or Response for each of the four methods in the interface (for example a ApplyChangesResponse). After that add a

    using Microsoft.Synchronization.Data;

    to the beginning of the file. All this will save you from some AttributeExceptions and HOURS trying to figure what the hell is going on. In the ContractClient class you will find a field called EndpointAddres. It should look like this: "http://localhost:62291/Service" and you should change it to whichever your IP-ADDRESS is (this is important - do NOT leave it localhost, because the device's localhost is the device itself, and do NOT change that to your machine name, because it doesn't work either).

     

    Now we are ready to consume our service. In whichever method you want to use (I guess that will be an eventhandler for a click event of a "Synchronize" button on the mobile), you can write as simple as that:

     

    LocalDataCacheSyncAgent syncAgent = new LocalDataCacheSyncAgent(new LocalDataCacheSyncContractClient());

    syncAgent.MyTable.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;

    SyncStatistics syncStats = syncAgent.Synchronize();

     

    where you must change the syncAgent to whichever is your own name (it should be in the mobile application's generated code from the Local Data Cache template), and the ContractClient which you worked with just now. And that's all! You have your sync code. If you don't want bidirectional synchonization, you can remove the second line.

     

    Some other points of interest - you could get an exception that a "sqlceme35.dll" or something can't be referenced... if you are using a 64-bit OS, be sure to build the desktop application under x86 from the configuration manager. Another thing (I am unsure of this because I haven't tried) is that the Local Data Cache wizard doesn't seem to see some Foreign Key constraints in my database, it doesn't put them in the newly created mobile one, it doesn't put them in the DataSet and I guess the code in the SyncProvider (which is in the server part - the desktop one) doesn't put the tables (if you have more than one) in a single SyncGroup, which might be a problem. Let's hope that to be fixed until the release of SP1 for VS2008.

     

    Well, I guess that is for the WCF Service hosted in a desktop application, which is referenced from a mobile device to synchronize. If anyone has any questions or problems, I will be glad to help. The Web Reference part is pretty much the same, but I will write a (much) shorter step-by-step for it too. But that will be in a couple of days, because I have an exam tomorrow. Smile Good night. Smile

     

    Edit: of course, something very important. All this simply WON'T work if you haven't connected your device to your PC with Windows Mobile Device Center (that is for Vista, I don't know how's it in XP). If you are using an emulator - be sure to Tools drop-down in Visual Studio, in the Devices Manager, to set Cradle for your emulator and to connect it via Windows Mobile Device Center.

    • Moved by Hengzhe Li Friday, April 22, 2011 2:26 AM (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
    Sunday, June 15, 2008 10:20 PM

Answers

All replies

  •  

    Still getting _clientID error even after adding XmlSerializerFormat. No idea where to go from here.
    Tuesday, June 17, 2008 1:58 PM
  • Hi,

    I Followed your Steps still i'm gertting the Argument Exception while calling Synchronize()...

    Please Some one Help....

     

    Regards,

    Sathish Babu A

    Wednesday, November 5, 2008 7:56 AM
  • I managed to get rid of the exceptions but my local database cache never gets updated. If I make a change on the server and try to synchronize, the syncstatistics say that the changed were downloaded but I don't see the changes made to the local database cache .sdf in my project. Does anyone know how to get the local database cache updated?

    It would be of great help!
    Monday, November 10, 2008 3:29 PM
  • Hi,

    I have a problem because there is no synccontract in my project. Is the reason because my Visual studio 2008 doesnt include service pack?
    What should I do now?

    Please give me some advice

    Thanks, =)
    Friday, April 24, 2009 12:02 PM
  • hi all,

    use the following link for developing mobile application-

    http://social.msdn.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/38a1166a-9dea-4120-96b7-41fd483eab6d


    hope it will help u....

    Cheers.....................
    Tuesday, July 28, 2009 5:28 AM