Wednesday, October 31, 2012

How to make sure your laptop is still portable

A year ago I was buying a new personal laptop, which would be used for all personal tasks (web, email, music, movies), hobby development projects and occasional gaming.The decision at that time was to buy the biggest and most powerful (well, at least big and powerful enough) laptop out there, for those reasons:
  • For the mentioned tasks, I needed computing power
  • I think the bigger the screen(s) - the better.
  • At that point in my life, I was trying to not buy any more stuff, than I needed, to be able to move with relative ease - that meant no external monitors.
  • My laptop moved only between my living room and bedroom, so size/weight didn't matter
I've  ended up buying Dell XPS 17 (17"@FullHD/i7/6GB RAM/GT555M 3 GB/2x500GB HDD), with which I was quite happy at that time.

As everything in life - the situation changed now - I'm working from home, so I needed to buy external monitors for productivity, so the screen size on the laptop itself doesn't really matter. And as I'm connecting to a remote machine to do the actual work on - the computing power of the laptop itself doesn't matter that much. Plus, I'm traveling around 30% of my time, which means, that I have to carry this laptop around quite a lot.

Given all of the changes above, there are no more reasons for me to have this huge beast, but this blog post is not about my need to change hardware.

I have realized, that I almost never remove my laptop from my desk now (except when I'm traveling). Even though I'd maybe like to watch a movie in some different location, or work in my balcony. When I started analyzing the possible reason, I discovered, that the main reason is not the size or weight of the laptop - the main thing is.... all the external devices connected to it (two monitors, printer, headset, microphone and a charger), which means, that I'd have to disconnect all of these and then reconnect them again each time I move my laptop somewhere else. And this wouldn't change even if the laptop was a 10" ultraportable.

The solution obviously is a docking station. What came as a surprise to me, even if your laptop doesn't have a docking port, you can still buy a universal USB docking station (like this one), which will not only connect your network, USB and audio, but even a monitor or two. The only drawback in these is that they won't charge your laptop, but hey, I'd still be down from 6+ cables to only two.



Sunday, June 10, 2012

SignalR: finding your clients

As SignalR is all about server-to-client communications, obviously, it's important to be able to find your clients, that your server wants to talk to. There are several scenarios for this, depending on what you're aiming to achieve and are inside a hub, or outside it.
One of the most simple cases, is when your inside a hub and just want to call a method on the client, that just called the server side method - there's a Caller property on the hub object, which gives you a dynamic reference to a calling client, so you can do something like this:
Caller.populateOrders(orders);
If instead you'd like to execute a method on all of your clients, that's also quite easy - just use Clients property on the hub:
Client.removeOrder(id);
What if you want to invoke a method only on a subset of your clients? Well, first, you have to add those clients into specific groups yourself, like this:
// this is how we obtain unique identifier for a current client
string clientId = Context.ConnectionId;
Groups.Add(clientId, "myGroupName1");
// we can add the same client to as many groups as we want
Groups.Add(clientId, "myGroupName2");
And then we can invoke methods on all the clients, belonging to a specific group:
Clients["myGroupName2"].removeOrder(orderId);
Using the same syntax, we can also reach individual clients, by their ID:
Clients[destinationClientConnectionId].privateMessageReceived(message);
This is all nice and easy, as long as you're inside a hub. What if you're not?
First, you need to achieve a reference, to IHubContext object, which then has same properties Clients and Groups, as a Hub object does and youll know what to do from there.
This is fairly simple - just call this static method:
SignalR.GlobalHost.ConnectionManager.GetHubContext();
And this is it - you can now reach all your clients, as if you were in a hub!

Monday, May 7, 2012

SignalR: client disconnects

It is often neccessary to take action, when we lose connection with a client - at least notify the user, that they're disconnected and should not expect any further real-time updates. It turns out, that it's really simple to do that with SignalR, as described in the link below:
Stackoverflow: How to determine server disconnection

So don't leave your users out there, without any notification, when a disconnect occurs :)

Saturday, April 21, 2012

SignalR: Handling results returned from server to JS

So, when we're calling server methods from our JS code, obviously, most of the times there will be some kind of result from this call - be it data returned from the server, or even if your method does not return any data - it can always return errors.
For the happy path scenarios, to get the data returned from the server just, we just need to call "done()" function of the object, returned from the hub method, and pass happy path callback to it.
hub.getOrders().done(function(orders){
    // populate some list with orders
});
In my initial post, I've used a different approach - I used a callback, which was called from server method, to return results to the client, simply because I was not aware of this "done()" method.
As for errors, you can access them too, using "fail()" function, like this:
hub.getOrders().done(function(orders){
    // populate some list with orders
})
.fail(function (e) {
    // handle error
});
The function parameter e contains the message of exception being thrown (that's the scenario I've tested) - or if it's just HTTP erorr - I'd guess it'll contain HTTP status message. It would be usefull to have a little bit more info in the fail method, like HTTP status code, or exception type name.

Hope this short post will be useful to someone looking how to handle errors.

Monday, February 13, 2012

SignalR: My journey into .NET Server-to-Client communications - first bumps on the road

SignalR itself says that it's an async signalling library for .NET, but I see it as a very convenient way to call JS functions from server-side and server-side functions from JS.  The official page is here. I have first read about this library in Scott Hanselman's blog and as I'm now starting a new hobby-project, I've decided to try it out.

SignalR has its NuGet package, so I've installed it from there.

Before moving to anything more complex, I wanted to create a simple, "proof-of-concept", where the client just sends a message to the server, when the page is loaded and server replies back with some initial set of data. Again, for this initial phase, I'm trying to keep things simple, so I'm using Hubs. My initial hub is here:
    [HubName("myHub")]
    public class MyHub: Hub
    {
        public void Register()
        { 
            var result = new Order[] {
                new Order
                {
                    OrderId = 1,
                    Product= "lorem"
                },
                new Order
                {
                    OrderId = 2,
                    Product = "ipsum"
                }
            };
            Caller.registerCallback(result);
        }
    }
Now, here it's all pretty simple: we inherit the class from SignalR.Hubs.Hub, to indicate that it's a hub. A hub is the class, which will receive communications from the client side. We're also decorating it with HubName attribute, which specifies the name of our hub, which we'll use in JS and the ending of our url for cummunications.

The class contains a single method - Register (I could have chosen any name I want) which will be called from the client side and return a hard-coded list of orders via a client callback. See the Caller property, that I'm using to invoke the registerCallback? (that's the name of the function, which we'll define in JS, which will handle our results) It is used to communicate only with the client, which just invoked our method - and it's all automatic :)

Next comes our client side part:

var hub;
$(document).ready(function () {
     hub = $.connection.myHub;

     hub.addOrder = function (addOrderMessage) {
        $(".orderList").append("<li id='" + addOrderMessage.OrderId + "'>" + addOrderMessage.Product+ "</li>");
    };

    hub.registerCallback = function (initialListOfOrders) {
        for (var i = 0; i < initialListOfOrders.length; i++) {
            var order = initialListOfOrders[i];
            hub.addOrder(order);
        }
    };

    $.connection.hub.start(function () { hub.register(); });
});
Again, code is simple enogh - after the page is loaded, we're assigning our hub to a local variable. Then, we're defining two functions on our hub (which both can be invoked from the server side) - addOrder, which takes a single order and adds it to the list and registerCallback, which gets initial list of order.
And on the last line, we're starting the communication process. And that's where I initially hit my first bump.
You see, the example in Scott's blog post starts the hub without passing any function to the start method. Some other exmaples did the same. So initially the ending of my script looked like this:

    ...
    $.connection.hub.start();
    hub.register();

But instead of registering with the server, script threw an exception on hub.register, which stated that:
SignalR: Connection must be started before data can be sent. Call .start() before .send()
Which was rather confusing, given that I was calling my register() method just after calling hub.start(). To make things worse, all the other examples I had, were working perfectly, so I rejected the idea that something is missing in my hosting environment. And it seemed, that nobody else was seeing this issue.
And then I realized - Scott's example isn't calling anything on the hub immediately after it is started - his app only calls hub method on events from the user - and that gives the hub plenty of time to initialize. So after some more googling, I've found, that hub.start() has a callback, which is invoked after the hub is initialized.

Now, you're probably wondering, how does my JS code know about this $.connection.myHub, which I've declared on the server-side? In order for this to work, I need to include two JS files:

<script src="@Url.Content("~/Scripts/jquery.signalR.js")" type="text/javascript"></script>
<script src="@Url.Content("~/signalr/hubs")" type="text/javascript"></script>

The first one is the signalR JQuery plugin. And the second one.... if you'll check your source folder, you won't find anything like it, but it's generated at the runtime by SignalR and includes all the hubs you've delcared.

So that's it for my first post (hopefully - out of many) about SignalR. So far, I'm really happy with this library, as it provides a very simple way for .NET developers to get a very smooth user experience.

Who am I and what will this blog be about

About
To those of you, who do not know me personally - my name is Tomas, and I'm a .NET software developer, currently working and living in the Republic of Ireland. I'm usually mostly interested in the server-side of things and in services (ASMX WS, WCF etc) in particular, because I think that I lack this essential attention to details, needed to write good user-facing code. On the other hand, I've work for several years as a front-end developer - and everyone seeemed happy enough.

What is this blog about?
This blog will be for my software development related talks, usually perhaps related to some explorations into new (to myself at least) technologies, or about some technical problems, which I've successfully solved and whose solution might help some lost soul on the internet.

Why English?
Now this might not be a natural question to those of you, who don't know me. You see, I am a Lithuanian, and so my mother tongue might look like an obvious choice for the language of this blog, but for several reasons, I've decided to write this blog in english. Why?

  • First and foremost - this way I can possibly reach the largest number of readers, as most of software developers know English quite well. I myself search for technical articles only in English. So, if any of the posts here can be of any help to someone - this hugely increases my chances of reaching that  someone .
  • Another reason, although not as important as the first one, is to continually improve my English, so please, those of you, that are native English speakers and see any big mistakes in my writings - please be so kind to let me know about them in the comments.
What will not be published here
I will not be talking here about anything related to my day-to-day work. Even though technologies might sometimes be similar to those I use during my work hours (hey, I'm .NET dev during the daytime too!), but I am only blogging about things, that I do in my free-time.