NAVmoble - the pocket-sized ERP
Optimized for Microsoft Dynamics NAV and Windows Mobile powered devices

Sunday, December 10, 2006

True or False: The geek's quest for the golden hammer

I'm looking at me as a regular tech geek spending the most of my personal time to educate my self . I'm reading ,listening , attending ,arguing and blogging in my private personal march to the perfection.
Experts, blogs,podcasts, community sites, companies, journalists - all of them are arguing about the best methodology, technology and techniques. All of them are yelling that this or that is the silver bullet for my problems:



"So this week, we're introducing a general-purpose tool-building factory factory factory, so that all of your different
tool factory factories can be produced by a single, unified factory. The factory factory factory will produce only the
tool factory factories that you actually need, and each of those factory factories will produce a single factory based
on your custom tool specifications. The final set of tools that emerge from this process will be the ideal tools for your
particular project. You'll have *exactly* the hammer you need, and exactly the right tape measure for your task, all at
the press of a button (though you may also have to deploy a few *configuration files* to make it all work according to
your expectations)."
                                                                                                                                     Why I Hate Frameworks, BenjiSmith


And I'm in the center of all this madness! Alone with my geeky problems waiting to recognize the real panacea for my daily technical problems.
I'm into this everlasting quest for the golden hammer for quite a long time and actually this is what thrills me the most in my lonely geeky nights. I don't know actually what I like the most: the moment of feeling, that I found the silver bullet or the next day, when I'm realizing that my geeky quest will continue. We geeks are kind of explorers, arn't we! If we discontinue our exploration activities, we won't be explorers anymore.


I've got this moments, when I feel consistent:  I do not have doubts, I know exactly which tool or technique to use, I feel I'm following up all the new concepts around. And there are short moments, when I feel lost, tired and totally disoriented. This is the payoff for raping my brain with tons of information night after night.


Along with my nightly activities, It is not rare for me to answer to questions from other people around me. Often these are new "kids" in the industry, who think I know the answers of all questions.
And here comes my big personal question: TRUE OR FALSE?
I am spending a lot of time around my team's young devs and hence I get this kind of questions, when I doubt, what is the right answer. All these guys are trying to get a simple and straightforward answer - the answer of all answers. They ask:



  • Is the ORM approach better than the classic Table-driven approach. Why we use ORM, when in on CodeProject somebody said it is a doomed concept.

  • Why we have a 3  layers architecture. I've read on Channel 9 that the 4 layers architecture rules.

  • Why we are not using WCF, but classic Asp.NET Web Services. They all talk about WCF.

  • They said on DotNetRocks.com that  Rubby is so great,  but we are still using C#. Why?

  • Why we use Scrum?  My university teacher said that XP is better!

  • There is article on MSDN, which says that the future is in the Software Factories and we use some third party Code Gen products. Why's that?

  • Shall I use custom Service Locator implementation or using some light container implementation like Castle?

  • They said that Personal Social Number should never be a primary key in a table. Why we broke this global rule in our project?

TRUE or FALSE? What to tell these guys, who want to get a simple question to solve their problems. How to give them a simple answer, when there is only a long and complicated one. How to give them this simple answer, when the decisions are bound also to our specific political , business and culture context. They want all-time global and easy answers. This are the moments, when they are learning how to get decisions. Shall I tell them that (often) there is no global and absolute arguments. Shall I tell them that I just don't know for sure , but I think this way it will work just fine . TRUE or FALSE?  Telling TRUE may break their confidence in the industry, in experts  in practices. Telling them FALSE (by hiding some part of the truth) may gave them the wrong idea that this industry is like a religion:that it is all about idols and absolute true.


 


What do you answer in such situation? TRUE or FALSE?

Saturday, December 09, 2006

"How To" Series: Building a Signature Control in Compact Framework

It is not a rare requirement for a mobile application to provide functionality for capturing a person signature.
So, let's see if we can provide this feature into a mobile application with .NET Compact Framework.
The image bellow outlines the problem that we want to solve:



We have a mobile salesman, who collects customer orders. Our salesman should collect the customer's signatures along with the order's details. Our salesman is carrying a Pocket PC device. We should create
a software solution to allow customer's signature capturing and transmition of the signature over the wire to the office. There we have a Sql Server database to store the signatures into and signatures consuming app. , which may process the stored signatures.


We should solve the following tasks:



  1. Capturing a signature from a person from the mobile device
  2. Saving the captured signature locally on the mobile device
  3. Transmitting the saved signature over the wire and storing it on the server side
  4. Consuming the transmitted and saved signature on the server side

Let's try to solve these tasks:


Solving Task 1: Capturing a signature from a person on the mobile device


If a person should place its signature on a Pocket PC, he will probably use the stylus to write his signature on the Pocket PC screen. All we have to do is to capture the on-screen tapings and convert them into a bitmap. We will create a User Control to encapsulate this functionality. The main functionality is divided between the following UserControl event handlers:



  • OnMouseDown - here we will "remember" the coordinates of the last on-screen tapping
  • OnMouseMove - here we will draw a line from the remembered coordinates to the new(after the mouse move) on-screen mouse coordinates.


Following code example(simplified version)
...
private Bitmap SignatureImage;
private Graphics GraphicsHandle;
privte Point MouseCoords;
....
SignatureImage = new Bitmap(this.Width, this.Height);
GraphicsHandle = Graphics.FromImage(SignatureImage);
...
//remembering the coords of the last on-screen tapping into  MouseCoords member
protected override void OnMouseDown(MouseEventArgs e)
{
  base.OnMouseDown(e);
  MouseCoords.X = e.X;
  MouseCoords.Y = e.Y;
}
//draw a line from the remembered coords to the new on-screen tapping coords
protected override void OnMouseMove(MouseEventArgs e)
{
  base.OnMouseMove(e); 
  GraphicsHandle.DrawLine(SignaturePen, MouseCoords.X, MouseCoords.Y, e.X, e.Y); 
  MouseCoords.X = e.X;
  MouseCoords.Y = e.Y;

//saves the captured bitmap image into a stream
public void Save(Stream stream)
{
   SignatureImage.Save(stream, ImageFormat.Bmp);
}  


Solving Task 2: Saving the captured signature locally on the mobile device


This task is simpler. Let's pretend, we should save the captured image into a local SqlServer Mobile database.
We should have a table containing a field of type image to save the signature into it.



CRATE TABLE CUSTOMERSIGN
{


   customerNo:int not null identity
   sign:image
}


Following the code to save the captured signature:


//our signature control placed into a form
private
SignatureControl MySignatureControl;
...
string connectionString =  ...;
...
using (SqlCeConnection connection = new SqlCeConnection(connectionString))
{
  connection.Open();
  SqlCeCommand command = new SqlCeCommand("INSERT INTO CUSTOMERSIGN(sign)VALUES(?)", connection); 
 


  //getting the captured signature as stream
  MemoryStream signStream = new MemoryStream();
  MySignatureControl.Save(signStream);


  param = new SqlCeParameter("sign", SqlDbType.Binary);
  param.Value = signStream.ToArray();
  command.Parameters.Add(param);


  command.ExecuteNonQuery();
  connection.Close();
}
Now we have the signature saved locally...
We may save the signature into another storage type like a file for example.


Solving Task 3: Transmitting the saved signature over the wire


Usually the most valuable mobile applications provide functionality to send and receive data to/from some in-house systems running in the company's office.
Let's see if we can send the captured image back to the office over the wire. Although there are various communication options that may be used to transmit the signature over the wire, we will see only the Xml Web Services way in this article. Other possible options are TCP/IP transmition with sockets, Merge Replication,RDA  and why not E-mail .
First, we should create our Xml Web Service. This Xml Web Service will run on the company's office web server. The web server its self should be "http reachable" by  our PocketPC. So, when our Pocket PC device gets a network connection, it may invoke our Xml Web Service and send all the captured signs back to the office.
Let's have a similar table (CUSTOMERSIGN) created into a Sql Server, which also runs in our office. Our Xml Web Service will receive the captured signatures from the mobile app. and will save them into the CUSTOMERSIGN table in the Sql Server. Later another app. may fetch the stored signs to process them in some way.


The  Xml Web Service will have one web method like this:




[WebMethod]
public void TransmitSignature(int customerId, byte[]
signature)
{
  using(SqlConnection connection = new SqlConnection(connectionString))
  {
     SqlCommand insertCmd = new SqlCommand("INSERT INTO CUSTOMERSIGN(customerId,sign)VALUES(@customerId,@signature)", connection); 
     insertCmd.Parameters.AddWithValue("@customerId", customerId); 
     insertCmd.Parameters.AddWithValue("@signature",signature);
     insertCmd.ExecuteNonQuery();
  }


}


Then on the mobile side, we may create a web reference to our Web service and consume it, when a network connection is available


OfficeService.SignService signService = new OfficeService.SignService();
using(SqlCeConnection cnn = new SqlCeConnection(connectionString))
{      


        SqlCeCommand cmd = new SqlCeCommand("SELECT customerId,signature FROM CUSTOMERSIGN",cnn);
        SqlCeDataReader reader  =  cmd.ExecuteReader();
        while(reader.Read())
        {
            int customerId= (int)reader[0];


            //read the signature from the mobile database
            int imgSize = reader.GetBytes(1,0,null,0,0); 
            byte[] signImageData = new byte[imgSize];
            reader.GetBytes(1,0,signImageData,0,0); 


            //transmit signature over the wire
            signService.TransmitSignature(customerId,signImageData);
         }          


         //delete transmited signatures from the mobile database
         
SqCeCommand deleteCmd = new SqCeCommand("DELETE FROM CUSTOMERSIGN",cnn);
         deleteCmd.ExecuteNonQuery();
 } 


Note, that this example is not quite efficient from a performance point of view. It will be more performant to have a Web Method, which accepts
a collection of signatures at a time. It may be performed easily by using DataSet to fetch and  transfer the captured signatures:

[WebMethod]
public void
TransmitSignature(DataSet signatures
)

Solving Task 4: Visualizing the transmited signature on the server side


Once we have the captured signatures saved on the server side, we may need to consume them. For example we may want to show them as images on the screen.
In order to do this we should fetch them from the database:



//picturebox control to show the signature
private PictureBox pictureBox1;
...
int interestingCusotmerId;
 ...
SqlCommand cmd = new SqlCommand("SELECT signature FROM CUSTOMERSIGN WHERE customerId=@customerId", connection);
cmd.Parameters.AddWithValue("@customerId",interestingCusotmerId);
SqlDataReader reader  =  cmd.ExecuteReader();
if(reader.Read())
{
    //read the signature from the database
    int imgSize = reader.GetBytes(0,0,null,0,0); 
    byte[] signImageData = new byte[imgSize];
    reader.GetBytes(0,0,signImageData,0,0);
    //show the signature as Bitmap image
    using(MemoryStream ms = new MemoryStream(signImageData))
    {
      pictureBox1.Image = new Bitmap(ms);
    }
}          


The presented example is not a complete solution. It just outlines some of the common problems, which should be addressed if one needs to build a signature capturing solution. 
A real world solution may be far more complicated and should address a lot of problems not mentioned here. For example there are other signature capturing techniques ,which may store the signature in more compressed format. One may need to encrypt/decrypt the captured signature to protect it or validate the signature(biometric). Please see the links bellow for more examples.



Links:


Monday, December 04, 2006

WPF/E CTP is out

Microsoft released the first CTP for WPF/E.

“WPF/E” is the Microsoft solution for delivering rich, cross-platform, interactive experiences including animation, graphics, audio, and video for the Web and beyond. Utilizing a subset of XAML (eXtensible Application Markup Language)-based Windows Presentation Foundation technology, “WPF/E” will enable the creation of content and applications that run within multiple browsers and operating systems (Windows and Macintosh) using Web standards for programmability. Consistent with Web architecture, the XAML markup is programmable using JavaScript and works well with ASP.NET AJAX. Broadly available for customers in the first half of 2007, “WPF/E” experiences will require a lightweight browser plug-in made freely available by Microsoft.



The CTP contains the WPF/E plugin itself and SDK



There is a Macintosh version as well

Links:

WPF/E Downloads

WPF/E Dev Center

Sunday, December 03, 2006

Microsoft Days in Sofia University

I had a short presentation discussing the .NET Compact Framework goodies, during the Microsoft Days in the Sofia University
The Slides and the source code are available(in Bulgarian):
If you have any questions or troubles compiling the source code, please contact me at r underscore trifonov at hotmail dot com

Friday, December 01, 2006

"How To" Series: Detect network connection in Compact Framework

There is several ways to accomplish this and I will outline some of them in this post.


The following snippet may be used to detect if the device is connected to a network.
It checks if the device has an IP address assigned. This approach will not work properly if the device has a static IP. It is not guaranteed that a specific network destination is reachable.


bool IsConnected
{
    get
    { 
        try
        {  
            string hostName = Dns.GetHostName(); 
            IPHostEntry curHost = Dns.GetHostByName(hostName); 
            return curHost.AddressList[0].ToString() != IPAddress.Loopback.ToString(); 
        } 
        catch
        {
            return false; 
        }
    }
}


Another possible approach is to check if there is a "path" to a specific destination.


public bool IsNetworkPathAvailable(string destinationAddress)
{
     bool connected = false
     HttpWebRequest request;
     HttpWebResponse response;
     try
     {
          request = (HttpWebRequest)WebRequest.Create(destinationAddress);
          response = (HttpWebResponse)request.GetResponse();
          request.Abort(); 
          if (response.StatusCode == HttpStatusCode.OK)
         {
              connected = true;
         }
    }
    catch (WebException ex)
    {
        connected = false;
    }
    catch (Exception ex)
    {
       connected = false;
    }
    finally
    {
       if(response != null)
          response.Close();    
    }
    return connected;
 }
//here we will use the network detection
if(IsNetworkPathAvailable(http://www.ritsoftware.com"))
            SendSomeDataOverTheWire();  


Another way to accomplish this is to use the InternetGetConnectedState function from wininet.dll
[DllImport("wininet.dll")]
private static extern bool InternetGetConnectedState(ref uint flags, uint dwReserved);

public bool IsConnected
{
   get
   {
        uint flags;
        return InternetGetConnectedState(ref flags,0);
   }
}  


 


Links
ConnectionManager class from www.opennetcf.org
Compact Framework Newsgroups