how to setup a C# winforms application to host SignalR Hubs? - c#

I have read through the SignalR docs and watched a few of the videos, however I can not get SignalR to host within a winforms application.
I have tried using source code off the SignalR wiki: https://github.com/SignalR/SignalR/wiki/Self-host
If you look at the "Full Sample - Hubs", what is the "server" variable? I do not understand how this works or how to convert it to C#. According to the wiki "The default SelfHost implementation is built on HttpListener and can be hosted in any kind of application (Console, Windows Service etc). "
I would like to host SignalR in C# and consume it in asp.net. Could anyone please shed some light on this for me?

The sample in the Wiki works fine.
Please install the SignalR.Hosting.Self package using NuGet (Package Manager Console)
Install-Package SignalR.Hosting.Self
The Server lives in the SignalR.Hosting.Self namespace.
Sample
Console Application
using System;
namespace MyConsoleApplication
{
static class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8081/";
var server = new SignalR.Hosting.Self.Server(url);
// Map the default hub url (/signalr)
server.MapHubs();
// Start the server
server.Start();
Console.WriteLine("Server running on {0}", url);
// Keep going until somebody hits 'x'
while (true)
{
ConsoleKeyInfo ki = Console.ReadKey(true);
if (ki.Key == ConsoleKey.X)
{
break;
}
}
}
public class MyHub : SignalR.Hubs.Hub
{
public void Send(string message)
{
Clients.addMessage(message);
}
}
}
}
Asp.NET / Javascript
<script type="text/javascript" src="Scripts/jquery-1.7.2.js"></script>
<script src="/Scripts/jquery.signalR.js" type="text/javascript"></script>
<script src="http://localhost:8081/signalr"></script>
<script type="text/javascript">
$(function () {
// create signalr hub connection
myHub= $.connection.myHub;
// start hub connection and call the send method
$.connection.hub.start(function () {
myHub.Send('Hello');
});
});
</script>
Please leave a comment if you have additional answers

In order to make this to work for C# and ASP.NET I had to use "Cross Domain".
In the JavaScript I used:
<script type="text/javascript" src='http://localhost:8081/signalr/hubs'></script>
and added:
$.connection.hub.url = 'http://localhost:8081/signalr'

Related

How to trigger a SignalR command outside of the front end

I feel like I'm either missing the point of the SignalR service or I've got the architecture of it wrong.
Using an Azure SignalR service I've got the front-end to front-end communication working as such;
Startup.cs
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
app.MapAzureSignalR(this.GetType().FullName);
}
Hub.cs
private void BroadcastMessage(string message)
{
Clients.All.broadcastMessage(message);
}
Index.html
hubName.client.broadcastMessage = function (message) {
alert(message);
};
$('#btn').click(function () {
hubName.server.broadcastMessage("Hello World");
});
This is fine, and when I need the back-end to trigger a message I am using the following;
Functions.cs
HubConnection signalr = new HubConnection("http://localhost:57690/");
IHubProxy hub = null;
if (signalr.State == ConnectionState.Disconnected)
{
hub = signalr.CreateHubProxy(hubName);
signalr.Start().Wait();
}
hub.Invoke(functionName, args);
signalr.Stop();
While this works it leaves me wondering if I have implemented it wrong as this leaves http://localhost:57690/signalr/hubs open to posts from any source.
In the front-end, I have to provide the Endpoint=https://appName.service.signalr.net;AccessKey=xxxxx setting but not from the back-end.
As well as a security concern, this leaves me questioning what purpose the SignalR service has in this.
Surely there must be a better way to invoke signalr from the back-end.
Many Thanks,
Tom
In the Startup.cs you gotta have a line of code like this
services.AddSignalR().AddAzureSignalR();
By not passing a parameter to AddAzureSignalR(), this code uses the default configuration key, Azure:SignalR:ConnectionString, for the SignalR Service resource connection string.
You can find more info in this article

Streaming live tweets to the my .net website

I am working on an web based application in which I want to display a twitter stream on a specific query. User does need to refresh the webpage view and it will load the tweets automatically.
So far, I have created a simple console application using tweetinvi which read tweeets and performs all the custom logic on the tweets.
Next I need to know that how do I create project layout/infrastructure that my web app gets the constant feeds without client interaction.
As Nathan Cooper notes, SignalR is the best way of achieving this. As I've literally just built what you've described, I'll give you a detailed rundown of what you need to do..
Create a new ASP.NET MVC project, and install ASP.NET SignalR using NuGet as well as Tweetinvi
Right click on the App_Start folder and add a new OWIN Startup class (this should be listed in the contextual menu if you have installed SignalR using NuGet).
Your OWIN startup class should look like this:
[assembly: OwinStartup(typeof(TwitterClient.Web.App_Start.Startup))]
namespace TwitterClient.Web.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Add a new Folder to the project called "Hubs" and add a new SignalR Hub class (this should also be available as a template in the new file dialog in Visual Studio).
Create a new class called "TwitterConnection" wherever you feel like in the project. In the constructor for this class, do all of the stuff you did in your console application to connect to the Twitter API with Tweetinvi. Usually when you broadcast data from server to client in SignalR, you do it from within the Hub class, but you can obtain a reference to the SignalR hub outside of the hub class itself by using GlobalHost.ConnectionManager.GetHubContext<HUBNAME>(); where HUBNAME is the name of your hub. So your TwitterConnection class should look something like this:
public class TwitterConnection {
private string _consumerKey = ConfigurationManager.AppSettings.Get("consumerKey");
private string _consumerSecret = ConfigurationManager.AppSettings.Get("consumerSecret");
private string _accessKey = ConfigurationManager.AppSettings.Get("accessToken");
private string _accessToken = ConfigurationManager.AppSettings.Get("accessTokenSecret");
private IHubContext _context = GlobalHost.ConnectionManager.GetHubContext<TwitterHub>();
public TwitterConnection()
{
// Access the filtered stream
var filteredStream = Stream.CreateFilteredStream();
filteredStream.MatchingTweetReceived += (sender, args) =>
{
_context.Clients.All.broadcast(args.Tweet.Text);
};
filteredStream.StartStreamMatchingAllConditions();
}
}
In terms of the server-side stuff, you need to find a way of ensuring that there is only one instance of a stream open to Twitter at any one time. My quick and dirty way of doing this was to use Task.Factory.StartNew to create a new Task to manage to stream in the Global.asax file:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Start a new instance of the TwitterConnection class
Task.Factory.StartNew(() => new TwitterConnection());
}
Finally, you need to hook up the client-side element of SignalR. In your MVC Layout view (i.e. Views/Shared/_Layout.cshtml), add in a reference at the bottom of the HTML markup to the SignalR JavaScript library, the generated Hub proxy and to your external JavaScript file where your boilerplate SignalR JavaScript will go:
<!--Reference the SignalR library. -->
<script src="../../Scripts/jquery.signalR-2.2.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
<script src="../../Scripts/application.js"></script>
Finally, your boilerplate code in application.js (or whatever you want to call it), will look something like this:
// document ready shorthand
$(function () {
// obtain reference to the hub proxy and hub itself
var theHub = $.connection.twitterHub;
// this is the function that the server will call to broadcast new tweets
theHub.client.broadcast = function (tweet) {
var item = '<li>' + tweet.text + '</li>';
$('ul.tweets').prepend(item);
};
// this is a function that indicates that connection to the hub has been successful
$.connection.hub.start().done(function () {
console.log("connected");
});
});
Your Index.cshtml file will simply have an empty <ul> in it, where new tweets will be prepended to as and when they are received:
#{
ViewBag.Title = "Home Page";
}
<div class="row">
<div class="col-md-12">
<ul class="tweets"></ul>
</div>
</div>
You need to push live data to the browser. Use SignalR.
SignalR is great library for ASP.NET that allows you to write real time web applications. It uses Websockets under the covers, but has a number of fallback positions for older browsers. tutorial link

SignalR refusing connections

I'm trying to configure my signalR demo to my project
framework : 4.0 ,
SignalR version : 1.1.3
Here's my code
$(function () {
var connection = $.hubConnection('http://localhost:32555/');
var chat = connection.createHubProxy('myChatHub');
chat.on('send', function (message) {
$('#chat').html($('#chat').html() + "\r\n" + message);
});
connection.logging = true;
connection.start().done(function () {
alert("Connection Complete");
$('#sendBtn').click(function () {
chat.invoke('send', $('#message').val());
});
}).fail(function (param) {
console.log(param);
});
});
Global.asax
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHubs(new HubConfiguration { EnableCrossDomain = true });
}
.Cs
namespace vPortal
{
[HubName("myChatHub")]
public class LetsChat : Hub
{
public void send(string message,string userid,string Name)
{
Clients.All.addMessage(message, userid, Name);
}
}
}
When I tried to run the page I got this error
SignalR: Error during negotiation request:
But, I have enabled proxy in the global.asax I have tried upgrading my signalR to version 2.2.3.
But, my project packages are incompatible with the current version so I installed version 1.1.3.
I don't know what I'm doing wrong here I see there is a connection but can not establish.
A lots of credit goes to this man.
he made my problem easy to solve.
See, first of all my all the references were to 4.0 then So I used Signalr Older version 1.1.4
Here's is my errors scenario:
SignalR could not connect:
I removed this error by adding the lines RouteTable.Routes.MapHubs(); in my Global.asax file.
Negotiation of request: There was a silly mistake done by me the namespace was different in the my chat.aspx page.
Version Conflicts: See, I got previous libraries which were incompatible with the current version (2.3.2) of signalR. So, I had to stick to previous version of it (1.1.3) the steps are given here and its pretty neat.
Again,I was pretty sure about my code signalR will work fine:
So, run my chat and my first message was succeed then Again there was an error after sometime and the error was
the added or subtracted value results in an un-representable datetime. signlar
So, this was the big headache for me.This is definately nothing do with the signalR
I got the clue from frebin and I realized that in my web.config
<httpRuntime executionTimeout="180" maxRequestLength="512000" />
The executionTimeout previous value was 9999999999
i changed to 180 and its works fine!!!
I have added all the scenarios for the future preferences.

SignalR cannot set property '' of undefined

I'm trying to set SignalR in my MVC4 app.
The problem is - even though when I browse to path /signalr/hubs I do see code (and fiddler shows 200OK for /signalr/hubs), it does not seem to contain any reference to my hub and client side code also doesn't see the hub and methods.
I get these errors when starting debugging (IIS Express, VS Express 2012):
Application_Start in Global.asax contains:
//RouteTable.Routes.MapHubs("/signalr", new HubConfiguration());
RouteTable.Routes.MapHubs();
RouteConfig.RegisterRoutes(RouteTable.Routes);
(I assume this generates the /signalr/hubs, this seems to work but nothing links to my actual hub. As can be seen I tried both options).
In my project I got folder "Hubs" in root with MessageHub.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace Prj.Hubs
{
[HubName("messagehub")]
public class MessageHub : Hub
{
public void MessageAll(string message)
{
Clients.All.writeMessage(message);
}
public void MessageOthers(string message)
{
Clients.Others.writeMessage(message);
}
public void MessageSingle(string message)
{
}
}
}
In my _Layout.cshtml I have just before the closing tag:
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.signalR-1.1.2.js"></script>
<script src="/signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
// create proxy on the fly
var proxy = $.connection.messagehub; // this connects to our 'messageHub' Hub as above
// for SignalR to call the client side function we need to declare it with the Hub
proxy.messageAll = function (message) {
$('#messages').append('<li>' + message + ''); // when the Hub calls this function it appends a new li item with the text
};
// declare function to be called when button is clicked
$("#broadcast").click(function () {
// calls method on Hub and pass through text from textbox
proxy.messageAll($("#message").val());
});
// Start the connection
$.connection.hub.start();
});
</script>
(side note - SignalR didn't like at all the #Scripts.Render("~/bundles/jquery"), but a direct jquery script include seems to work).
So why doesn't it recognize "messagehub" exactly?
I solved this - my solution contains multiple projects, and although I had uninstalled SignalR, in some of these projects in the bin/Debug folder there were still traces of an older SignalR version that I tried months ago.
At runtime, SignalR was trying to connect some old dll's with the new references. So if you have this error then
uninstall SignalR
do a search for "SignalR" in your entire solution folder and delete everything
reinstall SignalR from Nuget Package Manager.

SignalR cannot read property client of undefined

I'm trying to add SignalR to my project (ASPNET MVC 4). But I can't make it work.
In the below image you can see the error I'm receiving.
I've read a lot of stackoverflow posts but none of them is resolving my issue.
This is what I did so far:
1) Ran Install-Package Microsoft.AspNet.SignalR -Pre
2) Added RouteTable.Routes.MapHubs(); in Global.asax.cs Application_Start()
3) If I go to http://localhost:9096/Gdp.IServer.Web/signalr/hubs I can see the file content
4) Added <modules runAllManagedModulesForAllRequests="true"/> to Web.Config
5) Created folder Hubs in the root of the MVC application
6) Moved jquery and signalR scripts to /Scripts/lib folder (I'm not using jquery 1.6.4, I'm using the latest)
This is my Index.cshtml
<h2>List of Messages</h2>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion">
</ul>
</div>
#section pageScripts
{
<!--Reference the SignalR library. -->
<script src="#Url.Content("~/Scripts/jquery.signalR-1.0.0-rc1.min.js")" type="text/javascript"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script type="text/javascript" src="~/signalr/hubs"></script>
<script src="#Url.Content("~/Scripts/map.js")" type="text/javascript"></script>
}
This is my IServerHub.cs file (located inside Hubs folder)
namespace Gdp.IServer.Ui.Web.Hubs
{
using Microsoft.AspNet.SignalR.Hubs;
[HubName("iServerHub")]
public class IServerHub : Hub
{
public void Send(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
}
}
And this is map.js
$(function () {
// Declare a proxy to reference the hub.
var clientServerHub = $.connection.iServerHub;
// Create a function that the hub can call to broadcast messages.
clientServerHub.client.broadcastMessage = function (name, message) {
$('#discussion').append('<li><strong>' + name + '</strong>: ' + message + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Html encode display name and message.
var encodedName = $('<div />').text($('#displayname').val()).html();
var encodedMsg = $('<div />').text($('#message').val()).html();
// Call the Send method on the hub.
clientServerHub.server.send(encodedName, encodedMsg);
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
The DLL's I see references for SignalR are:
Microsoft.AspNet.SignalR.Core
Microsoft.AspNet.SignalR.Owin
Microsoft.AspNet.SignalR.SystemWeb
Any ideas how to get it work?
Should I make any change because the scripts are in /Script/lib folder?
NOTE
I'm following the instruction found here on how to set up Windsor Castle to make it work with SignalR, and again, seems that the proxy cannot be created and I'm getting the same error:
Cannot read property client of undefined
meaning that the proxy to the hub was not created
This is how I have it in the server
public class IncidentServerHub : Hub
and like this in the client
var clientServerHub = $.connection.incidentServerHub;
Again, I can see the dynamically created file here:
/GdpSoftware.Server.Web/signalr/hubs
So, why is the proxy not created?
I fixed that problem by changing my js code from:
var myHub = $.connection.SentimentsHub;
to
var myHub = $.connection.sentimentsHub;
So if you have some hub with class name TestHub you must use testHub(first letter is lowercase) name in js
For those who tried to add the generated proxy file path in the bundle.
Do not include the "~/signalr/hubs" in your BundleConfig.cs.
You can have the JQuery.SignalR in the bundle:
bundles.Add(new ScriptBundle("~/bundles/signalr").Include(
"~/Scripts/jquery.signalR-{version}.js"));
But you will need to add "/signalr/hubs" it in your view:
#section Scripts {
#Scripts.Render("~/bundles/signalr")
#Scripts.Render("/signalr/hubs")
}
I hope this helps.
I had the same error message and resolved the issue by fixing a typo I had in the [HubName] attribute on the hub class - it was not exactly matching the property in the client-side javascript.
C# hub class:
[HubName("gameHub")]
public class GameHub : Hub
{
client-side javascript:
var foo = $.connection.gameHub;
"gameHub" must be the same.
hth
For ASP.Net MVC folks:
Check your _Layout.cshtml: If you are calling the jquery bundle after the #RenderBody(), you will get this error.
Resoultion: Just move the #Scripts.Render("~/bundles/jquery") to the head section or write all signalr scripts in the scripts "section"
Your hub classes must be defined as public. For example:
class ChatHub : Hub
should actually be
public class ChatHub : Hub
Ok, I've found the issue, one thing I needed to do was:
These two references were missing:
Microsoft.AspNet.SignalR.Hosting.AspNet
Microsoft.AspNet.SignalR.Hosting.Common
Now, I included them getting nuget package: WebApiDoodle.SignalR which uses those two.
My question is why those Dlls weren't added one I installed the Nuget Package:
Microsoft.AspNet.SignalR -Pre?
Bug?
Then I had this in my global.asax.cs
using SignalR;
so
RouteTable.Routes.MapHubs();
was using that one, I needed to remove that using and use this one:
using Microsoft.AspNet.SignalR;
So the MapHubs use that one, and started to work.
Hope this helps others.
Guillermo.
You should put SignalR and jQuery scripts, in correct order :
<script src="/Scripts/jquery-1.6.4.min.js" ></script>
<script src="/Scripts/jquery.signalR-1.1.4.js"></script>
<script src="/signalr/hubs"></script>
In my case, I lost Microsoft.Owin.Host.SystemWeb.dll & Microsoft.Owin.Security.dll in my project. After adding References to them, that error was solved. it's working now.
Make sure you add
app.MapSignalR();
inside startup.cs and Configuration method,
like this:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
For Asp.net Core
Add
services.AddSignalR();
in ConfigureServices methode in your startup.cs
And add
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
in Configure methode in your startup.cs
Making the Hub class "public" solved it for me.
Most probably, could be the wrong name given in the class and reference in JavaScript is wrong.
var chat = $.connection.chatHub; //did not work
var chat = $.connection.myHub; // this worked
This is my class
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addNewMessageToPage(name, message);
}
}

Categories