Not able to get SignalR working in my machine (with IE9). On entering some text and clicking submit, the text is not getting listed as intended. Also, I would expect the list getting updated from multiple instances of browser and It does not happen. There is no error. Could anybody help here?
C#
namespace TestSignalR.Hubs
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for ChatHub.
/// </summary>
public class ChatHub : SignalR.Hubs.Hub
{
public void TestMessage(string message)
{
Clients.writeMessage(message);
}
}
}
ASPX
<input type="text" name="txtInput" id="txtInput" />
<button id="btnSubmit">Submit</button>
<ul id="messages">
</ul>
<script type="text/javascript" src="SignalR/Hubs"></script>
<script type="text/javascript">
$(document).ready(function (message) {
var chat = $.connection.chatHub;
chat.writeMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#btnSubmit").click(function () {
var text = $("#txtInput").val();
chat.testMessage(text);
});
$.connection.hub.start();
});
</script>
Master page has the references for the JQuery and SignalR files:-
<script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-0.5.2.min.js" type="text/javascript"></script>
Today I was working with the same issue.
First you need to add an atribute to your Hub with the name, as following:
[HubName("chathub")]
public class ChatHub : SignalR.Hubs.Hub
The next to do is to change the order of your calls in the javascript. You need to do the connection next to instantiate the hub.
So, the code will be as following:
$(document).ready(function (message) {
var chat = $.connection.chatHub;
$.connection.hub.start();
chat.writeMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#btnSubmit").click(function () {
var text = $("#txtInput").val();
chat.testMessage(text);
});
});
I hope it works for you.
Please install the 1.0 version of SignalR from Nuget as well. From your script references it looks like you are using 0.5.2 and the latest supported version at the time of writing this post is 1.0. Please download Microsoft.AspNet.SignalR from Nuget
Related
I am seeking a logic to implement a display screen which displays some information when another page postback occures.
To be more precise I have a token queue management system in which the counter officer process a token (in token.aspx page) and when that happens the display screen (display.aspx) should highlight that token.
Which will be the most efficient mechanism to achieve this
Edit -using SignalR
My Startup class in App_Code
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Startup1))]
public class Startup1
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
My Hub class in App_Code
using Microsoft.AspNet.SignalR;
public class MyHub1 : Hub
{
public void Send( string message)
{
Clients.All.addNewMessageToPage( message);
}
}
Now my page for sending data (send.aspx) to hub
<script src="Scripts/jquery-1.6.4.min.js" ></script>
<script src="Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="/signalr/hubs"></script>
<script>
$(function () {
var chat = $.connection.myHub1;
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () { //sendmessage is a button
chat.server.send( $('#message').val()); //message is a text field
});
});
});
</script>
No my Display.aspx page
<script src="Scripts/jquery-1.6.4.min.js" ></script>
<script src="Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="/signalr/
<script>
$(function () {
var chat = $.connection.myHub1;
chat.client.addNewMessageToPage = function (message) {
alert(message);
};
});
</script>
I have tested and verified that Send.aspx page do send the message to Hub and it is well received. But the Display.aspx page doesnt show the alert.
Edit 2
I got it. Actually i forgot to add $.connection.hub.start(); in Display.aspx page. Now all ok
Use SignalR
My Startup class in App_Code
using Microsoft.Owin;
using Owin;
.........
[assembly: OwinStartup(typeof(Startup1))]
public class Startup1
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
My Hub class in App_Code
using Microsoft.AspNet.SignalR;
...............
public class MyHub1 : Hub
{
public void Send( string message)
{
Clients.All.addNewMessageToPage( message);
}
}
Now my page for sending data (send.aspx) to hub
<script src="Scripts/jquery-1.6.4.min.js" ></script>
<script src="Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="/signalr/hubs"></script>
<script>
$(function () {
var chat = $.connection.myHub1;
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () { //sendmessage is a button
chat.server.send( $('#message').val()); //message is a text field
});
});
});
</script>
Now my Display.aspx page
<script src="Scripts/jquery-1.6.4.min.js" ></script>
<script src="Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="/signalr/
<script>
$(function () {
var chat = $.connection.myHub1;
chat.client.addNewMessageToPage = function (message) {
alert(message);
};
$.connection.hub.start();
});
</script>
I am trying to pass data to server in angular using webapi. Thanks to people on the forum I was able to fill 1 drop down based on another using entity framework and angular. The next thing I wanted to figure out was how to pass screen data back to the server using webapi.
When the angular code is being called I am getting an error: badreq 'Http request configuration must be an object'
This error shows in the $http
I found an example online where it shows the ability of creating a parent model used by each of the html controls. In the case of the example online they were using textboxes, but I am using select lists, but I assume this should also work.
Can someone please tell me what I am doing wrong?
I appreciate it!!
FOLLOW UP: The problem I am having at this point seems to be that Data in the Angular saveattributecontroller states as UNDEFINED. So the issue I don't believe at this point is the call to the webapi, but the data not being passed from "Detail" in the HTML.
FOLLOW UP 2: based on Lorenzo's comment below. By putting the attributevaluecontroller around the submit button, I can now see the data passed to the saveattributecontroller in the attribute.js which is good. I also realized I needed to reference Data.A and Data.V in the saveattributecontroller. But now it seems the call to the WebAPIAttribute controller is not happening. I tried both the way I originally had and the other way that was suggested earlier yet the call to the controller never seems to go through. Can anyone help me with that?
Follow UP 3: The error I am finding as I step through the angular javascript is Resource can't be found. So I am assuming it is not finding the webapi controller for some reason. It's probably something very simple, but I am not seeing it.
var myapp = angular.module('attributeapp', []);
myapp.controller('attributecontroller', function ($scope, $http) {
$http.get('/Attribute/AttributeIndex/').then(function (response) {
$scope.Attributes = response.data;
})
})
myapp.controller('attributevaluecontroller', function ($scope, $http) {
$scope.getattributevalues = function (id)
{
$http.get('/Attribute/getattributevalues/' + id).then(function (response) {
$scope.A = id;
$scope.AttributeValues = response.data;
})
}
})
myapp.controller('saveattributecontroller', function($scope, $http){
$scope.attributesave = function (Data) {
var GetAll = new Object();
GetAll.AttributeKey = Data.AttributeKey;
GetAll.AttributeValueKey = Data.AttributeValueKey;
$http({
url: "WebAPIAttribute/attributesave",
dataType: 'json',
method: 'POST',
data: GetAll,
headers: {
"Content-Type": "application/json"
}
}).success(function (response) {
$scope.value = response;
})
.error(function (error) {
alert(error);
});
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/angular.js"></script>
<script src="Scripts/attribute.js"></script>
</head>
<body data-ng-app="attributeapp">
<div data-ng-controller="attributecontroller">
<span data-ng-controller="attributevaluecontroller">
<select data-ng-model="detail.A" data-ng-change="getattributevalues(detail.A)" data-ng-options="Attribute.Attribute_Key as Attribute.Attribute_Desc for Attribute in Attributes"><option value="">--Select--</option></select><br />{{detail.A}}
<select data-ng-model="detail.V" data-ng-options="Attribute_Value.Attribute_Value_Key as Attribute_Value.Attribute_Value_Desc for Attribute_Value in AttributeValues"><option value="">--Select--</option></select>{{detail.V}}
</span>
<br />
<span data-ng-controller="saveattributecontroller">
<input type="button" value="submit" data-ng-click="attributesave(detail)"/>
</span>
</div>
</body>
</html>
//AttributeControler.cs
using System;
using System.Collections.Generic;
using MVC_APP1.Models;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVC_APP1.Controllers
{
public class AttributeController : Controller
{
//
// GET: /Attribute/
public ActionResult AttributeIndex()
{
Cafe_CPDEntities objEntity = new Cafe_CPDEntities();
var data = objEntity.Attributes.ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
public ActionResult getattributevalues(int id)
{
Cafe_CPDEntities objEntity = new Cafe_CPDEntities();
var data = objEntity.Attribute_Value.Where(m=>m.Attribute_Key==id);
//string test = data.FirstOrDefault().Attribute_Value_Desc;
return Json(data, JsonRequestBehavior.AllowGet);
}
public ActionResult attributesave(List<int> ReturnData)
{
return null;
}
}
}
// WebAPIAttributeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace MVC_APP1.Controllers
{
public class WebAPIAttributeController : ApiController
{
public class GetAll
{
public string AttributeKey { get; set; }
public string AttributeValueKey { get; set; }
}
[HttpPost]
public string attributesave(HttpRequestMessage request,
[FromBody] GetAll getAll)
{
return "Data Reached";
}
}
}
Try to
$scope.attributesave = function (Data) {
var GetAll = new Object();
GetAll.AttributeKey = Data.AttributeKey;
GetAll.AttributeValueKey = Data.AttributeValueKey;
$http.post("WebAPIAttribute/attributesave", getAll)
.then(function(response){
//here your operations
})
}
(I THOUGHT I POSTED THIS EARLIER, BUT IT DID NOT SAVE)
I figured out the last part. I needed to add api/ to the route.
api/WebAPIAttributes/attributesave/
The call to webapi now goes through and passes the data from the screen.
Thanks so much to all those who helped answer the earlier issues I was having.
We use SignalR library in our ASP.NET web application. The code looks as following:
Server:
[HubName("ticketsCounterHub")]
public class MassivePrintHub : Hub
{
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
}
public class HubFactory
{
private HubFactory() {}
public static readonly HubFactory Current = new HubFactory();
public IHubProxy GetMassivePrintHubProxy()
{
var hubConnection = new HubConnection(ConfigUtils.GetRequiredSettingValue("adminPath"));
var hubProxy = hubConnection.CreateHubProxy("ticketsCounterHub");
hubConnection.Start().Wait();
return hubProxy;
}
}
Client (JavaScript):
MassivePrintApp.controller("ListController", function ($scope, Dates) {
var hubManager = (function () {
var massivePrintHub = $.connection.ticketsCounterHub;
$.connection.hub.start();
return { massivePrintHub: massivePrintHub };
} ());
hubManager.massivePrintHub.client.Send = function (ticketsCount) {
$scope.action.Quantity = ticketsCount;
$scope.$digest();
};
});
The key part of code is in MVC controller:
public FileResult PrintAction(int actionId, int count, DateTime actionDate, bool isThermo=false)
{
var ticketsCount = _ticketService.GetTicketsInStatusCount(actionId, actionDate, TicketStatusEnum.ToPrint);
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
var stream = new MemoryStream();
xmlResponse.Save(stream);
stream.Flush();
stream.Position = 0;
return File(stream,ContentTypeEnum.XML.ToString(),String.Format("массовая {0} мероприятия {1} {2}шт.xml", isThermo?"термопечать":"печать", action.Artist,count));
}
As you can see, we have this line:
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
And that causes the issue, that is whenever we call it one more instance of hub was added to "Requests" section on IIS.
I understand we already started hub in JavaScript code, but I'm not sure how can I use the existing connection or how to get rid of HubFactory or delete created hub instance.
And I don't understand why hub hangs on IIS.
Starting from a more simple example will help you a lot I guess. After that you can look into hosting your SignalR server differently (Console App or Windows Service) the basics won't change
(First installed SignalR: NuGet: install-package Microsoft.AspNet.SignalR)
I made a simple web-app example. The project has a Hub class:
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SRTest
{
public class MassivePrintHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MassivePrintHub>();
// Can be called from your Javascript code
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
// Can be called from your c# code
public static void Static_PostTicketsCount(long count)
{
hubContext.Clients.All.Send(count);
}
}
}
An Owin startup class:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SRTest.Startup))]
namespace SRTest
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);
}
}
}
Page (Razor just to be able to call a simulator which calls a c# class to post message from backend):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST PAGE</title>
<!--Reference the jQuery library. -->
<script src='Scripts/jquery-1.6.4.js'></script>
<!--Reference the SignalR library. -->
<script src='Scripts/jquery.signalR-2.2.0.js'></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
</head>
<body>
THIS IS A TEST PAGE
<!-- Call simulator (trigger event every 5 seconds) -->
#{SRTest.SendFromBackEnd.SimulateSend();}
<script>
$(function () {
var printHub = $.connection.massivePrintHub;
// when send event happens
printHub.client.send = function (count) {
console.log("Send " + count + " tickets");
};
$.connection.hub.start().done(function () {
console.log("Connected");
});
$.connection.hub.logging = true;
});
</script>
</body>
</html>
And I added a dummy class which triggers the event through hubcontext every 5 seconds.
using System.Threading;
using System.Web;
namespace SRTest
{
public class SendFromBackEnd
{
public static void SimulateSend()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
MassivePrintHub.Static_PostTicketsCount(2);
Thread.Sleep(5000);
}
}).Start();
}
}
}
I added some loggings to the SignalR, add some debug points, it will help you understand the basics, then it will be much easier to build what you are planning to build.
EDIT
About the hanging request: As long as you have a client connected to your SignalR server with SSE or AJAX Long-Polling, you will have an ongoing request, which never finishes. (In case of AJAX Long-polling, it finishes for very short times and comes back). In the apps where I use only Javascript clients, I only see the request if a page is open where I am listening to events. If no page or static page open then no request.
In the apps where I am using .NET clients, as long as the two apps are running, and both Sartup classes executed, the request will always be there, even if no page open. (Since the .NET client is still listening to events.)
For more info: http://hanselminutes.com/291/damian-edwards-explains-the-realtime-web-for-aspnet-with-signalr
This is a Threading related issue. Try like this
Task.Run(() => connection.Start().ContinueWith(task =>
{
.....
})).Wait();
I am currently developing a page which is (nearly) fully inline-editable with CKEditor. So after the user has finished editing I want to get the plain HTML Code, remove the editor controls and send the result via eMail. This disqualifies the WebRequest-Method as this "reloads" the page. Is there an option to get the CURRENT html from the page in a string?
Most likely you have to do this by AJAX. Get the contents of the HTML to a JavaScript variable, then POST the variable to your backend (where you now have the WebRequest). Try something like this if you use jQuery:
var markup = document.documentElement.innerHTML;
alert("Submitting: " + markup"); // big alert...
$.ajax({
type: "POST",
url: "path/to/HTML_handler.aspx",
data: { html: markup }
})
.done(function(msg) {
alert("Data Saved: " + msg);
});
Then in your backend read the posted html variable a vomit it into a backend.
Edit 11.9.2014
I'm an MVC guy myself, but the classic ASP.net way of doing this I think is something like this: in your aspx view, add a button, such as this: <button id="Derp">I love ponies</button>. Add a reference to jQUery: <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> (I'm using the Google CDN here). Then bind a click event to the button:
<script type="text/javascript">
$(function() {
var btn = $('#Derp');
btn.click(function() {
var markup = document.documentElement.innerHTML;
alert("Submitting...");
$.ajax({
type: "POST",
url: "AJAXRequest.ashx", // Important that this points to the right file...
data: { html: markup }
})
.done(function(msg) {
alert("Data Saved: " + msg);
});
});
});
</script>
Then create a backend handler (Google for more tutorials) that goes something like this:
AJAXRequest.asgx (yeah, just one line):
<%# WebHandler Language="C#" CodeBehind="AJAXRequest.ashx.cs" Class="WebApplication1.AJAXRequest" %>
AJAXRequest.ashx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
namespace WebApplication1
{
public class AJAXRequest : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Not sure which one to use here, try both
string html1 = context.Request["html"];
string html2 = context.Request.Form["html"];
// Do whatever you want with the html...
context.Response.Write("OMG I just found: " + html1);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Yeah, this code is very much untested, but I think you get the gist of it.
I added SignalR to an existing ASP.Net 4 Web Forms application. Created a new folder called Hubs and added a Hub like so:
[HubName("UpdatesHub")]
public class UpdatesHub : Hub
{
public void DownloadUpdates()
{
// Code Removed
}
}
Added the RouteTable.Routes.MapHubs(); to Application_Start and added the following to the page:
<script src="/Scripts/jquery-1.9.1.js"></script>
<script src="/Scripts/jquery.signalR-1.0.1.js"></script>
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var upd = $.connection.UpdatesHub;
// Code Removed
// Start the connection.
$.connection.hub.start().done(function () {
$('#btnDownload').click(function () {
upd.server.DownloadUpdates();
});
});
});
</script>
But whenever I click the button I just get "Uncaught TypeError: Object # has no method 'DownloadUpdates'". I have tried removing and readding signalr via NuGet but can't seem to get this to work, help!
SignalR camelCases the method names on the server. Try checking if downloadUpdates() exists.