I was pointed to this GITHub sample code by David Fowler himself to track SignalR users and states. I have implemented all of it and it works great except I can't figure out the displaying of Hub connection state changes. I have this which doesn't seem to work. Does anyone know why?
!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
#state {
width: 20px;
height: 50px;
}
</style>
</head>
<body>
<h3 id="msg"></h3>
<div id="state"></div>
<script src="../Scripts/jquery-1.10.2.min.js"></script>
<script src="../Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src="signalr/hubs"></script>
<script>
$(function () {
var userTracking = $.connection.alphaHub;
// Need at least one callback for events to be raised on the hub
userTracking.client.void = function () { };
$.connection.logging = true;
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.connected) {
$('#state').css('background-color', 'green');
} else if (change.newState === $.signalR.connectionState.reconnecting) {
$('#state').css('background-color', 'yellow');
} else if (change.newState === $.signalR.connectionState.disconnected) {
$('#state').css('background-color', 'red');
}
});
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 1000);
});
});
</script>
</body>
</html>
My Hub is shown partially here:
public class AlphaHub : Hub
{
public override async Task OnConnected()
{
try
{
var name = Context.User.Identity.Name;
using (savitasEntities2 entities = new savitasEntities2())
{
var user = entities.SUsers
.Include(u => u.SConnections)
.SingleOrDefault(u => u.UserName == name);
if (user == null)
{
user = new SUser
{
UserName = name,
SConnections = new List<SConnection>()
};
entities.SUsers.Add(user);
}
user.SConnections.Add(new SConnection
{
ConnectionID = Context.ConnectionId,
UserAgent = Context.Request.Headers["User-Agent"],
LastActivity = DateTimeOffset.UtcNow
});
// entities.SaveChanges();
await entities.SaveChangesAsync();
}
}
public override async Task OnDisconnected()
{
try
{
using (savitasEntities2 db = new savitasEntities2())
{
var connection = await db.SConnections.FindAsync(Context.ConnectionId);
db.SConnections.Remove(connection);
await db.SaveChangesAsync();
}
}
catch (Exception ex)
{
c.LogError(ex.Message, "AlphaHub.cs" + " - " + this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
}
}
Looks like your hubs can't be found.
Change:
<script src="signalr/hubs"></script>
to:
<script src="~/signalr/hubs"></script>
Related
I am very new to the term SignalR . I was try to configure the signalR into my empty website and Added following code.
In App_Code
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Super.App_Code.Startup))]
namespace Super.App_Code
{
public class Startup
{
public static void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
and the hub class Inside App_Code
namespace Super.App_Code
{
[HubName("toastHub")]
public class ToastHub : Hub
{
public void BroadcastToast(string type ,string msg)
{
Clients.All.sendToast(type , msg);
}
}
}
and in Default.aspx
<head runat="server">
<title></title>
<link rel="stylesheet" href="content/toastr.min.css" />
<script src="Scripts/jquery-1.6.4.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-2.4.1.js" type="text/javascript"></script>
<script src="Scripts/toastr.min.js" type="text/javascript"></script>
<script src="signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#SuccessLink").click(function () {
console.log("Success Click");
$.connection.toastHub.client.broadcastToast('success', 'you have done');
});
$("#ErrorLink").click(function () {
console.log("Error Click");
$.connection.toastHub.client.broadcastToast("error", "you have not done");
});
$.connection.hub.start().done(function () {
console.log('SignalR connected');
})
.fail(function (data) {
console.log('SignalR failed to connect: ' + data);
});
$.connection.toastHub.client.sendToast = function (type, msg) {
console.log("sendToast Called");
toastr[type](msg);
};
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<a id="SuccessLink" style="color: lightgreen">Success Toast</a><br />
<a id="ErrorLink" style="color: red">Error Toast</a>
</div>
</form>
</body>
</html>
but when i run my website the javascript console says this when click on one of the tag
SignalR connected
Default.aspx:20 Success Click
Default.aspx:21 Uncaught TypeError: $.connection.toastHub.client.broadcastToast is not a function
at HTMLAnchorElement.<anonymous> (Default.aspx:21)
at HTMLAnchorElement.handle (jquery-1.6.4.js:3001)
at HTMLAnchorElement.eventHandle (jquery-1.6.4.js:2635)
Am i doing anything wrong please help me any help would be greatful .i am totally new to SignalR .
signalr/hub
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
function registerHubProxies(instance, shouldSubscribe) {
var key, hub, memberKey, memberValue, subscriptionMethod;
for (key in instance) {
if (instance.hasOwnProperty(key)) {
hub = instance[key];
if (!(hub.hubName)) {
// Not a client hub
continue;
}
if (shouldSubscribe) {
// We want to subscribe to the hub events
subscriptionMethod = hub.on;
} else {
// We want to unsubscribe from the hub events
subscriptionMethod = hub.off;
}
// Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
for (memberKey in hub.client) {
if (hub.client.hasOwnProperty(memberKey)) {
memberValue = hub.client[memberKey];
if (!$.isFunction(memberValue)) {
// Not a client hub function
continue;
}
// Use the actual user-provided callback as the "identity" value for the registration.
subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue), memberValue);
}
}
}
}
}
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['toastHub'] = this.createHubProxy('toastHub');
proxies['toastHub'].client = { };
proxies['toastHub'].server = {
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
Something is not correctly initialized with your SignalR project, I guess accessing a hubContext should have a Dependency Injector in your startup.cs. But doing context injection with DI for SignalR is an advanced level problem.
However, please try this minimal sample, if it's working for you: https://github.com/bezzad/MVC-SignalR-2
Looks to me like you need to just change the calls to broadcastToast from client to server. As that method is in the Hub and so requires the server instead.
$.connection.toastHub.client.broadcastToast
To
$.connection.toastHub.server.broadcastToast
I have developed an application, and in this application I want to import file Excel to multiple table in my DB, and since i am a beginner in angularJS and .NET, I work with .net web api and angularjs, and I develop a function, it works when I import the data into a singe table, but the problem how to import the data into 3 table in DB !!! . and the 3 tables are linked to each other (in my exemple code there 2 table Candidature and Candidat). My question is: how to import Excel file to multiple table in DB and thank's. ( i work with asp.net web API and angularJS )
controller.cs:
/////
[Route("api/Candidature/SaveData")]
[HttpPost]
[ResponseType(typeof(Candidat))]
public IHttpActionResult SaveData(List<Candidature> Candidatures, List<Candidat> candidat)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
foreach (var data in Candidatures)
{
db.Candidature.Add(data);
}
db.SaveChanges();
foreach (var data in candidat)
{
db.Candidat.Add(data);
}
db.SaveChanges();
return StatusCode(HttpStatusCode.OK);
////
service.js:
SaveData: {
method: 'POST' ,
url: serviceBase + 'Candidature/SaveData',
isArray: true,
headers: {
'Content-Type' : 'application/json'
}
},
CandidatureCtrl.js :
$scope.Importation = function (data) {
$scope.SelectedFileForUpload = null;
$scope.UploadFile = function (files) {
$scope.$apply(function () { //I have used $scope.$apply because I will call this function from File input type control which is not supported 2 way binding
$scope.Message = "";
$scope.SelectedFileForUpload = files[0];
})
};
//Parse Excel Data
$scope.ParseExcelDataAndSave = function () {
var file = $scope.SelectedFileForUpload;
if (file) {
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
//XLSX from js-xlsx library , which I will add in page view page
var workbook = XLSX.read(e.target.result, { type: 'binary', cellDates:true, cellStyles:true });
var sheetName = workbook.SheetNames[0];
var excelData = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if (excelData.length > 0) {
//Save data
Candidature.SaveData(excelData).then(function (data) {
if (data.status) {
$scope.Message = excelData.length + " record inserted";
}
else {
$scope.Message = "Failed";
}
}, function (error) {
$scope.Message = "Error";
});
// Candidature.SaveDatacandidature(excelData).then(function (data) {
// if (data.status) {
// $scope.Message = excelData.length + " record inserted";
// }
// else {
// $scope.Message = "Failed";
// }
// }, function (error) {
// $scope.Message = "Error";
// });
// $scope.SaveData(excelData);
}
else {
$scope.Message = "No data found";
}
}
reader.onerror = function (ex) {
console.log(ex);
}
reader.readAsBinaryString(file);
}
};
var dialogOpts = {
backdrop: 'static',
keyboard: false,
scope: $scope,
size: 'lg',
templateUrl: 'views/candidature/Importation.html',
controller: ['$scope', '$uibModalInstance','$sce',
function ($scope, $uibModalInstance, $sce) {
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}
]
};
$uibModal.open(dialogOpts);
};
Importation.html :
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.1/xlsx.full.min.js"></script>
<script src="http://oss.sheetjs.com/js-xlsx/jszip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<!--<script src="app/views/candidature/candidatureCtrl.js"></script>-->
</head>
<body ng-app="agu">
<div ng-controller="candidatureCtrl" class="container" style="margin-top:50px;">
<div class="form-inline">
<input type="file" name="file" class="form-control"
onchange="angular.element(this).scope().UploadFile(this.files)"/>
<input type="button" value="Import" class="btn btn-success" ng-disabled="!SelectedFileForUpload"
ng-click="ParseExcelDataAndSave()" />
<br/>
<span style="color:red">
{{Message}}
</span>
</div>
</div>
</body>
</html>
In your web api, you are expecting two arrays for Candidatures and candidat.
But from your controller you are passing only one array of data excelData.
So when it comes to api it doesn't execute this code,
foreach (var data in candidat)
{
db.Candidat.Add(data);
}
Because candidat is either null or undefined. So it can't go through the loop which the below code is never executed.
db.Candidat.Add(data);
I'm trying to implement a websocket-server with Progress OpenEdge. I still didn't get it working.
I've successfully created a socket-server with the example i-sktsv1.p from here.
When I run my html-page, which looks like:
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8" />
<title>WebSocket Client</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:3333/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
// websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<body>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>
I getting a error that the websocket connection could not be established.
The problem is (I think) that Progress offers a socket, not a websocket. Do you know how to get this working?
I have a task that, need to sync my websites's full calendar with google calendar private data. I could able to extract data from google, but while trying to display that to the Jquery full calendar, it shows an error that TypeError: $(...).fullCalendar is not a function, but when page loads full calender is loading properly. I'm getting this error only when refreshing the calendar after fetching data from google.
Here is the code i'm using:
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API Quickstart</title>
<meta charset='utf-8' />
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.css' />
</head>
<body>
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>
<pre id="content"></pre>
<div id='calendar'></div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.js'></script>
<script type="text/javascript">
var events = [];
$('#calendar').fullCalendar({
eventSources: [
// your event source
{
events: events,
color: 'black', // an option!
textColor: 'yellow' // an option!
}
// any other event sources...
]
});
var CLIENT_ID = 'My Id';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
}).then(function () {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listUpcomingEvents();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
function refreshCalander(eventData) {
$('#calendar').fullCalendar({
eventSources: [
// your event source
{
events: eventData,
color: 'black', // an option!
textColor: 'yellow' // an option!
}
// any other event sources..
]
});
}
function listUpcomingEvents() {
gapi.client.calendar.events.list({
'calendarId': 'primary',
'timeMin': (new Date()).toISOString(),
'showDeleted': false,
'singleEvents': true,
'maxResults': 10,
'orderBy': 'startTime'
}).then(function (response) {
var googleEvents = response.result.items;
if (googleEvents.length > 0) {
for (i = 0; i < googleEvents.length; i++) {
var event = googleEvents[i];
var when = event.start.dateTime;
if (!when) {
when = event.start.date;
}
events.push({ "title": event.summary, "start": when });
}
refreshCalander(events);
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
I would not like to call asp.net server side code with jquery $.ajax .
So I have written a pure javascript ajax file .But when I call webmethod,this do not work.
Can anyony help me out how correct this? THANK you very much .
ajax.js:
var ajax = {
_params: null,
_callback: null,
_xhr: null,
_createXHR: function () {
if (window.ActiveXObject) {
_xhr = new ActiveXObject("Microsoft.XMLHTTP"); //IE
}
else if (window.XMLHttpRequest) {
_xhr = new XMLHttpRequest(); //FireFox,Chrome et.
}
},
_ajaxcallback: function () {
if (_xhr.readyState == 4) {
if (_xhr.status == 200) {
_callback.call(this, _xhr.responseText)
}
}
},
_changeParams: function () {
var args = arguments[0];
var s = "";
for (var i in args) {
s += "&" + i + "=" + args[i];
}
_params = s;
},
get: function (url, params, callback) {
_callback = callback;
ajax._createXHR();
ajax._changeParams(params);
if (null != _xhr) {
_xhr.open('get', url + '?' + _params, true);
_xhr.onreadystatechange = ajax._ajaxcallback;
_xhr.send();
}
},
post: function (url, params, callback) {
_callback = callback;
ajax._createXHR();
ajax._changeParams(params);
if (null != _xhr) {
_xhr.open('post', url, true);
_xhr.onreadystatechange = ajax._ajaxcallback;
_xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
_xhr.send(_params);
}
}
}
WebForm1.aspx
<head runat="server">
<title></title>
<script src="ajax.js" type="text/javascript"></script>
<script type="text/javascript">
function ajaxtest() {
var uid = document.getElementById("txtuid").value;
var pwd = document.getElementById("txtpwd").value;
ajax.post("WebForm1.aspx/GetModel", "{ 'uid':" + uid + ", 'pwd':" + pwd + " }", function (data) {
alert(data);
});
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="text" id="txtuid" value="eeee" />
<input type="text" value="222" id="txtpwd" onblur="ajaxtest()"/>
WebForm1.cs:
[WebMethod]
public static string GetModel(string uid,string pwd)
{
return "1";
}
In your markup you need to have a ScriptManager with EnablePageMethods set to true. Doing this will ensure you can call the methods you have marked up with [WebMethod].
In your JavaScript you can then call your method like this: PageMethods.GetModel("userName", "password", OnSuccessMethod, OnFailureMethod); - you won't need any of the ActiveXObject/XmlHttpRequest stuff if you do it this way, which keeps things much simpler.
Use AJAX.PRO from Michael Schwarz --> http://www.ajaxpro.info/