My understanding is that with signalr I can just send objects back and forth. I am trying to set up a .net client to receive notifications that orders have been placed on a web site. I am trying to set up a very simple example so that I understand the concepts. It works great when I am sending a string notification back to the client, but when I try to send an object I get an error:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException was unhandled by user code
HResult=-2146233088
Message=The best overloaded method match for 'ConsoleHub.Program.DisplayOrder(ConsoleHub.Order)' has some invalid arguments
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at CallSite.Target(Closure , CallSite , Type , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
at ConsoleHub.Program.<Main>b__6(Object o) in c:\Working\OrderNotifier\ConsoleHub\Program.cs:line 23
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxyExtensions.<>c__DisplayClass6`1.<On>b__4(JToken[] args)
at Microsoft.AspNet.SignalR.Client.Hubs.Subscription.OnData(JToken[] data)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.InvokeEvent(String eventName, JToken[] args)
at Microsoft.AspNet.SignalR.Client.Hubs.HubConnection.OnReceived(JToken message)
at Microsoft.AspNet.SignalR.Client.Connection.Microsoft.AspNet.SignalR.Client.IConnection.OnReceived(JToken message)
at Microsoft.AspNet.SignalR.Client.Transports.HttpBasedTransport.ProcessResponse(IConnection connection, String response, Boolean& timedOut, Boolean& disconnected)
InnerException:
My class:
public class Order
{
public int OrderId { get; set; }
public string Name { get; set; }
public string OrderItem { get; set; }
}
My hub:
using Microsoft.AspNet.SignalR.Hubs;
using OrderNotifier.Models;
using System.Linq;
using System.Threading.Tasks;
namespace OrderNotifier.Hubs
{
public class NotifierHub : Hub
{
OrderContext db = new OrderContext();
public void Hello()
{
Clients.Caller.Welcome("hello");
}
}
}
My controller action:
[HttpPost]
public ActionResult Create(Order order)
{
if (ModelState.IsValid)
{
db.Orders.Add(order);
db.SaveChanges();
SendNotifier.SendOrderNotification(String.Format("{0} ordered {1}", order.Name, order.OrderItem), order);
return RedirectToAction("Index");
}
return View(order);
}
SendNotifier - which is a little weird because I am having it send both a string version and an object version for testing:
public class SendNotifier
{
public static void SendOrderNotification(string message, Order order)
{
var context = GlobalHost.ConnectionManager.GetHubContext<NotifierHub>();
context.Clients.All.Notify(message);
context.Clients.All.Order(order);
}
}
And my console application:
using Microsoft.AspNet.SignalR.Client.Hubs;
using OrderNotifier.Models;
using System;
namespace ConsoleHub
{
class Program
{
static void Main(string[] args)
{
var hubConnection = new HubConnection("http://localhost:60692");
var order = hubConnection.CreateHubProxy("NotifierHub");
//
// Set up action handlers
//
order.On("Welcome", message => Console.WriteLine(message));
order.On("Notify", message => Console.WriteLine(message));
order.On("Order", o => DisplayOrder(o));
hubConnection.Start().Wait();
order.Invoke("Hello").Wait();
Console.WriteLine("Initialized...");
Console.ReadLine();
}
public void DisplayOrder(Order o)
{
Console.WriteLine(String.Format("Order object received.../r/nOrderId: {0}/r/nName: {1}/r/nOrderItem: {2}", o.OrderId, o.Name, o.OrderItem));
//Console.WriteLine(o);
}
}
}
If I change the DisplayOrder parameter to be a string it works. I know I could probably manually deserialize it using Json.Net, but my understanding is that I should just be able to work with it as an object and let signalr deserialize. What am I missing?