What a Web Service contract requires

A comment on one of my earlier posts lead me to think of a feature that is missing from web services. The whole point of using web services is to decouple links between products so that it comes down to a service agreement. I think that these agreements should have a defind duration. This should be of the form “I promise to keep this service available for 3 years and I will update my future intentions after 2 years”. This could permit a web service to evolve over time without breaking the contract.

COM used to have immutable contracts – although these were occasionly broken ( OLE-DB has a great feature that breaks the IUnknown contract – the behaviour of IUnknown on a provider varies depending upon whether the connection is connected).

This would require some extensions to the basic infrastructure but would save a lot of trouble in the future. This would prevent a system being built with a dependance upon somrthing that is just due to expire.

Cognotive Distance

A discussion in this dot net rocks show explained why an experienced C++ devloper would chose to use VB.NET over C#. The two languages are of equivalent expressiveness but have slightly different biases. VB.NET is better for dealing with variants and default parameters while C# has unmanaged code support.

Kate’s argument was that C# was too close to C++ to make freely jumping between them difficult and error prone this made VB.NET a more natural choice. I have had similar experiences. Currently I am working in Delphi, SQL and C#.

I find that keeping the SQL in strict upper case allows me the seperation so that I don’t find myself adding “then” to the end of my if statements. This allows me to keep a Cognative Distance between the two languages. Since Delphi and C# have a suitable distance between them (begin end vs {} ) I generally don’t have a problem switching..

The major gotcha that I have between Delphi and C# is the calling of a method with an empty parameter list. In Delphi you can call foo; where C# requires foo();

C# reserves foo for referencing the method itself.

The other niggle that I have with C# is the casting syntax.

In Delphi if I wanted to cast a class to a specific descendant and then use a method exclusive to that type I would use:

TChild(aParent).ChildMethod;

C# would require:

((TChild)aParent).ChildMethod();

which has slighly too many brackets for my taste.
I know this was implemented for the C and Java developers but since one of the aims of C# was to correct the mistakes of the C and C++ world this could have been improved.

 

Greasemonkey documentation

Greasemonkey is a Firefox extension that allows the reconfiguration of websites.

The documentation can be found here.

The general idea is that if you find a site that does not work how you want it to you can rescript it to avoid annoyances. I will be experimenting with this and will record my progress.

MSMQ Samples

Here is a sample of  using MSMQ

The example in .NET Framework essentials does not seem to work.

This is still a simpliefied version, not actually handling timeouts very cleanly.

//This is Enque:
// Enque.cs
using System;
using System.Messaging;

namespace EnqueSample
{
    [Serializable]public struct Customer
    {
        public string Last;
        public string First;
    }
    class EnqueSample
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                string path = “.\\PRIVATE$\\NFE_queue”;
                if (!MessageQueue.Exists(path))
                {
                    MessageQueue.Create(path);
                }

                MessageQueue q = new MessageQueue(path);

                Customer c = new Customer();
                c.Last = “Eyre”;
                c.First = “Chris”;

                q.Send(c);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}
// Deque
// Deque.cs
using System;
using System.Messaging;

namespace Dequeue
{
    [Serializable]public struct Customer
    {
        public string Last;
        public string First;
    }
   
     class Dequeue
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                string strQueuePath = “.\\PRIVATE$\\NFE_queue”;

                if (!MessageQueue.Exists(strQueuePath))
                {
                    throw new Exception(strQueuePath + ” does’nt exist”);
                }
                MessageQueue q = new MessageQueue(strQueuePath);

                Type[] t = {typeof(Customer)};
                ((XmlMessageFormatter)q.Formatter).TargetTypes = t;

                Message m = q.Receive(new TimeSpan(0,0,5));

                Customer c = (Customer) m.Body;

                Console.WriteLine(“Customer: {0} {1}”, c.First, c.Last);

            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            System.Console.ReadLine();
        }
    }
}

Second step in remoting example.

This is an extension of my earlier example.
This version makes the remote object methods virtual.
This means that the client does not actually need to know anything about the actual
type of the implement object.

Common library:
// SimpleRemoting.cs
using System;
using System.Runtime.Remoting;

// Add a reference to System.Runtime.Remoting
namespace SimpleRemotingLibrary
{
    /// <summary>
    /// This is a common object for the remoting
    /// </summary>
    public class RemoteHello  : MarshalByRefObject
    {
        static string msg = “Hello, Universe of .NET”;
        public virtual string SayHello()
        {
            Console.WriteLine(RemoteHello.msg);
            return msg;
        }   
    }
}

// Server
// HelloServer.cs

using System;

// Add a reference to System.Runtime.Remoting
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
// Add a reference to SimpleRemotingLibrary
using SimpleRemotingLibrary;

namespace SimpleServer
{

    public class RemoteServer : MarshalByRefObject
    {
        [STAThread]
        public static void Main(string[] args)
        {
            TcpChannel channel = new TcpChannel(4000);
            ChannelServices.RegisterChannel(channel);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(HelloDescendant),
                “HelloDotNet”,
                WellKnownObjectMode.Singleton);
            System.Console.WriteLine(“Hit <enter> to exit…”);
            System.Console.ReadLine();
        }
    }
    /// <summary>
    /// This is one technique where you can distribute a common base class
    /// and only implement the details in the server object.
    /// </summary>
    class HelloDescendant : RemoteHello
    {
        private static string msg = “This is a descendant”;
        public override string SayHello()
        {
            Console.WriteLine(HelloDescendant.msg);
            return msg;
        }   
    }

}

// Client – this is unchanged
//  HelloClient.cs
using System;

// Add a reference to System.Runtime.Remoting
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
// Add a reference to SimpleRemotingLibrary
using SimpleRemotingLibrary;

class RemoteClient
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            TcpChannel channel = new TcpChannel();
            ChannelServices.RegisterChannel(channel);

            RemoteHello h = (RemoteHello) Activator.GetObject(typeof(RemoteHello),
                “tcp://127.0.0.1:4000/HelloDotNet”);
            System.Console.WriteLine( h.SayHello() );
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        System.Console.ReadLine();

    }
}

Minimal Remoting sample that works in the VS.NET IDE

This is a small sample app that actually works in the VS.NET IDE.

This is in three parts:

One common library to implement the remoting object,
One server and one client.

Common library (simple library project):

// SimpleRemoting.cs

using System;
using System.Runtime.Remoting;

// Add a reference to System.Runtime.Remoting
namespace SimpleRemotingLibrary
{
    /// <summary>
    /// This is a common object for the remoting
    /// </summary>
    public class RemoteHello  : MarshalByRefObject
    {
        static string msg = “Hello, Universe of .NET”;
        public string SayHello()
        {
            Console.WriteLine(RemoteHello.msg);
            return msg;
        }   
    }
}

// HelloServer.cs

using System;

// Add a reference to System.Runtime.Remoting
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
// Add a reference to SimpleRemotingLibrary
using SimpleRemotingLibrary;

public class RemoteServer : MarshalByRefObject
{
    [STAThread]
    public static void Main(string[] args)
    {
        TcpChannel channel = new TcpChannel(4000);
        ChannelServices.RegisterChannel(channel);
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteHello),
                                                            “HelloDotNet”,
                                                            WellKnownObjectMode.Singleton);
        System.Console.WriteLine(“Hit <enter> to exit…”);
        System.Console.ReadLine();
    }

}

// HelloClient.cs

using System;

// Add a reference to System.Runtime.Remoting
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
// Add a reference to SimpleRemotingLibrary
using SimpleRemotingLibrary;

class RemoteClient
{
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            TcpChannel channel = new TcpChannel();
            ChannelServices.RegisterChannel(channel);

            RemoteHello h = (RemoteHello) Activator.GetObject(typeof(RemoteHello),
                “tcp://127.0.0.1:4000/HelloDotNet”);
            System.Console.WriteLine( h.SayHello() );
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        System.Console.ReadLine();

    }
}

You need to start the server first…

Dot Net Rocks Answers

I have been listening my way through the back catalog of Dot Net Rocks.
There have been some reoccouring questions:

How do I move a web service
How do I keep my code updated with respect to changes in my database structure.

There stock answers are:

You should never need to move a web service.
You should design your database up-front so it should not need to change.

These are grossly simplified. I have encountered a case where a website had to move due to legal questions about the name – the site had been located where it was for a year. Web services can and will suffer the same fate.

Database structures will change. We had to add an entire subsystem to the product that we are working on to support one line in the requirements. Change happens. The trick is to use tools that minimise that change. That can mean restricting the use of strongly typed datasets.

Guys please think about your snappy answers.