Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Oh to be an Exception....

After reading Mitch's discussion on throwing Exceptions and quickly refreshing my brain as to what the official Microsoft position is, I went away and was rethinking how I determine if/when I'm going to throw an exception.

I started off with the following concepts:

-   An exception should be thrown when a method/operation cannot be completed successfully.

-   Exceptions should no be used for application flow control.

-   Return values should not be used to indicate if a method/operation has been completed successfully

Now I must say that I agree with all of these.  However there is one concept that I definitely think has merit, which is:

-   An additional set of functionality should be provided to allow a developer to query whether a method/operation will be successful if called (eg "CanConnect" to be called prior to an attempt to call "Connect").

This last concept does cause me some concern though.  The main reason that you would want this functionality is to reduce the number of exceptions that are used for application flow control (see concept above) - for example in the case of the Connect method you would use a condition based on the CanConnect method to determine if Connect should be called.  So, what are the downsides:

-   Firstly, I see having these guards might lead to sloppy programming where exceptions don't get managed.  For example, just because I have called CanConnect, doesn't mean that Connect won't fail.  If it does and an exception is thrown, I still need to handle it!

-   Secondly, the query functionality may increase the time taken to call the method.  For example the CanConnect method might take as long as a call to Connect, in which case if this is routinely called everytime you need to connect it may well negatively affect performance. I guess there is a trade off here the again has to be managed.

My last thought regarding exceptions is that I still believe that .NET is missing a feature that I loved/hated in Java (and yes for my sins I did do a bit of Java programming way back when it was all the rage).  This feature is the way that methods specify which exceptions may be thrown. The reason I say loved/hated is that I loved it when I was building robust code, as it forced me to think about how I was using that method and whether I had handled the different responses (including exceptions) from the method. 

I hated this feature for two reasons.  Firstly, that it was a pain cause the compiler insisted that I rethrow exceptions that I didn't handle in my code (for example if I used a method that could throw an  IOException I either had to catch this or specify that my method could also throw this exception) - why can't the compiler be sensible and deduce this for me, after all when I use that method it's not that I look at the method itself to work out what exceptions are thrown, that's again the compilers job (or intellisense - does Java have that now??).  The second reason is that some developers are sloppy and just say that every method could throw Exception - kind of defeats the purpose of having this feature, right!!

Now it would appear that we may have missed the boat as it would be too difficult to go back and force every .NET method to specify which exceptions are thrown.  However, this is an area where tool support might provide a good compromise.  Now that both C# and VB.NET support rich xml commenting it may be an opportunity to really make use of this functionality.  By specifying in the comments which exceptions a method may throw, this could be used by the IDE to warn developers if they haven't handled theses exceptions when a method call is made.  As with most othe IDE support this could be an option that can be configured by the developer or dev team according to their preferences.

Mobile Client Software Factory (Dynamic Resolution)

The Dynamic Resolution application block is just way too cool.  So one of the on going issues with building applications for mobile devices with different screen orientations and resolutions is what to do when it changes (eg toggle between portait and landscape on a single device).  With version 2 of the .NET CF we now have anchoring and docking, but this just doesn't cut it - a screen layout that is designed for a portait device, just isn't going to be appropriate when it is in landscape.  The solution to this is to have different resource files for each orientation/resolution.  This is where the Dynamic Resolution application block is useful (class library below).

This application block is broken into two parts.  There is a device project (DynamicResolution) which you SHOULD reference in your project and there is a desktop designer project (DynamicReosltion.Designer) which you should NOT reference in your project.

In order to take advantage of this application block you need to create a control (or multiple) that inherit from the DynamicResolutionControl.  When you open this control in the designer you will see that it starts to generate additional resx files (eg Form1.240x320.resx or Form1.320x240.resx).  If you want to adjust the layout for a different orientation/resolution you can use the control properties to specify:

  • FormFactor (drop down listing all skins installed)
  • IsDefault (whether this layout should be used if no other specific layout found)
  • Orientation (Horizontal or Vertical)

Alternatively if you only want to rotate the current layout you can select Rotate from either the right-click context menu (off the control) or from the action list on the properties grid.

As you change orientation/resolution you will see that additional resource files are created.  If you also change the language/region you will see that specific language resource files are created.  For example you may end up with a list of resource files like this:

MyControl.vb
      MyControl.Designer.vb
      MyControl.resources
         MyControl.resX
         MyControl.240x240.resX
         MyControl.240x320.resX
         MyControl.320x240.resX
         MyControl.320x240.ar.resX
         MyControl.320x240.ar-EG.resX

The last two resx files are Arabic (ar) language and Arabic (Egypt) (ar-EG) language/region resource files for the 320x240 display.

Now when you use this control you will see that it changes the layout depending on the orientation/resolution of the device that it is running on.  However, there is a slight issue with the current version that is evident if you dock your control (for example if you dock your control into the main Form area).  It appears that the resources are applied after docking occurs, which means that sub-controls appear in the wrong location and the wrong size. 

The fix for this is relatively straight forward.  Modify the ApplyResource method in the DynamicResolutionControl class to include the following lines:

      private void ApplyResources()
      {
         DockStyle oldStyle=this.Dock;
         if (this.Dock != DockStyle.None)
            this.Dock = DockStyle.None;
         ....
      
   this.Dock = oldStyle;
      }

Mobile Client Software Factory (Subscription Manager)

An alternative to using webservices is to use sql replication.  The Subscription Manager application block provides a simple interface with which to manage sql replication between a sql mobile database and a sql server via a web publication (class list below).

The following example illustrates how you can create a DatabaseService to connect to a SQL Mobile database.  A SubscriptionManager is created and a SubscriptionParameters object is created to hold the properties of the publication to connect to.  The Synchronize method invokes the synchronisation process - this can be wired up to the Connection Manager to automatically synchronize when a network connection becomes available.

 'Create the database service - ie which database
        Dim ds As DatabaseService = New SqlDatabaseService("DataSource=""AWReplication.sdf"";")
        Dim credentials As ISubscriptionCredentialService = New SubscriptionCredentialService()

        Dim subs As New SubscriptionManager(ds, credentials)

        Dim subParams As New SubscriptionParamaters()
        subParams.Filter = "Mr."
        subParams.InternetUrl = "http://192.168.1.100/AWSampleWWW/sqlcesa30.dll"
        subParams.Publication = "AWSample"
        subParams.Publisher = "serverName"
        subParams.PublisherDatabase = "AdventureWorks"
        subParams.Subscriber = "CustomerListSubscription"
        subs.Add(subParams)

        subs.Synchronize(Subscriber)

In this example an instance is created of the SubscriptionCredentialService.  This is a class that we have created (that implements ISubscriptionCredentialService).  In the future this will hopefully be merged with the CredentialService block.

Public Class SubscriptionCredentialService
    Implements ISubscriptionCredentialService

    Public Function FindCredentials(ByVal subscription As Subscription) As SubscriptionCredentials Implements ISubscriptionCredentialService.FindCredentials
        Dim cred As SubscriptionCredentials = New SubscriptionCredentials()
        cred.PublisherSecurityMode = SecurityType.NTAuthentication
        Return cred
    End Function
End Class
 

Mobile Client Software Factory (Credential and Disconnected Service)

Mobile applications often want to make webservice requests to either send a message to a server or as part of the synchronisation process.  However if a connection is not available this request needs to be queued.  When a connection is available, if the request is important enough it should be sent.  Whether or not a request is important enough is dependent on the information in the request (ie the number of "stamps" allocated to the request) and how expensive the connection is (ie the "price" of the connection type").  If you read my blog article on the Connection Manager blog you will have noted that each connection type is allocated a price.  What we need now is a way to assign a number of stamps to a request and to manage a queue for requests (which should survive an application restart).  To do this we use the Disconnected Service application block (class list shown below).

This block needs to be notified when the connectivity of the device changes. When a connection becomes available it can send pending requests.  So that the block can register for connection change events we use the Connection Management block:

      Dim configuration As String = "<Connections>" & _
         "  <Connection  Type='CellConnection' Price='8'/> " & _
         "  <Connection  Type='NicConnection' Price='2'/> " & _
         "  <Connection  Type='DesktopConnection' Price='1'/> " & _
         "</Connections>"
      Dim factory As IConnectionManagerFactory = New Implementations.ConnMgrApiFactory(configuration)
      Dim conManager As ConnectionManager = factory.Create()

In order to queue requests this block uses two databases (don't try to use the database as you will get exceptions) to manage a pending queue and a dead request queue (where failed requests get placed). So we create two DatabaseServices using the Data Access block.

        Dim requestPath As String = "DataSource=""AWReplication.sdf"";"
        Dim database As DatabaseService = New SqlDatabaseService(requestPath)

        Dim deadRequestPath As String = "DataSource=""AWReplicationDead.sdf"";"
        Dim deaddatabase As DatabaseService = New SqlDatabaseService(deadRequestPath)

The next thing we need to do is create a ProxyFactory that will be used to create the web service proxy class.  As we will be queuing the web requests this block needs to be able to create the proxy class automatically.  This is done using the ProxyFactory class.  At the moment users of the block need to create their own factory class that inherits from the abstract OnlineProxyFactory class.  Hopefully this dependence will be removed in future versions.  A sample implementation is as follows:

Public Class ProxyFactory
    Inherits OnlineProxyFactory

    Public Overrides Function GetOnlineProxy(ByVal request As Microsoft.Practices.Mobile.ApplicationBlocks.DisconnectedServiceAgent.Request) As Object
        If (request.OnlineProxyType Is GetType(HelloWorldService.Service)) Then
            Dim onlineProxy As New HelloWorldService.Service()
            If (onlineProxy IsNot Nothing) Then
                onlineProxy.Url = onlineProxy.Url.Replace("/localhost/", "/" & MyBase.GetEndpointPhysicalAddress(request) & "/")
            End If
            Return onlineProxy
        End If
        Return Nothing
    End Function
End Class

We can see from this example that the url of the web request gets dynamically updated. In order for this to happen we have to load a list of endpoints that will be used for this substitution.  This list loads from an xml configuration file as shown in the following example:

        Dim pf As New OnlineProxyFactory 'ProxyFactory

        'Load the list of address endpoints
        Dim catalog As New AddressCatalog()
        catalog.Load("\Program Files\DispatcherSample\endpoints.xml")
        pf.Catalog = catalog

        'Load the list of credentials
        Dim credService As New CredentialsService()
        credService.Load("\Program Files\DispatcherSample\credentials.xml")
        pf.Credentials = credService

This example also loads a series of credentials from an alternative configuration file.  This makes use of the CredentialService application block (class file list below):

Sample configuration files:

Credentials.xml
<?xml version="1.0" encoding="Windows-1252"?>
<CredentialsCatalog>
  <Credentials>
    <Credential ServiceName="ServiceProxy://HelloWorldService" UserName="" Password="" />
  </Credentials>
</CredentialsCatalog>

Endpoints.xml
<?xml version="1.0" encoding="utf-8" ?>
<AddressCatalog>
  <Endpoints>
    <Endpoint Name="MyHost">
      <Network Name="My ISP" Address="192.168.1.100" />
    </Endpoint>
  </Endpoints>
</AddressCatalog>

So now we have a ConnectionManager, Pending and Dead request databases, and a ProxyFactory.  Now all we need to do is create the DispatchService:

      Private ds As New DispatchService

      ds.SetConnectionManager(conManager)
      ds.SetRepository(New DbQueueRepository(database))
      ds.SetDeadRequestsRepository(New DbQueueRepository(deaddatabase))
      ds.SetProxyFactory(pf)
      ds.Start()

A note of caution - make sure you place the DispatchService so that it won't get garbage collected (ie don't make it a local method variable). This DispatchService is all ready to go, so we can go ahead and create a new request.

            req = New Request()
      req.Id = Guid.NewGuid()
      req.CallParameters = New CallParameters()
      req.MethodName = "HelloWorld"
      req.OnlineProxyType = GetType(HelloWorldService.Service)
      req.Endpoint = "MyHost"
      req.Behavior.Tag = "Hello"
      req.Behavior.ReturnCallback = New CommandCallback(GetType(DispatchResponse), "ReturnCallbackMethod")
      req.Behavior.ExceptionCallback = New CommandCallback(GetType(DispatchResponse), "ExceptionCallbackMethod")
      req.Behavior.MaxRetries = 0
      req.Behavior.Stamps = 5

This creates a new web request for the HelloWorld web service.  You will notice that two call back methods are provided (specified by class and method name).  These will be invoked when the web request is executed or an exception is thrown.  We also allocate the number of "stamps" for this request.  The request will only be sent when a connection type of a price less than or equal to 5 is active.  Now all we have to do is use the DispatchService to enqueue the request.

        ds.Process(req)

 

Mobile Client Software Factory (Data Mapping)

In my previous post on the MCSF we saw how the Data Access application block can be used to simplify data access.  However, once we have retrieved the correct data rows from the database we still need to work with them.  We could either pipe them into a dataset and work with them as untyped data, or we could use the Data Mapper application block to convert the data into business objects.   The classes in this block are shown in the following image.

For anyone familiar with the work being done on the Linq/Dlinq project the way that the Data Mapping block works will look very similar.  We start of by defining our business object and by placing special attributes on the field or properties we want to map to specific columns in the database.  In the following code we use fields to keep the code sample short, but they would usually be placed on properties for proper encapsulation:

Public Class Customer

    Public Sub New()
    End Sub

    <DataMapping.DataMap("Customer Id", Data.DbType.String, 5)> _
    Public CustomerId As String
    <DataMapping.DataMap("Company Name", Data.DbType.String, 40)> _
    Public CompanyName As String
    <DataMapping.DataMap("Contact Name", Data.DbType.String, 30)> _
    Public ContactName As String

End Class

To work with the Data Mapper block we need to create an instance of the DataMapper class.  Again this is an abstract class so we need to use the concrete AttributeDataMapper class which provides the implementation details for working with attribute mapped business classes.  The DataMapper class supports a method for creating instance(s) of a particular business class.  This is illustrated in the following code example:

        Dim mapper As DataMapper(Of Customer) = New AttributeDataMapper(Of Customer)
        Dim customerSearch As String = "CustomerParameter"
        Dim sql As String = "Select * from Customers where [Customer ID] like " & ds.ParameterName(customerSearch)
        Dim para As System.Data.Common.DbParameter = ds.CreateParameter(ds.ParameterName(customerSearch))
        Dim reader As Data.Common.DbDataReader = ds.ExecuteReader(sql, para)

        Dim list As New List(Of Customer)
        list.AddRange(mapper.CreateAllInstances(reader))
        reader.Close()

        For Each c As Customer In list
            MsgBox(c.CompanyName)
        Next

Although the Data Mapper block can reduce the code you need to write to populate your business objects, it currently doesn't support a mechanism for creating, deleting or updating data in the database.  It also requires the developer to specify the sql expression used to retrieve the information from the database - since the required columns are all identified by the attributes this code could be automatically generated.  In comparison to the Dlinq model that supports class to table mapping attributes, the current DataMapper class is very limited, but could be used to build a much more flexible application block.

Other useful Mobile resources

A couple of worthy resources for developers wanting to build applications that will work on a variety of mobile devices:

  • Landscape Smartphone Emulator - HERE
  • Treo Windows Mobile Emulator - HERE (you will need to join the Palm PluggedIn developer program)

Mobile Client Software Factory (Data Access)

The next application block available in drop 5 of the MCSF is the Data Access block.  At the moment this is a very simple block containing two classes that can be used to eliminate some of the unnecessarily repetitive code that goes into accessing databases.  These classes are illustrated in the following screenshot.

The DatabaseService base class provides a series of methods that allow you to execute sql commands and retrieve a dbdatareader.  Behind the scenes a database connection is opened and closed for you.  As this class is an abstract class it doesn’t provide the implementation details for any specific data source.  In the case of a SQL Mobile database, the QLDatabaseService class derives from the DatabaseService class, providing implementation details.  If you wanted to, you could also provide an implementation that targets other database types, for example SQL Server.

To work with these classes you need to create an instance of the SqlDatabaseService class, passing in the connection string for the SQL Mobile database you want to access. 

      Dim ds As DatabaseService = New SqlDatabaseService("DataSource=””\Program Files\Dataaccessblocksample\Northwind.sdf””")

At the moment the implementation of this class leaves a little to be desired as the constructor takes a single connection string parameter.  Since the list of parameters for a SQL Mobile database are fairly limited, it would make sense to provide alternative constructors that could simplify the use of this class.  The other recommendation would be to do some checking to validate a particular database file exists.  For example, the current constructor for the SqlDatabaseService class is:

      public SqlDatabaseService(string connectionString) : base(connectionString){}

Perhaps an alternative constructor could be:

      public SqlDatabaseService(string databasePath)  :  base()
      {
         if (!System.IO.File.Exists(databasePath))
            throw new ApplicationException("Database doesn't exist at path " + databasePath);
         ConnectionString = "Data Source =\"" + databasePath + "\";";
      }

This could be extended to a second constructor that might accept a password or other parameters as required.  For this to work the ConnectionString property would also need to be modified to have a protected set operator (using the new mixed property accessibility feature in .NET CF v2).

After you have a DatabaseService, the first thing that you will want to do is to select some data from the database, this can be done using the ExecuteReader command.  This command has a couple of overloads that accept either a DBCommand or a (Select) string.  In the following example we illustrate how you can use a sql string with an embedded parameter to select customer rows from the database:

      Dim customerSearch As String = "CustomerParameter"
      Dim sql As String = "Select * from Customers where [Customer ID] like " & ds.ParameterName(customerSearch)
      Dim para As System.Data.Common.DbParameter = ds.CreateParameter(ds.ParameterName(customerSearch))
      
Dim reader As Data.Common.DbDataReader = ds.ExecuteReader(sql, para)
 

SkypeIn service arrives in Australia

A bit of a hidden gem was discovered while reading the Age newspaper this morning (I'm in Melbourne at the moment so I'm catching up on all the rubbish that seems to go into every newspaper at the moment - at least here it is new rubbish about a city that I'm visiting).  Anyhow, there was an article about Skype and the fact that they have just released a SkypeIn service for Australia. 

This is great news as I no longer have to rely on one of the local Telcos for a landline number.  As this line automatically routes to Skype, it means that when I'm connected, it comes straight to me (wherever I am).  Better yet, when I'm not connected it goes through to my voicemail, where they can leave a message which I can play back the next time I'm online - strikes me that this is the best of both worlds.

The only thing we now have to do is work out how we can get ADSL without having to pay for a landline to be installed - I don't use my home landline as I have a mobile (and now Skype)!!!

ActiveSync 4.2 Beta

For anyone experiencing issue with ActiveSync 4.1, please feel free to download and try out the BETA version of ActiveSync 4.2 from the Windows Mobile download centre.  Be sure to provide any feedback you have!!

MEDC site goes live

Over the last couple of months I have been talking to various people about the up and coming Mobile and Embedded DevCon (MEDC) here in Australia.  Just recently the registration site has gone live on the Microsoft Australia website.  For your records the event is being held in Melbourne on May 25th.

Last year's event was a massive success with some top presenters from the US joining forces with sessions from local mobility MVPs.  Don't miss out this year!!!

Mess with Messenger gets the scoop on building Addins for Live Messenger

Anyone who is part of the Live Messenger Beta (ideas.live.com) and is interested in building managed addins for Live Messenger should head over to the Mess with Messenger website.  They have managed to get hold of build 8.0.0683 which includes a special tab for Addins under Tools-->options (samples etc are also available from their website).

By default the Addins tab is missing, so you have to enable it via a registry key:

[HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger]
"AddInFeatureEnabled"=dword:00000001

Once enabled, the Addins tab should appear (you will need to exit and restart Live Messenger) after you have signed in.

The next thing you have to do is to build your Live Messenger Addin.  This is relatively easy as there is now a MessengerClient.dll in the application folder for Live Messenger (eg c:\Program Files\MSN Messenger).  This is a managed wrapper dll which you need to reference in your addin.

So in summary to create your addin you create a class library project (VB.NET, C# or any other .NET language) and you use Add Reference to select the MessengerClient.dll. You then need to create your addin class with which to access the api though.  This class is called by Messenger when your addin is initialized so it MUST be named the same as your class library (just without the dll).  Do NOT put it in a namespace or it will not be found (for VB.NET developers this means you have to remove the default namespace). This class also must implement the IMessengerAddIn interface (which is in the Microsoft.Messenger namespace - I found it easier just to import this namespace).

Implementing this interface requires the Initialize method into which an instance of the MessengerClient class is passed.  I would suggest holding a reference to this class as you can attach handlers so that you can invoke your code when certain actions/events occur.  The following code is a quick Addin I wrote that shows how you can have event handlers for the various Messenger events.  Note that this is compiled into NickSampleLiveAddin.dll

Imports Microsoft.Messenger

Public Class NickSampleLiveAddin
    Implements IMessengerAddIn

    Private theMessenger As MessengerClient

    Public Sub Initialize(ByVal messenger As Microsoft.Messenger.MessengerClient) Implements Microsoft.Messenger.IMessengerAddIn.Initialize
        Me.theMessenger = messenger

        Me.theMessenger.AddInProperties.Creator = "Nick Randolph @ SoftTeq"
        Me.theMessenger.AddInProperties.Description = "Sample plugin!"
        Me.theMessenger.AddInProperties.FriendlyName = "SoftTeq Addin"
        Me.theMessenger.AddInProperties.PersonalStatusMessage = "Nick's working on an Addin...."
        Me.theMessenger.AddInProperties.Status = UserStatus.Busy
        Me.theMessenger.AddInProperties.UserTile = My.Resources.Nick
        Me.theMessenger.AddInProperties.Url = New Uri("
https://blogimages.builttoroam.com/nick")


        'AddHandler Me.theMessenger.StatusChanged, AddressOf OnStatusChanged
        'AddHandler Me.theMessenger.Shutdown, AddressOf OnShutdown
        'AddHandler Me.theMessenger.ShowOptionsDialog, AddressOf OnShowOptionsDialog
        'AddHandler Me.theMessenger.OutgoingTextMessage, AddressOf OnOutgoingTextMessage
        'AddHandler Me.theMessenger.IncomingTextMessage, AddressOf OnIncomingTextMessage
    End Sub

End Class


Once you have create and compiled your Addin you can go back to Live Messenger and select it in the Addins tab.  In order to debug your Addin you can simply attach Visual Studio to the messenger process (msnmsgr.exe) and go ahead and set breakpoints.

Oh, a couple of last things about Addins:  Live Messenger only seems to be able to run 1 Addin at a time - kind of sux really, hopefully they will change this.  Addins also run in a tight security sandbox, so if you were hoping to do malicious things, think again. Lastly, when an Addin is running you get a message at the top of your messenger windows saying that the Addin is running.

Happy Messengering...

A Couple of Blog references to start the day....

After my morning coffee I sat down to read through what people have been saying while I was asleep last night.  The first thing that grabbed my attention was that Monad had been renamed to PowerShellMitch has started a petition to get the name changed and I figured I'd better blog this for two reasons.  Firstly, if we all blog about the fact that the new name kinda sux it might be changed.  Secondly, even if the name isn't changed, the more we blog about PowerShell the more relevance it will receive when people do search for it.

The other thing that grabbed me was a blog article by the Windows Mobile Team.  Although this article is somewhat random, it is a trick definitely worth noting if you are building signed mobile applications!!!

Mobile Client Software Factory (Connection Manager)

Anyone doing Windows Mobile development should be aware of the fantastic work the team over at OpenNETCF have been doing with the Smart Device Framework.  This has provided missing functionality for both v1 and v2 of the .NET Compact Framework.  Recently they also released a series of application blocks that made application development much easier. 

Now the Patterns and Practices team at Microsoft has come to the table and have started to work with the community to improve support for writing enterprise grade mobile applications.  The project, entitled the Mobile Client Software Factory, is made up of a series of application blocks, a testing framework and the mobile composity UI block.  Up to their 5th community drop, this project is progressing nicely and I would recommend that you take a look.

We will use a simple example to illustrate how the connection manager application block can be used.

   Dim configuration As String = "<Connections>" & _
      "  <Connection  Type='CellConnection' Price='8'/> " & _
      "  <Connection  Type='NicConnection' Price='2'/> " & _
      "  <Connection  Type='DesktopConnection' Price='1'/> " & _
      "</Connections>"
   Dim factory As IConnectionManagerFactory = New ConnMgrApiFactory(configuration)
   Dim conManager As ConnectionManager = factory.Create()

   AddHandler conManager.ActiveNetworkChanged, AddressOf ActiveChanged

In this example we use a connection string (typically stored in a configuration file) which defines a series of connection types with their associated price.  One of the problems that is encountered when writing a occasionally connected application is determining when a web request can be made.  For example if the device is connected via a GPRS connection you would only want to make essential request, queuing less urgent and larger requests until a cheaper connection is made available.  The solution to this problem is very similar to the postal system where you have to purchase sufficient stamps in order to send a package of a given size a certain distance.  In the case of connections each connection type has an associated price.  When making web requests you allocate them a number of stamps.  If the number of stamps is >= the price of the active network the request will be made, otherwise it will be queued until a cheaper network is available.

The XML connection string is passed into the constructor for the ConnMgrApiFactory which implements the IConnectionManagerFactory interface.  The Create method on this interface returns a ConnectionManager that contains a list of networks and connections that are defined for the mobile device.

In addition to exposing the list of networks and connection, the ConnectionManager also exposes the ActiveNetworkChanged event.  We will see later that this event is used by the DisconnectedService application block to automatically invoke queued web requests when a connection with an appropriate price becomes active.

The following diagram illustrates the interfaces and the classes that are currently included in the Connection Manager application block.

The main class that you will need to interact with is the ConnectionManager class.  When the active network event is raised you can access the active network via the ActiveNetwork property.  The Network exposes properties such as IsConnected and a PingComponent that can be used to call DoPing to invoke a ping (this can be used to determine if a certain endpoint can be connected to).

SP1 Beta for the .NET Compact Framework V2.0

I guess this is pretty old news already, but since this is an area of interest to me I thought that I should at least add to the clutter on the Internet by blogging the fact that a Beta for SP1 for the .NET Compact Framework has been announced and that more information on the added functionality and bug fixes is available on the team's blog

SQL goes wild everywhere

Since the release of SQL Server 2005 late last year the mobile devices community have been discussing the usage of the SQL Mobile product for application development.  One of the main discussion points has been the usage of SQL Mobile on platforms other than Windows Mobile.  Now you might say, "not support", but in actual fact you would be partially wrong.  Not only was SQL Mobile designed to work on the WinXP platform, it is actually supported on WinXP Tablet edition.  Intuitively this makes some sense since a Tablet PC can be thought of (in particular when you consider the UMPC devices) as a large PDA and as such it would be convenient to have the same programming model for both devices. 

So, why has this topic received so much attention, well despite the support for running SQL Mobile on Tablet PCs the licensing states that it cannot be run on the standard WinXP platform.  This means that if one of your clients is using a laptop instead of a Tablet PC then they will not be able to run an application based on SQL Mobile.  When you look at it in this light, the decision to support one, but not the other seems quite silly.

Anyhow, lets cut to the chase - Late last week it was announced that a "new" (in fact rebadged/relicensed would be more appropriate) product line would be added called SQL Server Everywhere Edition.  This was followed up with a useful blog entry by Steve Lasker regarding the details of what this new product line would entail. Basically the up shot will be that you can build mobile applications that target SQL Mobile that will run on Windows Mobile and WinXP, allowing you to easily target PDAs, UMPC, Tablet PCs, Laptops and even Desktop PCs.  Note the limitation (of course) around using SQL/e as the db for your web app!

Presenting Skills 101

I have lost count of the number of presentations that I have literally fallen asleep in.  Mainly it has nothing to do with the content, since I wouldn't be there if I wasn't a little interested in the topic.  99% of the time it has to do with the presenter and their usage of powerpoint.  Ok, so I'm not going to come out and say what you should or shouldn't do because I don't actually believe there is one "best way" to present.  Everyone has their own style.  This said, I think some general pointers are always useful so I would like to point people to an article I read today on the do's and don'ts of using presenting with powerpoint.

Would be interested to here comments from others as to what they thought about this article.

 

Using PhoneCellBroadcast in WM5 for cheap location aware applications

A couple of weeks ago a fellow MVP, Mitch Denny, asked me a question about the Notification Broker in Windows Mobile 5.  For anyone not familiar with the Notification Broker it is a mechanism where you can not only query system information about the device, but you can also register for notification when a system property changes.  Anyhow, Mitch's question was regarding the PhoneCellBroadcast property and the fact that it didn't seem to be returning any data. 

Despite talking over Messenger I did my best job to look puzzled having never really played around with that particular property. Mitch proceeded to explain that it was supposed to access broadcast messages from the current cell the mobile was connected to.  Interestingly enough, Australia is one of the few places in the world where the networks appear to broadcast useful information.  To access this information you firstly have to do the following (the steps here apply to Windows Mobile 5 and have been tested on both the K-Jam and JasJar - let me know if it does/doesn't work on other devices):

Start -> Settings
Select Personal tab -> Phone
Select More tab -> Tick the Broadcast Channels checkbox and hit Settings button
Tick the Receive channel list checkbox
Select English from language dropdown
Hit New... button
Enter Cell (or any other description) into Name textbox and 50 (this varies in different countries but should be correct for Australian networks) for the Channel number
Hit Ok
Make sure the new entry in the Select item to receive: list is checked
Hit Ok
Hit Ok (again, which should take you back to the main settings page)
Wait 10-20 secs and you should receive a notification bubble with the name of the Cell (eg Subiaco) in it.

Ok, so now that we can see the cell broadcast, what can we do with it.  Well firstly, the usage is going to be somewhat limited because although in some cases the cell name is the suburb, in others it is a cryptic abbreviation (eg EstVicPrk for East Victoria Park) or simply a placeholder (eg New Coverage which we got somewhere around North Fremantle).  This said, I'm sure that someone will come up with a use for it so the important thing is that we can extract the contents of this message.

For those familiar with the Notification Broker you will be aware that we can extract information about the current system state using the following lines of code:

Dim x as new Microsoft.WindowsMobile.Status.SystemState(SystemProperty.PhoneCellBroadcast)
MsgBox(x.CurrentValue())

Alternatively, if we want to be notified every time this property changes we can attach an event handler to the Changed event of the SystemState object.  Unfortunately there is a little documented issue with using either of these techniques.  Unless the PhoneCellBroadcast property has a value you will either experience a NullReferenceException or the CurrentValue method will return nothing.

To get this property to function correctly we need to tweak a registry setting which was kindly given to me by one of the mobility guys, Paul Kormann, at Microsoft. By default if you look at the key HKEY_LOCAL_MACHINE\Software\Microsoft\Inbox\Svc\SMS you will see that there is an entry TreatImmediateModeCBAsClass0SMS which has a value of 1.  As the entry implies a value of 1 (ie true I guess) implies that the system should Treat Immediate Mode Cell Broadcasts (ie the network messages we were receiving earlier) as Class 0 SMS.  As I found out from my quick read of the SMS FAQ a Class 0 SMS is designed to be displayed then discarded (versus a Class 1 (ie normal) SMS which is stored).  The net result is that having this value set gives us the notification bubble we saw from the steps above.  Changing the value of this entry (using either a remote registry editor or a registry editor for the device) to 0 should mean that we can access these messages using the notification broker. 

Ok, so I was happy with this and proceeded to change the registry value.  Unfortunately it didn't immediately work for two reasons.  Firstly in my playing I had disabled the Broadcast channels (the first checkbox in the above steps).  Secondly I hadn't reset my device.  So the steps to get this to work are:

Complete steps above to enable Broadcast channels
Change Registry value for TreatImmediateModeCBAsClass0SMS
Reset device

Now for the bad news.  I was pleasantly surprised when this worked on my K-Jam so I was quick to pass on the news to Mitch.  Unfortunately try as he might he couldn't get the same instructions to work on his JasJar.  John also tried this on the SoftTeq JasJar with the same result.

While we were experimenting we did find a useful area of the Registry. HKEY_LOCAL_MACHINE\System\State contains a number of keys relating to the current state of the system.  Of particlar interest to what we were doing was the Phone key.  On my K-Jam, after applying the steps above, there was an entry for Cell Broadcast which contained the most recent cell broadcast.  However on the JasJar this entry never seemed to exist.  Interestingly enough when Mitch manually populated this entry the value was accessible in code (as if it has been correctly received via the notification broker).

I hope this is useful to anyone interested in delievering a cheap location aware application.  If anyone can get this to work with the JasJar please let us know.

Enterprise Development using Patterns and Practices

Last night, John presented an overview of the Enterprise Library to the Perth .NET Community of Practice.  It was clear that there were mixed experiences within the audience ranging from those that were working with v2 of the library (1 or 2), those working, in anger, with v1 of the library (half a dozen or so) and those that either won't admit to it or weren't using it at all.  Having been involved with a large scale application that didn't use either the application blocks or the Enterprise Library I can only commiserate with those in the same boat - word of advise... spend the time and money to incorporate the Library into your application.  This doesn't need to be done all at once, you can bring it in piece by piece, but in the long run it should save you time and ensure your product is more reliable.

Ok, so this said, there are some other things that you should really check out, particularly if you are starting a new application and want some guidance on how to build a consistent user experience.

Composite UI Application Block (here)

Mobile Baseline Architecture Toolkit (here)

Also, touch base with John's blog as he looks at the various application blocks in the Enterprise Library itself. (For those that missed the presentation last night, the slides should be available on the user group site by the end of the week).