Sunday, July 13, 2014

Javascript Input Mask jQuery Plugin

Below is a jQuery plugin that can easily be adapted to mask or limit keystrokes while you type in a textbox. This script blocks invalid keystrokes from being processed. It seems to work reliably in all modern browsers except Chrome for Android (Chrome for Android doesn't seem to fully support the keydown/keypress events). The example below only allows a valid currency value.

Credit: the caret function was borrowed from Masked Input Plugin.

Usage

$(document).ready(function()
{
 $('#text').currencyMask();
});

Code

$.fn.currencyMask = function(options)
{
    options = options || {};
    options.valid = function(s) { return s.match(/^\-?\d{0,7}(:?\.\d{0,2})?$/); };
    return this.inputMask(options);
}

$.fn.inputMask = function(options)
{
 if (this.length == 0)
        return;
 
 return this.each(function()
 {
  $(this).keydown(function(e)
  {
   if (e.which == 8 || e.which == 46) //backspace or delete?
    filter(this, false, e);
  });
  
  $(this).keypress(function(e)
  {
   if (e.which != 0 && e.which != 8) //is it printable?
    filter(this, true, e);
  });
  
  $(this).bind('paste cut blur', function(e)
  {
   setTimeout($.proxy(function()
   {
    if (!options.valid($(this).val()))
     $(this).val('');
   }, $(this)), 0);
  });
 });
 
 function filter(element, press, e)
 {
  if (!e.ctrlKey && !e.altKey && !e.metaKey)
  {
   var caret = $(element).caret();
   var begin = caret.begin;
   var end = caret.end;
   var val = $(element).val();
   var src = String.fromCharCode(e.which);
   var result = val;
   
   if (!press && e.which == 8) //backspace
   {
    begin = begin != end ? begin : Math.max(begin - 1, 0);
    result = val.substring(0, begin) + val.substring(end);
   }
   else if (!press && e.which == 46) //delete
   {
    end = begin != end ? end : Math.min(end + 1, val.length);
    result = val.substring(0, begin) + val.substring(end);
   }
   else if (press) //printable
   {
    result = val.substring(0, begin) + src + val.substring(end);
   }
   
   if (!options.valid(result))
   {
    e.preventDefault();
   }
  }
 }
};

$.fn.caret = function()
{
    if (this.length == 0)
        return;
    
 var begin = 0, end = 0;
    var item = this[0];
    
 item.focus();
    if (item.setSelectionRange)
 {
        begin = item.selectionStart;
        end = item.selectionEnd;
    }
 else if (document.selection && document.selection.createRange)
 {
        var range = document.selection.createRange();
        begin = 0 - range.duplicate().moveStart('character', -100000);
        end = begin + range.text.length;
    }
    return { begin: begin, end: end };
}

Android Fragment Replace vs. Remove+Add and the Backstack

The Android documentation has this to say about FragmentTransaction.replace:

Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

I found the documentation to be slightly misleading because there is an important difference between replace vs. remove+add when the backstack is involved:

  1. If the backstack A->B->C is built using remove+add, then popped back to fragment A, then fragment B's onResume method will be triggered.
  2. If the backstack A->B->C is build using replace, then popped back to fragment A, then fragment B's onResume method will NOT be triggered.

Android Drawable Cache (Xamarin / Mono)

The code below is useful if you need to cache images in Android. Weak references are used to help protect against memory leaks.

Drawable Cache Class:
public class DrawableCache
{
 public Context Context { get; set; }
 Dictionary<object, WeakReference<Drawable.ConstantState>> _cache = new Dictionary<object, WeakReference<Drawable.ConstantState>>();

 public DrawableCache(Context context)
 {
  Context = context;
 }

 public void Put(object key, Drawable drawable)
 {
  _cache[key] = new WeakReference<Drawable.ConstantState>(drawable.GetConstantState(), false);
 }

 public Drawable Get(object key)
 {
  WeakReference<Drawable.ConstantState> value;
  if (_cache.TryGetValue(key, out value))
  {
   Drawable.ConstantState target;
   if (value.TryGetTarget(out target))
   {
    return target.NewDrawable(Context.Resources);
   }
   _cache.Remove(key);
  }
  return null;
 }
}
Optional Drawable Cache Key class
public class DrawableCacheKey
{
 public int Key { get; set; }
 public int Flags { get; set; }

 public DrawableCacheKey(int key, int flags)
 {
  Key = key;
  Flags = flags;
 }

 public override int GetHashCode()
 {
  int hash = 17;
  hash = hash * 23 + Key.GetHashCode();
  hash = hash * 23 + Flags.GetHashCode();
  return hash;
 }

 public override bool Equals(object obj)
 {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  var cast = obj as DrawableCacheKey;
  return cast != null && Key == cast.Key && Flags == cast.Flags;
 }
}

Sunday, January 5, 2014

Simple C# Artificial Neural Network

Artificial intelligence interests me, especially when modeled from or inspired by biology. Artificial neural networks are one such example:

"Artificial neural networks are computational models inspired by animals' central nervous systems (in particular the brain) that are capable of machine learning and pattern recognition. They are usually presented as systems of interconnected "neurons" that can compute values from inputs by feeding information through the network." - Wikipedia

I'm not going to try explain how artificial neural networks work. The topic is much too complex and there is already good documentation available elsewhere. If you are interested in learning more about artificial neural networks then I recommend the following article: Neural Network Back-Propagation Using C#. Most of the code in this post is based on the ideas presented in that article.

There are many different types of artificial neural networks. My implementation is a feed-forward, multi-layer, perceptron network which uses the back-propagation algorithm for learning. I believe this is one of the most common types of neural networks and is a good place to start for beginners. I'm still a beginner myself; I understand the basic concepts but the math is still slightly mysterious. Hopefully I can find time in the future to learn more about neural networks and artificial intelligence.

I tried to make the code as simple as possible. Code is below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NeuralNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
            var network = new NeuralNetwork(2, 3, 1);

            Console.WriteLine("Training Network...");
            for (int i = 0; i < 100000; i++)
            {
                network.Train(0, 0);
                network.BackPropagate(1);

                network.Train(1, 0);
                network.BackPropagate(0);

                network.Train(0, 1);
                network.BackPropagate(0);

                network.Train(1, 1);
                network.BackPropagate(1);
            }

            double error;
            double output;

            output = network.Compute(0, 0)[0];
            error = network.CalculateError(1);
            Console.WriteLine("0 XOR 0 = " + output.ToString("F5") + ", Error = " + error.ToString("F5"));

            output = network.Compute(1, 0)[0];
            error = network.CalculateError(0);
            Console.WriteLine("1 XOR 0 = " + output.ToString("F5") + ", Error = " + error.ToString("F5"));

            output = network.Compute(0, 1)[0];
            error = network.CalculateError(0);
            Console.WriteLine("0 XOR 1 = " + output.ToString("F5") + ", Error = " + error.ToString("F5"));

            output = network.Compute(1, 1)[0];
            error = network.CalculateError(1);
            Console.WriteLine("1 XOR 1 = " + output.ToString("F5") + ", Error = " + error.ToString("F5"));
        }
    }

    public class NeuralNetwork
    {
        public double LearnRate { get; set; }
        public double Momentum { get; set; }
        public List<Neuron> InputLayer { get; set; }
        public List<Neuron> HiddenLayer { get; set; }
        public List<Neuron> OutputLayer { get; set; }
        static Random random = new Random();

        public NeuralNetwork(int inputSize, int hiddenSize, int outputSize)
        {
            LearnRate = .9;
            Momentum = .04;
            InputLayer = new List<Neuron>();
            HiddenLayer = new List<Neuron>();
            OutputLayer = new List<Neuron>();

            for (int i = 0; i < inputSize; i++)
                InputLayer.Add(new Neuron());

            for (int i = 0; i < hiddenSize; i++)
                HiddenLayer.Add(new Neuron(InputLayer));

            for (int i = 0; i < outputSize; i++)
                OutputLayer.Add(new Neuron(HiddenLayer));
        }

        public void Train(params double[] inputs)
        {
            int i = 0;
            InputLayer.ForEach(a => a.Value = inputs[i++]);
            HiddenLayer.ForEach(a => a.CalculateValue());
            OutputLayer.ForEach(a => a.CalculateValue());
        }

        public double[] Compute(params double[] inputs)
        {
            Train(inputs);
            return OutputLayer.Select(a => a.Value).ToArray();
        }

        public double CalculateError(params double[] targets)
        {
            int i = 0;
            return OutputLayer.Sum(a => Math.Abs(a.CalculateError(targets[i++])));
        }

        public void BackPropagate(params double[] targets)
        {
            int i = 0;
            OutputLayer.ForEach(a => a.CalculateGradient(targets[i++]));
            HiddenLayer.ForEach(a => a.CalculateGradient());
            HiddenLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
            OutputLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
        }

        public static double NextRandom()
        {
            return 2 * random.NextDouble() - 1;
        }

        public static double SigmoidFunction(double x)
        {
            if (x < -45.0) return 0.0;
            else if (x > 45.0) return 1.0;
            return 1.0 / (1.0 + Math.Exp(-x));
        }

        public static double SigmoidDerivative(double f)
        {
            return f * (1 - f);
        }
    }

    public class Neuron
    {
        public List<Synapse> InputSynapses { get; set; }
        public List<Synapse> OutputSynapses { get; set; }
        public double Bias { get; set; }
        public double BiasDelta { get; set; }
        public double Gradient { get; set; }
        public double Value { get; set; }

        public Neuron()
        {
            InputSynapses = new List<Synapse>();
            OutputSynapses = new List<Synapse>();
            Bias = NeuralNetwork.NextRandom();
        }

        public Neuron(List<Neuron> inputNeurons) : this()
        {
            foreach (var inputNeuron in inputNeurons)
            {
                var synapse = new Synapse(inputNeuron, this);
                inputNeuron.OutputSynapses.Add(synapse);
                InputSynapses.Add(synapse);
            }
        }

        public virtual double CalculateValue()
        {
            return Value = NeuralNetwork.SigmoidFunction(InputSynapses.Sum(a => a.Weight * a.InputNeuron.Value) + Bias);
        }

        public virtual double CalculateDerivative()
        {
            return NeuralNetwork.SigmoidDerivative(Value);
        }

        public double CalculateError(double target)
        {
            return target - Value;
        }

        public double CalculateGradient(double target)
        {
            return Gradient = CalculateError(target) * CalculateDerivative();
        }

        public double CalculateGradient()
        {
            return Gradient = OutputSynapses.Sum(a => a.OutputNeuron.Gradient * a.Weight) * CalculateDerivative();
        }

        public void UpdateWeights(double learnRate, double momentum)
        {
            var prevDelta = BiasDelta;
            BiasDelta = learnRate * Gradient; // * 1
            Bias += BiasDelta + momentum * prevDelta;

            foreach (var s in InputSynapses)
            {
                prevDelta = s.WeightDelta;
                s.WeightDelta = learnRate * Gradient * s.InputNeuron.Value;
                s.Weight += s.WeightDelta + momentum * prevDelta;
            }
        }
    }

    public class Synapse
    {
        public Neuron InputNeuron { get; set; }
        public Neuron OutputNeuron { get; set; }
        public double Weight { get; set; }
        public double WeightDelta { get; set; }
        
        public Synapse(Neuron inputNeuron, Neuron outputNeuron)
        {
            InputNeuron = inputNeuron;
            OutputNeuron = outputNeuron;
            Weight = NeuralNetwork.NextRandom();
        }
    }
}

Saturday, October 26, 2013

UDP Proxy / Minecraft PE Proxy

Here is a UDP Proxy implemented in Java that can be used for Minecraft Pocket Edition. Inspired by the Node.js implementation. Runs great on Raspberry Pi.
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class UdpProxy
{
 public static void main(String[] args) throws Exception
 {
  boolean testMode = args.length == 0;
  String serverHost;
  int serverPort;
  int proxyPort;

  if (args.length != 3 && !testMode)
  {
   System.out.println("Use: java UdpProxy <serverhost> <serverport> <proxyport>");
   return;
  }

  if (!testMode)
  {
   serverHost = args[0];
   serverPort = Integer.parseInt(args[1]);
   proxyPort = Integer.parseInt(args[2]);
  }
  else
  {
   serverHost = "192.168.1.114";
   serverPort = 19132;
   proxyPort = 19133;
  }

  new UdpProxy(serverHost, serverPort, proxyPort).runServer();
 }
 
 static final int CONNECTION_TIMEOUT = 60000;
 HashMap<InetSocketAddress, ChannelInfo> channelMap = new HashMap<InetSocketAddress, ChannelInfo>();
 InetSocketAddress serverAddress;
 int proxyPort;

 public UdpProxy(String serverHost, int serverPort, int proxyPort) throws Exception
 {
  InetAddress resolvedAddress = InetAddress.getByName(serverHost);
  this.serverAddress = new InetSocketAddress(resolvedAddress, serverPort);
  this.proxyPort = proxyPort;
 }

 public void runServer() throws Exception
 {
  System.out.println("Listening on " + proxyPort + ", forwarding to " + serverAddress);

  ByteBuffer buff = ByteBuffer.allocate(1024*1024); //this is probably more than necessary
  Selector selector = Selector.open();
  DatagramChannel proxyChannel = addChannel(selector, proxyPort);
  long connectionTestTime = System.currentTimeMillis();
  
  while (true)
  {
   try
   {
    selector.select(10000); //selector.selectNow();
    Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
    
    while (keyIterator.hasNext())
    {
     SelectionKey key = keyIterator.next();
     keyIterator.remove();
     
     if (key.isReadable())
     {
      DatagramChannel currentChannel = (DatagramChannel) key.channel();
      InetSocketAddress localAddress = (InetSocketAddress) currentChannel.socket().getLocalSocketAddress();
      buff.clear();
      InetSocketAddress remoteAddress = (InetSocketAddress) currentChannel.receive(buff);
      buff.flip();
      
      if (!fromServer(remoteAddress))
      {
       ChannelInfo info = channelMap.get(remoteAddress);
       if (info == null)
       {
        DatagramChannel tempChannel = addChannel(selector, serverAddress);
        InetSocketAddress tempAddress = (InetSocketAddress) tempChannel.socket().getLocalSocketAddress();
        info = new ChannelInfo(tempChannel, remoteAddress);
        channelMap.put(remoteAddress, info);
        System.out.println("Added key = " + remoteAddress.toString());
        channelMap.put(tempAddress, info);
        System.out.println("Added key = " + tempAddress.toString());
       }
       
       info.rxTime = System.currentTimeMillis();
       info.channel.send(buff, serverAddress);
      }
      else
      {
       ChannelInfo info = channelMap.get(localAddress);
       if (info != null)
       {
        proxyChannel.send(buff, info.remoteAddress);
       }
      }
     }
    }
    
    //Test & remove old connections
    if (System.currentTimeMillis() - connectionTestTime >= CONNECTION_TIMEOUT)
    {
     connectionTestTime = System.currentTimeMillis();
     Iterator<Map.Entry<InetSocketAddress, ChannelInfo>> entryIterator = channelMap.entrySet().iterator();
     while (entryIterator.hasNext())
     {
      Map.Entry<InetSocketAddress, ChannelInfo> entry = entryIterator.next();
      InetSocketAddress address = entry.getKey();
      ChannelInfo info = entry.getValue();
      if (connectionTestTime - info.rxTime >= CONNECTION_TIMEOUT)
      {
       info.channel.close();
       entryIterator.remove();
       System.out.println("Removed key = " + address.toString());
      }
     }
    }
   }
   catch (Exception ex)
   {
    ex.printStackTrace();
   }
  }
 }
 
 public boolean fromServer(InetSocketAddress address)
 {
  return address.getAddress().equals(serverAddress.getAddress());
 }

 public DatagramChannel addChannel(Selector selector, int bindPort) throws Exception
 {
  DatagramChannel channel = DatagramChannel.open();
  channel.configureBlocking(false);
  channel.socket().bind(new InetSocketAddress(bindPort));
  channel.register(selector, SelectionKey.OP_READ);
  return channel;
 }

 public DatagramChannel addChannel(Selector selector, InetSocketAddress address) throws Exception
 {
  DatagramChannel channel = DatagramChannel.open();
  channel.configureBlocking(false);
  channel.connect(address);
  channel.register(selector, SelectionKey.OP_READ);
  return channel;
 }

 public static class ChannelInfo
 {
  public ChannelInfo()
  {
  }

  public ChannelInfo(DatagramChannel channel, InetSocketAddress remoteAddress)
  {
   this.channel = channel;
   this.localAddress = (InetSocketAddress) channel.socket().getLocalSocketAddress();
   this.remoteAddress = remoteAddress;
  }

  DatagramChannel channel;
  InetSocketAddress localAddress;
  InetSocketAddress remoteAddress;
  long rxTime;
 }
}

Saturday, March 23, 2013

Show / Hide Android Soft Keyboard

Here is a helpful utility class for showing and hiding the Android soft keyboard. The code is written in C# using Mono for Android but should be easy to convert to Java. Similar behavior can be accomplished using Window.SetSoftInputMode but unfortunately SetSoftInputMode doesn't always play well with a tab / fragment architecture.

This code is my attempt to simplify the process of manually showing and hiding of the soft keyboard, which is much more complicated than it has a right to be (I blame vague documentation). My earlier attempts to accomplish this were laden with frustrating bugs and strange side-effects. Now, (hopefully) all those bugs and side-effects have been corrected.

By default there is a 200 millisecond delay on the ShowSoftKeyboard method; this is to accommodate any fragment transition animations that may occur. Showing the keyboard while running an animation can result in poor performance so the workaround is to wait until the animation is finished. If you are not using fragment transition animations then the delay can be eliminated.

*Code has been tested on a handful of real devices as well as a wide range of emulator versions (2.2+).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Views.InputMethods;
using Android.InputMethodServices;
using Android.Util;

namespace Mobile.Util
{
    public static class ActivityExtensions
    {
        public static void HideSoftKeyboard(this Activity activity)
        {
            new Handler().Post(delegate
            {
                var view = activity.CurrentFocus;
                if (view != null)
                {
                    InputMethodManager manager = (InputMethodManager)activity.GetSystemService(Context.InputMethodService);
                    manager.HideSoftInputFromWindow(view.WindowToken, 0);
                }
            });
        }

        public static void ShowSoftKeyboard(this Activity activity, View view = null, int delay = 200)
        {
            new Handler().PostDelayed(delegate
            {
                view = view ?? activity.CurrentFocus;
                if (view != null)
                {
                    if (view.HasFocus)
                        view.ClearFocus(); //bug fix for older versions of android

                    view.RequestFocus();
                    InputMethodManager manager = (InputMethodManager)activity.GetSystemService(Context.InputMethodService);
                    manager.ShowSoftInput(view, 0);
                }
            }, delay);
        }
    }

    public static class DialogExtensions
    {
        public static void HideSoftKeyboard(this Dialog dialog)
        {
            new Handler().Post(delegate
            {
                var view = dialog.CurrentFocus;
                if (view != null)
                {
                    InputMethodManager manager = (InputMethodManager)dialog.Context.GetSystemService(Context.InputMethodService);
                    manager.HideSoftInputFromWindow(view.WindowToken, 0);
                }
            });
        }

        public static void ShowSoftKeyboard(this Dialog dialog, View view = null, int delay = 200)
        {
            new Handler().PostDelayed(delegate
            {
                view = view ?? dialog.CurrentFocus;
                if (view != null)
                {
                    if (view.HasFocus)
                        view.ClearFocus(); //bug fix for older versions of android

                    view.RequestFocus();
                    InputMethodManager manager = (InputMethodManager)dialog.Context.GetSystemService(Context.InputMethodService);
                    manager.ShowSoftInput(view, 0);
                }
            }, delay);
        }     
    }
}

Friday, February 22, 2013

Raspberry Pi

My Raspberry Pi arrived in the mail today. These things are great and only cost about $35-$40. Lots of fun.

Raspberry Pi Model B

Wednesday, July 25, 2012

Mono for Android Resource Naming Convention

When you create a default Mono for Android project the included resource files are named using a mixture of uppercase and lowercase letters. Please, do NOT follow this naming convention because this is the cause of a variety of unresolved, mostly minor bugs. Instead name all your resource files using all lowercase letters and underscores. It is much safer to follow this practice as opposed to the one presented by Xamarin.

Wednesday, July 11, 2012

ActionBarSherlock with Mono for Android

3/7/2013 - I updated the blog post so everything should be current and relevant as of today. This was long overdue, sorry.

For instant gratification try downloading the Xamarin sample project. However this will most likely yield an outdated version of the ActionBarSherlock library.

Today I will explain how to bind the ActionBarSherlock Java library so that it can be used with Mono for Android. ActionBar compatibility is important since over 90% of Android users are still running a pre 3.0 platform. It's a luxury Java programmers have enjoyed for awhile now, which can finally be shared with fellow C# programmers.

The required steps are listed below:

Build the ActionBarSherlock Zip

  1. First, if necessary, download and install the latest version of Eclipse along with the ADT Plugin.
  2. Next, download the latest version of ActionBarSherlock. After the download finishes extract the library folder from archive.
  3. Rename the library folder to actionbarsherlock. In this tutorial, the library folder has been renamed/moved to c:\downloads\actionbarsherlock.
  4. Start Eclipse and create a new workspace. In this tutorial, I created a workspace located at c:\projects\actionbarsherlock.
  5. Begin creating a new Android project by clicking File -> New -> Other -> Android -> Android Project From Existing Code. Click Next.
  6. In the "Root Directory" field, browse to c:\downloads\actionbarsherlock. Check the "Copy projects into workspace" field. Click Finish.
  7. Click Project -> Clean and wait for Eclipse to finish building the project. Exit Eclipse after the build is complete. If you encounter any compile errors ensure that you are targetting Java 6+.
  8. Open Windows Explorer, and browse to c:\projects\actionbarsherlock\actionbarsherlock. Select the bin, assets, and res folders and add them to a new Zip file. Name the file actionbarsherlock.zip.
  9. Now browse to c:\projects\actionbarsherlock\actionbarsherlock\libs and locate the file android-support-v4.jar. No action is required yet, but remember this file location for future use.
  10. Later, both the actionbarsherlock.zip and android-support-v4.jar files will be copied into Visual Studio.

Create the Binding Library

  1. Open Visual Studio and create a new JAR Bindings Library project (click File -> New -> Project -> Mono for Android -> Java Bindings Library). Name the project ActionBarSherlockBinding and click OK.
  2. Click Project -> ActionBarSherlockBinding Properties and change the Target API level to 14+.
  3. Add a reference to the Mono.Android.Support.v4 binding library by clicking Project -> Add Reference and switching to the .NET tab. Select the Mono.Android.Support.v4 library and click OK.
  4. Now copy the actionbarsherlock.zip and android-support-v4.jar files (from the previous section) into the Jars folder of the ActionBarSherlockBinding project in Visual Studio.
  5. In the properties pane, right click on the the actionbarsherlock.zip file and change the Build Action to "LibraryProjectZip". Next, right click on the android-support-v4.jar file and change the Build Action to "ReferenceJar".
  6. Open the Metadata.xml file located under the the Transforms folder and replace all of its contents with the XML code below. Save and close the file when finished.
    <metadata>
    
      <!-- Don't bind internal packages/classes -->
      <remove-node path="/api/package[starts-with(@name, 'com.actionbarsherlock.internal')]" />
      
      <!-- Normalize the API, forced to use underscore to avoid name conflicts -->
      <attr path="/api/package[@name='android.support.v4.app']" name="managedName">Android.Support.V4.App</attr>
      <attr path="/api/package[@name='com.actionbarsherlock']" name="managedName">ActionBar_Sherlock</attr>
      <attr path="/api/package[@name='com.actionbarsherlock.app']" name="managedName">ActionBar_Sherlock.App</attr>
      <attr path="/api/package[@name='com.actionbarsherlock.view']" name="managedName">ActionBar_Sherlock.View</attr>
      <attr path="/api/package[@name='com.actionbarsherlock.widget']" name="managedName">ActionBar_Sherlock.Widget</attr>
    
    </metadata>
    
    Note: Additional documentation regarding this step can be found here. Lines 6-11 are trivial but line 4 is important.

  7. Build the solution and verify that there are no errors. There will probably be some warnings but it should still build successfully.

Reference the Binding Library

  1. In Visual Studio, add a new Android Application project to the existing solution (click File -> Add -> New Project -> Mono for Android -> Android Application). Name the project ActionBarSherlockDemo and click OK.
  2. Click Project -> ActionBarSherlockDemo Properties and change the Target API level to 14+.
  3. Add a reference to the binding library by clicking Project -> Add Reference and switching to the Projects tab. Select the ActionBarSherlockBinding project and click OK.
  4. Also add a reference to the Mono.Android.Support.v4 binding library from the .NET tab of the Add Reference dialog.
  5. Rebuild the solution and verify that there are no errors.

Extend the SherlockActivity Class

  1. Open Activity1.cs and change it so that it inherits from the ActionBar_Sherlock.App.SherlockActivity class. Documentation for the ActionBarSherlock library is more or less equivalent to the native ActionBar API.
  2. Items can be added to the ActionBar by creating a menu resource and overriding the OnCreateOptionsMenu method.
  3. Generate the AndroidManifest.xml and then edit it and set the SDK and theme like this:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly">
      <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" />
      <application android:theme="@style/Theme.Sherlock" />
    </manifest>
    
  4. Rebuild the solution, deploy to the emulator or device, and congratulations, you're finished!



By Request - An ActionBar Tab Example

This is a quick and dirty example of ActionBar tabs with Mono for Android using ActionBarSherlock. This code is only intended as a demonstration of basic concepts. Please refer to the official Android ActionBar documentation for best practices and for a more complete example.

using System;

using Android.OS;
using Android.Views;
using ActivityAttribute = Android.App.ActivityAttribute;
using ActionBarNavigationMode = Android.App.ActionBarNavigationMode;
using Android.Support.V4.App;
using ActionBar_Sherlock.App;
using Tab = ActionBar_Sherlock.App.ActionBar.Tab;

namespace ActionBarSherlockDemo
{
    [Activity(Label = "Tab Activity", MainLauncher = true)]
    public class TabActivity : SherlockFragmentActivity, ActionBar_Sherlock.App.ActionBar.ITabListener
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);

            SupportActionBar.NavigationMode = (int)ActionBarNavigationMode.Tabs;
            SupportActionBar.SetDisplayShowTitleEnabled(true);

            Tab tab = SupportActionBar.NewTab();
            tab.SetTag("TAB1");
            tab.SetText("TAB 1");
            tab.SetTabListener(this);
            SupportActionBar.AddTab(tab);
            
            tab = SupportActionBar.NewTab();
            tab.SetTag("TAB2");
            tab.SetText("TAB 2");
            tab.SetTabListener(this);
            SupportActionBar.AddTab(tab);
        }

        public void OnTabSelected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        {
            string tag = tab.Tag.ToString();

            Fragment f = SupportFragmentManager.FindFragmentByTag(tag);
            if (f != null)
            {
                ft.Show(f);
                return;
            }

            if (tag == "TAB1")
                f = new TestFragment1();
            else if (tag == "TAB2")
                f = new TestFragment2();

            ft.Add(Resource.Id.fragmentPlaceholder, f, tag);
        }


        public void OnTabUnselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        {
            string tag = tab.Tag.ToString();

            Fragment f = SupportFragmentManager.FindFragmentByTag(tag);
            if (f != null)
            {
                ft.Hide(f);
                return;
            }
        }

        public void OnTabReselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        {
            //Do nothing
        }
    }

    public class TestFragment1 : Fragment
    {
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle)
        {
            return inflater.Inflate(Resource.Layout.test1, container, false);
        }
    }

    public class TestFragment2 : Fragment
    {
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle)
        {
            return inflater.Inflate(Resource.Layout.test2, container, false);
        }
    }
}

Wednesday, June 13, 2012

ThreadStaticAttribute

Possibly one of the coolest tricks I've learned in awhile, adding the ThreadStaticAttribute to your .NET static field makes it static but only visible or accessible within the context of the current executing thread. So there can be multiple threads executing at the same time, referencing the same thread-static field, but the value returned is potentially different for each individual thread. This allows you to easily share a static value between different classes / methods of a thread while still encapsulating it from other threads. Because of this it is slightly more insulated than a normal static field, and can be useful in some cases where you don't necessarily want to chain-pass an object as a parameter from method to method, especially if the parameter is passed across many different classes with method calls many layers deep.

Perhaps a good use case for the ThreadStaticAttribute is managing database transactions. Often you need to pass the Transaction object between different method calls, and frequently these method calls are divided into different classes. You can declare a separate class that holds a thread-static reference to the current Transaction which eliminates the need to chain pass it as a parameter between the different methods. Of course this is not strictly necessary anymore since the introduction of the TransactionScope class, but guess what, this is basically exactly how the TransactionScope class is implemented - the associated Transaction class maintains a thread-static reference to the current Transaction.

A word of warning though, be careful when using the ThreadStaticAttribute if you are not in complete control of the thread. Examples of potentially dangerous situations are Thread Pools, ASP .NET, and WCF. I'm not saying that you absolutely shouldn't use the ThreadStaticAttribute in these situations, but you need to be knowledgeable about the thread's lifecycle so as to avoid unexpected errors. In cases like these you need to handle when and if the thread is re-used, terminated, or if your code runs on different threads during different phases of its lifecycle. So, if you use the thread-static feature then do so wisely, cautiously, and test thoroughly. It's not a feature you should overuse or abuse, but occasionally it may be a good solution for some niche problem.

Below is an example of actually using the ThreadStaticAttribute:

[ThreadStatic]
private static string foo;

Warning: ThreadStaticAttribute fields are initialized in the static constructor which only executes once. In the example below the variable foo will only be initialized to "TEST" for the first thread, but the value will be null for subsequent threads.

[ThreadStatic]
private static string foo = "TEST";

To work around this problem trying using a property to access and initialize the ThreadStaticAttribute field:

[ThreadStatic]
private static string _foo;

public static string Foo
{
   get
   {
     return _foo ?? "TEST";
   }
}

Note: There's also something new in .NET 4.0 called ThreadLocal, which is similar to ThreadStatic but doesn't require the variable to be static. I may write a separate blog about it sometime in the future.

Links:

Thursday, April 5, 2012

How to Improve SyntaxHighlighter

SyntaxHighlighter is a javascript library that I use on this blog to colorize and display my code snippets. SyntaxHighlighter is a great tool and the author deserves a lot of respect, but the default "select all" and "copy and paste" functionality can be somewhat frustrating. For the last few days I've been troubleshooting various issues with the "select all" and "copy and paste" functionality. Depending on the configuration and the browser, sometimes it copies the text with non-breaking spaces which causes errors in certain IDEs. Other times it copies the text with the wrong indentation or with no line breaks at all.

Even the fact that you can quickly select all of the text is not immediately apparent; SyntaxHighlighter contains a "hidden" feature that allows double clicking the text to select all of it (of course the average user would never know this functionality existed). Finally, when it does select all of the text it copies it from its native, colorized form into a simple, monochrome textarea control that is created dynamically using some javascript magic. The performance can be a little slow, it may cause the view to randomly jump or scroll in Internet Explorer, and the transition just looks a little tacky.

Below is a script you can embed in the header section of your website or blog that will correct some of these problems. It changes the the default behavior of the "select all" operation and it also adds a button to the top-right corner that is clearly labelled "Select All" (you can still double click the text too).

If you use this script for Blogger, be sure to replace any ampersands with &amp; and any less than signs with &lt; and any greater than signs with &gt;. If you don't do this you will get a cryptic error when you try to upload the html. Blogger requires these characters to be escaped since it uses XML.

<!-- jQuery -->
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js' type='text/javascript'></script>

<!-- Syntax Highlighter Additions START -->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeEclipse.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script>

<style>
.syntaxwrapper
{
 position: relative;
}

.syntaxwrapper .toolbar
{
 position: absolute;
 z-index: 10;
 right: -7px;
 top: -17px;
 width: 65px;
 height: 20px;
 line-height: 20px;
 text-align: center; 
 color: #777;
 font-family: arial;
 font-size: 12px;
 cursor: pointer;
}
</style>

<script language='javascript' type='text/javascript'>

 function selectAll(element)
 {
     if (window.getSelection && document.createRange)
     {
         var selection = window.getSelection();
         var range = document.createRange();
         range.selectNodeContents(element);
         selection.removeAllRanges();
         selection.addRange(range);
     }
     else if (document.body.createTextRange)
     {
         var range = document.body.createTextRange();
         range.moveToElementText(element);
         range.select();
     }
 }

 function customizeSyntaxHighlighter()
 {
     var syntax = $('.syntaxhighlighter');
     if (syntax.length == 0)
     {
         setTimeout(function() { customizeSyntaxHighlighter(); }, 100);
         return;
     }

     syntax.each(function(index)
     {
         var selector = $(this);
         var wrapper = $(document.createElement('div')).addClass('syntaxwrapper');
         var toolbar = $(document.createElement('div')).addClass('toolbar').html('Select All');
         var code = selector.find('.code').first();

         selector.wrap(wrapper).before(toolbar);

         toolbar.get(0).onclick = code.get(0).ondblclick =
         function()
         {
             selectAll(code.get(0));
             syntax.scrollLeft(0);
             return false;
         };

         code.find('.line').each(
         function(index)
         {
             //this hack seems to fix all versions of IE
             this.appendChild(document.createTextNode('\r'));
         });
     });
 }

 SyntaxHighlighter.config.bloggerMode = true;
 SyntaxHighlighter.defaults.toolbar = false;
 SyntaxHighlighter.defaults['quick-code'] = false;
 SyntaxHighlighter.all();
 customizeSyntaxHighlighter();
 
</script>
<!-- Syntax Highlighter Additions END -->

Here is the SyntaxHighlighter website:

http://alexgorbatchev.com/SyntaxHighlighter/

Tuesday, March 27, 2012

SNMP Introduction: Communicating with your Router

"Simple Network Management Protocol (SNMP) is an Internet-standard protocol for managing devices on IP networks. Devices that typically support SNMP include routers, switches, servers, workstations, printers, modem racks, and more. It is used mostly in network management systems to monitor network-attached devices for conditions that warrant administrative attention." - Wikipedia

Below is a Java code snippet which uses the 3rd party library snmp4j to communicate with a router. In this example we obtain the name of the router and the current data usage. Before executing the code confirm that your router supports SNMP and that it is enabled. Also verify that the SNMP read and write community is set to "public". These are configurable values that can be updated from within your router's administrative application.

Note that the OID variables contain long and cryptic numeric values. These values can be obtained using a free SNMP browser such as iReasoning's MIB Browser. When using an SNMP browser you must supply your router's IP address and SNMP port (usually 161) to connect to your router. Once connected you can browse through the different properties as a tree structure and obtain any of the numeric values for the OIDs.

import java.io.*;
import org.snmp4j.*;
import org.snmp4j.mp.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.*;

public class SnmpClient
{
 public static final OID sysNameOID = new OID(".1.3.6.1.2.1.1.5.0");
 public static final OID ifNumberOID = new OID(".1.3.6.1.2.1.2.1.0");
 public static final OID ifOutOctetsOID = new OID(".1.3.6.1.2.1.2.2.1.16.1");
 public static final OID ifInOctetsOID = new OID(".1.3.6.1.2.1.2.2.1.10.1");
 
 private String address;
 private Snmp snmp;
 
 public static void main(String[] arg)
 {
  try
  {
   //Create a client with the router's IP Address and SNMP port (161 is default)
   SnmpClient client = new SnmpClient("udp:192.168.0.1/161");
   
   //Get the router's name
   String name = client.getAsString(sysNameOID);
   
   //Display the router's name
   System.out.println("ROUTER'S NAME: " + name);
   
   //Update the router's name (sysName is one of the few properties that are writable)
   client.setAsString(sysNameOID, "TEST");
   
   //I had to read this property before reading the other data usage properties
   client.getAsInt(ifNumberOID);
   
   //Get total number of bytes sent since last router reboot
   int bytesSent = client.getAsInt(ifOutOctetsOID);
   
   //Get total number of bytes received since last router reboot
   int bytesReceived = client.getAsInt(ifInOctetsOID);
   
   //Calculate total number of bytes sent and received
   int bytesTotal = bytesSent + bytesReceived;
   
   //Display combined total data usage in megabytes
   System.out.println("DATA USAGE: " + (bytesTotal / 1024 / 1024) + " MB");
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }
 }
 
 public SnmpClient(String address) throws IOException
 {
  this.address = address;
  start();
 }

 private void start() throws IOException
 {
  DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
  snmp = new Snmp(transport);
  transport.listen();
 }
 
 public void stop() throws IOException
 {
  snmp.close();
 }
 
 private Target createTarget()
 {
  Address targetAddress = GenericAddress.parse(address);
  CommunityTarget target = new CommunityTarget();
  target.setCommunity(new OctetString("public"));
  target.setAddress(targetAddress);
  target.setRetries(3);
  target.setTimeout(1500);
  target.setVersion(SnmpConstants.version1);
  return target;
 }
 
 private PDU createGetPDU(OID oid)
 {
  PDU pdu = new PDU();
  pdu.setType(PDU.GET);
  pdu.add(new VariableBinding(oid));   
  return pdu;
 }
 
 public Variable get(OID oid) throws IOException
 {
  PDU response = snmp.send(createGetPDU(oid), createTarget()).getResponse();
  if (response != null && response.size() > 0)
  {
   return response.get(0).getVariable();
  }
  throw new IOException("Unable to obtain response from server");
 }
 
 public String getAsString(OID oid) throws IOException
 {
  return get(oid).toString();
 }
 
 public int getAsInt(OID oid) throws IOException
 {
  return get(oid).toInt();
 }
 
 private PDU createSetPDU(OID oid, Variable value)
 {
  PDU pdu = new PDU();
  pdu.setType(PDU.SET);
  pdu.add(new VariableBinding(oid, value));
  return pdu;
 } 
 
 public void set(OID oid, Variable value) throws IOException
 {
  snmp.send(createSetPDU(oid, value), createTarget());
 }
 
 public void setAsString(OID oid, String value) throws IOException
 {
  set(oid, new OctetString(value));
 }
 
 public void setAsInt(OID oid, int value) throws IOException
 {
  set(oid, new Integer32(value));
 }
}

Monday, March 19, 2012

Search SQL Server Column Names

Below is a short T-SQL code snippet that demonstrates how to search for some text in all the column names in all the tables in a SQL Server database.

declare @SEARCHTEXT varchar(256)
set @SEARCHTEXT = 'TEXT YOU WANT TO SEARCH FOR'
select t.table_name,
c.column_name,
c.data_type,
c.character_maximum_length
from information_schema.tables t
inner join information_schema.columns c
on c.table_name = t.table_name
where c.column_name like '%' + @SEARCHTEXT + '%'
order by t.table_name, c.column_name

Search SQL Server Stored Procedures and Functions

Below is a short T-SQL code snippet that demonstrates how to search for some text in all the stored procedures and functions in a SQL Server database.

DECLARE @SEARCHTEXT VARCHAR(256)
SET @SEARCHTEXT = 'TEXT YOU WANT TO SEARCH FOR'
SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE OBJECT_DEFINITION(OBJECT_ID(ROUTINE_NAME)) LIKE '%' + @SEARCHTEXT + '%'
ORDER BY ROUTINE_NAME

Wednesday, February 22, 2012

Network Reachability Test for .NET

The code below is used to test if a specific server and port is reachable. This code uses a socket to connect to the server and doesn't wait for a response so it is quicker than using a full WebClient request, etc. This code will return true if the server was reachable and false if it was not (within the provided timeout).

public class NetworkReachability
{
 public static bool IsReachable(string url, int timeout)
 {
  return IsReachable(new Uri(url), timeout);
 }

 public static bool IsReachable(Uri uri, int timeout)
 {
  return IsReachable(uri.Host, uri.Port, timeout);
 }

 public static bool IsReachable(string host, int port, int timeout)
 {
  if (AppConfig.IsDebugCompile)
  {
   Thread.Sleep(250);
   return true;
  }

  try
  {
   using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
   {
    var handler = new ManualResetEvent(false);
    var e = new SocketAsyncEventArgs();
    e.RemoteEndPoint = new DnsEndPoint(host, port);
    e.Completed += delegate { handler.Set(); };
    if (!socket.ConnectAsync(e))
     handler.Set();

    return handler.WaitOne(timeout) &&
     e.ConnectByNameError == null &&
     socket.Connected;
   }
  }
  catch
  {
   return false;
  }
 }
}

Tuesday, February 21, 2012

Mono for Android Pros & Cons

Updated 5/4/2013

Recently, I had the opportunity to develop a project using Mono for Android. For those of you who are unfamiliar with Mono for Android, it enables you to develop Android apps using a .NET language like C# instead of Java. Overall, I've had a good experience using Mono for Android and I'm happy with the results. I've created a handful of apps using Mono for Android and they've all been successful.

The Mono for Android API closely mirrors the standard Android API. For example, nearly all of the same classes, methods, and fields are present in both APIs. One of the main differences is that Mono for Android utilizes properties and delegates which are non-existent in Java. I liked how closely the two APIs were related since this made it easy to switch back and forth between them and to use the wealth of documentation that already exists for the standard Android API.

Below is a list of pros and cons regarding Mono for Android:

PROS

  1. Share Code Between Platforms - If used in conjunction with the Mono Touch API and the Windows Phone API you can potentially reuse your business logic code for both the iPhone and Windows Phone platforms. This is possible since everything can be coded using a single, common programming language instead of 3 different programming languages. Please note that this only applies to business logic code though; presentation specific code will be different for each platform because of differences in the APIs. In my mind the ability to reuse code is the single greatest benefit in using Mono for Android.

  2. Use Your Existing .NET Skills - If you or the majority of your team members are knowledgeable with a .NET language but not with Java then using Mono for Android may be appropriate. However, I think this advantage is somewhat diminished by the fact that C# and Java are so similar. There is probably a greater benefit in using Mono Touch since this eliminates the need to learn Objective C which poses much more of a learning curve than Java.

  3. The C# Language - In my own opinion, the C# language has several advantages over Java (comparing only the core language and not other aspects such as frameworks, community, etc). LINQ, lamdas, and delegates are some of the features I love most about C#. These features aren't irreplaceable but they save time and effort. Perhaps Java's position will improve when version 8 is finally released.

CONS

  1. 3rd Party Android Libraries - In general it's more difficult (but not impossible) to use 3rd parties libraries with Mono for Android. Since most Android libraries are written in Java they must either be rewritten in C# or invoked with JNI. Mono for Android version 4.2+ includes a Binding project that can automatically wrap Java code in a JNI wrapper. The Binding tooling automates much of an otherwise difficult process. However, there is still a learning curve and manual adjustments are often necessary.

  2. Bugs - There is a significant amount of bugs in Mono for Android. Well, perhaps significant is too strong a word, but it is definitely more stable to use Java vs. Mono for Android. Two of the most serious bugs I encountered are: DateTime.Now returns time in the wrong time-zone (UTC), and using a SSL connection with WebClient causes an exception. (I believe these bugs are fixed now). Here is a full list of outstanding bugs.

  3. Debugging - Using the Mono for Android debugger can be a frustrating experience. It sometimes causes your app to crash or skips breakpoints for unknown reasons. Usually I resort to logging and avoid the debugger altogether. Xamarin has tried to fix the debugger but the problem has persisted for over a year now.

  4. Other Limitations - A list of other limitations is available here.

Personally, I'd lean more towards using Java and the standard Android API rather than using C# and the Mono for Android API. I say this because, first, I have a strong background in Java, and, second, using Java will likely result in less complications and limitations. However the ability to share the same code between Android, iPhone, and Windows Phone is very tempting and may be a deciding factor in some cases. At my current job I am part of a team of Microsoft developers, so using Mono for Android is typically the preferred method for creating apps within that environment.

Below is the Mono for Android website:

http://xamarin.com/monoforandroid

Tuesday, December 13, 2011

CSS3 Decoration for Internet Explorer 6 - 9

I recently discovered a javascript library named CSS3 PIE. PIE makes Internet Explorer 6-9 capable of rendering several of the most useful CSS3 decoration features. The list currently includes border-radius, box-shadow, border-image, multiple background images, and linear-gradient as background image. The property that interests me most though is border-radius, since I hate having to create new images every time I want rounded corners with a different radius.

To get started with PIE download the files from their website (css3pie.com). The download includes multiple files but in most cases all you really need is the PIE.htc file. Copy the PIE.htc file into your web project and then reference it using the CSS behavior property. The behavior property is proprietary to Internet Explorer so all other browsers will ignore it. PIE uses the standard CSS3 border-radius property so you will need to add that too, as well as the -moz and -webkit versions for Firefox, Chrome, and Safari. Below is an example:

<html>
<head>

<style>
.rounded
{
 behavior: url(pie.htc);
 border-radius: 10px;
 -moz-border-radius: 10px;
 -webkit-border-radius: 10px;
 background-color: red;
 color: white;
}
</style>

</head>

<body>

<div class="rounded">
 TESTING
</div>

</body>
</html>

After adding PIE you should have CSS3 decoration support for all the major browsers with the exception of Opera although personally I never really consider Opera much anyways.

Note: I've noticed that PIE's rendering of rounded corners is quite slow in Internet Explorer. Because of this, I've decided NOT to use PIE on my blog, so anyone who is unfortunate enough to use Internet Explorer version 8 or lower will see squared corners instead of rounded corners. Upgrade your browser or switch to a better one.

Friday, November 4, 2011

Generic Method For Converting From DBNull

public static T FromDB<T>(object o)
{
   return o is DBNull ? default(T) : (T)o;
}

The method above is written in C# using generics. This method is used to cast weakly typed objects returned from a DataRow to strongly typed objects and it will automatically handle the conversion of DBNull. This method can also be used with nullable types which is convenient since capturing null values is often important when querying databases.

Below is a full example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            object i1 = 7;
            object i2 = DBNull.Value;
            object i3 = 3;
            object i4 = DBNull.Value;
            object i5 = "TEST";
            object i6 = DBNull.Value;

            int o1 = FromDB<int>(i1);
            int o2 = FromDB<int>(i2);
            int? o3 = FromDB<int?>(i3);
            int? o4 = FromDB<int?>(i4);
            string o5 = FromDB<string>(i5);
            string o6 = FromDB<string>(i6);

            Console.WriteLine("o1 = {0}", o1); //can't be null since its value type
            Console.WriteLine("o2 = {0}", o2); //can't be null since its value type
            Console.WriteLine("o3 = {0} {1}", o3, o3 == null ? "(NULL)" : "");
            Console.WriteLine("o4 = {0} {1}", o4, o4 == null ? "(NULL)" : "");
            Console.WriteLine("o5 = {0} {1}", o5, o5 == null ? "(NULL)" : "");
            Console.WriteLine("o6 = {0} {1}", o6, o6 == null ? "(NULL)" : "");
        }

        public static T FromDB<T>(object o)
        {
            return o is DBNull ? default(T) : (T)o;
        }
    }
}

The output would be:

o1 = 7
o2 = 0
o3 = 3
o4 = (NULL)
o5 = TEST
o6 = (NULL)

Saturday, September 24, 2011

Configuring Apache HTTP Server for PHP

First install Apache HTTP Server and then install PHP.

Next you must edit the httpd.conf file located in the conf directory of your Apache Install Directory. Add the follow lines to the end of the file (the lines may already exist; if so then verify they are correct and make any required changes):

#BEGIN PHP INSTALLER EDITS - REMOVE ONLY ON UNINSTALL
PHPIniDir "<PHP_INSTALL_DIRECTORY>"
LoadModule php5_module "<PHP_INSTALL_DIRECTORY>\php5apache2_2.dll"
<FilesMatch \.php$>
 SetHandler application/x-httpd-php
</FilesMatch>
#END PHP INSTALLER EDITS - REMOVE ONLY ON UNINSTALL

Replace the placeholder for the PHP Install Directory with a valid value and restart the Apache server. This example is specific to Apache 2.2 installed on Windows, so you may need to make slight tweaks if using a different version or operating system. See the following link for more information:

http://www.php.net/manual/en/install.php

Monday, September 19, 2011

How to Connect to DB2 with .NET

First you must install either the IBM Data Server Client or the IBM Data Server Runtime Client. The IBM Data Server Client has some additional developer tools but they are optional, so if you are searching for the most lightweight install then choose the IBM Data Server Runtime Client.

Next you must determine if a license is required. If you are connecting through a DB2 Connect Gateway then a license is not required, but if you are connecting directly to the DB2 Database then a license must be activated on the client computer.

To activate the license you must locate the db2conpe.lic file on your DB2 / DB2 Connect install CD. Once you have located this file, copy it to the client computer in the following directory: "C:\Program Files\IBM\SQLLIB\BIN" (location where your DB2 Client was installed). Now open a command prompt and change the directory to "C:\Program Files\IBM\SQLLIB\BIN" and execute this command: "db2licm -a db2conpe.lic". It should say that your license was successfully activated. You can verify this by typing "db2licm -l".

Now you are ready to start programming. Open Visual Studio and start a new console project. Before you start add a new reference (Project -> Add Reference) and browse to "C:\Program Files\IBM\SQLLIB\BIN\netf20\IBM.Data.DB2.dll".

Now copy and paste this code into your class file:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using IBM.Data.DB2;

namespace ConnectToDB2
{
    class Program
    {
        static void Main(string[] args)
        {
            string sql = "SELECT * FROM SYSIBM.SYSDUMMY1";
            DB2Connection con = new DB2Connection("Database=<DATABASE>;UserID=<USER_ID>;Password=<PASSWORD>;Server=<SERVER>:<PORT>");
            con.Open();

            DB2Command cmd = new DB2Command(sql, con);
            DB2DataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                Console.WriteLine(reader.GetString(0));
            }
        }
    }
}

Obviously replace the placeholders in the connection string with valid values.