Tuesday, August 30, 2011

Hansen8 Developers Group Meeting VI

WCF

Pradeep presented WCF and it's ability to, via configuration alone, communicate using different bindings using endpoints. He demonstrated self-hosted and IIS-hosted services. He also demonstrating calling the same method using multiple bindings from the WCF Test Client.

The meeting got interesting when Russell asked Pradeep to create a method which accepts one int parameter and load it as a Web Service. Here is what we learned.

First, create a new "WCF Service Application" it will generate this code for you:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Now add a new Console Project to this solution and add this service as a Web Reference and look at the implementation of the GetData proxy:
       [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/IService1/GetData", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        [return: System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
        public string GetData(int value, [System.Xml.Serialization.XmlIgnoreAttribute()] bool valueSpecified) {
            object[] results = this.Invoke("GetData", new object[] {
                        value,
                        valueSpecified});
            return ((string)(results[0]));
        }

And it only gets worse. Notice the return is decorated with IsNullable=true so let's modify the return type to be a non-nullable type:

        public int GetData(int value)
        {
            return value + 1;
        }

And regenerate the proxy. Now the implementation of GetData has moved the return value into two out parameters:

        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
          "http://tempuri.org/IService1/GetData", 
          RequestNamespace="http://tempuri.org/", 
          ResponseNamespace="http://tempuri.org/", 
          Use=Description.SoapBindingUse.Literal,
          ParameterStyle=Protocols.SoapParameterStyle.Wrapped)]
        public void GetData(
          int value, 
          [XmlIgnoreAttribute()] bool valueSpecified, 
          out int GetDataResult, 
          [XmlIgnoreAttribute()] out bool GetDataResultSpecified) {
            object[] results = this.Invoke("GetData", new object[] {
                        value,
                        valueSpecified});
            GetDataResult = ((int)(results[0]));
            GetDataResultSpecified = ((bool)(results[1]));
        }

So now you are force to write code like this:

            int result;
            bool hasResult;
            test.GetData(
                value: 1,
                valueSpecified: false,
                GetDataResult: out result,
                GetDataResultSpecified: out hasResult
                );

I would have assumed that in the above code, where the value:1 is not actually provided (because valueSpecified:false) that this would throw an exception on the server. But instead of a fault it assumes a value of 0! So how do we make it default to a 10?

Obviously what is missing here is the ability to mark method parameters as *optional* to complement the feature of marking a field or property as required. And of course the C# language has syntax for that already:

        public int GetData(int value = 10) // does not work
        {
            return value;
        }

But don't count on this optional parameter defaulting to 10 because if valueSpecified is false it will get 0.

I went out in search of an explanation to this lunacy but only found this forum post dating back to August 24, 2006 with no solution in sight.

Best practices dictate the use of a composite type so all service methods accept one parameter and return one result. It's possible to decorate fields of a composite type as required using [DataMember(IsRequired=true)] but the same is not true for method parameters.

WCF and Microsoft are not perfect...I just wish I understood what they were thinking.

Back to Pradeep's presentation, here is is configuration which contains endpoints for the following bindings:
  • wsHttpBinding
  • mexHttpBinding
  • basicHttpBinding
  • netTcpBinding
  • netNamedPipeBinding

He did not discuss nor am I familiar with the purpose of certificateReference .

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.web>
  <compilation debug="true" />
 </system.web>
 <!-- When deploying the service library project, the content of the config file must be added to the host's
 app.config file. System.Configuration does not support config files for libraries. -->
 <system.serviceModel>
  <services>
   <service behaviorConfiguration="EvalServiceLibrary.Service1Behavior"
    name="EvalServiceLibrary.EvalService">
    <clear />
    <endpoint address="ws" binding="wsHttpBinding" name="wsHttp"
     contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" name="Mex" contract="IMetadataExchange"
     listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="basic" binding="basicHttpBinding" name="basicHttp"
     contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="net.tcp://localhost:8888/EvalService" binding="netTcpBinding"
     name="netTCP" contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="net.pipe://localhost/EvalService" binding="netNamedPipeBinding"
     bindingConfiguration="" name="pipe" contract="EvalServiceLibrary.IEvalService" />
    <host>
     <baseAddresses>
      <add baseAddress="http://localhost:8080/EvalService" />
     </baseAddresses>
    </host>
   </service>
  </services>
  <behaviors>
   <serviceBehaviors>
    <behavior name="EvalServiceLibrary.Service1Behavior">
     <!-- To avoid disclosing metadata information,
     set the value below to false and remove the metadata endpoint above before deployment -->
     <serviceMetadata httpGetEnabled="True"/>
     <!-- To receive exception details in faults for debugging purposes,
     set the value below to true. Set to false before deployment
     to avoid disclosing exception information -->
     <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
 </system.serviceModel>
</configuration>

Friday, August 26, 2011

Browser Based Windows Manager

Managing Parent-Child relationships among Browser Windows


The following code demonstrates how to manage the parent-child relationship among browser windows in a way that does not result in accessing properties on closed windows by managing a global list of windows. Features include:

  • Close child windows
  • Alerts in child, parent, root windows
  • Close all windows




window.privateLab = {
    alert: function (msg) {
        window.alert(msg);
    },
    alertParent: function (msg) {
        if (window.opener) window.opener.alert(msg);
    },
    alertRoot: function (msg) {
        globalLab.alert(msg);
    },
    injectText: function (container, text) {
        window.globalLab.injectText(window.document, container, text);
    },
    closeAll: function () {
        window.globalLab.closeAll(null);
    },
    closeChildren: function () {
        window.globalLab.closeAll(window);
    },
    createTopWindow: function (url) {
        return window.globalLab.createWindow(null, url);
    },
    createChildWindow: function (url) {
        return window.globalLab.createWindow(window, url);
    }
};

window.onunload = function () {
    window.globalLab.removeWindow(window);
    window.globalLab.closeAll(window);
};

if (window.opener) {
    window.globalLab = window.opener.globalLab;
} else {
    window.onbeforeunload = function () {
        var children = window.globalLab.getWindows();
        if (children.length) {
            window.globalLab.closeAll(window);
            return "You will lose globalLab!";
        }
    };
    window.globalLab = {
        count: 0,
        windows: {},
        createWindow: function (parent, url) {
            var count, w, windows;
            parent = parent || window;
            url = url || "WindowLab.htm";
            windows = this.windows;
            var id = "WindowLabChildWindow" + ++this.count;
            w = parent.open(url, id, true);
            windows[id] = w;
            return w;
        },
        removeWindow: function (child) {
            if (!child) return;
            delete this.windows[child.name];
        },
        alert: function (msg) {
            window.alert(msg);
        },
        getWindows: function (parent) {
            var result, windows;
            parent = parent || window;
            windows = this.windows;
            result = [];
            for (var name in windows) {
                if (windows.hasOwnProperty(name)) {
                    w = windows[name];
                    if (!w.closed && w.opener == parent) {
                        result.push(w);
                    }
                }
            }
            return result;
        },
        closeAll: function (parent) {
            var w, i, windows;
            parent = parent || window;
            w = this.getWindows(parent);
            for (i = 0; i < w.length; i++) {
                w[i].close();
            }
        }
    };
}

Tuesday, August 23, 2011

HANGMAN and Regex


Kind of childish but I got home and started looking at 8080 emulators because Daniel, my new colleague and friend, is excited about writing one. Somehow that degraded into playing Hangman. I thought I had the game beat with a few regex and LinqPad but I was mistaken!


Hansen8 Developers Group Meeting V

IIS Express 7.5

Daniel did a fantastic job giving a brief and convincing argument for IIS Express. IIS Express 7.5 replaces Cassini and enables edit-and-continue in an IIS environment.

You can download it here.

He put a nice Power Point presentation together explaining the Benefits, Requirements and specific setup instructions for our Hansen product. I uploaded it here.

He also briefly discussed the Visual Studio Browser Switcher Toolbar, found here, to allow switching browsers without having to right-click the file and select Browser With...

He hinted about a WebMatrix but unfortunately didn't get into any details!

Tuesday, August 16, 2011

Hansen8 Developers Group Meeting IV

Microsoft Enterprise Library


Raja introduced us to Microsoft Enterprise Library via five examples:

  1. Dependency Injection
  2. Exception Handling
  3. Logging
  4. Caching
  5. Validation

To me, the best part was that the app.config file can be edited visually making it a straightforward matter to modify logging, exception handling and validation rules. Russell pointed out that this is an example of Aspect Oriented Programming which allows for the separation of cross-cutting concerns.
Dependency Injection was demonstrated via a UnityContainer which acts as a sort of factory to produce an instance of RateTable containing a strategy:

        using (IUnityContainer container = new UnityContainer())
        {
            container.LoadConfiguration();
            var rt = container.Resolve(); 
            rt.Calculate();
        }

The specific strategy is specified in the app.config:

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <container>
      <register type="IRateAlgorithm" mapTo="FlatRate"/>
    </container>
  </unity>

Exception Handling requires an ExceptionManager instance:

    exManager = EnterpriseLibraryContainer.Current.GetInstance();
    catch ( Exception e) exManager.HandleException(e, "BillRun"); 
Without the Enterprise Library Configuration Editor installed on my machine it's difficult to describe the app.config, but essentially it maps "BillRun" exceptions (a policy) through a exception type to an exception handler allowing logging, substitution and custom handling of the exception.

Logging is very similar to exceptions. A LogWriter instance is required. Also, a LogEntry object further clarifies the message category:

	private LogWriter writer = EnterpriseLibraryContainer.Current.GetInstance();
	public void DoLogging()
	{
	    LogEntry log = new LogEntry();
	    log.Message = "Delinquency Run Starting....";
	    log.Categories.Add(Category.General);
	    log.Categories.Add(Category.BillRun);
	    log.Priority = Priority.Normal;
	    writer.Write(log);
	}

Caching contains too much code...skipping

Validation requires a ValidatorFactory to create a specific validator:

  valFactory = EnterpriseLibraryContainer.Current.GetInstance();
  customerValidator = valFactory.CreateValidator();

Validation and ValidationResult:

	ValidationResults results = customerValidator.Validate(customer);
	if (!results.IsValid)
	{
		StringBuilder builder = new StringBuilder();
		builder.AppendLine("Customer is not valid:");
		foreach (ValidationResult result in results)
		{
			//do stuff
		}
	}
At a minimum using Microsoft.Practices.EnterpriseLibrary give guidance for basic coding practices.

Thursday, August 11, 2011

Microsoft Web Services, Java Client

Microsoft .asmx?wsdl produces valid WSDL that Java cannot consume. In fact Java produces valid WSDL that Java cannot consume.

Specifically, the Java stub generators (WSDL2Java, JAXWS, etc.) cannot handle method overloading. I have found through trial-and-error that to resolve this you must give the <operation@name> unique values. This involves changing them in both the <porttype> and <binding>.

For example, given this:

<operation name='LoadByKey'>
<input name='LoadByKeySoapIn' />
<output name='LoadByKeySoapOut' />
</operation>

<operation name='LoadByKey'>
<input name='LoadByKey1SoapIn' />
<output name='LoadByKey1SoapOut' />
</operation>

You would need to rename the second operation 'LoadByKey1'. These same <porttype>/<operation> names are found in each <binding>/<operation> and therefore the <operation@name> must change there as well:

<operation name='LoadByKey1'>
<input name='LoadByKey1SoapIn' />
<output name='LoadByKey1SoapOut' />
</operation>

Hansen8 Developers Group Meeting III

Microsoft Kinect

Laszlo took the initiative to get an exciting opportunity to play with the the Kinect. There seems to be no shortage of gesture-based coding going on and Gesture Recognition gets simplified thanks to the Kinect SDK.

Laszlo quickly introduced the Kinect and it's infra-red projector and camera as well as the fact that it was extremely easy to register for data-ready notifications. Depth and vector data is provided at intervals.

He went on vacation before I asked him for code-level details so I had a look at another project for details.

Setup the runtime:
r = new Nui.Runtime()

Register callbacks:

r.DepthFrameReady += DepthFrameReady
r.SkeletonFrameReady += SkeletonFrameReady


Ask for notification:

r.Initialize(UseDepth | UseSkeletalTracking)


Laszlo then demonstrated the limitations of the device (800mm to 4096mm) as well as the limits of the devices (it's not a mouse!).

He is working on a trial-and-error basis to discover what gestures work. He created a pluggable design to switch experiments quickly. He was surprised to discover that some worked better in the large conference room and some worked worse in the visually noisy environment.

He demonstrated navigating a cursor within a box and clicking that box. Beyond that he didn't dream much in the meeting but I did...I'd like to know some wood-chopping stats:
  • How much wood did I chop?
  • How many chops before it split?
  • How long between chops?
But I suspect the wood chips would become the new "bugs".

My take-away was the Kinect as-is cannot replace the mouse or voice but it makes a lot of sense as a gaming device and maybe Laszlo will figure out how to make it reliably click a button.