2013-08-31

Full day Microsoft awareness workshop at Wayamba University of Sri Lanka

We have conducted a full day workshop for the students and lecturers at Wayamba University of Sri Lanka on 14th of August, 2013. There were DPE lead of Sri Lanka Microsoft – Wellington Perera, 3 Sri Lankan MVPs (Hasitha, Preethiviraj and myself) and two Microsoft student ambassadors.

My part was to deliver a session on SignalR - which is a very useful and latest technology in .NET. The duration was about 1 hour for my session. I have uploaded the presentation slides and source codes of the sample applications in the below link

http://sdrv.ms/14KeK9M

Below are few photos taken at the event.

WellingtonPreethiRuchiraHasithaLahiruSachiraAudience 1Audience 2Audience 3Group photo

2013-08-09

Difference between Dispose and Close methods

Most of the time, we use those methods interchangeably without knowing the true context of them. Sometimes we call both of the methods. So let’s see what are the difference between those two methods and whether we should call both of the methods when we need to close a connection. I will take an SQL connection as the example,

SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Test"].ToString());
con.Open();
con.Close();
con.Open(); //2nd attempt

In the above code, the 2nd attempt would not fail. Close will simply close the connection. But it does not necessarily release the memory and do the clean up (It will release the resources temporarily). So it's possible for you to open the same connection again. Now let's use the Dispose instead and see the result

SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Test"].ToString());
con.Open();
con.Dispose();
con.Open(); //2nd attempt

Now on the 2nd attempt, it will throw me an exception saying "The ConnectionString property has not been initialized.". Why is that? That's because I have already release all the resources including the Connection String, by calling the Dispose method.

So when you are really done with a connection (If you do not wish to open it again), you should call Dispose method. It will implicitly call the Close method.

Efficient way of changing the image on hover

It’s a common thing that we change the images on mouse hover of the buttons and other selectable/clickable items. But did you notice that if the connection is slow, it takes time to render the images we are displaying on the hover state? That breaks the UI and it’s not a good user experience.

To get rid of that pain, we can use a trick. We can combine the images for the two states (hover and normal state) and set the background position on hover of the element. Something like below should work. Make sure you correctly append the two images using a photo editing software.

#imgBtn{
   background: url('/Images/SaveCombined.png');
}

#imgBtn:hover{
    background-position: 0 -50px;
}

The above CSS will set the vertical value of the background position to –50px on hover state. So, instead of swapping images on the hover state, it will simply change the background position of the one image. It will result in image position go upwards. Give the correct value for the vertical position of the background so it will display the other part of the image which should be visible for the hover state.

That’s it!

2013-08-05

Creating a self hosted app in SignalR and connect clients to it

On my previous blog posts, I’ve used a SignalR code hosted on a web server. But we can run a self hosted SignalR code and without a web application at all. On this example, I’m going to show you how to write the same chat application I’ve described here, using a console app.

First, you have to install SignalR Self hosted package using NuGet Package Manager for Visual Studio. At the moment I write this article, the package is in beta (Prerelease). So you have to select “Include Prerelease”.

Following is the code for the self hosted console application

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using System.Collections.Concurrent;

namespace SignalRSelfHosting
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "
http://localhost:8080";

            using (WebApp.Start<Startup>(url))
            {
                Console.WriteLine("Server running on {0}", url);
                Console.ReadLine();
            }
        }
    }

    class Startup
    {
        public void Configuration(IAppBuilder app)
        {

// Turn cross domain on 
var config = new HubConfiguration { EnableCrossDomain = true };

            // This will map out to http://localhost:8080/signalr by default
            app.MapHubs(config);
        }
    }

    public class ChatHub : Hub
    {
        static ConcurrentDictionary<string, string> dictionary = new ConcurrentDictionary<string, string>();

        public void Notify(string name, string id)
        {
            if (dictionary.ContainsKey(name))
            {
                Clients.Caller.differentName();
            }
            else
            {
                dictionary.TryAdd(name, id);

                foreach (KeyValuePair<String, String> entry in dictionary)
                {
                    Clients.Caller.online(entry.Key);
                }

                Clients.Others.enters(name);
            }
        }

        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }

        public void sendToSpecific(string name, string message, string to)
        {
            // Call the broadcastMessage method to update clients.
            Clients.Caller.broadcastMessage(name, message);
            Clients.Client(dictionary[to]).broadcastMessage(name, message);
        }

        public override Task OnDisconnected()
        {
            var name = dictionary.FirstOrDefault(x => x.Value == Context.ConnectionId.ToString());
            string s;
            dictionary.TryRemove(name.Key, out s);
            return Clients.All.disconnected(name.Key);
        }
    }
}

You may note, my ChatHub class is same as I’ve used in the web application. All the methods in my hub class is same.

All you have to do is, run the console application as same as you run the web application project. This will not require a web server like IIS. The console application will use a HTTP listener and OWIN to process the HTTP requests it get. Here I’m using http://localhost:8080 as my server. So my clients should point the hub URL to that.

If we are going to change the sample JavaScript client I’ve show in below blog post,

http://ruchirac.blogspot.com/2013/02/creating-chat-application-in-aspnet.html

I’ve to add the below line at the top of the JavaScript code to tell that, use this URL as the hub connection.

$(function () {
        $.connection.hub.url = “
http://localhost:8080/signalr”;

………………

All the same, in order to point my .NET client applications I’ve described at below blog posts,

Console App - http://ruchirac.blogspot.com/2013/03/connecting-net-client-console.html

Windows Store App - http://ruchirac.blogspot.com/2013/07/connecting-windows-store-app-to-website.html

I have to pass the new URL for self hosted application when I make my hub connection. I can do it like this

var hubConnection = new HubConnection(“http://localhost:8080/signalr”);

So that’s all it take to convert the web hosted SignalR application to a self hosted console application! You don’t need a web server at all!

2013-07-30

CSS selector for all the textboxes

Usual way of applying styles for all the textboxes is like below

input[type="text"] {
    /*CSS here*/
}

Problem with the above is, it will not include the textboxes which get renders when you simply put a <input> tag. Note that when you do not specify the type attribute in input elements, it will render as the default input element, textbox. The above CSS selector won't work in such cases. In such cases, you can use the below

input:not([type]), input[type="text"]
{
  /*CSS here*/
}

It will select all the input control without a type attribute as well as which are marked as type=”text”

2013-07-25

Sri Lanka .NET forum monthly user group meeting – July 2013

I’ve successfully delivered a session on “Introduction to SignalR” for the Monthly .NET User Group Meeting - July 2013. Below are the details of my session

Description: Find it really difficult to develop and manage real time web applications? With SignalR, which is a new library for ASP.NET, you can add real time web functionality to your ASP.NET application within minutes!

Duration: 45 minutes

Date: 4th July 2013

Venue: Microsoft Sri Lanka

Sri lanka .NET Forum - July user group meeting

You can download the archived file which contains all the Demo applications (Moving the scooby doo – First step for creating a multiplayer web based game, Chat application and the console application) I’ve used for the session. Below is the link for the source codes

http://sdrv.ms/125WGWC

You can access to the presentation slides using below link

https://skydrive.live.com/#!/view.aspx?cid=56E5E527D356065A&resid=56E5E527D356065A%21124&app=PowerPoint

Below is the full video of the Session

http://www.youtube.com/watch?feature=player_detailpage&v=Vy4FA8lZAJI&t=2804

2013-07-24

Connecting a Windows Store app to a website with SignalR

There are different kinds of clients we can use with SignalR. Web browsers, Silverlight, WinRT, WPF are some of them.

On this post, I’ve shown you how to create a chat application with ASP.NET using SignalR library. There I’ve used the browser as the client. I extend that example to integrate a console application as the client in this post.

Now I’m going to show you how to connect a Windows 8 Store app to a website with SignalR library. If you need to know how to implement the server side, please go to the below link

http://ruchirac.blogspot.com/2013/02/creating-chat-application-in-aspnet.html

As the first step, I have to install SignalR .NET Client library to my Windows Store App project. I can easily do this using NuGet Package Manager (PROJECT –> Manage NuGet Package Manager…). Type SignalR on the Manage NuGet Packages dialog box so it will list down all the SignalR libraries. Select Microsoft ASP.NET SignalR .NET Client and click install. It will take care of adding all the relevant DLLs to my project.

Now we are ready to develop the Windows Store App.

I’m going to use the default MainPage.xaml. Below is the markup of that page.

<Page
    x:Class="SignalRWindows8App.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SignalRWindows8App"
    xmlns:d="
http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Loaded="Page_Loaded">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Popup x:Name="enterName">
            <Popup.ChildTransitions>
                <TransitionCollection>
                    <PaneThemeTransition />
                </TransitionCollection>
            </Popup.ChildTransitions>
            <Border BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
                Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
                BorderThickness="2" x:Name="border">
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock Text="Enter your name:" FontSize="26.667" Margin="0,50,0,0"/>
                    <TextBox x:Name="chatName" HorizontalAlignment="Center" FontSize="26.667" Height="50" Width="300" Margin="0,50,0,0" />
                    <Button Content="OK" HorizontalAlignment="Center" Click="Button_Click_1" Height="50" Width="100" Margin="0,50" />
                </StackPanel>
            </Border>
        </Popup>
        <TextBlock x:Name="chatShow" Margin="0,0,0,243" FontSize="14.667" ScrollViewer.HorizontalScrollMode="Auto" ScrollViewer.VerticalScrollMode="Auto"/>
        <TextBox x:Name="txtMessage" Height="100" Margin="31,573,778,95" />
        <Button Click="Button_Click" Content="Send" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="609,0,655,95" Height="50" Width="100" />
    </Grid>
</Page>

I’m using a popup to enter the name for the user.

Then I have a TextBlock called ‘chatShow’ to display the chat and a TextBox called ‘txtMessage’ for user to enter the chat message. Finally I’m using a button to send the message.

Let’s look at the code behind implementation.

using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Hubs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace SignalRWindows8App
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        IHubProxy chat;
        public SynchronizationContext Context { get; set; }

        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            if (!enterName.IsOpen)
            {
                border.Width = Window.Current.Bounds.Width;
                border.Height = Window.Current.Bounds.Height;
                enterName.IsOpen = true;
                chatName.Focus(FocusState.Pointer);
            }
        }

        async private void makeConnection()
        {
            try
            {
                var hubConnection = new HubConnection("
http://localhost:53748");
                chat = hubConnection.CreateHubProxy("ChatHub");
                chatShow.Text = "";
                Context = SynchronizationContext.Current;
                chat.On<string, string>("broadcastMessage",
                    (name, message) =>
                        Context.Post(delegate
                    {
                        this.chatShow.Text += name + ": "; this.chatShow.Text += message + "\n";
                    }, null)
                        );
                await hubConnection.Start();
                await chat.Invoke("Notify", chatName.Text, hubConnection.ConnectionId);
            }
            catch (Exception ex)
            {

            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            sendMessage();
        }

        async private void sendMessage()
        {
            try
            {
                await chat.Invoke("Send", chatName.Text, txtMessage.Text);
            }
            catch (Exception ex)
            {
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (enterName.IsOpen)
            {
                enterName.IsOpen = false;
            }
            makeConnection();
        }
    }
}

Let’s analyze the code behind.

Since I’m going to use my Hub Proxy in more than one places (Page_Loaded method and Button_Click method), I declare it as a Global variable.

IHubProxy chat;

Also, here I’m using a SynchronizationContext to separately handle the updates from UI thread.

I’m going to show a popup as soon as application launches. My popup control’s name is ‘enterName’.

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    if (!enterName.IsOpen)
    {
        border.Width = Window.Current.Bounds.Width;
        border.Height = Window.Current.Bounds.Height;
        enterName.IsOpen = true;
        chatName.Focus(FocusState.Pointer);
    }
}

So on the Page_Loaded method, I’m checking whether it’s already opened by calling enterName.IsOpen. If it returns false, I set the width and height of the popup to window width and height because I like my popup to take the entire screen when it displayed. Then I set the cursor to textbox ‘chatName’ so user can enter the name.

When the user press OK button, I hide the popup and make the connection between the server and Windows Store App. To make the connection, I’m calling the makeConnection() method as shown below.

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    if (enterName.IsOpen)
    {
        enterName.IsOpen = false;
    }
    makeConnection();
}

Following is the implementation of makeConnection() method.

async private void makeConnection()
{
    try
    {
        var hubConnection = new HubConnection("
http://localhost:53748");
        chat = hubConnection.CreateHubProxy("ChatHub");
        chatShow.Text = "";
        Context = SynchronizationContext.Current;
        chat.On<string, string>("broadcastMessage",
            (name, message) =>
                Context.Post(delegate
            {
                this.chatShow.Text += name + ": "; this.chatShow.Text += message + "\n";
            }, null)
                );
        await hubConnection.Start();
        await chat.Invoke("Notify", chatName.Text, hubConnection.ConnectionId);
    }
    catch (Exception ex)
    {

    }
}

Note that I’ve made the method as async. I’m wishing to call some long running processes inside that method. So I need to use the await keyword in front of that method.

I’m creating the hub connection by passing the URL I need my app to connect to. Since I run my web application from Visual Studio, I use the localhost address.

var hubConnection = new HubConnection("http://localhost:53748");

Next I’m using that connection to create a hub proxy. The class name of my server side hub is ‘ChatHub’. So I’m passing that name to create a hub proxy.

chat = hubConnection.CreateHubProxy("ChatHub");

Then I register the ‘broadcastMessage’ method on my app to display the messages I get from the server (The server will actually broadcast the messages get from clients). I’m getting two values, name and message from the server and I display them on my app.

chat.On<string, string>("broadcastMessage",
           (name, message) =>
               Context.Post(delegate
           {
               this.chatShow.Text += name + ": "; this.chatShow.Text += message + "\n";
           }, null)
               );

Then I start the connection between server and my app. I will call a server method at next line. When I go to next line, I need to be sure that connection has been made to the server in order to run the server method. Since I’m using await keyword, the method will return but will not execute the rest of the lines in async method until the the connection has been made.

await hubConnection.Start();

Then I’m calling a server method called ‘Notify’, which will be responsible for notifying other clients that my app is connected to the chat system. For that I’m using the below code

await chat.Invoke("Notify", chatName.Text, hubConnection.ConnectionId);

I’m passing the name I got from the popup and the connection ID which get assigned to my app. There also I’m using await because I need it to be finished first before I start sending the messages from my app.

Now we have successfully made the connection between my app and the server. Now let’s look how we can send messages through my app.

On the Send button click event, I’m calling a method called ‘sendMessage’

private void Button_Click(object sender, RoutedEventArgs e)
{
    sendMessage();
}

The sendMessage method implementation is like below

async private void sendMessage()
{
    try
    {
        await chat.Invoke("Send", chatName.Text, txtMessage.Text);
    }
    catch (Exception ex)
    {
    }
}

This method is also marked as async. I invoke the server side method called “Send” to send the messages. I pass the name and message to that method so the server method can broadcast my message to other connected clients.

That’s all it takes to create a windows store app which connects, display and send messages in real time with a browser client, using SignalR library.

Following is a screenshot of the first screen of my app (Popup)

1

Below is how it interacts with the browser

2

As you can see, it updates the messages in real time both in windows store app and browser!

2013-07-08

A quick guide to choosing the right ASP.NET programming modal for your project

First of all, I must say that choosing the right programming modal for your ASP.NET project really depends on lot of factors like project requirements, the knowledge of the team, the time duration set for the project etc. What I’m trying to discuss in this article is providing a brief overview of how to decide what programming modal should be use for your project.
If you choose the right programming modal according to the project, every programming modal can be used very powerfully and effectively. Basically there are 3 programming modals in ASP.NET
  1. WebForms
  2. MVC
  3. WebPages
I would not discuss about pros and cons in each modal or compare/contrast those. I will take some situations and point out what modal would be the ideal choice.
  • You need friendly URLs for SEO – Since the MVC have a default URL routing logic, MVC will make it easier. If you use WebForms, you would have to write the routing logic.
  • Performance – Performance wise, MVC is better than WebForms. That’s mainly because MVC does not make use of ViewState which carry a lot of information to the server.
  • Experience of the developers – If the developers are much more familiar with WinForms development, they will find it easier to develop with WebForms. WebForms is an event driven development modal. And also, we can drag and drop controls to our page just like we did in WinForm applications. So developers will find a lot of similarities between developing WinForms and WebForms. MVC, on the other hand, requires a good basic understanding of how the web applications work. If the developers are really novice and newbies to web developments, WebPages would be a better choice. It’s light weighted and easier to understand compared to other two.
  • You need a good control of the UI – There is a much more control over the UI if you use MVC over WebForms. MVC will allow developers to create the UI independently from the server code.
  • You need a good separation of the UI and server side code – Since MVC works as Modal-View-Controller, it allows developers to work independently of the server side code and UI. This comes very useful if the UI is going to be designed by a web designer and server side code is going to develop by a web developer. If you use WebForms, it’s not possible (Or at least, really hard) to work on a one page by many people because it tightly couples with the code behind file.
  • Rapid Application Development – If the project is about developing it as soon as you can and if you don’t have to care much about performance, then WebForms would be a better approach. This is true mostly for the intranet web applications. In an intranet application, you don’t have to worry about Search Engine Optimization too. So WebForms will be an ideal choice to develop intranet web applications because you don’t have to worry much about the performance and SEO aspects.
  • You need a test driven environment – Unit testing is much more easier in MVC framework than in WebForms.
MVC seems to over complicate simple things. But once you have a good grasp of it, things will turn out really easy for you. Above are few of the factors which affect for deciding the program modal. There are many more.

2013-04-11

Hiding the ASPX markup when publishing an ASP.NET Web application

There are times that we need to hide the markup source from the published ASPX files. We have an option for that in the Visual Studio 2012 Update 2.

1) Right click on the web project from the solution explorer and choose Publish…

1

2) In the Publish Web dialog box, create a new profile (Or update an existing profile) and press Next > (Or choose the Connection tab). From there, choose your publish method (I’m using File System) and press Next >

2

3) In the Settings tab, expand the File Publish Options and tick Precompile during publishing.

3

4) Then click the Configure link next to Precompile during publishing option. It will open up a window shown as below. From there, un-tick Allow precompiled site to be updatable option and click OK.

4

5) Now you are done! Click Publish and it will publish the project. If you look in to the source code of ASPX, you will see the message “This is a marker file generated by the precompilation tool, and should not be deleted!”. But you can’t see the source code. If you look in to the bin folder of the published project, you will see additional files (Extension with .compiled) which are responsible for mapping the assembly code in to ASPX files.

For visual studio 2010 and Visual Studio 2012 (Without update), you will have to install the updates as describe in this link.

2013-04-01

How to make transparent elements without affecting the child elements

If we define the Opacity of an element with the usual CSS Opacity style, it will affect for the child elements too. It doesn’t matter whether you override the opacity in child element or not, it won’t change back. To get rid of that, we can use the below CSS3 style.

rgba(0, 0, 0, 0.4);

rgba is a CSS3 style. We can define the color using R G B values and as the final parameter, we can pass the opacity level. Then it will affect only for that element. See how cool and easy it is?

If you are worrying about the support of CSS3 in your browser, then you have two options.

1. Instead of making the elements as inner, you could always use position and margin styles to place the element on top of the other element. In that way, there are no child elements so won’t affect the opacity.

2. You can simply make images of the transparent elements and use them.

2013-03-31

Connecting a .NET client (Console application) to a website with SignalR

On one of my previous posts, I’ve shown you how to build a web based chat application with the use of SignalR. SignalR isn’t only restricted to web clients. It also works with many other clients like iOS, Android (There are no official support for them yet though. Those projects are community driven at this stage.) and Silverlight, .NET clients. In this blog post, I’m going to show you how to integrate a .NET client to my already built web application.

Following is the link to the web application I’ve created using SignalR

http://ruchirac.blogspot.com/2013/02/creating-chat-application-in-aspnet.html

Now I’m going to connect my .NET client (Console application) to that hosted website. For that, first of all I have to install SignalR .NET Client for my Console application. I can either do it by manually adding the DLL files and adding the references to the project or install it directly using NuGet Package manager. Since Installing it via NuGet Package manager is a lot easier, I’m going to use that.

.net client

After installing the Microsoft ASP.NET SignalR .NET Client, we are ready to develop our application. Following is the code for the Console app

using Microsoft.AspNet.SignalR.Client.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var hubConnection = new HubConnection("
http://localhost:53748");
            var chat = hubConnection.CreateHubProxy("ChatHub");
            chat.On<string, string>("broadcastMessage", (name, message) => { Console.Write(name + ": "); Console.WriteLine(message); });
            hubConnection.Start().Wait();
            chat.Invoke("Notify", "Console app", hubConnection.ConnectionId);
            string msg = null;

            while ((msg = Console.ReadLine()) != null)
            {
                chat.Invoke("Send", "Console app", msg).Wait();
            }
        }
    }
}

At the first line, I’m connecting to the hosted website. In this example, the chat server. I’m using localhost because I’m using Visual Studio to run the application. If you’ve already hosted the application in somewhere else, then you have to give that web address to the HubConnection Constructor.

var hubConnection = new HubConnection("http://localhost:53748");

The above line will create a Connection to the Hub hosted in http://localhost:53748. We can use that to create a Hub Proxy. In my example, the hub name is ChatHub (The class name in server). So I’ve passed that to CreateHubProxy method. Then I’ve registered the method “braodcastMessage”, to display the messages on Console, app which I get from the other clients.

chat.On<string, string>("broadcastMessage", (name, message) => { Console.Write(name + ": "); Console.WriteLine(message); });

I’m getting two parameters from the server call, name and message. I’m writing them on the console as I get them. My server method looks like below

public void Send(string name, string message)
{
    // Call the broadcastMessage method to update clients.
    Clients.All.broadcastMessage(name, message);
}

As you can see, there I’m calling the method “broadcastMessage” on all clients. In the next line I’m starting the connection with the server.

hubConnection.Start().Wait();

I’m calling the Wait() method in order to wait till the connection made between server and my .NET client.

Next, I’m calling the Notify method in the server. It’s responsible for adding the connection ID to the client list and notifying other clients about the arrival of Console client.

chat.Invoke("Notify", "Console app", hubConnection.ConnectionId);

Here I’ve hardcoded the name “Console app”.

After that, I’m running a loop to get the messages from Console app. Then I invoke the server method as soon as I get a message from the .NET Client user. Then the server method, in this case “Send”, is responsible for broadcasting the message to all other connected clients.

string msg = null;

while ((msg = Console.ReadLine()) != null)
{
    chat.Invoke("Send", "Console app", msg).Wait();
}

So that’s all what it takes to build up a simple .NET client application which connects to a SignalR hub to do the real time communication. Following is a screenshot of how it looks like when it communicates with a web client.

SignalR console

2013-03-22

Crop an image when uploading to the server in ASP.NET

To crop an image when saving it to the server through asp:FileUpload control, we can use the below code. Here I’m using the Clone method of the Bitmap class and I’ve specified my area from the Rectangle. It actually creates a copy of the image within the specified area by the Rectangle.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;

namespace WebApplication1
{
    public partial class About : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            int x, y, width, height;
            x = y = 0; //X, Y values for crop the image.
            width = 300;
            height = 300;

            Rectangle cropArea = new Rectangle(x, y, width, height);

            Bitmap bmpImage = new Bitmap(FileUpload1.PostedFile.InputStream);
            Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
            bmpCrop.Save(@"D:\test.jpg");
        }
    }
}

Since we are using Rectangle and Bitmap classes, we have to import the System.Drawing namespace. Here I’m defining the width and height as 300px and X, Y value to 0. So it will crop 300x300 area from the image from the top left corner. Following is the markup I’ve used

<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button"
    onclick="Button1_Click" />

Following is an example image file I’ve uploaded:

1

After upload it and being cropped, following is the result file uploaded to the server.

test

Application_Error method Vs. Custom Error pages

I’m going to answer two FAQ about Application_Error method and Custom error pages.

1. If we have defined a custom error pages for our application, will the Application_Error method get fired?

Of course it will. Application_Error method in the Global.asax file will get fired whenever an unhandled exception occurs. Application_Error method will invoke every time an unhandled exception occurs regardless of whether you've declared a custom error page or not. After that method being executed, it will display the custom error page.

2. If we are doing a Response.Redirect or Server.Transfer inside the Application_Error method, then what will happen? Will the custom error page get displayed after that?

No it will not. Then the application will be redirected to the page which we've defined in the Application_Error method. It will not go to the custom error page since we are overriding the redirect page in global.asax.

Restrict user access to a website based on IP address

Though the method I’m going to describe below would not work 100%, it is the closest thing you can do within few minutes.

First, you may need to keep track of the suspected IP list in a database table or in some other storage. At the Application_BeginRequest method of the Global.asax file, iterate through each IP and match it with the current user’s IP. If it matches, then redirect the user to a permission denied page.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string ip = HttpContext.Current.Request.UserHostAddress;

    if(ip == suspectedIP){
        Response.Redirect("~/PermissionDenied.aspx");
    }
}

2013-03-12

Logging with ASP.NET - Part 2 (Using an XML file as the configuration file and logging levels)

Here I've shown how to use an XML file as the log4net configuration file and how to use logging levels in log4net to manage our log info efficiently into log files. Also, I've shown how the RollingFileAppender works and how to give a dynamic name to the log file (ex:-Date) I'm using Visual Studio 2012 and C#.NET to do the demonstration.

If the text isn’t clear, please use the HD format and full screen mode.

2013-02-26

Basics of creating a multiplayer web based game with jQuery and SignalR

In this article, I’m going to show how to use jQuery to move an object on web page and how we can use SignalR to notify all the connected clients about the movement and replicate that movement on each client.

The basic rule of a multiplayer web based game is, you have to reflect the changes done in a one player machine on other players machines, real-time. The challenge is how you are going to do this in real time. If you are using some polling mechanism, then some movements will get missed or slower to replicate in other players machine. Use with SignalR, multiplayer web based games are much easier to develop.

Let’s have a look at how to accomplish the basic rules of a multiplayer game, i.e. reflecting the changes real time in other clients, in an ASP.NET application with the help of SignalR.

Before we begin, following is a screen shot of the sample application. As you can see, I’m running the same application on two different browsers and I’m expecting the same movement of Scooby on both web pages without browser refresh.

Untitled

First of all, we have to add the reference to SignalR client and server libraries. Easiest way to do this is by NuGet packages. Right click on your project and click on Manage NuGet Packages…. Then type SignalR on the search box and click Install. Now you have SignalR in your application. I’m going to use some animation in my game, so let’s also install the jQuery UI from NuGet Packages.

Now we are ready to develop our application.

First, I’m going to add the Hub routing in my Global.asax file as shown below

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.MapHubs();
}

Then, I’m going to add the page where I’m going to develop the game. In there, I’m referencing to the jQuery latest version, jQuery UI library, SignalR client library. SignalR Hubs which will dynamically be created on the fly.

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js" charset="utf-8">
</script>
<script src="Scripts/jquery-ui-1.10.0.js"></script>
<script src="Scripts/jquery.signalR-1.0.0.js"></script>
<script src="/signalr/hubs"></script>

Next I’m going to develop my game using the jQuery/JavaScripts. Following is the code for that

<script type="text/javascript">
       $(function () {
           var moveScooby = $.connection.moveScoobyHub;

           moveScooby.client.runScoobyForward = function () {
               $("#scooby").animate({
                   marginLeft: '+=1'
               }, 0);
           }

           moveScooby.client.runScoobyBackward = function () {
               $("#scooby").animate({
                   marginLeft: '-=1'
               }, 0);
           }

           moveScooby.client.runScoobyUpward = function () {
               $("#scooby").animate({
                   marginTop: '-=30'
               }, 500, 'easeOutCubic', function () {
                   $("#scooby").animate({
                       marginTop: '+=30'
                   }, 500, 'easeInExpo');
               });
           }

           $.connection.hub.start().done(function () {
               $(document).keydown(function (e) {
                   var audio = document.getElementById("snd");
                   switch (e.which) {
                       case 32:
                           $("#scooby").animate({
                               marginTop: '-=30'
                           }, 500, 'easeOutCubic', function () {
                               $("#scooby").animate({
                                   marginTop: '+=30'
                               }, 500, 'easeInExpo');
                           });
                           moveScooby.server.moveScoobyUpward();
                           break;
                       case 37:
                           $("#scooby").animate({
                               marginLeft: '-=1'
                           }, 0);
                           moveScooby.server.moveScoobyBackward();
                           break;
                       case 39:
                           $("#scooby").animate({
                               marginLeft: '+=1'
                           }, 0);
                           moveScooby.server.moveScoobyForward();
                           break;
                   }
               });
           }
           );
       });
   </script>

Here, I will be using a Scooby-doo image and I will move it on the web page as we press arrow keys. Scooby will jump when you press the space bar.

My hub class name is MoveScoobyHub.cs. In SignalR, we must use lower case camel notation in order to access the server properties/methods. So I access my hub like below

var moveScooby = $.connection.moveScoobyHub;

Note the “m” in “moveScoobyHub” is simple even though the class name has capital “M”.

Next I’ve declared 3 methods to move the Scooby on all the client machines.

moveScooby.client.runScoobyForward = function () {
    $("#scooby").animate({
        marginLeft: '+=1'
    }, 0);
}

moveScooby.client.runScoobyBackward = function () {
    $("#scooby").animate({
        marginLeft: '-=1'
    }, 0);
}

moveScooby.client.runScoobyUpward = function () {
    $("#scooby").animate({
        marginTop: '-=30'
    }, 500, 'easeOutCubic', function () {
        $("#scooby").animate({
            marginTop: '+=30'
        }, 500, 'easeInExpo');
    });
}

First method will take care of moving the Scooby forward. It will add 1 unit to the margin left of the scooby object. I’m using jQuery animate() method to add the motion to the object. To make the movement to a normal speed, I’m setting the duration of the animation to 0. You can make the movement slow by increasing the duration. Same as in runScoobyForward function, I’ve written the runScoobyBackward function to move the Scooby backward. There I’m deducting a one unit from the left margin so the object will move backward.

Third method is for make the Scooby jump. I’m setting the top margin of the scooby object to –30px so the object will move upwards. To make the jumping looks real, I’m adding easeOutCubic to the animation. Once the animation is done, I’m calling the animate() method once again to move the Scooby to the ground (He can’t jump and stay forever in the air!). To do that, I’m adding 30px for the scooby object and I’m using easeInExpo for the animation so it looks more realistic with the gravity effect. So now the Scooby will back in the ground (-30px + 30px = 0)

Now those are the three methods I’m using to to do the movement of Scooby.

$.connection.hub.start().done(function () {
    $(document).keydown(function (e) {
        switch (e.which) {
            case 32:
                moveScooby.server.moveScoobyUpward();
                break;
            case 37:
                moveScooby.server.moveScoobyBackward();
                break;
            case 39:
                moveScooby.server.moveScoobyForward();
                break;
        }
    });
}
);

Once the connection to hub starts, I’m adding a function to keydown event of the web page. In that function I’m getting the keycode of the key pressed. If it’s the space bar (keycode=32), I’m calling the moveScoobyUpward method in the server. It looks like below

public void moveScoobyUpward()
{
    Clients.All.runScoobyUpward();
}

As you can see, it will in return call the runScoobyUpward() function on all the clients.

If it’s the left arrow (keycode=37), I’m calling the moveScoobyBackward method in the server. It looks like below

public void moveScoobyBackward()
{
    Clients.All.runScoobyBackward();
}

As you can see, it will in return call the runScoobyBackward() function on all the clients.

If it’s the right arrow (keycode=39), I’m calling the moveScoobyForward method in the server. It looks like below

public void moveScoobyForward()
{
    Clients.All.runScoobyForward();
}

As you can see, it will in return call the runScoobyForward() function on all the clients.

So that’s it! As for my markup, I’m simply using an image inside a div. I’ve set a background image for the div.

<body>
    <div style="background-image: url('Images/scooby01.jpg'); background-repeat: no-repeat; height: 438px; width: 584px">
        <img src="Images/aniscooby.gif" id="scooby" width="100" height="100" style="margin-top: 340px;" />
    </div>
</body>

Altogether, following is the complete aspx page markup. Of course there are no code behind code for that. You can surely copy paste this to a simple HTML page and it will work.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UI.aspx.cs" Inherits="SignalRUIChange.UI" %>

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript"
        src="
http://code.jquery.com/jquery-latest.js" charset="utf-8">
    </script>
    <script src="Scripts/jquery-ui-1.10.0.js"></script>
    <script src="Scripts/jquery.signalR-1.0.0.js"></script>
    <script src="/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var moveScooby = $.connection.moveScoobyHub;

            moveScooby.client.runScoobyForward = function () {
                $("#scooby").animate({
                    marginLeft: '+=1'
                }, 0);
            }

            moveScooby.client.runScoobyBackward = function () {
                $("#scooby").animate({
                    marginLeft: '-=1'
                }, 0);
            }

            moveScooby.client.runScoobyUpward = function () {
                $("#scooby").animate({
                    marginTop: '-=30'
                }, 500, 'easeOutCubic', function () {
                    $("#scooby").animate({
                        marginTop: '+=30'
                    }, 500, 'easeInExpo');
                });
            }

            $.connection.hub.start().done(function () {
                $(document).keydown(function (e) {
                    switch (e.which) {
                        case 32:
                            moveScooby.server.moveScoobyUpward();
                            break;
                        case 37:
                            moveScooby.server.moveScoobyBackward();
                            break;
                        case 39:
                            moveScooby.server.moveScoobyForward();
                            break;
                    }
                });
            }
            );
        });
    </script>
</head>
<body>
    <div style="background-image: url('Images/scooby01.jpg'); background-repeat: no-repeat; height: 438px; width: 584px">
        <img src="Images/aniscooby.gif" id="scooby" width="100" height="100" style="margin-top: 340px;" />
    </div>
</body>
</html>

And following is the server side code for the Hub. Note that I’m inheriting it from the SignalR Hub class in order to make it a hub.

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SignalRUIChange
{
    public class MoveScoobyHub: Hub
    {
        public void moveScoobyForward()
        {
            Clients.All.runScoobyForward();
        }

        public void moveScoobyBackward()
        {
            Clients.All.runScoobyBackward();
        }

        public void moveScoobyUpward()
        {
            Clients.All.runScoobyUpward();
        }
    }
}

2013-02-18

Logging with ASP.NET - Part 1 (Configuring log4net)

Here I've shown how to do basic logging with an ASP.NET application. I've used log4net logging provider for that. I'm using Visual Studio 2012 and C#.NET to do the demonstration.

Here is the first part of a video tutorial series I’m hoping to do in log4net. If the text isn’t clear in the demo, please use the HD format and full screen mode.

2013-02-11

Creating a chat application in ASP.NET with SignalR

There are many things we can do with SignalR. It’s never been this easier to build real time web applications. In this post, I’m going to show how to build a chat application and add some additional functionality to it.

First of all, we have to get the SignalR library and include it in our ASP.NET web application. Easiest way to do this is by going to NuGet package manager and install it from there. You can go to the NuGet package manager in Project – > Manage NuGet Packages…

After you install it, you can see there are new script files in the Script folder as well as some new references. Scripts are for the SignalR client library and references are there for SignalR server library.

Now we are ready to develop our application with SignalR.

Let’s start by building the web page. Following is the body section of my HTML page. Note that I’m using a simple HTML page as my chat page.

<body style="border: solid gray; height: 90%;">
    <input type="hidden" id="displayname" />
    <div style="height: 80%;">
        <div id="chats" style="width: 80%; float: left;"></div>
        <div id="onlineList" style="width: 19%; float: right; border-left: solid red 2px; height: 100%;">
            <div style="font-size: 20px; border-bottom: double">Online Users</div>
        </div>
    </div>
    <div style="height: 19%; border-top: double black; background-color: lightgray">
        <div style="float: left; height: 90%; top: 10%; position: relative;">
            <textarea spellcheck="true" id="message" style="width: 625px; height: 80%"></textarea>
        </div>
        <div style="position: relative; top: 30%; float: left;">
            <input type="button" id="sendmessage" value="Send" />
        </div>
        <div style="position: relative; top: 30%; float: left;">
            <select id="users">
                <option value="All">All</option>
            </select>
        </div>
    </div>
</body>

I’m using a hidden field to store the username. A div called ‘chats’ to display the chat messages. A div called ‘onlineList’ to display the online users. At the bottom, I’ve placed the text area along with the send button. Also, I’ve included a dropdown list to display the online users so the user can select to whom (s)he is going to send the message or (s)he can simply select ‘All’ option to send the message to all users.

So that’s the layout of my webpage. Now let’s look at the head section of it.

<head>
    <style>
        .border {
            border-bottom: solid gray 1px;
        }

        .smileys {
            height: 15px;
        }
    </style>

    <title>Chat demo in ASP.NET using SignalR</title>

    <script src="Scripts/jquery-1.6.4.min.js"></script>

    <script src="Scripts/jquery.signalR-1.0.0-rc2.js"></script>

    <!--Reference the autogenerated SignalR hub script. -->
    <script src="/signalr/hubs"></script>

    <script type="text/javascript">
        $(function () {

            var chat = $.connection.chatHub;

            // Get the user name.
            $('#displayname').val(prompt('Enter your name:', ''));

            chat.client.differentName = function (name) {
                // Prompts for different user name
                $('#displayname').val(prompt('Please enter different username:', ''));
                chat.server.notify($('#displayname').val(), $.connection.hub.id);
            };

            chat.client.online = function (name) {
                // Update list of users
                if (name == $('#displayname').val())
                    $('#onlineList').append('<div class="border" style="color:red">You: ' + name + '</div>');
                else {
                    $('#onlineList').append('<div class="border">' + name + '</div>');
                    $("#users").append('<option value="' + name + '">' + name + '</option>');
                }
            };

            chat.client.enters = function (name) {
                $('#chats').append('<div class="border"><i>' + name + ' enters chatroom</i></div>');
                $("#users").append('<option value="' + name + '">' + name + '</option>');
                $('#onlineList').append('<div class="border">' + name + '</div>');
            };

            // Create a function that the hub can call to broadcast chat messages.
            chat.client.broadcastMessage = function (name, message) {
                //Interpret smileys
                message = message.replace(":)", "<img src=\"/emoticons/smile.png\" class=\"smileys\" />");
                message = message.replace(";)", "<img src=\"/emoticons/wink.png\" class=\"smileys\" />");
                message = message.replace(":D", "<img src=\"/emoticons/laugh.png\" class=\"smileys\" />");

                //display the message
                $('#chats').append('<div class="border"><span style="color:blue">' + name + '</span>: ' + message + '</div>');
            };

            chat.client.disconnected = function (name) {
                //Calls when someone leaves the page
                $('#chats').append('<div class="border"><i>' + name + ' leaves chatroom</i></div>');
                $('#onlineList div').remove(":contains('" + name + "')");
                $("#users option").remove(":contains('" + name + "')");
            }

            // Start the connection.
            $.connection.hub.start().done(function () {
                //Calls the notify method of the server
                chat.server.notify($('#displayname').val(), $.connection.hub.id);

                $('#sendmessage').click(function () {
                    if ($("#users").val() == "All") {
                        // Call the Send method on the hub.
                        chat.server.send($('#displayname').val(), $('#message').val());
                    }
                    else {
                        chat.server.sendToSpecific($('#displayname').val(), $('#message').val(), $("#users").val());
                    }
                    // Clear text box and reset focus for next comment.
                    $('#message').val('').focus();
                });

            });
        });
    </script>
</head>

At the head section of the HTML file, I’ve added styles, references to the jQuery library, SignalR library and auto generated SignalR hub script. Next I’ve included the client side functions which are responsible for displaying chats, notify when a user enters or leaves the chat room, sending the chats and maintaining up to date online users list.

Following is the whole code behind responsible for handling the client side events. I have written it in a CS files called ChatHub.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace SingalRTest
{
    public class ChatHub : Hub
    {
        static ConcurrentDictionary<string, string> dic = new ConcurrentDictionary<string, string>();

        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }

        public void sendToSpecific(string name, string message, string to)
        {
            // Call the broadcastMessage method to update clients.
            Clients.Caller.broadcastMessage(name, message);
            Clients.Client(dic[to]).broadcastMessage(name, message);
        }

        public void Notify(string name, string id)
        {
            if (dic.ContainsKey(name))
            {
                Clients.Caller.differentName();
            }
            else
            {
                dic.TryAdd(name, id);

                foreach (KeyValuePair<String, String> entry in dic)
                {
                    Clients.Caller.online(entry.Key);
                }

                Clients.Others.enters(name);
            }
        }

        public override Task OnDisconnected()
        {
            var name = dic.FirstOrDefault(x => x.Value == Context.ConnectionId.ToString());
            string s;
            dic.TryRemove(name.Key, out s);
            return Clients.All.disconnected(name.Key);
        }
    }
}

Now let’s have a look at both the client side events and server side events. First, I’m referencing to my server hub using the below code in client side

var chat = $.connection.chatHub;

Note that I’m using the same name as the class name to refer to the hub. My class, ChatHub is inherited from the SignalR Hub class.

Then I’m prompting the user for a username and I’m storing the username in the ‘displayname’ hidden field. That’s what the below code do

            $('#displayname').val(prompt('Enter your name:', ''));

In code behind, I’m using a concurrent static Dictionary to maintain the online users lists.

static ConcurrentDictionary<string, string> dic = new ConcurrentDictionary<string, string>();

Whenever a user enters the chat room, I’m adding the username as the key and connection ID as the value to that dictionary. That’s what the below server side method do

        public void Notify(string name, string id)
        {
            if (dic.ContainsKey(name))
            {
                Clients.Caller.differentName();
            }
            else
            {
                dic.TryAdd(name, id);

                foreach (KeyValuePair<String, String> entry in dic)
                {
                    Clients.Caller.online(entry.Key);
                }

                Clients.Others.enters(name);
            }
        }

As you can see, I’m passing two parameters, name and id.

As soon as the connection made with the server, I’m calling that method.

$.connection.hub.start().done(function () {
    //Calls the notify method of the server
    chat.server.notify($('#displayname').val(), $.connection.hub.id);
.............................................……………………………………..

As you can see from the above code, I’m passing the username I’ve stored in the hidden field and I’m passing the unique ID which was generated when the connection has been made with the server.

If the Dictionary already contains the username entered, I’m calling the method diiferentName for the Caller. Note that I’m calling that method ONLY to the calling client. That’s why I’ve used Client.Caller. So now, it will call the differentName method in the client side for the Caller Client. Following is the differentName method in my client side script.

chat.client.differentName = function (name) {
    // Prompts for different user name
    $('#displayname').val(prompt('Please enter different username:', ''));
    chat.server.notify($('#displayname').val(), $.connection.hub.id);
};

As you can see, I’m prompting again for a different username. Then I’m again calling the Notify method in the server by passing the new username and connection ID.

If there is no user by that name, then it will add the username to the Dictionary.

dic.TryAdd(name, id);

Then I have to display the online list to the just entered client. For that, I’m calling the online method for the Caller Client. Note that, online client function will only get called for the calling client, not for all the clients.

foreach (KeyValuePair<String, String> entry in dic)
{
    Clients.Caller.online(entry.Key);
}

For each user in the list, I’m calling the online function. Below is that function

chat.client.online = function (name) {
    // Update list of users
    if (name == $('#displayname').val())
        $('#onlineList').append('<div class="border" style="color:red">You: ' + name + '</div>');
    else {
        $('#onlineList').append('<div class="border">' + name + '</div>');
        $("#users").append('<option value="' + name + '">' + name + '</option>');
    }
};

As you can see, if the name equals to the caller client, I’m adding a You: in front of the name and it will get displayed in red color. Otherwise I’m just appending the usernames to the onlineList div and adding an option to the dropdown list.

For the rest of the clients, I’m notifying that a new user enters the chat room. For that, I’m using the below code

Clients.Others.enters(name);

Note that I’m using Clients.Others, which will display the message to all the connected clients except the caller (There is no point of notifying the caller that (s)he just entered to the chat room). So I am calling the enters method in the client side and I’m passing the username so I can notify others who has just entered to the chat room. Following is the enters function.

chat.client.enters = function (name) {
    $('#chats').append('<div class="border"><i>' + name + ' enters chatroom</i></div>');
    $("#users").append('<option value="' + name + '">' + name + '</option>');
    $('#onlineList').append('<div class="border">' + name + '</div>');
};

As you can see, I’m showing username enters chatroom in the chats div. For rest of the clients, I have to update the online users list too. So I’m going to do that in the enters method by appending the new user name to the onlineList div and adding a new option to the users dropdown list.

Now that’s what happened when a client made a connection with the server, in this example, when the user joins the chat room. Now let’s see how to send the chat messages to users. For that, I’ve bound the below client side function to the Send button.

$('#sendmessage').click(function () {
    if ($("#users").val() == "All") {
        // Call the Send method on the hub.
        chat.server.send($('#displayname').val(), $('#message').val());
    }
    else {
        chat.server.sendToSpecific($('#displayname').val(), $('#message').val(), $("#users").val());
    }
    // Clear text box and reset focus for next comment.
    $('#message').val('').focus();
});

In the dropdown list, if the user has selected “All” option, then I’m calling the Send method in the server. I’m passing the username along with the text in the message textarea. Following is the send method in the server

public void Send(string name, string message)
{
    // Call the broadcastMessage method to update clients.
    Clients.All.broadcastMessage(name, message);
}

It will accept the two parameters and it will call the broadcastMessage function for all the clients. Since the user has selected “All” option in the dropdown list, now it will send the message to all the connected clients. The broadcastMessage function will get called for all the clients.

chat.client.broadcastMessage = function (name, message) {
    //Interpret smileys
    message = message.replace(":)", "<img src=\"/emoticons/smile.png\" class=\"smileys\" />");
    message = message.replace(";)", "<img src=\"/emoticons/wink.png\" class=\"smileys\" />");
    message = message.replace(":D", "<img src=\"/emoticons/laugh.png\" class=\"smileys\" />");

    //display the message
    $('#chats').append('<div class="border"><span style="color:blue">' + name + '</span>: ' + message + '</div>');
};

As you can see, it will accept the two parameters which were passed from the server. First it will check for the smiley syntaxes in the message and replace those with emoticons. Smile

After building the final message with the images, I’m appending it to the chats div along with the username. Now all the clients will get the message with the username!

Now let’s move on to the part where a user can send messages only to specific user (not all the clients). For that I’m calling the sendToSpecific server side method. As you can see from the Send button event, if the value selected in the dropdown list is not “All”, I’m calling the sendToSpecific method by passing the caller name, message and the callee name (The selected value in the dropdown list). My sendToSpecific method looks like below

public void sendToSpecific(string name, string message, string to)
{
    // Call the broadcastMessage method to update clients.
    Clients.Caller.broadcastMessage(name, message);
    Clients.Client(dic[to]).broadcastMessage(name, message);
}

Since now I need to display the message only between two users, I’m calling the Clients.Caller.broadcastMessage and Clients.Client(dic[to]).broadcastMessage. By calling the Clients.Caller.broadcastMessage, I’m displaying the message to the caller. By calling the below line, I’m displaying the message ONLY to the particular client. That’s why I’m passing the connection ID of that client to the Client method.

Clients.Client(dic[to]).broadcastMessage(name, message);

I’m passing the callee name to the Dictionary so it will return the connection ID associated for that username. Now it will broadcast the message only to that specific client.

So that’s how we can broadcast messages between two specific clients. Now let’s move to the final part, what will happen when a user leaves the chat room? Pretty simple, I will need to remove that username from the online user lists and from the dropdown list in client side and I will need to remove the particular dictionary entry associated for that user from the server side. Let’s see how to do that.

There is a server side method in the SignalR library, called OnDisconnected(), which will get called whenever the connection get closed from a client. So we can handily use that for our purpose here.

public override Task OnDisconnected()
{
    var name = dic.FirstOrDefault(x => x.Value == Context.ConnectionId.ToString());
    string s;
    dic.TryRemove(name.Key, out s);
    return Clients.All.disconnected(name.Key);
}

As you can see, first I’m removing the entry in the dictionary associated with that username. Then I’m calling the disconnected client side function for all the clients.

chat.client.disconnected = function (name) {
    //Calls when someone leaves the page
    $('#chats').append('<div class="border"><i>' + name + ' leaves chatroom</i></div>');
    $('#onlineList div').remove(":contains('" + name + "')");
    $("#users option").remove(":contains('" + name + "')");
}

From the disconnected function, I’m simply notifying all the clients that particular user leaves the chat and then remove his/her name from both the online list and dropdown list.

Well, that’s how we can simply create a chat application in ASP.NET with SignalR. SmileFollowing are some screenshots of running application

Untitled

leaves