DEU Bilgisayar Topluluğu Izmir 2. Teknoloji Zirvesi

DEU Bilgisayar Topluluğu Izmir 2. Teknoloji Zirvesi: if you are in Izmir this weekend (5 – 6 January, 2013), don’t miss this event.
2013-01-03 10:43
Tugberk Ugurlu


If you are in Izmir this weekend (5 – 6 January, 2013), don’t miss this event. Me, Fatih Boy, İlkay İlknur and Umut Erkal will be giving talks on several interesting topics.

Facebook event page: http://www.facebook.com/events/189388904534737

A_cVGTvCYAAXvL5

Mapping ASP.NET SignalR Connections to Real Application Users

One of the common questions about SignalR is how to broadcast a message to specific users and the mapping the SignalR connections to your real application users is the key component for this.
2013-01-01 15:32
Tugberk Ugurlu


SignalR; the incredible real-time web framework for .NET. You all probably heard of it, maybe played with it and certainly loved it. If you haven’t, why don’t you start by reading the SignalR docs and @davidfowl’s blog post on Microsoft ASP.NET SignalR? Yes, you heard me right: it’s now officially a Microsoft product, too (and you may see as a bad or good thing).

One of the common questions about SignalR is how to broadcast a message to specific users and the answer depends on what you are really trying to do. If you are working with Hubs, there is this notion of Groups which you can add connections to. Then, you can send messages to particular groups. It’s also very straight forward to work with Groups with the latest SignalR server API:

public class MyHub : Hub
{
    public Task Join()
    {
        return Groups.Add(Context.ConnectionId, "foo");
    }

    public Task Send(string message)
    {
        return Clients.Group("foo").addMessage(message);
    }
}

You also have a chance to exclude some connections within a group for that particular message. However, if you have more specific needs such as broadcasting a message to user x, Groups are not your best bet. There are couple of reasons:

  • SignalR is not aware of any of your business logic. SignalR knows about currently connected connections and their connection ids. That’s all.
  • Assume that you have some sort of authentication on your application (forms authentication, etc.). In this case, your user can have multiple connection ids by consuming the application with multiple ways. So, you cannot just assume that your user has only one connection id.

By considering these factors, mapping the SignalR connections to actual application users is the best way to solve this particular problem here. To demonstrate how we can actually solve this problem with code, I’ve put together a simple chat application and the source code is also available on GitHub.

image

This application obviously not a production ready application and the purpose here is to show how to achieve connection mapping. I didn’t even use a persistent data storage technology for this demo.

The scenarios I needed to the above sample are below ones:

  • A user can log in with his/her username and can access to the chat page. A user also can sign out whenever they want.
  • A user can see other connected users on the right hand side at the screen.
  • A user can send messages to all connected users.
  • A user can send private messages to a particular user.

To achieve the first goal, I have a very simple ASP.NET MVC controller:

public class AccountController : Controller {

    public ViewResult Login() {

        return View();
    }

    [HttpPost]
    [ActionName("Login")]
    public ActionResult PostLogin(LoginModel loginModel) {

        if (ModelState.IsValid) {

            FormsAuthentication.SetAuthCookie(loginModel.Name, true);
            return RedirectToAction("index", "home");
        }

        return View(loginModel);
    }

    [HttpPost]
    [ActionName("SignOut")]
    public ActionResult PostSignOut() {

        FormsAuthentication.SignOut();
        return RedirectToAction("index", "home");
    }
}

When you hit the home page as an unauthenticated user, you will get redirected to login page to log yourself in. As you can see from the PostLogin action method, everybody can authenticate themselves by simply entering their name which is obviously not what you would want in a real world application.

As I am hosting my SignalR application under the same process with my ASP.NET MVC application, the authenticated users will flow through the SignalR pipeline, too. So, I protected my Hub and its methods with the Microsoft.AspNet.SignalR.Hubs.AuthorizeAttribute.

[Authorize]
public class ChatHub : Hub { 

    //...
}

As we are done with the authorization and authentication pieces, we can now move on and implement our Hub. What I want to do first is to keep track of connected users with a static dictionary. Now, keep in mind again here that you would not want to use a static dictionary on a real world application, especially when you have a web farm scenario. You would want to keep track of the connected users with a persistent storage system such as MongoDB, RavenDB, SQL Server, etc. However, for our demo purposes, a static dictionary will just work fine.

public class User {

    public string Name { get; set; }
    public HashSet<string> ConnectionIds { get; set; }
}

[Authorize]
public class ChatHub : Hub {

    private static readonly ConcurrentDictionary<string, User> Users 
        = new ConcurrentDictionary<string, User>();
        
    // ...
}

Each user will have a name and associated connection ids. Now the question is how to add and remove values to this dictionary. SignalR raises three particular events on your hub: OnConnected, OnDisconnected, OnReconnected and the purposes of these events are very obvious.

During OnConnected event, we need to add the current connection id to the user’s connection id collection (we need to create the User object first if it doesn’t exist inside the dictionary). We also want to broadcast this information to all clients so that they can update their connected users list. Here is how I implemented the OnConnected method:

[Authorize]
public class ChatHub : Hub {

    private static readonly ConcurrentDictionary<string, User> Users 
        = new ConcurrentDictionary<string, User>();
        
    public override Task OnConnected() {

        string userName = Context.User.Identity.Name;
        string connectionId = Context.ConnectionId;

        var user = Users.GetOrAdd(userName, _ => new User {
            Name = userName,
            ConnectionIds = new HashSet<string>()
        });

        lock (user.ConnectionIds) {

            user.ConnectionIds.Add(connectionId);
            
            // TODO: Broadcast the connected user
        }

        return base.OnConnected();
    }
}

First of all, we have gathered the currently authenticated user name and connected user’s connection id. Then, we look inside the dictionary to get the user based on the user name. If it doesn’t exist inside the dictionary, we create one and set it to the local variable named user. Lastly, we add the connection id and updated the dictionary.

Notice that we have a TODO comment at the end telling that we need to broadcast the connected user’s name. Obviously, we don’t want to broadcast this information to the caller itself. However, we still have two options here and which one you would choose may depend on your case. As the user might have multiple connections, broadcasting this information over Clients.Others API is not a way to follow. Instead, we can use Clients.AllExcept method which takes a list of connection ids as parameter to exclude. So, we can pass the all connection ids of the user and we are good to go.

public override Task OnConnected() {

    // Lines omitted for brevity
    
    Clients.AllExcept(user.ConnectionIds.ToArray()).userConnected(userName);

    return base.OnConnected();
}

This is a fine approach if we want to broadcast each connection of the user to every client other than the user itself. However, we may only want to broadcast the first connection. Doing so is very straight forward, too. We just need to inspect the count of the connection ids and if it equals to one, we can broadcast the information. This approach is the one that I ended up taking for this demo.

public override Task OnConnected() {

    // Lines omitted for brevity

    lock (user.ConnectionIds) {

        // Lines omitted for brevity
        
        if (user.ConnectionIds.Count == 1) {

            Clients.Others.userConnected(userName);
        }
    }

    return base.OnConnected();
}

When the disconnect event is fired, OnDisconnected method will be called and we need to remove the current connection id from the users dictionary. Similar to what we have done inside the OnConnected method, we need to handle the fact that user can have multiple connections and if there is no connection left, we want to remove the user from Users dictionary completely. As we did when a user connection arrives, we need to broadcast the disconnected users, too and we have the same two options here as well. I added both to the below code and commented out the one that we don’t need for our demo.

[Authorize]
public class ChatHub : Hub {

    private static readonly ConcurrentDictionary<string, User> Users 
        = new ConcurrentDictionary<string, User>();

    public override Task OnDisconnected() {

        string userName = Context.User.Identity.Name;
        string connectionId = Context.ConnectionId;
        
        User user;
        Users.TryGetValue(userName, out user);
        
        if (user != null) {

            lock (user.ConnectionIds) {

                user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));

                if (!user.ConnectionIds.Any()) {

                    User removedUser;
                    Users.TryRemove(userName, out removedUser);

                    // You might want to only broadcast this info if this 
                    // is the last connection of the user and the user actual is 
                    // now disconnected from all connections.
                    Clients.Others.userDisconnected(userName);
                }
            }
        }

        return base.OnDisconnected();
    }
}

When the OnReconnected method is invoked, we don’t need to perform any special logic here as the connection id will be the same. With these implementations, we are now keeping track of the connected users and we have mapped the connections to real application users.

Going back to our scenarios list above, we have the 4th requirement: a user sending private messages to a particular user. This is where we actually need the connection mapping functionality. As an high level explanation, the client will send the name of the user that s/he wants to send the message to privately. So, server needs to make sure that it is only sending the message to the designated user. I am not going to go through all the client code (as you can check them out from the source code and they are not that much related to the topic here) but the piece of JavaScript code that actually decides whether to send a public or private message is as below:

$sendBtn.click(function (e) {

    var msgValue = $msgTxt.val();
    if (msgValue !== null && msgValue.length > 0) {

        if (viewModel.isInPrivateChat()) {

            chatHub.server.send(msgValue, viewModel.privateChatUser()).fail(function (err) {
                console.log('Send method failed: ' + err);
            });
        }
        else {
            chatHub.server.send(msgValue).fail(function (err) {
                console.log('Send method failed: ' + err);
            });
        }
    }
    e.preventDefault();
});

The above code inspects the KnockoutJS view model to see if the sender is at the private chat mode. If s/he is, it invokes the send hub method on the sever with two parameters which means that this will be a private message. If the sender is not at the private chat mode, we will just invoke the send hub method by passing only one parameter for the message. Let’s first look at Send Hub method that takes one parameter:

public void Send(string message) {

    string sender = Context.User.Identity.Name;

    Clients.All.received(new { 
        sender = sender, 
        message = message, 
        isPrivate = false 
    });
}

Inside the send method above, we first retrieved the sender's name through the authenticated user principal. Then, we are broadcasting the message to all clients with a few more information such as the sender name and the privacy state of the message. Let’s now look at the second Send method inside the Hub whose job is to send private messages:

public void Send(string message, string to) {

    User receiver;
    if (Users.TryGetValue(to, out receiver)) {

        User sender = GetUser(Context.User.Identity.Name);

        IEnumerable<string> allReceivers;
        lock (receiver.ConnectionIds) {
            lock (sender.ConnectionIds) {

                allReceivers = receiver.ConnectionIds.Concat(
                    sender.ConnectionIds);
            }
        }

        foreach (var cid in allReceivers) {
        
            Clients.Client(cid).received(new { 
                sender = sender.Name, 
                message = message, 
                isPrivate = true 
            });
        }
    }
}

private User GetUser(string username) {

    User user;
    Users.TryGetValue(username, out user);

    return user;
}

Here, we are first trying to get the receiver based on the to parameter that we have received. If we find one, we are also retrieving the sender based on the his/her name. Now, we have the sender and the receiver in our hands. What we want is to broadcast this message to the receiver and the sender. So, we are putting the sender’s and the receiver’s connection ids together first. Finally, we are looping through that connection ids list to send the message to each connection by using the Clients.Client method which takes the connection id as a parameter.

When we try this out, we should see it working as below:

image

Grab the solution and try it yourself, too. I hope this post helped you to solve your problem Smile

References

Pro ASP.NET Web API's Sample Project (PingYourPackage) Source Code is Up on GitHub

We wanted to give you an early glimpse on the Pro ASP.NET Web API's sample application(PingYourPackage) and its source code is now up on GitHub.
2012-12-20 21:32
Tugberk Ugurlu


You may know that I have been co-authoring a book on ASP.NET Web API for a while now and it is available as an alpha book if you would like to get the early bits and pieces. One of the aim’s of this book is to provide a well-structured resource for ASP.NET Web API and also to give you a hint on how you would go and build a real world application with this super-awesome framework. In order to make our second goal easy, we have dedicated 3 chapters to build a real world HTTP API from scratch for a small city delivery company and we called it PingYourPackage. These three chapters will be covering the application structure, building the data layer, building and testing the core API layer, creating the .NET wrapper around this API and consuming this through an ASP.NET MVC 4 web application.

Although the writing process for those chapters are still not completed, we wanted to give you an early glimpse on the sample application and the source code of the project is now up on GitHub.

image

If you are not familiar with GitHub and Git, I recommend watching the Phil Haack’s talk on Git and GitHub for Developers on Windows and its more hardcore version from Keith Dahlby: Git More Done.

After cloning the source code, you can either directly build the project through the Visual Studio 2012 (or Web Developer Express) or you can run the build script. You can open up the entire solution by double clicking the PingYourPackage.sln file and build it from there.

image

To run the build script, open up a PowerShell console and make sure your execution policy is not restricted. When you run the .\scripts\build.ps1 script, it will install the missing NuGet packages, build the entire application and runs the unit/integration tests. The output will be put under .\artifacts folder.

image

As mentioned, it’s not completely done yet but the server level code is complete. The .NET wrapper and web client will be there so soon.

Enjoy Winking smile

Why am I not Using NancyFx Instead of ASP.NET MVC / Web API

Why am I not using NancyFx instead of ASP.NET MVC / Web API? Because of a very important and vital missing part with NancyFx: asynchrony!
2012-12-18 19:50
Tugberk Ugurlu


Note: If you don't understand asynchrony and its benefits, you are better off without this blog post. If you are willing to learn the importance of asynchrony for server applications, here are two videos for you to start:

Update 2013-10-08:

Great news! NancyFx now has asyncronous processing ability. See Jonathan Channon's post for more details: Async Route Handling with Nancy 

Server side .NET ecosystem is not just about the frameworks that Microsoft builds and ships such as ASP.NET MVC, ASP.NET Web API, etc. There are other open source frameworks out there such as NancyFx which has been embraced by the community. I haven’t played with NancyFx that much but I really wanted to understand how it is more special than its equivalent frameworks. As far as I can tell, it’s not but I am nowhere near to make that judgment because I only spared 10 minutes to figure that out, which is obviously not enough to judge a framework. Why and where did I stop? Let’s get to that later.

You may have also noticed that I have been kind of opinionated about ASP.NET Web API lately. It’s not because I am writing a book on ASP.NET Web API. The reason of my passion is related to fact that I know how it works internally and I can see that none of the other equivalent frameworks hasn’t been able to get asynchrony right as this framework did (SignalR also gets asynchrony right but it’s kind of a different area)! Please do inform me and make me happy if you think that there is any other framework which we can put under this category. I didn’t put ASP.NET MVC under this category either because it’s not possible to go fully asynchronous throughout the pipeline with ASP.NET MVC. However, it’s has a really nice asynchronous support for most of the cases.

I’m not going to get into the details of how asynchrony is important for a server application because I have tried to do that several times. Let’s stick with the topic: why am I not using NancyFx instead of ASP.NET MVC / Web API? Don’t get me wrong here. NancyFx is a great framework as far as I can see and I’m all supportive for any .NET open source project which makes it easy to get our job done. @TheCodeJunkie and the other NancyFx members have been doing a great job on maintaining this awesome open source framework. However, there is a very important missing part with this framework and it’s vital to any server application: asynchrony! We are now about to see why this is important.

I have created two applications which do the same thing in a different way: downloading the data over HTTP and return it back as a text. I used NancyFx to create one of these applications and this application will make the HTTP call synchronously because there is no way to do it asynchronously with NancyFx. The other application has been implemented using ASP.NET Web API and the only difference will be that it will make the HTTP call asynchronously.

It’s fairly straight forward to get started with NancyFx. I jumped to one of the framework’s documentation page and I was good to go by installing the NuGet package and adding the following module. It was a nice and quick start.

public class HelloModule : NancyModule {

    public HelloModule() {

        Get["/"] = (p) => {

            using (var client = new WebClient()) {
                var textData = client.DownloadString("http://localhost:52907/api/cars");
                return textData;
            }
        };
    }
}

I used WebClient on both applications here because HttpClient has no synchronous methods and making blocking calls with HttpClient has some overheads. I also created an ASP.NET Web API application which does the same thing but asynchronously.

public class DefaultController : ApiController {

    public async Task<string> Get() {

        using (var client = new WebClient()) {

            var textData = await client.DownloadStringTaskAsync(
                "http://localhost:52907/api/cars");

            return textData;
        }
    }
}

As you can see, it’s extremely easy to write asynchronous code with the ".NET 4.5 + C# 5.0 + ASP.NET Web API" combination. You probably noticed that I am making a call against http://localhost:52907/api/cars. This is a simple HTTP API which takes minimum 500 milliseconds to return. This wait is is on purpose to simulate a a-bit-long-running call. Let me also be clear on why I’ve chosen to make a comparison by making an HTTP call. This really doesn’t matter here. Any type of I/O operation could have been a perfect case here but an HTTP call scenario is simple to demonstrate.

Finally, I now have an endpoint on http://localhost:47835 for NancyFx application and another on http://localhost:49167 for ASP.NET Web API application. I have opened up a command line console and get the ab.exe (Apache HTTP Server Benchmarking Tool) under my path. When I generate a request for each one (only one request), I will have a result which is similar to the below screenshot (NancyFx is the lest side, ASP.NET Web API is the right side).

image

Notice that both have taken approx. the same amount of time to complete the request but this’s not the place where asynchrony shines. Let’s now generate totally 200 request (30 concurrent requests at a time) to each endpoint and see the result (NancyFx is the lest side, ASP.NET Web API is the right side).

image

15.31 requests per second with NancyFx + synchronous processing and 49.35 requests per second with ASP.NET Web API + asynchronous processing. Besides the fact that this’s totally an on-the-fly benchmarking (I’m not even sure whether we can call this a benchmark) on my Windows 8 machine, the result is pretty compelling.

Let’s now have a look at the reason why I stopped discovering NancyFx further. Go to NancyFx GitHub repository and navigate to Nancy.Hosting.Aspnet.NancyHttpRequestHandler class file. This is located under the ASP.NET host project for NancyFx and actually the HTTP handler the framework uses to process requests. Earlier today I tweeted after I had a look at this class:

image

Yes, it’s sitting right there. By exposing the framework with a normal handler implementation instead of the IHttpAsyncHandler implementation, you are making your ASP.NET framework suffer. It’s possible for you to handle synchronous calls with an asynchronous handler but it’s impossible (or either not right and easy) to do this with a normal handler. On the other hand, we know that NancyFx doesn’t only have an ASP.NET host option. You can even host this framework under katana with its OWIN Host implementation but it’s not going to matter unless the framework itself has asynchronous processing capabilities and by looking at the above handler and this issue, I can see that it doesn’t have that.

This is not an I-hate-you-and-I-will-stay-that-way-forever-please-go-the-hell-away blog post. Again: NancyFx is a great project and it deserves a good amount of respect. However, this post explains my reason on why I am not using NancyFx instead of ASP.NET Web API or ASP.NET MVC. Will it going to change? Unless #148 is not fixed, it is certainly not. Even if it is fixed, I already have applications running on ASP.NET Web API and ASP.NET MVC. Why bother then? We will see that in the future.

SignalR - Real-time Web Applications Webcast Recording (In Turkish) is Available

SiganlR - Real-time Web Applications webcast recording (in Turkish) is available. The video is available on NedirTV and Vimeo.
2012-11-14 08:57
Tugberk Ugurlu


A week ago, we tried to organize a webcast on ASP.NET SignalR and the network connection was very poor again. So, the participation was low but I managed to record it successfully. The video is now available on NedirTV: SignalR - Gerçek Zamanlı Web Uygulamaları.

Source code is also available under my GitHub account: https://github.com/tugberkugurlu/SignalRWebcast201211

You can also watch it on Vimeo:

SignalR - Gerçek Zamanli Web Uygulamalari from Tugberk Ugurlu on Vimeo.

Enjoy Smile