Handling in LightSwitch commands in less than 10 lines of code.
Introduction
I elaborated some months ago and approach for sending command from client to server in LightSwitch because I thought we should start being serious about the command table pattern.
The approach was more or less ok, but quite incompatible with the idea of simplicity in LightSwitch. In other words, it was too cumbersome to set things up, etc. ..
I’m happy I can come up now with something new and based on both a very serious improvement in the LightSwitch base architecture and on a brilliant library called “SignalR”.
The improvent in LightSwitch is the recent introduction of the ServerApplicationContext class. This allows you to break into (but in a completely secure way) the LightSwitch application context from outside LightSwitch. For example from a web page or from a WCF dataservice. Jan Van der Haegen has a great post on how to do this. (executing-an-arbitrary-method-or-long-running-process-on-the-lightswitch-server)
The next building block is the SignalR library. This post is not a tutorial on SignalR. I will only focus on how to use it in LightSwitch. I kindly refer to the SignalR documentation for more details. In fact, most of the time, I’m quite reluctant to adopt a third-party library, but I’m quite happy to make an exception for SignalR, because it’s simply brilliant.
In my view, if you currently use the command table pattern. Consider throwing away all these classes, throw away your command table and start using following approach.
Many things to Jewel for bringing SignalR in my radar !
Setting up SignalR
We will need to include both client and server side a nuget package for SignalR.
In case you don’t know you to include a Nuget package:
- Put your solution in file view
- Right-click the client project and select “Manage Nuget Packages”
- Find SignalR.Client.Silverlight5
- Go now to the server project and do the same as for the client project, except select now as package: SignalR.Hosting.AspNet
That’s pretty simple. We have now all SignalR related assemblies in our client and server project.
Update: in case you have problems with the client side nuget package, you can download the dlls here as well: http://sdrv.ms/SDodpL .
Defining the command parameters
Commands will typically have parameters: the client needs to provide parameters to the server and the server will return certain parameters.
We add server side a class with following very simple command:
namespace LightSwitchApplication
{
public class RequestParams
{
public string RequestParam1 { get; set; }
public string RequestParam2 { get; set; }
}
public class ResponseParams
{
public string ResponseParam1 { get; set; }
public string ResponseParam2 { get; set; }
}
}
We will no longer use the common project because it’s gone in case you didn’t know.
As a result we will simply add the class client side via a file reference:
Right-click the client project and take “add existing item” and make sure you select “add as link”. By doing so, potential changes to the command structure are always propagated to the client project.
Great, now both client and server side have access to your command.
Setting up the command handling Server side
SignalR works in terms of Hubs. We have to setup such a Hub class. It will host the command, in my example called “MyCommand”.
We leverage here the new feature in the LightSwitch preview 2: the ServerApplicationContext. As you can see, we can inside our command access the full DataWorkspaces of our LightSwitch application. To proof this, we send back some information for the customer collection in the command response.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Security.Server;
using SignalR.Hubs;
using System.Diagnostics;
using System.Threading;
using SignalR;
using Microsoft.LightSwitch.Framework;
namespace LightSwitchApplication
{
public class MyHub : Hub
{
public ResponseParams MyCommand(RequestParams requestParams)
{
using (ServerApplicationContext serverContext = Application.CreateContext())
{
var customers = serverContext.DataWorkspace.ApplicationData.Customers; // full access !!
string input = requestParams.RequestParam1;
Thread.Sleep(5000); // this emulates a typical long running process.
return new ResponseParams
{
ResponseParam1 = "just for letting you know",
ResponseParam2 = "We can access the data in your workspace: first customer: " + customers.First().LastName
};
}
}
}
}
Note that the above command is designed for demo purposes only, it’s not actually doing something useful, but it shows the plumbing.
You can see that my command needs access to the “customers” collection, so make sure you have Customer type in your dataworkspace and provide some sample customers (at least one).
Setting up the comand client side
We first need to setup a HubProxy, which allows to comunicate with the server. We do this in the Application_Initialize event. By doing so, all screens will have access to the HubProxy:
using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using SignalR.Client.Hubs;
using Microsoft.LightSwitch.Security;
namespace LightSwitchApplication
{
public partial class Application
{
public IHubProxy HubProxy { get; set; }
partial void Application_Initialize()
{
HubConnection hubConnection;
hubConnection = new HubConnection("http://localhost:8010"); //make sure it matches your port in dev
HubProxy = hubConnection.CreateProxy("MyHub");
hubConnection.Start().Wait();
}
}
}
Next we will call our command behind a simple lightSwitch button. I do this on a CustomerListDetail screen:
using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using SignalR.Client.Hubs;
namespace LightSwitchApplication
{
public partial class CustomersListDetail
{
partial void MyFirstCommand_Execute()
{
Application.HubProxy.Invoke<ResponseParams>("MyCommand",
new RequestParams { RequestParam1 = "request 1", RequestParam2 = "request 2" }).ContinueWith((task) =>
{
var responseparam2 = task.Result.ResponseParam2;
this.Details.Dispatcher.BeginInvoke(() =>
{
this.ShowMessageBox("Thanks for " + responseparam2);
});
});
this.ShowMessageBox("The show must go on, why should we wait before the task completes?");
}
}
}
What’s next?
SignalR is really huge. Note that without the new ServerApplicationContext it would be impossible to access the application context (and thus the data). Well,… it would be possible via a service reference to the application service endpoint, but making service references between artefacts server side is not so elegant. Furthermore there is no service reference between client and server.
I have also the impression that microsoft treats SignalR as a “first class citizen”… and that’s not without reason.
Furthermore, SignalR is not only usable for sending commands between client and server (and getting back the response), it has also an extremely powerfull publish/subscribe mechanism. In other words we could use it to broadcast message to all or a subset of clients connected to the server. That will probably my next post.



That’s great, Paul! I didn’t know about the new ServerApplicationContext thing… this is big! I’ve got to go try it now.
Hi Jewel,
Indeed, many new opportunities!
Hi Paul,
Thanks for useful post.
But, I couldn’t find ‘SignalR.Client.Silverlight5′
in client using manage NuGet packages. but I found and download ‘SignalR.Hosting.AspNet’
for server.
Hi David,
Indeed, there seems to a problem with nuget.
Here are the 3 dlls you need to include in the references of the client project: http://sdrv.ms/SDodpL
Thanks Paul,
You give me the chance to test it. I’ll tried it and love it.
Hi David,
I’m glad you like it. It’s a pitty, the nuget for the silverlight client is not available, otherwise … setting up both a command infrastructure and a pub/subscribe is a matter of minutes.
I think the whole SignalR story, is very compatible with LightSwitch. Furthermore, it has been designed by very very competent people.
Don’t hesitate to let me know, if you see other potential usage of SignalR.
Take care
Thanks so much Paul for this article, I love Lightswitch but I’m new to Web development.
I was stcked at STEP
“”Setting up the command handling Server side”"
Is there any way to add more detail?
Thanks,
So much,
Rachida
Hi Paul,
I Couldn’t find SignalR.Hosting.AspNet. Would it be possible to share related binaries?
Thanks,
Suneel
Yes, I know, they are in the process of reorganizing these libraries.
try: Microsoft.AspNet.SignalR
i think the silverlight lib is somewhere on my blog, no?
Take the silverlight lib from my blog: http://sdrv.ms/SDodpL
Thanks for the Reply Paul, I have downloaded silverlight binaries from your blog. Will try after some time for the Hosting binaries, in nuget feed.
-Suneel
It gives error Error
1 The type or namespace name ‘Hubs’ does not exist in the namespace ‘SignalR’ (are you missing an assembly reference?) c:\users\nurkmez\documents\visual studio 2012\Projects\Application1\Application1\Server\Class1.cs 7 15 Server
Hi paul,
Can you send me a full sample project? I have some error due to the binary reference?
[...] Handling in LightSwitch commands in less than 10 lines of code. [...]
[...] Handling in LightSwitch commands in less than 10 lines of code. [...]
great example, but i cannot run it (translated to VB) any idea why? im getting aggregate exception on “hubConnection.Start.Wait()”, but your demo app works (after few quircks) fine, not sure why, cause i used nuget packages from your demo app..
the simplest is to download signalRfrom github and compile the silverlight dll.
The server side part you can simply nuget in the server project. it’s the release candidate version.
hi Paul!
i manage it to work with html preview 2, but when i try to do the same in LS2012 “vanilla” application, i’m getting 404 “not found” error.. can this be cause html preview 2 uses IIS express, and LS2012 uses lightswitch development server?
It only works in the preview, because you need serverapplicationcontext.
Try the webapi approach as well, I think that for commanding it’s simpler.
thanks! you just saved me from another session of head-scratching..
i wanted to show little chat / notifications demo app created in html preview 2 to my colleagues from work (they don’t take lightswitch very seriously), but i cannot get it to work when published.. bummer! hitting the walls in every direction..
i’ll take a look at webapi.. in LSv1 i was sending SMS and mail messages trough custom ria service, signalR was perfect solution for “new version” in LS2012, maybe webapi would simplify things a littlebit..
For chat app I would SignalR rather than webapi, because with signalR you can initiate messages from server.
SignalR works when deployed, but you should make sure that the URL is ok, in my code it points to localhost. Needs to point to correct url of deployed app.
hah! silly me! i didn’t consider this url at all! gonna look if this causes error! thank you (for now
)!
Don’t feel silly, I made same mistake myself first time
I can see how to execute SP’s with “being serious about the command table pattern”
How do i approach my SP with SignalR?
Using this method?
Just running a stored procedure with some parameters and receiving a response?
- Johan
Call our SP inside the server side hub.
Check also the approach with Web-Api, which is simpler in my view.
Thank you i’l look into that, but non the less this looks interesting i want to get it running. I followed your guide above but it says
The application has stopped responding due to an error and needs to be restarted. Error details: One or more errors occurred.
even before i run the code behind the button. I’m using the same connection as when i run it as a website. http://localhost:3333/Client .
If this is the problem where / how can i find the correct port?
-Johan
Johan,
I compiled a new sample based on the latest SignalR bits.
Can you please respond if it’s not working.
See: http://blog.pragmaswitch.com/?p=809
thanks