Monday, June 22, 2009

An easy way to communicate between two processes in .net

In order to communicate between two processes, we uses named pipes. Named pipes provide one-way or duplex pipes for communication between a pipe server and one or more pipe clients. Named pipes can be used for inter process communication locally or over network. Any process can act as either a named piped server or client or both.

Let’s see an example where a string value will be shared between two processes. .NET framework 3.5 has released a new class for creating named pipes server. The name of the class is NamedPipeServerStream. After creating the named pipes server, it will wait for a client process to connect to it. There is a new class NamedPipeClientStream in .NET framework3.5 which is used for creating the named pipes client. Let’s create the named pipes server:

//create the server instance
NamedPipeServerStream server = new NamedPipeServerStream("SetuInstance", PipeDirection.InOut);
//the following code snippet make the server always in a listening mode.
while (true)
{
server.WaitForConnection();
using (StreamReader reader = new StreamReader(server))
{
string stringValue = reader.ReadLine();
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate
{
MessageBox.Show(stringValue);
});
}
server = new NamedPipeServerStream("SetuInstance", ipeDirection.InOut);
}

As you can see in the above code snippet, after creating the named pipes server, it waits for the client connection. As soon as it connects to the named pipe client, it reads the string value.

Now, let’s create the named pipes client:

using (NamedPipeClientStream client = new NamedPipeClientStream(".", "SetuInstance", PipeDirection.InOut))
{
try
{
//try to connect to IPC Server
client.Connect(500);
//write data to the pipe so that IPC server can get the string.
using (StreamWriter writer = new StreamWriter(client))
{
writer.WriteLine("An easy way to communicate between two processes!");
}
}
catch
{

}
}

In the above code snippet, you can see, how easily you can pass string to named pipes server.

NamedPipeClientStream and NamedPipeServerStream are very helpful class added in .NET framework 3.5. Now the processes can easily communicate between each others.

Hope this help!

Friday, June 19, 2009

Disconnect the client from WCF service and notifiy the client before disconnecting.

A colleague of mine was asking me to create a Client-Server demo application using WCF. The following are the requirements:

1>Service instance mode is “PerSession”.
2>Session mode has to be “Required”.
3>WCF Server will be able to terminate a session at any time. In other words, WCF Server can disconnect a WCF client.
4>Before terminating the session, the WCF client will be notified.

In order to meet the above requirement, I have used the WCF Callback for notifying the Client and disconnect the client by closing the incoming channel. Let’s see step by step of the implementation.

Step 1> Create the WCF Contact:

[ServiceContract(CallbackContract=typeof(INotifyClientCallback), SessionMode=SessionMode.Required)]
public interface IService1
{
[OperationContract]
bool StartingService();
}
public interface INotifyClientCallback
{
[OperationContract(IsOneWay = true)]
void Disconnecting();
}

INotifyClientCallback interface for Callback.

Step 2> Implementation of the Contact:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{

private static readonly Dictionary subscribers = new Dictionary();
public static event EventHandler onClientAdded;

///
/// Returns the IP Address of the Client
///

///
public string GetAddressAsString()
{
if (!OperationContext.Current.IncomingMessageProperties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
return "127.0.0.1";
}
RemoteEndpointMessageProperty clientEndpoint =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return clientEndpoint.Address;
}


public bool StartingService()
{
//Get the callback reference
INotifyClientCallback callback = OperationContext.Current.GetCallbackChannel();

string IPAddress = GetAddressAsString();
lock (subscribers)
{
if (!subscribers.ContainsKey(IPAddress))
{
subscribers[IPAddress] = new CommunicationStore() { NotifyCallback = callback, IService = OperationContext.Current.InstanceContext };
if (onClientAdded != null)
{
onClientAdded(IPAddress, null);
}
}
}
return true;
}


public static void Disconnect(string ipAddress)
{
if (subscribers.ContainsKey(ipAddress))
{
CommunicationStore com = subscribers[ipAddress];
if (((ICommunicationObject)com.NotifyCallback).State == CommunicationState.Opened)
{
try
{
//fires the callback method
com.NotifyCallback.Disconnecting();
com.IService.IncomingChannels.FirstOrDefault().Close();
}
catch (Exception)
{
throw;
}
}
}
}

}
public class CommunicationStore
{
public InstanceContext IService { get; set; }
public INotifyClientCallback NotifyCallback { get; set; }
}

Some important points of the service implementation:
a>Use a static dictionary to keep the Client’s IP and callback channel. Before writing on the share object, lock the object.

b>Gets the IP address of the client using the GetAddressAsString method. You can get the IP of the client from the incoming message. The following statement shows how can we get the IP adddress of the Client in WCF:

RemoteEndpointMessageProperty clientEndpoint = OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
String ipAddress = clientEndpoint.Address;

If you are using the namepipe binding, you will not get the RemoteEndpointMessageProperty.

c>When the client creates the proxy of the service, it will call StartingService method immediately. Inside the StartingService method, I am keeping the callback channel of the client and current instance into the dictionary.

d>When the user of WCF service wants to disconnect a client, he/she will call the Disconnect method with the IP Address of the client.

e>The Disconnect method uses the IP Address to get the callback channel of the client and associate service instance of the client from the dictionary. Eventually, it notifies the client by using callback channel and close the incoming channel.

I am done with the service implementation.

Step 3> Implementation of the callback and create the proxy of the service:

public class Proxy
{
public static DuplexChannelFactory factory;
static IService1 _IService1;
private static bool Connect()
{

try
{
WSDualHttpBinding binding = new WSDualHttpBinding();

EndpointAddress address1 = new EndpointAddress(@"http://localhost:9008/Service1");

EndpointAddress address = new EndpointAddress(@"net.tcp://localhost:9002/");
NetTcpBinding nettcp = new NetTcpBinding();
nettcp.ReliableSession.Enabled = true;
nettcp.ReliableSession.InactivityTimeout = new TimeSpan(0, 0, 30);

NetNamedPipeBinding namepipe = new NetNamedPipeBinding();
EndpointAddress addressPipe = new EndpointAddress(@"net.pipe://localhost/");


InstanceContext context = new InstanceContext(new NotifyCallback());

binding.ClientBaseAddress = new Uri(@"http://localhost:9010/");

factory = new DuplexChannelFactory(context, binding, address1);

_IService1 = factory.CreateChannel();
_IService1.StartingService();
}
catch (Exception ex)
{

}
return true;
}

}

public static IService1 ServiceProxy
{
get
{
if (_IService1 == null)
{
Connect();
}

return _IService1;
}
}
}


public class NotifyCallback : INotifyClientCallback
{

#region INotifyClientCallback Members

public void Disconnecting()
{
MessageBox.Show("You are about to disconnect from the service");
}

#endregion
}
Points to ponder of the above code snippet:

a>When you use the WCF callback, you have to use the DuplexChannelFactory rather then ChannelFactory to create the proxy.Othewise, you can generate the proxy.

b>WCF callback supports the following binding: WSDualHttpBinding, NetTcpBinding and NetNamedPipeBinding. When you use the WSDualHttpBinding, don’t forget to set the ClientBaseAddress.

c>Implement the callback interface.

That’s it.

If you need the source code of this demo, you can email me.

Happy Programming!

Sunday, June 14, 2009

Create a CheckListBox in WPF

Many developers are frustrated with lack of basic WPF controls. The WPF and WPF toolkit have some important and cool controls. However, some basic and necessary controls are still missing. But it is easy to create the basic controls in WPF. The article will show you how to create a checklistbox in WPF.

Here, I will create a custom control which will inherit from Listbox. The following code snippet shows the entire source code for the CheckListBox.

namespace MyControlLibrary
{
public class CheckListBox:ListBox
{
public CheckListBox()
{

}
///
/// Item Source of the check list box
///

public new IEnumerable ItemsSource
{
get
{
return this.ItemsSource;
}
set
{
//set the template
this.ItemTemplate = GetTemplate();
base.ItemsSource = value;

}
}

///
/// Gets or sets the property of source object. The property value will be displayed as a content of the checkbox.
///

public string DisplayMember { get; set; }
///
///
///

public string ValueMember { get; set; }


///
/// returns the template for the checkbox.
///

///
private DataTemplate GetTemplate()
{
DataTemplate template = new DataTemplate();
Binding binding = new Binding(this.DisplayMember);
FrameworkElementFactory fwfactory = new FrameworkElementFactory(typeof(CheckBox));
fwfactory.SetValue(CheckBox.NameProperty, "chk");
fwfactory.SetValue(CheckBox.ContentProperty, binding);
fwfactory.SetValue(CheckBox.TagProperty, new Binding(this.ValueMember));
template.VisualTree = fwfactory;
return template;
}

///
/// returns the checked list items.
///

public IEnumerable GetCheckListItems
{
get
{
List list = new List();
for (int index = this.Items.Count-1; index >= 0; index--)
{
CheckBox chk = GetCheckBoxFromDataTemplate(index);
if (chk != null && chk.IsChecked.HasValue && chk.IsChecked.Value)
{
list.Add(this.Items[index]);
}

}
return list;
}
}

///
/// set the checked list items
///

public IEnumerable SetCheckListItems
{
set
{
PropertyInfo listItemPorperty = null;
if(this.Items.Count > 0)
{
listItemPorperty = this.Items[0].GetType().GetProperty(this.ValueMember);
}
PropertyInfo itemPropertyInfo = null;

foreach (var item in value)
{
itemPropertyInfo = item.GetType().GetProperty(this.ValueMember);
break;
}
if (itemPropertyInfo == null listItemPorperty == null) { return; }

for (int index = this.Items.Count - 1; index >= 0; index--)
{
foreach (var item in value)
{
if (listItemPorperty.GetValue(this.Items[index], null) == itemPropertyInfo.GetValue(item, null))
{
CheckBox chk = GetCheckBoxFromDataTemplate(index);
if (chk != null)
{
chk.IsChecked = true;
}
}
}

}
}
}

///
/// returns the checkbox from the data template.
///

///
///
private CheckBox GetCheckBoxFromDataTemplate(int index)
{
ListBoxItem item = this.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem;
if (item == null) { return null; }

DataTemplate template = item.ContentTemplate;

Border border = VisualTreeHelper.GetChild(item, 0) as Border;
ContentPresenter cp = border.Child as ContentPresenter;
return template.FindName(template.VisualTree.Name, cp) as CheckBox;
}

}
}

The following XAML shows how can you use this control :


<Window x:Class="MyControlLibrary.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chklst="clr-namespace:MyControlLibrary"
Title="Window1" Height="300" Width="300">

<chklst:checklistbox name="chklstBox"/>

</window>



Now set the Item source of the CheckListBox:

ObservableCollection col = new ObservableCollection()
{
new {Name="Setu", ID="1"},
new {Name="Ledu", ID="2"},
new {Name="Tonmoy", ID="3"}
};
chklstBox.DisplayMember = "Name";
chklstBox.ValueMember = "ID";
chklstBox.ItemsSource = col;

You can get the checkedList items by using the GetCheckListItems property and set the checkedlist items by using the SetCheckListItems property.

This is how you can easily create a CheckListBox. Now if you want to create RadioButtonListBox, you can follow the same procedure. All you need to do is just replace the CheckBox by the RadioButton.

Hope this Helps!

Friday, June 12, 2009

How to reconnect to WCF service after exception occurred

There can be several reasons to raise exception when calling a WCF service. I am not going to discuss why the exception can be occurred. I will, however, discuss here how to reconnect to WCF service after exception.

If any exception occurs while calling WCF service, the proxy of the WCF service goes to invalid state. Invalid means you cannot use that proxy any more. You have to recreate the proxy before calling any operation of the service.

I will use ChannelFactory here in order to create the proxy of the WCF service. Let the service contact is IService. The following code snippet shows how a proxy would be created using ChannelFactory:

private static ChannelFactory _Factory;
private static IService _Proxy;
public static Timer _reconnectTimer;
public static bool CreateProxy()
{
try
{

//get the factory instance
_Factory = new ChannelFactory("ServiceEndpoint");

_Proxy = _jerichoFactory.CreateChannel();
_Proxy.IsServiceLive();
//add the faulted event
((ICommunicationObject)_Proxy).Faulted += new EventHandler(Proxy_Faulted);

if (_reconnectTimer != null)
{
_reconnectTimer.Stop();
}
}
catch (Exception)
{
return false;
}

return true;
}

In the above code, I have subscribed the Faulted event of the proxy. Make sure you have cast the proxy into ICommunicationObject. Faulted event is fired whenever any exception occurres during the service call. Notice, I have called IsServiceLive() method after creating the channel. IsServiceLive() method simply returns true to make sure that the proxy can connect to the service. The following code snippet is the implementation of Faulted event.

static void Proxy_Faulted(object sender, EventArgs e)
{
IChannel channel = sender as IChannel;
if (channel != null)
{
channel.Abort();
channel.Close();
}
//Disable the keep alive timer now that the channel is faulted
//The proxy channel should no longer be used
AbortProxy();
//fire the OnProxyFaulted event
if (OnProxyFaulted != null)
{
OnProxyFaulted(null, null);
}
if (_reconnectTimer == null)
{
_reconnectTimer = new Timer(2000 * 60);
_reconnectTimer.Elapsed += new ElapsedEventHandler(ReconnectTimer_Elapsed);
}

//Enable the try again timer and attempt to reconnect
_reconnectTimer.Start();
}

static public void AbortProxy()
{
if (_Factory != null)
{
_Factory.Abort();
_Factory.Close();
_Factory = null;
}
}

In the implementation of the Faulted event, I have canceled and aborted the channel of the proxy. After that, I have created a time which will be fired in every two seconds. Let’s see the implementation of the timer.

static void ReconnectTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (CreateProxy())
{
_reconnectTimer.Stop();
}
}

This is very straightforward implementation of the timer. If it can create the proxy and connect to the service, it will stop the timer. This is how you can reconnect to the WCF service after exception.

I could have created the proxy in the Faulted event. But it is better to use a timer to poll the service after a certain time.

Happy programming!

Thursday, June 11, 2009

How to check file types when uploading file in ASP.NET

In order to upload a file in ASP.NET, we can use the FileUpload control. The FileUpload control is built-in in ASP.NET. FileUpload control meets the basic requirement of uploading file. However, this control has some limitations. For example, we cannot specify the type of the file that a user can upload. But we can easily create a Custom Validator to set the type of file that a user can upload. The following code snippet shows the custom validator:

public class FileUploadTypeValidator : CustomValidator
{
public FileUploadTypeValidator()
{
base.ErrorMessage = "pdf, doc, docx, xls, xlsx, and ppt files are allowed.";
base.Text = "*";
base.SetFocusOnError = true;
base.ToolTip = "pdf, doc, docx, xls, xlsx, and ppt files are allowed.";
base.ClientValidationFunction = "ClientValidateFileType";
this.FileTypes = "pdfPDFdocDOCdocxDOCXxlsXLSxlsxXLSXpptPPT";
}

protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), this.ClientID + "ADDScript", GetScript(), true);
}

protected override bool OnServerValidate(string value)
{
//return base.OnServerValidate(value);
FileUpload fu = this.Parent.FindControl(this.ControlToValidate) as FileUpload;
if (fu != null && !string.IsNullOrEmpty(fu.FileName))
{
string ext = System.IO.Path.GetExtension(fu.FileName);
string[] fileTypes = this.FileTypes.Split('');
foreach (string item in fileTypes)
{
if (!ext.Equals( "." + item))
{
return true;
}
}
}
return false;
}

public string FileTypes { get; set; }

private string GetScript()
{
string script = string.Empty;
script = @"function ClientValidateFileType(source, arguments) {"
+ " var FilePath = arguments.Value;"
+ " var Extension = FilePath.substring(FilePath.lastIndexOf('.') + 1).toLowerCase();"
+ " var exten = new Array();"
+ " exten = \"" + this.FileTypes + "\";"
+ " var extens = exten.split(\"\");"
+ " var isValid = false;"
+ " for (var i = 0; i < extens.length; i++) {"
+ " if (extens[i] == Extension) {"
+ " isValid = true;"
+ " break;"
+ " }"
+ " }"
+ " arguments.IsValid = isValid;"
+ " }";
return script;
}
}

The above code snippet checks the type of the in both the client and server side. In order to use this custom validator, use the following markup:




AELCtl is the tagprefix of the custom validator. You can set the type of files you want to allow by using the FileTypes property. The above validator allows jpg, jpeg and GIF files

Hope this help!

Wednesday, June 10, 2009

How to disable an USB hard drive in windows XP

In order to disable the USB hard drive in windows XP, follow the following steps:
1> Open the registry editor.
2> Expand the System under HKEY_LOCAL_MACHINE.
3> Click on Services under CurrentControlSet.
4> Click on UsbStor.
5> Double click on start and make the value 4.

Now, your XP operating system is not suppose to detect the USB hard drive.

Hope this help!

How to count the number of active session in WCF

There are three ways we can manage instance of WCF service. In other words, WCF supports three types of instance activation. These three types of activation are:
1> Per-call session – It allocates a new service instance per client request.
2> Sessionful session – It allocates a new service instance per client connection.
3> Singleton session – All clients share the same service instance.

Here, our goal is to count the number of active WCF service instance and set the limit of maximum concurrent client when the activation mode is Sessionful.
Let’s create a WCF Service. We will start by creating a WCF Contact.

ServiceContract(SessionMode=SessionMode.Required)]
public interface ISessionCount
{
[OperationContract]
string GetData(string s);
[OperationContract]
bool StartingService();
[OperationContract]
bool StopingService();
}
Here, the above code snippet is a WCF Contact where the SessionMode is Required. It means the client has to use the session mode.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class SessionCount : ISessionCount, IDisposable
{
//static int Counter;
static object Counter = new object();
static SessionCount()
{
Counter = 0;
}
public SessionCount()
{

}

public string GetData(string s)
{
return "This is from Service :" + s;
}

public bool StartingService()
{

lock (Counter)
{
int localCount = Convert.ToInt32(Counter);
Counter = localCount + 1;
if (localCount > 2)
{
this.Dispose();
return false;
}

}
return true;
}

public bool StopingService()
{
return true;
}

#region IDisposable Members

public void Dispose()
{
lock (Counter)
{
Counter = Convert.ToInt32(Counter) - 1;
}
}

#endregion
}

The above code snippet is the implementation of the service contact. Let’s examine the implementation point by point.

1> Implement the IDisposable Interface. When the service instance will be disposed, the Dispose method will be fired.
2> Declare a static Counter object. Instead of primitive type(Int, Long), I am using Object here because I have to lock the object before accessing this. We have to lock the object because of thread related issue.
3> Initialize the counter object in the type constructor. Type constructor is fired once in the application domain regardless of the number of new instance created.
4> Assume the maximum concurrent client of the WCF service can be 2.
5> When a client will create a proxy of the WCF service, it will call the start Service.
6> In the start service, we will increase the counter and check whether it exceeds the maximum concurrent user limet or not. If it exceeds then dispose the current instance return false.
7> When the client will be shutdown, it will call the stop service method which eventually will dispose the service instacne. However, if the client close the proxy, the service instace will be disposed. The responsibility of the dispose method is to decrease the Counter.

This is straight forward way we can protect the maximum concurrent client in WCF service.